##// END OF EJS Templates
summary: clear "commonincoming" also if branches are different...
FUJIWARA Katsunori -
r18997:4cf09a1b default
parent child Browse files
Show More
@@ -1,5848 +1,5851 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge, graphmod
18 import dagparser, context, simplemerge, graphmod
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
19 import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
20 import phases, obsolete
20 import phases, obsolete
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ('', 'hidden', False, _('consider hidden changesets')),
52 ('', 'hidden', False, _('consider hidden changesets')),
53 ]
53 ]
54
54
55 dryrunopts = [('n', 'dry-run', None,
55 dryrunopts = [('n', 'dry-run', None,
56 _('do not perform actions, just print output'))]
56 _('do not perform actions, just print output'))]
57
57
58 remoteopts = [
58 remoteopts = [
59 ('e', 'ssh', '',
59 ('e', 'ssh', '',
60 _('specify ssh command to use'), _('CMD')),
60 _('specify ssh command to use'), _('CMD')),
61 ('', 'remotecmd', '',
61 ('', 'remotecmd', '',
62 _('specify hg command to run on the remote side'), _('CMD')),
62 _('specify hg command to run on the remote side'), _('CMD')),
63 ('', 'insecure', None,
63 ('', 'insecure', None,
64 _('do not verify server certificate (ignoring web.cacerts config)')),
64 _('do not verify server certificate (ignoring web.cacerts config)')),
65 ]
65 ]
66
66
67 walkopts = [
67 walkopts = [
68 ('I', 'include', [],
68 ('I', 'include', [],
69 _('include names matching the given patterns'), _('PATTERN')),
69 _('include names matching the given patterns'), _('PATTERN')),
70 ('X', 'exclude', [],
70 ('X', 'exclude', [],
71 _('exclude names matching the given patterns'), _('PATTERN')),
71 _('exclude names matching the given patterns'), _('PATTERN')),
72 ]
72 ]
73
73
74 commitopts = [
74 commitopts = [
75 ('m', 'message', '',
75 ('m', 'message', '',
76 _('use text as commit message'), _('TEXT')),
76 _('use text as commit message'), _('TEXT')),
77 ('l', 'logfile', '',
77 ('l', 'logfile', '',
78 _('read commit message from file'), _('FILE')),
78 _('read commit message from file'), _('FILE')),
79 ]
79 ]
80
80
81 commitopts2 = [
81 commitopts2 = [
82 ('d', 'date', '',
82 ('d', 'date', '',
83 _('record the specified date as commit date'), _('DATE')),
83 _('record the specified date as commit date'), _('DATE')),
84 ('u', 'user', '',
84 ('u', 'user', '',
85 _('record the specified user as committer'), _('USER')),
85 _('record the specified user as committer'), _('USER')),
86 ]
86 ]
87
87
88 templateopts = [
88 templateopts = [
89 ('', 'style', '',
89 ('', 'style', '',
90 _('display using template map file'), _('STYLE')),
90 _('display using template map file'), _('STYLE')),
91 ('', 'template', '',
91 ('', 'template', '',
92 _('display with template'), _('TEMPLATE')),
92 _('display with template'), _('TEMPLATE')),
93 ]
93 ]
94
94
95 logopts = [
95 logopts = [
96 ('p', 'patch', None, _('show patch')),
96 ('p', 'patch', None, _('show patch')),
97 ('g', 'git', None, _('use git extended diff format')),
97 ('g', 'git', None, _('use git extended diff format')),
98 ('l', 'limit', '',
98 ('l', 'limit', '',
99 _('limit number of changes displayed'), _('NUM')),
99 _('limit number of changes displayed'), _('NUM')),
100 ('M', 'no-merges', None, _('do not show merges')),
100 ('M', 'no-merges', None, _('do not show merges')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ('', 'stat', None, _('output diffstat-style summary of changes')),
102 ('G', 'graph', None, _("show the revision DAG")),
102 ('G', 'graph', None, _("show the revision DAG")),
103 ] + templateopts
103 ] + templateopts
104
104
105 diffopts = [
105 diffopts = [
106 ('a', 'text', None, _('treat all files as text')),
106 ('a', 'text', None, _('treat all files as text')),
107 ('g', 'git', None, _('use git extended diff format')),
107 ('g', 'git', None, _('use git extended diff format')),
108 ('', 'nodates', None, _('omit dates from diff headers'))
108 ('', 'nodates', None, _('omit dates from diff headers'))
109 ]
109 ]
110
110
111 diffwsopts = [
111 diffwsopts = [
112 ('w', 'ignore-all-space', None,
112 ('w', 'ignore-all-space', None,
113 _('ignore white space when comparing lines')),
113 _('ignore white space when comparing lines')),
114 ('b', 'ignore-space-change', None,
114 ('b', 'ignore-space-change', None,
115 _('ignore changes in the amount of white space')),
115 _('ignore changes in the amount of white space')),
116 ('B', 'ignore-blank-lines', None,
116 ('B', 'ignore-blank-lines', None,
117 _('ignore changes whose lines are all blank')),
117 _('ignore changes whose lines are all blank')),
118 ]
118 ]
119
119
120 diffopts2 = [
120 diffopts2 = [
121 ('p', 'show-function', None, _('show which function each change is in')),
121 ('p', 'show-function', None, _('show which function each change is in')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
122 ('', 'reverse', None, _('produce a diff that undoes the changes')),
123 ] + diffwsopts + [
123 ] + diffwsopts + [
124 ('U', 'unified', '',
124 ('U', 'unified', '',
125 _('number of lines of context to show'), _('NUM')),
125 _('number of lines of context to show'), _('NUM')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
126 ('', 'stat', None, _('output diffstat-style summary of changes')),
127 ]
127 ]
128
128
129 mergetoolopts = [
129 mergetoolopts = [
130 ('t', 'tool', '', _('specify merge tool')),
130 ('t', 'tool', '', _('specify merge tool')),
131 ]
131 ]
132
132
133 similarityopts = [
133 similarityopts = [
134 ('s', 'similarity', '',
134 ('s', 'similarity', '',
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
135 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
136 ]
136 ]
137
137
138 subrepoopts = [
138 subrepoopts = [
139 ('S', 'subrepos', None,
139 ('S', 'subrepos', None,
140 _('recurse into subrepositories'))
140 _('recurse into subrepositories'))
141 ]
141 ]
142
142
143 # Commands start here, listed alphabetically
143 # Commands start here, listed alphabetically
144
144
145 @command('^add',
145 @command('^add',
146 walkopts + subrepoopts + dryrunopts,
146 walkopts + subrepoopts + dryrunopts,
147 _('[OPTION]... [FILE]...'))
147 _('[OPTION]... [FILE]...'))
148 def add(ui, repo, *pats, **opts):
148 def add(ui, repo, *pats, **opts):
149 """add the specified files on the next commit
149 """add the specified files on the next commit
150
150
151 Schedule files to be version controlled and added to the
151 Schedule files to be version controlled and added to the
152 repository.
152 repository.
153
153
154 The files will be added to the repository at the next commit. To
154 The files will be added to the repository at the next commit. To
155 undo an add before that, see :hg:`forget`.
155 undo an add before that, see :hg:`forget`.
156
156
157 If no names are given, add all files to the repository.
157 If no names are given, add all files to the repository.
158
158
159 .. container:: verbose
159 .. container:: verbose
160
160
161 An example showing how new (unknown) files are added
161 An example showing how new (unknown) files are added
162 automatically by :hg:`add`::
162 automatically by :hg:`add`::
163
163
164 $ ls
164 $ ls
165 foo.c
165 foo.c
166 $ hg status
166 $ hg status
167 ? foo.c
167 ? foo.c
168 $ hg add
168 $ hg add
169 adding foo.c
169 adding foo.c
170 $ hg status
170 $ hg status
171 A foo.c
171 A foo.c
172
172
173 Returns 0 if all files are successfully added.
173 Returns 0 if all files are successfully added.
174 """
174 """
175
175
176 m = scmutil.match(repo[None], pats, opts)
176 m = scmutil.match(repo[None], pats, opts)
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
177 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
178 opts.get('subrepos'), prefix="", explicitonly=False)
178 opts.get('subrepos'), prefix="", explicitonly=False)
179 return rejected and 1 or 0
179 return rejected and 1 or 0
180
180
181 @command('addremove',
181 @command('addremove',
182 similarityopts + walkopts + dryrunopts,
182 similarityopts + walkopts + dryrunopts,
183 _('[OPTION]... [FILE]...'))
183 _('[OPTION]... [FILE]...'))
184 def addremove(ui, repo, *pats, **opts):
184 def addremove(ui, repo, *pats, **opts):
185 """add all new files, delete all missing files
185 """add all new files, delete all missing files
186
186
187 Add all new files and remove all missing files from the
187 Add all new files and remove all missing files from the
188 repository.
188 repository.
189
189
190 New files are ignored if they match any of the patterns in
190 New files are ignored if they match any of the patterns in
191 ``.hgignore``. As with add, these changes take effect at the next
191 ``.hgignore``. As with add, these changes take effect at the next
192 commit.
192 commit.
193
193
194 Use the -s/--similarity option to detect renamed files. This
194 Use the -s/--similarity option to detect renamed files. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. With a parameter greater than 0,
196 be identical) as its parameter. With a parameter greater than 0,
197 this compares every removed file with every added file and records
197 this compares every removed file with every added file and records
198 those similar enough as renames. Detecting renamed files this way
198 those similar enough as renames. Detecting renamed files this way
199 can be expensive. After using this option, :hg:`status -C` can be
199 can be expensive. After using this option, :hg:`status -C` can be
200 used to check which files were identified as moved or renamed. If
200 used to check which files were identified as moved or renamed. If
201 not specified, -s/--similarity defaults to 100 and only renames of
201 not specified, -s/--similarity defaults to 100 and only renames of
202 identical files are detected.
202 identical files are detected.
203
203
204 Returns 0 if all files are successfully added.
204 Returns 0 if all files are successfully added.
205 """
205 """
206 try:
206 try:
207 sim = float(opts.get('similarity') or 100)
207 sim = float(opts.get('similarity') or 100)
208 except ValueError:
208 except ValueError:
209 raise util.Abort(_('similarity must be a number'))
209 raise util.Abort(_('similarity must be a number'))
210 if sim < 0 or sim > 100:
210 if sim < 0 or sim > 100:
211 raise util.Abort(_('similarity must be between 0 and 100'))
211 raise util.Abort(_('similarity must be between 0 and 100'))
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
212 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
213
213
214 @command('^annotate|blame',
214 @command('^annotate|blame',
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
215 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
216 ('', 'follow', None,
216 ('', 'follow', None,
217 _('follow copies/renames and list the filename (DEPRECATED)')),
217 _('follow copies/renames and list the filename (DEPRECATED)')),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
218 ('', 'no-follow', None, _("don't follow copies and renames")),
219 ('a', 'text', None, _('treat all files as text')),
219 ('a', 'text', None, _('treat all files as text')),
220 ('u', 'user', None, _('list the author (long with -v)')),
220 ('u', 'user', None, _('list the author (long with -v)')),
221 ('f', 'file', None, _('list the filename')),
221 ('f', 'file', None, _('list the filename')),
222 ('d', 'date', None, _('list the date (short with -q)')),
222 ('d', 'date', None, _('list the date (short with -q)')),
223 ('n', 'number', None, _('list the revision number (default)')),
223 ('n', 'number', None, _('list the revision number (default)')),
224 ('c', 'changeset', None, _('list the changeset')),
224 ('c', 'changeset', None, _('list the changeset')),
225 ('l', 'line-number', None, _('show line number at the first appearance'))
225 ('l', 'line-number', None, _('show line number at the first appearance'))
226 ] + diffwsopts + walkopts,
226 ] + diffwsopts + walkopts,
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
227 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
228 def annotate(ui, repo, *pats, **opts):
228 def annotate(ui, repo, *pats, **opts):
229 """show changeset information by line for each file
229 """show changeset information by line for each file
230
230
231 List changes in files, showing the revision id responsible for
231 List changes in files, showing the revision id responsible for
232 each line
232 each line
233
233
234 This command is useful for discovering when a change was made and
234 This command is useful for discovering when a change was made and
235 by whom.
235 by whom.
236
236
237 Without the -a/--text option, annotate will avoid processing files
237 Without the -a/--text option, annotate will avoid processing files
238 it detects as binary. With -a, annotate will annotate the file
238 it detects as binary. With -a, annotate will annotate the file
239 anyway, although the results will probably be neither useful
239 anyway, although the results will probably be neither useful
240 nor desirable.
240 nor desirable.
241
241
242 Returns 0 on success.
242 Returns 0 on success.
243 """
243 """
244 if opts.get('follow'):
244 if opts.get('follow'):
245 # --follow is deprecated and now just an alias for -f/--file
245 # --follow is deprecated and now just an alias for -f/--file
246 # to mimic the behavior of Mercurial before version 1.5
246 # to mimic the behavior of Mercurial before version 1.5
247 opts['file'] = True
247 opts['file'] = True
248
248
249 datefunc = ui.quiet and util.shortdate or util.datestr
249 datefunc = ui.quiet and util.shortdate or util.datestr
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
250 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
251
251
252 if not pats:
252 if not pats:
253 raise util.Abort(_('at least one filename or pattern is required'))
253 raise util.Abort(_('at least one filename or pattern is required'))
254
254
255 hexfn = ui.debugflag and hex or short
255 hexfn = ui.debugflag and hex or short
256
256
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
257 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
258 ('number', ' ', lambda x: str(x[0].rev())),
258 ('number', ' ', lambda x: str(x[0].rev())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
259 ('changeset', ' ', lambda x: hexfn(x[0].node())),
260 ('date', ' ', getdate),
260 ('date', ' ', getdate),
261 ('file', ' ', lambda x: x[0].path()),
261 ('file', ' ', lambda x: x[0].path()),
262 ('line_number', ':', lambda x: str(x[1])),
262 ('line_number', ':', lambda x: str(x[1])),
263 ]
263 ]
264
264
265 if (not opts.get('user') and not opts.get('changeset')
265 if (not opts.get('user') and not opts.get('changeset')
266 and not opts.get('date') and not opts.get('file')):
266 and not opts.get('date') and not opts.get('file')):
267 opts['number'] = True
267 opts['number'] = True
268
268
269 linenumber = opts.get('line_number') is not None
269 linenumber = opts.get('line_number') is not None
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
270 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
271 raise util.Abort(_('at least one of -n/-c is required for -l'))
272
272
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
273 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
274 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
275
275
276 def bad(x, y):
276 def bad(x, y):
277 raise util.Abort("%s: %s" % (x, y))
277 raise util.Abort("%s: %s" % (x, y))
278
278
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
279 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 m = scmutil.match(ctx, pats, opts)
280 m = scmutil.match(ctx, pats, opts)
281 m.bad = bad
281 m.bad = bad
282 follow = not opts.get('no_follow')
282 follow = not opts.get('no_follow')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
283 diffopts = patch.diffopts(ui, opts, section='annotate')
284 for abs in ctx.walk(m):
284 for abs in ctx.walk(m):
285 fctx = ctx[abs]
285 fctx = ctx[abs]
286 if not opts.get('text') and util.binary(fctx.data()):
286 if not opts.get('text') and util.binary(fctx.data()):
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
287 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
288 continue
288 continue
289
289
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
290 lines = fctx.annotate(follow=follow, linenumber=linenumber,
291 diffopts=diffopts)
291 diffopts=diffopts)
292 pieces = []
292 pieces = []
293
293
294 for f, sep in funcmap:
294 for f, sep in funcmap:
295 l = [f(n) for n, dummy in lines]
295 l = [f(n) for n, dummy in lines]
296 if l:
296 if l:
297 sized = [(x, encoding.colwidth(x)) for x in l]
297 sized = [(x, encoding.colwidth(x)) for x in l]
298 ml = max([w for x, w in sized])
298 ml = max([w for x, w in sized])
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
299 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
300 for x, w in sized])
300 for x, w in sized])
301
301
302 if pieces:
302 if pieces:
303 for p, l in zip(zip(*pieces), lines):
303 for p, l in zip(zip(*pieces), lines):
304 ui.write("%s: %s" % ("".join(p), l[1]))
304 ui.write("%s: %s" % ("".join(p), l[1]))
305
305
306 if lines and not lines[-1][1].endswith('\n'):
306 if lines and not lines[-1][1].endswith('\n'):
307 ui.write('\n')
307 ui.write('\n')
308
308
309 @command('archive',
309 @command('archive',
310 [('', 'no-decode', None, _('do not pass files through decoders')),
310 [('', 'no-decode', None, _('do not pass files through decoders')),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
311 ('p', 'prefix', '', _('directory prefix for files in archive'),
312 _('PREFIX')),
312 _('PREFIX')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
313 ('r', 'rev', '', _('revision to distribute'), _('REV')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
314 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
315 ] + subrepoopts + walkopts,
315 ] + subrepoopts + walkopts,
316 _('[OPTION]... DEST'))
316 _('[OPTION]... DEST'))
317 def archive(ui, repo, dest, **opts):
317 def archive(ui, repo, dest, **opts):
318 '''create an unversioned archive of a repository revision
318 '''create an unversioned archive of a repository revision
319
319
320 By default, the revision used is the parent of the working
320 By default, the revision used is the parent of the working
321 directory; use -r/--rev to specify a different revision.
321 directory; use -r/--rev to specify a different revision.
322
322
323 The archive type is automatically detected based on file
323 The archive type is automatically detected based on file
324 extension (or override using -t/--type).
324 extension (or override using -t/--type).
325
325
326 .. container:: verbose
326 .. container:: verbose
327
327
328 Examples:
328 Examples:
329
329
330 - create a zip file containing the 1.0 release::
330 - create a zip file containing the 1.0 release::
331
331
332 hg archive -r 1.0 project-1.0.zip
332 hg archive -r 1.0 project-1.0.zip
333
333
334 - create a tarball excluding .hg files::
334 - create a tarball excluding .hg files::
335
335
336 hg archive project.tar.gz -X ".hg*"
336 hg archive project.tar.gz -X ".hg*"
337
337
338 Valid types are:
338 Valid types are:
339
339
340 :``files``: a directory full of files (default)
340 :``files``: a directory full of files (default)
341 :``tar``: tar archive, uncompressed
341 :``tar``: tar archive, uncompressed
342 :``tbz2``: tar archive, compressed using bzip2
342 :``tbz2``: tar archive, compressed using bzip2
343 :``tgz``: tar archive, compressed using gzip
343 :``tgz``: tar archive, compressed using gzip
344 :``uzip``: zip archive, uncompressed
344 :``uzip``: zip archive, uncompressed
345 :``zip``: zip archive, compressed using deflate
345 :``zip``: zip archive, compressed using deflate
346
346
347 The exact name of the destination archive or directory is given
347 The exact name of the destination archive or directory is given
348 using a format string; see :hg:`help export` for details.
348 using a format string; see :hg:`help export` for details.
349
349
350 Each member added to an archive file has a directory prefix
350 Each member added to an archive file has a directory prefix
351 prepended. Use -p/--prefix to specify a format string for the
351 prepended. Use -p/--prefix to specify a format string for the
352 prefix. The default is the basename of the archive, with suffixes
352 prefix. The default is the basename of the archive, with suffixes
353 removed.
353 removed.
354
354
355 Returns 0 on success.
355 Returns 0 on success.
356 '''
356 '''
357
357
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
358 ctx = scmutil.revsingle(repo, opts.get('rev'))
359 if not ctx:
359 if not ctx:
360 raise util.Abort(_('no working directory: please specify a revision'))
360 raise util.Abort(_('no working directory: please specify a revision'))
361 node = ctx.node()
361 node = ctx.node()
362 dest = cmdutil.makefilename(repo, dest, node)
362 dest = cmdutil.makefilename(repo, dest, node)
363 if os.path.realpath(dest) == repo.root:
363 if os.path.realpath(dest) == repo.root:
364 raise util.Abort(_('repository root cannot be destination'))
364 raise util.Abort(_('repository root cannot be destination'))
365
365
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
366 kind = opts.get('type') or archival.guesskind(dest) or 'files'
367 prefix = opts.get('prefix')
367 prefix = opts.get('prefix')
368
368
369 if dest == '-':
369 if dest == '-':
370 if kind == 'files':
370 if kind == 'files':
371 raise util.Abort(_('cannot archive plain files to stdout'))
371 raise util.Abort(_('cannot archive plain files to stdout'))
372 dest = cmdutil.makefileobj(repo, dest)
372 dest = cmdutil.makefileobj(repo, dest)
373 if not prefix:
373 if not prefix:
374 prefix = os.path.basename(repo.root) + '-%h'
374 prefix = os.path.basename(repo.root) + '-%h'
375
375
376 prefix = cmdutil.makefilename(repo, prefix, node)
376 prefix = cmdutil.makefilename(repo, prefix, node)
377 matchfn = scmutil.match(ctx, [], opts)
377 matchfn = scmutil.match(ctx, [], opts)
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
378 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
379 matchfn, prefix, subrepos=opts.get('subrepos'))
379 matchfn, prefix, subrepos=opts.get('subrepos'))
380
380
381 @command('backout',
381 @command('backout',
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
382 [('', 'merge', None, _('merge with old dirstate parent after backout')),
383 ('', 'parent', '',
383 ('', 'parent', '',
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
384 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
385 ('r', 'rev', '', _('revision to backout'), _('REV')),
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
386 ] + mergetoolopts + walkopts + commitopts + commitopts2,
387 _('[OPTION]... [-r] REV'))
387 _('[OPTION]... [-r] REV'))
388 def backout(ui, repo, node=None, rev=None, **opts):
388 def backout(ui, repo, node=None, rev=None, **opts):
389 '''reverse effect of earlier changeset
389 '''reverse effect of earlier changeset
390
390
391 Prepare a new changeset with the effect of REV undone in the
391 Prepare a new changeset with the effect of REV undone in the
392 current working directory.
392 current working directory.
393
393
394 If REV is the parent of the working directory, then this new changeset
394 If REV is the parent of the working directory, then this new changeset
395 is committed automatically. Otherwise, hg needs to merge the
395 is committed automatically. Otherwise, hg needs to merge the
396 changes and the merged result is left uncommitted.
396 changes and the merged result is left uncommitted.
397
397
398 .. note::
398 .. note::
399 backout cannot be used to fix either an unwanted or
399 backout cannot be used to fix either an unwanted or
400 incorrect merge.
400 incorrect merge.
401
401
402 .. container:: verbose
402 .. container:: verbose
403
403
404 By default, the pending changeset will have one parent,
404 By default, the pending changeset will have one parent,
405 maintaining a linear history. With --merge, the pending
405 maintaining a linear history. With --merge, the pending
406 changeset will instead have two parents: the old parent of the
406 changeset will instead have two parents: the old parent of the
407 working directory and a new child of REV that simply undoes REV.
407 working directory and a new child of REV that simply undoes REV.
408
408
409 Before version 1.7, the behavior without --merge was equivalent
409 Before version 1.7, the behavior without --merge was equivalent
410 to specifying --merge followed by :hg:`update --clean .` to
410 to specifying --merge followed by :hg:`update --clean .` to
411 cancel the merge and leave the child of REV as a head to be
411 cancel the merge and leave the child of REV as a head to be
412 merged separately.
412 merged separately.
413
413
414 See :hg:`help dates` for a list of formats valid for -d/--date.
414 See :hg:`help dates` for a list of formats valid for -d/--date.
415
415
416 Returns 0 on success.
416 Returns 0 on success.
417 '''
417 '''
418 if rev and node:
418 if rev and node:
419 raise util.Abort(_("please specify just one revision"))
419 raise util.Abort(_("please specify just one revision"))
420
420
421 if not rev:
421 if not rev:
422 rev = node
422 rev = node
423
423
424 if not rev:
424 if not rev:
425 raise util.Abort(_("please specify a revision to backout"))
425 raise util.Abort(_("please specify a revision to backout"))
426
426
427 date = opts.get('date')
427 date = opts.get('date')
428 if date:
428 if date:
429 opts['date'] = util.parsedate(date)
429 opts['date'] = util.parsedate(date)
430
430
431 cmdutil.bailifchanged(repo)
431 cmdutil.bailifchanged(repo)
432 node = scmutil.revsingle(repo, rev).node()
432 node = scmutil.revsingle(repo, rev).node()
433
433
434 op1, op2 = repo.dirstate.parents()
434 op1, op2 = repo.dirstate.parents()
435 a = repo.changelog.ancestor(op1, node)
435 a = repo.changelog.ancestor(op1, node)
436 if a != node:
436 if a != node:
437 raise util.Abort(_('cannot backout change on a different branch'))
437 raise util.Abort(_('cannot backout change on a different branch'))
438
438
439 p1, p2 = repo.changelog.parents(node)
439 p1, p2 = repo.changelog.parents(node)
440 if p1 == nullid:
440 if p1 == nullid:
441 raise util.Abort(_('cannot backout a change with no parents'))
441 raise util.Abort(_('cannot backout a change with no parents'))
442 if p2 != nullid:
442 if p2 != nullid:
443 if not opts.get('parent'):
443 if not opts.get('parent'):
444 raise util.Abort(_('cannot backout a merge changeset'))
444 raise util.Abort(_('cannot backout a merge changeset'))
445 p = repo.lookup(opts['parent'])
445 p = repo.lookup(opts['parent'])
446 if p not in (p1, p2):
446 if p not in (p1, p2):
447 raise util.Abort(_('%s is not a parent of %s') %
447 raise util.Abort(_('%s is not a parent of %s') %
448 (short(p), short(node)))
448 (short(p), short(node)))
449 parent = p
449 parent = p
450 else:
450 else:
451 if opts.get('parent'):
451 if opts.get('parent'):
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
452 raise util.Abort(_('cannot use --parent on non-merge changeset'))
453 parent = p1
453 parent = p1
454
454
455 # the backout should appear on the same branch
455 # the backout should appear on the same branch
456 wlock = repo.wlock()
456 wlock = repo.wlock()
457 try:
457 try:
458 branch = repo.dirstate.branch()
458 branch = repo.dirstate.branch()
459 bheads = repo.branchheads(branch)
459 bheads = repo.branchheads(branch)
460 hg.clean(repo, node, show_stats=False)
460 hg.clean(repo, node, show_stats=False)
461 repo.dirstate.setbranch(branch)
461 repo.dirstate.setbranch(branch)
462 rctx = scmutil.revsingle(repo, hex(parent))
462 rctx = scmutil.revsingle(repo, hex(parent))
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
463 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
464 if not opts.get('merge') and op1 != node:
464 if not opts.get('merge') and op1 != node:
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.update(repo, op1)
467 return hg.update(repo, op1)
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470
470
471 e = cmdutil.commiteditor
471 e = cmdutil.commiteditor
472 if not opts['message'] and not opts['logfile']:
472 if not opts['message'] and not opts['logfile']:
473 # we don't translate commit messages
473 # we don't translate commit messages
474 opts['message'] = "Backed out changeset %s" % short(node)
474 opts['message'] = "Backed out changeset %s" % short(node)
475 e = cmdutil.commitforceeditor
475 e = cmdutil.commitforceeditor
476
476
477 def commitfunc(ui, repo, message, match, opts):
477 def commitfunc(ui, repo, message, match, opts):
478 return repo.commit(message, opts.get('user'), opts.get('date'),
478 return repo.commit(message, opts.get('user'), opts.get('date'),
479 match, editor=e)
479 match, editor=e)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
480 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
481 cmdutil.commitstatus(repo, newnode, branch, bheads)
482
482
483 def nice(node):
483 def nice(node):
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
484 return '%d:%s' % (repo.changelog.rev(node), short(node))
485 ui.status(_('changeset %s backs out changeset %s\n') %
485 ui.status(_('changeset %s backs out changeset %s\n') %
486 (nice(repo.changelog.tip()), nice(node)))
486 (nice(repo.changelog.tip()), nice(node)))
487 if opts.get('merge') and op1 != node:
487 if opts.get('merge') and op1 != node:
488 hg.clean(repo, op1, show_stats=False)
488 hg.clean(repo, op1, show_stats=False)
489 ui.status(_('merging with changeset %s\n')
489 ui.status(_('merging with changeset %s\n')
490 % nice(repo.changelog.tip()))
490 % nice(repo.changelog.tip()))
491 try:
491 try:
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
493 return hg.merge(repo, hex(repo.changelog.tip()))
493 return hg.merge(repo, hex(repo.changelog.tip()))
494 finally:
494 finally:
495 ui.setconfig('ui', 'forcemerge', '')
495 ui.setconfig('ui', 'forcemerge', '')
496 finally:
496 finally:
497 wlock.release()
497 wlock.release()
498 return 0
498 return 0
499
499
500 @command('bisect',
500 @command('bisect',
501 [('r', 'reset', False, _('reset bisect state')),
501 [('r', 'reset', False, _('reset bisect state')),
502 ('g', 'good', False, _('mark changeset good')),
502 ('g', 'good', False, _('mark changeset good')),
503 ('b', 'bad', False, _('mark changeset bad')),
503 ('b', 'bad', False, _('mark changeset bad')),
504 ('s', 'skip', False, _('skip testing changeset')),
504 ('s', 'skip', False, _('skip testing changeset')),
505 ('e', 'extend', False, _('extend the bisect range')),
505 ('e', 'extend', False, _('extend the bisect range')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
506 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
507 ('U', 'noupdate', False, _('do not update to target'))],
507 ('U', 'noupdate', False, _('do not update to target'))],
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
508 _("[-gbsr] [-U] [-c CMD] [REV]"))
509 def bisect(ui, repo, rev=None, extra=None, command=None,
509 def bisect(ui, repo, rev=None, extra=None, command=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
510 reset=None, good=None, bad=None, skip=None, extend=None,
511 noupdate=None):
511 noupdate=None):
512 """subdivision search of changesets
512 """subdivision search of changesets
513
513
514 This command helps to find changesets which introduce problems. To
514 This command helps to find changesets which introduce problems. To
515 use, mark the earliest changeset you know exhibits the problem as
515 use, mark the earliest changeset you know exhibits the problem as
516 bad, then mark the latest changeset which is free from the problem
516 bad, then mark the latest changeset which is free from the problem
517 as good. Bisect will update your working directory to a revision
517 as good. Bisect will update your working directory to a revision
518 for testing (unless the -U/--noupdate option is specified). Once
518 for testing (unless the -U/--noupdate option is specified). Once
519 you have performed tests, mark the working directory as good or
519 you have performed tests, mark the working directory as good or
520 bad, and bisect will either update to another candidate changeset
520 bad, and bisect will either update to another candidate changeset
521 or announce that it has found the bad revision.
521 or announce that it has found the bad revision.
522
522
523 As a shortcut, you can also use the revision argument to mark a
523 As a shortcut, you can also use the revision argument to mark a
524 revision as good or bad without checking it out first.
524 revision as good or bad without checking it out first.
525
525
526 If you supply a command, it will be used for automatic bisection.
526 If you supply a command, it will be used for automatic bisection.
527 The environment variable HG_NODE will contain the ID of the
527 The environment variable HG_NODE will contain the ID of the
528 changeset being tested. The exit status of the command will be
528 changeset being tested. The exit status of the command will be
529 used to mark revisions as good or bad: status 0 means good, 125
529 used to mark revisions as good or bad: status 0 means good, 125
530 means to skip the revision, 127 (command not found) will abort the
530 means to skip the revision, 127 (command not found) will abort the
531 bisection, and any other non-zero exit status means the revision
531 bisection, and any other non-zero exit status means the revision
532 is bad.
532 is bad.
533
533
534 .. container:: verbose
534 .. container:: verbose
535
535
536 Some examples:
536 Some examples:
537
537
538 - start a bisection with known bad revision 12, and good revision 34::
538 - start a bisection with known bad revision 12, and good revision 34::
539
539
540 hg bisect --bad 34
540 hg bisect --bad 34
541 hg bisect --good 12
541 hg bisect --good 12
542
542
543 - advance the current bisection by marking current revision as good or
543 - advance the current bisection by marking current revision as good or
544 bad::
544 bad::
545
545
546 hg bisect --good
546 hg bisect --good
547 hg bisect --bad
547 hg bisect --bad
548
548
549 - mark the current revision, or a known revision, to be skipped (e.g. if
549 - mark the current revision, or a known revision, to be skipped (e.g. if
550 that revision is not usable because of another issue)::
550 that revision is not usable because of another issue)::
551
551
552 hg bisect --skip
552 hg bisect --skip
553 hg bisect --skip 23
553 hg bisect --skip 23
554
554
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
555 - skip all revisions that do not touch directories ``foo`` or ``bar``
556
556
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
557 hg bisect --skip '!( file("path:foo") & file("path:bar") )'
558
558
559 - forget the current bisection::
559 - forget the current bisection::
560
560
561 hg bisect --reset
561 hg bisect --reset
562
562
563 - use 'make && make tests' to automatically find the first broken
563 - use 'make && make tests' to automatically find the first broken
564 revision::
564 revision::
565
565
566 hg bisect --reset
566 hg bisect --reset
567 hg bisect --bad 34
567 hg bisect --bad 34
568 hg bisect --good 12
568 hg bisect --good 12
569 hg bisect --command 'make && make tests'
569 hg bisect --command 'make && make tests'
570
570
571 - see all changesets whose states are already known in the current
571 - see all changesets whose states are already known in the current
572 bisection::
572 bisection::
573
573
574 hg log -r "bisect(pruned)"
574 hg log -r "bisect(pruned)"
575
575
576 - see the changeset currently being bisected (especially useful
576 - see the changeset currently being bisected (especially useful
577 if running with -U/--noupdate)::
577 if running with -U/--noupdate)::
578
578
579 hg log -r "bisect(current)"
579 hg log -r "bisect(current)"
580
580
581 - see all changesets that took part in the current bisection::
581 - see all changesets that took part in the current bisection::
582
582
583 hg log -r "bisect(range)"
583 hg log -r "bisect(range)"
584
584
585 - with the graphlog extension, you can even get a nice graph::
585 - with the graphlog extension, you can even get a nice graph::
586
586
587 hg log --graph -r "bisect(range)"
587 hg log --graph -r "bisect(range)"
588
588
589 See :hg:`help revsets` for more about the `bisect()` keyword.
589 See :hg:`help revsets` for more about the `bisect()` keyword.
590
590
591 Returns 0 on success.
591 Returns 0 on success.
592 """
592 """
593 def extendbisectrange(nodes, good):
593 def extendbisectrange(nodes, good):
594 # bisect is incomplete when it ends on a merge node and
594 # bisect is incomplete when it ends on a merge node and
595 # one of the parent was not checked.
595 # one of the parent was not checked.
596 parents = repo[nodes[0]].parents()
596 parents = repo[nodes[0]].parents()
597 if len(parents) > 1:
597 if len(parents) > 1:
598 side = good and state['bad'] or state['good']
598 side = good and state['bad'] or state['good']
599 num = len(set(i.node() for i in parents) & set(side))
599 num = len(set(i.node() for i in parents) & set(side))
600 if num == 1:
600 if num == 1:
601 return parents[0].ancestor(parents[1])
601 return parents[0].ancestor(parents[1])
602 return None
602 return None
603
603
604 def print_result(nodes, good):
604 def print_result(nodes, good):
605 displayer = cmdutil.show_changeset(ui, repo, {})
605 displayer = cmdutil.show_changeset(ui, repo, {})
606 if len(nodes) == 1:
606 if len(nodes) == 1:
607 # narrowed it down to a single revision
607 # narrowed it down to a single revision
608 if good:
608 if good:
609 ui.write(_("The first good revision is:\n"))
609 ui.write(_("The first good revision is:\n"))
610 else:
610 else:
611 ui.write(_("The first bad revision is:\n"))
611 ui.write(_("The first bad revision is:\n"))
612 displayer.show(repo[nodes[0]])
612 displayer.show(repo[nodes[0]])
613 extendnode = extendbisectrange(nodes, good)
613 extendnode = extendbisectrange(nodes, good)
614 if extendnode is not None:
614 if extendnode is not None:
615 ui.write(_('Not all ancestors of this changeset have been'
615 ui.write(_('Not all ancestors of this changeset have been'
616 ' checked.\nUse bisect --extend to continue the '
616 ' checked.\nUse bisect --extend to continue the '
617 'bisection from\nthe common ancestor, %s.\n')
617 'bisection from\nthe common ancestor, %s.\n')
618 % extendnode)
618 % extendnode)
619 else:
619 else:
620 # multiple possible revisions
620 # multiple possible revisions
621 if good:
621 if good:
622 ui.write(_("Due to skipped revisions, the first "
622 ui.write(_("Due to skipped revisions, the first "
623 "good revision could be any of:\n"))
623 "good revision could be any of:\n"))
624 else:
624 else:
625 ui.write(_("Due to skipped revisions, the first "
625 ui.write(_("Due to skipped revisions, the first "
626 "bad revision could be any of:\n"))
626 "bad revision could be any of:\n"))
627 for n in nodes:
627 for n in nodes:
628 displayer.show(repo[n])
628 displayer.show(repo[n])
629 displayer.close()
629 displayer.close()
630
630
631 def check_state(state, interactive=True):
631 def check_state(state, interactive=True):
632 if not state['good'] or not state['bad']:
632 if not state['good'] or not state['bad']:
633 if (good or bad or skip or reset) and interactive:
633 if (good or bad or skip or reset) and interactive:
634 return
634 return
635 if not state['good']:
635 if not state['good']:
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
636 raise util.Abort(_('cannot bisect (no known good revisions)'))
637 else:
637 else:
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
638 raise util.Abort(_('cannot bisect (no known bad revisions)'))
639 return True
639 return True
640
640
641 # backward compatibility
641 # backward compatibility
642 if rev in "good bad reset init".split():
642 if rev in "good bad reset init".split():
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
643 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
644 cmd, rev, extra = rev, extra, None
644 cmd, rev, extra = rev, extra, None
645 if cmd == "good":
645 if cmd == "good":
646 good = True
646 good = True
647 elif cmd == "bad":
647 elif cmd == "bad":
648 bad = True
648 bad = True
649 else:
649 else:
650 reset = True
650 reset = True
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
651 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
652 raise util.Abort(_('incompatible arguments'))
652 raise util.Abort(_('incompatible arguments'))
653
653
654 if reset:
654 if reset:
655 p = repo.join("bisect.state")
655 p = repo.join("bisect.state")
656 if os.path.exists(p):
656 if os.path.exists(p):
657 os.unlink(p)
657 os.unlink(p)
658 return
658 return
659
659
660 state = hbisect.load_state(repo)
660 state = hbisect.load_state(repo)
661
661
662 if command:
662 if command:
663 changesets = 1
663 changesets = 1
664 try:
664 try:
665 node = state['current'][0]
665 node = state['current'][0]
666 except LookupError:
666 except LookupError:
667 if noupdate:
667 if noupdate:
668 raise util.Abort(_('current bisect revision is unknown - '
668 raise util.Abort(_('current bisect revision is unknown - '
669 'start a new bisect to fix'))
669 'start a new bisect to fix'))
670 node, p2 = repo.dirstate.parents()
670 node, p2 = repo.dirstate.parents()
671 if p2 != nullid:
671 if p2 != nullid:
672 raise util.Abort(_('current bisect revision is a merge'))
672 raise util.Abort(_('current bisect revision is a merge'))
673 try:
673 try:
674 while changesets:
674 while changesets:
675 # update state
675 # update state
676 state['current'] = [node]
676 state['current'] = [node]
677 hbisect.save_state(repo, state)
677 hbisect.save_state(repo, state)
678 status = util.system(command,
678 status = util.system(command,
679 environ={'HG_NODE': hex(node)},
679 environ={'HG_NODE': hex(node)},
680 out=ui.fout)
680 out=ui.fout)
681 if status == 125:
681 if status == 125:
682 transition = "skip"
682 transition = "skip"
683 elif status == 0:
683 elif status == 0:
684 transition = "good"
684 transition = "good"
685 # status < 0 means process was killed
685 # status < 0 means process was killed
686 elif status == 127:
686 elif status == 127:
687 raise util.Abort(_("failed to execute %s") % command)
687 raise util.Abort(_("failed to execute %s") % command)
688 elif status < 0:
688 elif status < 0:
689 raise util.Abort(_("%s killed") % command)
689 raise util.Abort(_("%s killed") % command)
690 else:
690 else:
691 transition = "bad"
691 transition = "bad"
692 ctx = scmutil.revsingle(repo, rev, node)
692 ctx = scmutil.revsingle(repo, rev, node)
693 rev = None # clear for future iterations
693 rev = None # clear for future iterations
694 state[transition].append(ctx.node())
694 state[transition].append(ctx.node())
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
695 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
696 check_state(state, interactive=False)
696 check_state(state, interactive=False)
697 # bisect
697 # bisect
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
698 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
699 # update to next check
699 # update to next check
700 node = nodes[0]
700 node = nodes[0]
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 hg.clean(repo, node, show_stats=False)
703 hg.clean(repo, node, show_stats=False)
704 finally:
704 finally:
705 state['current'] = [node]
705 state['current'] = [node]
706 hbisect.save_state(repo, state)
706 hbisect.save_state(repo, state)
707 print_result(nodes, good)
707 print_result(nodes, good)
708 return
708 return
709
709
710 # update state
710 # update state
711
711
712 if rev:
712 if rev:
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
713 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
714 else:
714 else:
715 nodes = [repo.lookup('.')]
715 nodes = [repo.lookup('.')]
716
716
717 if good or bad or skip:
717 if good or bad or skip:
718 if good:
718 if good:
719 state['good'] += nodes
719 state['good'] += nodes
720 elif bad:
720 elif bad:
721 state['bad'] += nodes
721 state['bad'] += nodes
722 elif skip:
722 elif skip:
723 state['skip'] += nodes
723 state['skip'] += nodes
724 hbisect.save_state(repo, state)
724 hbisect.save_state(repo, state)
725
725
726 if not check_state(state):
726 if not check_state(state):
727 return
727 return
728
728
729 # actually bisect
729 # actually bisect
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
730 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
731 if extend:
731 if extend:
732 if not changesets:
732 if not changesets:
733 extendnode = extendbisectrange(nodes, good)
733 extendnode = extendbisectrange(nodes, good)
734 if extendnode is not None:
734 if extendnode is not None:
735 ui.write(_("Extending search to changeset %d:%s\n"
735 ui.write(_("Extending search to changeset %d:%s\n"
736 % (extendnode.rev(), extendnode)))
736 % (extendnode.rev(), extendnode)))
737 state['current'] = [extendnode.node()]
737 state['current'] = [extendnode.node()]
738 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
739 if noupdate:
739 if noupdate:
740 return
740 return
741 cmdutil.bailifchanged(repo)
741 cmdutil.bailifchanged(repo)
742 return hg.clean(repo, extendnode.node())
742 return hg.clean(repo, extendnode.node())
743 raise util.Abort(_("nothing to extend"))
743 raise util.Abort(_("nothing to extend"))
744
744
745 if changesets == 0:
745 if changesets == 0:
746 print_result(nodes, good)
746 print_result(nodes, good)
747 else:
747 else:
748 assert len(nodes) == 1 # only a single node can be tested next
748 assert len(nodes) == 1 # only a single node can be tested next
749 node = nodes[0]
749 node = nodes[0]
750 # compute the approximate number of remaining tests
750 # compute the approximate number of remaining tests
751 tests, size = 0, 2
751 tests, size = 0, 2
752 while size <= changesets:
752 while size <= changesets:
753 tests, size = tests + 1, size * 2
753 tests, size = tests + 1, size * 2
754 rev = repo.changelog.rev(node)
754 rev = repo.changelog.rev(node)
755 ui.write(_("Testing changeset %d:%s "
755 ui.write(_("Testing changeset %d:%s "
756 "(%d changesets remaining, ~%d tests)\n")
756 "(%d changesets remaining, ~%d tests)\n")
757 % (rev, short(node), changesets, tests))
757 % (rev, short(node), changesets, tests))
758 state['current'] = [node]
758 state['current'] = [node]
759 hbisect.save_state(repo, state)
759 hbisect.save_state(repo, state)
760 if not noupdate:
760 if not noupdate:
761 cmdutil.bailifchanged(repo)
761 cmdutil.bailifchanged(repo)
762 return hg.clean(repo, node)
762 return hg.clean(repo, node)
763
763
764 @command('bookmarks|bookmark',
764 @command('bookmarks|bookmark',
765 [('f', 'force', False, _('force')),
765 [('f', 'force', False, _('force')),
766 ('r', 'rev', '', _('revision'), _('REV')),
766 ('r', 'rev', '', _('revision'), _('REV')),
767 ('d', 'delete', False, _('delete a given bookmark')),
767 ('d', 'delete', False, _('delete a given bookmark')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
768 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
769 ('i', 'inactive', False, _('mark a bookmark inactive'))],
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
770 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
771 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
772 rename=None, inactive=False):
772 rename=None, inactive=False):
773 '''track a line of development with movable markers
773 '''track a line of development with movable markers
774
774
775 Bookmarks are pointers to certain commits that move when committing.
775 Bookmarks are pointers to certain commits that move when committing.
776 Bookmarks are local. They can be renamed, copied and deleted. It is
776 Bookmarks are local. They can be renamed, copied and deleted. It is
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
777 possible to use :hg:`merge NAME` to merge from a given bookmark, and
778 :hg:`update NAME` to update to a given bookmark.
778 :hg:`update NAME` to update to a given bookmark.
779
779
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
780 You can use :hg:`bookmark NAME` to set a bookmark on the working
781 directory's parent revision with the given name. If you specify
781 directory's parent revision with the given name. If you specify
782 a revision using -r REV (where REV may be an existing bookmark),
782 a revision using -r REV (where REV may be an existing bookmark),
783 the bookmark is assigned to that revision.
783 the bookmark is assigned to that revision.
784
784
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
785 Bookmarks can be pushed and pulled between repositories (see :hg:`help
786 push` and :hg:`help pull`). This requires both the local and remote
786 push` and :hg:`help pull`). This requires both the local and remote
787 repositories to support bookmarks. For versions prior to 1.8, this means
787 repositories to support bookmarks. For versions prior to 1.8, this means
788 the bookmarks extension must be enabled.
788 the bookmarks extension must be enabled.
789
789
790 If you set a bookmark called '@', new clones of the repository will
790 If you set a bookmark called '@', new clones of the repository will
791 have that revision checked out (and the bookmark made active) by
791 have that revision checked out (and the bookmark made active) by
792 default.
792 default.
793
793
794 With -i/--inactive, the new bookmark will not be made the active
794 With -i/--inactive, the new bookmark will not be made the active
795 bookmark. If -r/--rev is given, the new bookmark will not be made
795 bookmark. If -r/--rev is given, the new bookmark will not be made
796 active even if -i/--inactive is not given. If no NAME is given, the
796 active even if -i/--inactive is not given. If no NAME is given, the
797 current active bookmark will be marked inactive.
797 current active bookmark will be marked inactive.
798 '''
798 '''
799 hexfn = ui.debugflag and hex or short
799 hexfn = ui.debugflag and hex or short
800 marks = repo._bookmarks
800 marks = repo._bookmarks
801 cur = repo.changectx('.').node()
801 cur = repo.changectx('.').node()
802
802
803 def checkformat(mark):
803 def checkformat(mark):
804 mark = mark.strip()
804 mark = mark.strip()
805 if not mark:
805 if not mark:
806 raise util.Abort(_("bookmark names cannot consist entirely of "
806 raise util.Abort(_("bookmark names cannot consist entirely of "
807 "whitespace"))
807 "whitespace"))
808 scmutil.checknewlabel(repo, mark, 'bookmark')
808 scmutil.checknewlabel(repo, mark, 'bookmark')
809 return mark
809 return mark
810
810
811 def checkconflict(repo, mark, force=False, target=None):
811 def checkconflict(repo, mark, force=False, target=None):
812 if mark in marks and not force:
812 if mark in marks and not force:
813 if target:
813 if target:
814 if marks[mark] == target and target == cur:
814 if marks[mark] == target and target == cur:
815 # re-activating a bookmark
815 # re-activating a bookmark
816 return
816 return
817 anc = repo.changelog.ancestors([repo[target].rev()])
817 anc = repo.changelog.ancestors([repo[target].rev()])
818 bmctx = repo[marks[mark]]
818 bmctx = repo[marks[mark]]
819 if bmctx.rev() in anc:
819 if bmctx.rev() in anc:
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
820 ui.status(_("moving bookmark '%s' forward from %s\n") %
821 (mark, short(bmctx.node())))
821 (mark, short(bmctx.node())))
822 return
822 return
823 raise util.Abort(_("bookmark '%s' already exists "
823 raise util.Abort(_("bookmark '%s' already exists "
824 "(use -f to force)") % mark)
824 "(use -f to force)") % mark)
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
825 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
826 and not force):
826 and not force):
827 raise util.Abort(
827 raise util.Abort(
828 _("a bookmark cannot have the name of an existing branch"))
828 _("a bookmark cannot have the name of an existing branch"))
829
829
830 if delete and rename:
830 if delete and rename:
831 raise util.Abort(_("--delete and --rename are incompatible"))
831 raise util.Abort(_("--delete and --rename are incompatible"))
832 if delete and rev:
832 if delete and rev:
833 raise util.Abort(_("--rev is incompatible with --delete"))
833 raise util.Abort(_("--rev is incompatible with --delete"))
834 if rename and rev:
834 if rename and rev:
835 raise util.Abort(_("--rev is incompatible with --rename"))
835 raise util.Abort(_("--rev is incompatible with --rename"))
836 if mark is None and (delete or rev):
836 if mark is None and (delete or rev):
837 raise util.Abort(_("bookmark name required"))
837 raise util.Abort(_("bookmark name required"))
838
838
839 if delete:
839 if delete:
840 if mark not in marks:
840 if mark not in marks:
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
841 raise util.Abort(_("bookmark '%s' does not exist") % mark)
842 if mark == repo._bookmarkcurrent:
842 if mark == repo._bookmarkcurrent:
843 bookmarks.setcurrent(repo, None)
843 bookmarks.setcurrent(repo, None)
844 del marks[mark]
844 del marks[mark]
845 marks.write()
845 marks.write()
846
846
847 elif rename:
847 elif rename:
848 if mark is None:
848 if mark is None:
849 raise util.Abort(_("new bookmark name required"))
849 raise util.Abort(_("new bookmark name required"))
850 mark = checkformat(mark)
850 mark = checkformat(mark)
851 if rename not in marks:
851 if rename not in marks:
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
852 raise util.Abort(_("bookmark '%s' does not exist") % rename)
853 checkconflict(repo, mark, force)
853 checkconflict(repo, mark, force)
854 marks[mark] = marks[rename]
854 marks[mark] = marks[rename]
855 if repo._bookmarkcurrent == rename and not inactive:
855 if repo._bookmarkcurrent == rename and not inactive:
856 bookmarks.setcurrent(repo, mark)
856 bookmarks.setcurrent(repo, mark)
857 del marks[rename]
857 del marks[rename]
858 marks.write()
858 marks.write()
859
859
860 elif mark is not None:
860 elif mark is not None:
861 mark = checkformat(mark)
861 mark = checkformat(mark)
862 if inactive and mark == repo._bookmarkcurrent:
862 if inactive and mark == repo._bookmarkcurrent:
863 bookmarks.setcurrent(repo, None)
863 bookmarks.setcurrent(repo, None)
864 return
864 return
865 tgt = cur
865 tgt = cur
866 if rev:
866 if rev:
867 tgt = scmutil.revsingle(repo, rev).node()
867 tgt = scmutil.revsingle(repo, rev).node()
868 checkconflict(repo, mark, force, tgt)
868 checkconflict(repo, mark, force, tgt)
869 marks[mark] = tgt
869 marks[mark] = tgt
870 if not inactive and cur == marks[mark]:
870 if not inactive and cur == marks[mark]:
871 bookmarks.setcurrent(repo, mark)
871 bookmarks.setcurrent(repo, mark)
872 elif cur != tgt and mark == repo._bookmarkcurrent:
872 elif cur != tgt and mark == repo._bookmarkcurrent:
873 bookmarks.setcurrent(repo, None)
873 bookmarks.setcurrent(repo, None)
874 marks.write()
874 marks.write()
875
875
876 # Same message whether trying to deactivate the current bookmark (-i
876 # Same message whether trying to deactivate the current bookmark (-i
877 # with no NAME) or listing bookmarks
877 # with no NAME) or listing bookmarks
878 elif len(marks) == 0:
878 elif len(marks) == 0:
879 ui.status(_("no bookmarks set\n"))
879 ui.status(_("no bookmarks set\n"))
880
880
881 elif inactive:
881 elif inactive:
882 if not repo._bookmarkcurrent:
882 if not repo._bookmarkcurrent:
883 ui.status(_("no active bookmark\n"))
883 ui.status(_("no active bookmark\n"))
884 else:
884 else:
885 bookmarks.setcurrent(repo, None)
885 bookmarks.setcurrent(repo, None)
886
886
887 else: # show bookmarks
887 else: # show bookmarks
888 for bmark, n in sorted(marks.iteritems()):
888 for bmark, n in sorted(marks.iteritems()):
889 current = repo._bookmarkcurrent
889 current = repo._bookmarkcurrent
890 if bmark == current:
890 if bmark == current:
891 prefix, label = '*', 'bookmarks.current'
891 prefix, label = '*', 'bookmarks.current'
892 else:
892 else:
893 prefix, label = ' ', ''
893 prefix, label = ' ', ''
894
894
895 if ui.quiet:
895 if ui.quiet:
896 ui.write("%s\n" % bmark, label=label)
896 ui.write("%s\n" % bmark, label=label)
897 else:
897 else:
898 ui.write(" %s %-25s %d:%s\n" % (
898 ui.write(" %s %-25s %d:%s\n" % (
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
899 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
900 label=label)
900 label=label)
901
901
902 @command('branch',
902 @command('branch',
903 [('f', 'force', None,
903 [('f', 'force', None,
904 _('set branch name even if it shadows an existing branch')),
904 _('set branch name even if it shadows an existing branch')),
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
905 ('C', 'clean', None, _('reset branch name to parent branch name'))],
906 _('[-fC] [NAME]'))
906 _('[-fC] [NAME]'))
907 def branch(ui, repo, label=None, **opts):
907 def branch(ui, repo, label=None, **opts):
908 """set or show the current branch name
908 """set or show the current branch name
909
909
910 .. note::
910 .. note::
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
911 Branch names are permanent and global. Use :hg:`bookmark` to create a
912 light-weight bookmark instead. See :hg:`help glossary` for more
912 light-weight bookmark instead. See :hg:`help glossary` for more
913 information about named branches and bookmarks.
913 information about named branches and bookmarks.
914
914
915 With no argument, show the current branch name. With one argument,
915 With no argument, show the current branch name. With one argument,
916 set the working directory branch name (the branch will not exist
916 set the working directory branch name (the branch will not exist
917 in the repository until the next commit). Standard practice
917 in the repository until the next commit). Standard practice
918 recommends that primary development take place on the 'default'
918 recommends that primary development take place on the 'default'
919 branch.
919 branch.
920
920
921 Unless -f/--force is specified, branch will not let you set a
921 Unless -f/--force is specified, branch will not let you set a
922 branch name that already exists, even if it's inactive.
922 branch name that already exists, even if it's inactive.
923
923
924 Use -C/--clean to reset the working directory branch to that of
924 Use -C/--clean to reset the working directory branch to that of
925 the parent of the working directory, negating a previous branch
925 the parent of the working directory, negating a previous branch
926 change.
926 change.
927
927
928 Use the command :hg:`update` to switch to an existing branch. Use
928 Use the command :hg:`update` to switch to an existing branch. Use
929 :hg:`commit --close-branch` to mark this branch as closed.
929 :hg:`commit --close-branch` to mark this branch as closed.
930
930
931 Returns 0 on success.
931 Returns 0 on success.
932 """
932 """
933 if not opts.get('clean') and not label:
933 if not opts.get('clean') and not label:
934 ui.write("%s\n" % repo.dirstate.branch())
934 ui.write("%s\n" % repo.dirstate.branch())
935 return
935 return
936
936
937 wlock = repo.wlock()
937 wlock = repo.wlock()
938 try:
938 try:
939 if opts.get('clean'):
939 if opts.get('clean'):
940 label = repo[None].p1().branch()
940 label = repo[None].p1().branch()
941 repo.dirstate.setbranch(label)
941 repo.dirstate.setbranch(label)
942 ui.status(_('reset working directory to branch %s\n') % label)
942 ui.status(_('reset working directory to branch %s\n') % label)
943 elif label:
943 elif label:
944 if not opts.get('force') and label in repo.branchmap():
944 if not opts.get('force') and label in repo.branchmap():
945 if label not in [p.branch() for p in repo.parents()]:
945 if label not in [p.branch() for p in repo.parents()]:
946 raise util.Abort(_('a branch of the same name already'
946 raise util.Abort(_('a branch of the same name already'
947 ' exists'),
947 ' exists'),
948 # i18n: "it" refers to an existing branch
948 # i18n: "it" refers to an existing branch
949 hint=_("use 'hg update' to switch to it"))
949 hint=_("use 'hg update' to switch to it"))
950 scmutil.checknewlabel(repo, label, 'branch')
950 scmutil.checknewlabel(repo, label, 'branch')
951 repo.dirstate.setbranch(label)
951 repo.dirstate.setbranch(label)
952 ui.status(_('marked working directory as branch %s\n') % label)
952 ui.status(_('marked working directory as branch %s\n') % label)
953 ui.status(_('(branches are permanent and global, '
953 ui.status(_('(branches are permanent and global, '
954 'did you want a bookmark?)\n'))
954 'did you want a bookmark?)\n'))
955 finally:
955 finally:
956 wlock.release()
956 wlock.release()
957
957
958 @command('branches',
958 @command('branches',
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
959 [('a', 'active', False, _('show only branches that have unmerged heads')),
960 ('c', 'closed', False, _('show normal and closed branches'))],
960 ('c', 'closed', False, _('show normal and closed branches'))],
961 _('[-ac]'))
961 _('[-ac]'))
962 def branches(ui, repo, active=False, closed=False):
962 def branches(ui, repo, active=False, closed=False):
963 """list repository named branches
963 """list repository named branches
964
964
965 List the repository's named branches, indicating which ones are
965 List the repository's named branches, indicating which ones are
966 inactive. If -c/--closed is specified, also list branches which have
966 inactive. If -c/--closed is specified, also list branches which have
967 been marked closed (see :hg:`commit --close-branch`).
967 been marked closed (see :hg:`commit --close-branch`).
968
968
969 If -a/--active is specified, only show active branches. A branch
969 If -a/--active is specified, only show active branches. A branch
970 is considered active if it contains repository heads.
970 is considered active if it contains repository heads.
971
971
972 Use the command :hg:`update` to switch to an existing branch.
972 Use the command :hg:`update` to switch to an existing branch.
973
973
974 Returns 0.
974 Returns 0.
975 """
975 """
976
976
977 hexfunc = ui.debugflag and hex or short
977 hexfunc = ui.debugflag and hex or short
978
978
979 activebranches = set([repo[n].branch() for n in repo.heads()])
979 activebranches = set([repo[n].branch() for n in repo.heads()])
980 branches = []
980 branches = []
981 for tag, heads in repo.branchmap().iteritems():
981 for tag, heads in repo.branchmap().iteritems():
982 for h in reversed(heads):
982 for h in reversed(heads):
983 ctx = repo[h]
983 ctx = repo[h]
984 isopen = not ctx.closesbranch()
984 isopen = not ctx.closesbranch()
985 if isopen:
985 if isopen:
986 tip = ctx
986 tip = ctx
987 break
987 break
988 else:
988 else:
989 tip = repo[heads[-1]]
989 tip = repo[heads[-1]]
990 isactive = tag in activebranches and isopen
990 isactive = tag in activebranches and isopen
991 branches.append((tip, isactive, isopen))
991 branches.append((tip, isactive, isopen))
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
992 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
993 reverse=True)
993 reverse=True)
994
994
995 for ctx, isactive, isopen in branches:
995 for ctx, isactive, isopen in branches:
996 if (not active) or isactive:
996 if (not active) or isactive:
997 if isactive:
997 if isactive:
998 label = 'branches.active'
998 label = 'branches.active'
999 notice = ''
999 notice = ''
1000 elif not isopen:
1000 elif not isopen:
1001 if not closed:
1001 if not closed:
1002 continue
1002 continue
1003 label = 'branches.closed'
1003 label = 'branches.closed'
1004 notice = _(' (closed)')
1004 notice = _(' (closed)')
1005 else:
1005 else:
1006 label = 'branches.inactive'
1006 label = 'branches.inactive'
1007 notice = _(' (inactive)')
1007 notice = _(' (inactive)')
1008 if ctx.branch() == repo.dirstate.branch():
1008 if ctx.branch() == repo.dirstate.branch():
1009 label = 'branches.current'
1009 label = 'branches.current'
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1010 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1011 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1012 'log.changeset changeset.%s' % ctx.phasestr())
1012 'log.changeset changeset.%s' % ctx.phasestr())
1013 tag = ui.label(ctx.branch(), label)
1013 tag = ui.label(ctx.branch(), label)
1014 if ui.quiet:
1014 if ui.quiet:
1015 ui.write("%s\n" % tag)
1015 ui.write("%s\n" % tag)
1016 else:
1016 else:
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1017 ui.write("%s %s%s\n" % (tag, rev, notice))
1018
1018
1019 @command('bundle',
1019 @command('bundle',
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1020 [('f', 'force', None, _('run even when the destination is unrelated')),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1021 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1022 _('REV')),
1022 _('REV')),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1023 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1024 _('BRANCH')),
1024 _('BRANCH')),
1025 ('', 'base', [],
1025 ('', 'base', [],
1026 _('a base changeset assumed to be available at the destination'),
1026 _('a base changeset assumed to be available at the destination'),
1027 _('REV')),
1027 _('REV')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1028 ('a', 'all', None, _('bundle all changesets in the repository')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1029 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1030 ] + remoteopts,
1030 ] + remoteopts,
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1031 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1032 def bundle(ui, repo, fname, dest=None, **opts):
1032 def bundle(ui, repo, fname, dest=None, **opts):
1033 """create a changegroup file
1033 """create a changegroup file
1034
1034
1035 Generate a compressed changegroup file collecting changesets not
1035 Generate a compressed changegroup file collecting changesets not
1036 known to be in another repository.
1036 known to be in another repository.
1037
1037
1038 If you omit the destination repository, then hg assumes the
1038 If you omit the destination repository, then hg assumes the
1039 destination will have all the nodes you specify with --base
1039 destination will have all the nodes you specify with --base
1040 parameters. To create a bundle containing all changesets, use
1040 parameters. To create a bundle containing all changesets, use
1041 -a/--all (or --base null).
1041 -a/--all (or --base null).
1042
1042
1043 You can change compression method with the -t/--type option.
1043 You can change compression method with the -t/--type option.
1044 The available compression methods are: none, bzip2, and
1044 The available compression methods are: none, bzip2, and
1045 gzip (by default, bundles are compressed using bzip2).
1045 gzip (by default, bundles are compressed using bzip2).
1046
1046
1047 The bundle file can then be transferred using conventional means
1047 The bundle file can then be transferred using conventional means
1048 and applied to another repository with the unbundle or pull
1048 and applied to another repository with the unbundle or pull
1049 command. This is useful when direct push and pull are not
1049 command. This is useful when direct push and pull are not
1050 available or when exporting an entire repository is undesirable.
1050 available or when exporting an entire repository is undesirable.
1051
1051
1052 Applying bundles preserves all changeset contents including
1052 Applying bundles preserves all changeset contents including
1053 permissions, copy/rename information, and revision history.
1053 permissions, copy/rename information, and revision history.
1054
1054
1055 Returns 0 on success, 1 if no changes found.
1055 Returns 0 on success, 1 if no changes found.
1056 """
1056 """
1057 revs = None
1057 revs = None
1058 if 'rev' in opts:
1058 if 'rev' in opts:
1059 revs = scmutil.revrange(repo, opts['rev'])
1059 revs = scmutil.revrange(repo, opts['rev'])
1060
1060
1061 bundletype = opts.get('type', 'bzip2').lower()
1061 bundletype = opts.get('type', 'bzip2').lower()
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1062 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1063 bundletype = btypes.get(bundletype)
1063 bundletype = btypes.get(bundletype)
1064 if bundletype not in changegroup.bundletypes:
1064 if bundletype not in changegroup.bundletypes:
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1065 raise util.Abort(_('unknown bundle type specified with --type'))
1066
1066
1067 if opts.get('all'):
1067 if opts.get('all'):
1068 base = ['null']
1068 base = ['null']
1069 else:
1069 else:
1070 base = scmutil.revrange(repo, opts.get('base'))
1070 base = scmutil.revrange(repo, opts.get('base'))
1071 if base:
1071 if base:
1072 if dest:
1072 if dest:
1073 raise util.Abort(_("--base is incompatible with specifying "
1073 raise util.Abort(_("--base is incompatible with specifying "
1074 "a destination"))
1074 "a destination"))
1075 common = [repo.lookup(rev) for rev in base]
1075 common = [repo.lookup(rev) for rev in base]
1076 heads = revs and map(repo.lookup, revs) or revs
1076 heads = revs and map(repo.lookup, revs) or revs
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1077 cg = repo.getbundle('bundle', heads=heads, common=common)
1078 outgoing = None
1078 outgoing = None
1079 else:
1079 else:
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1080 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1081 dest, branches = hg.parseurl(dest, opts.get('branch'))
1082 other = hg.peer(repo, opts, dest)
1082 other = hg.peer(repo, opts, dest)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1083 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1084 heads = revs and map(repo.lookup, revs) or revs
1084 heads = revs and map(repo.lookup, revs) or revs
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1085 outgoing = discovery.findcommonoutgoing(repo, other,
1086 onlyheads=heads,
1086 onlyheads=heads,
1087 force=opts.get('force'),
1087 force=opts.get('force'),
1088 portable=True)
1088 portable=True)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1089 cg = repo.getlocalbundle('bundle', outgoing)
1090 if not cg:
1090 if not cg:
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1091 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1092 return 1
1092 return 1
1093
1093
1094 changegroup.writebundle(cg, fname, bundletype)
1094 changegroup.writebundle(cg, fname, bundletype)
1095
1095
1096 @command('cat',
1096 @command('cat',
1097 [('o', 'output', '',
1097 [('o', 'output', '',
1098 _('print output to file with formatted name'), _('FORMAT')),
1098 _('print output to file with formatted name'), _('FORMAT')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1099 ('r', 'rev', '', _('print the given revision'), _('REV')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1100 ('', 'decode', None, _('apply any matching decode filter')),
1101 ] + walkopts,
1101 ] + walkopts,
1102 _('[OPTION]... FILE...'))
1102 _('[OPTION]... FILE...'))
1103 def cat(ui, repo, file1, *pats, **opts):
1103 def cat(ui, repo, file1, *pats, **opts):
1104 """output the current or given revision of files
1104 """output the current or given revision of files
1105
1105
1106 Print the specified files as they were at the given revision. If
1106 Print the specified files as they were at the given revision. If
1107 no revision is given, the parent of the working directory is used,
1107 no revision is given, the parent of the working directory is used,
1108 or tip if no revision is checked out.
1108 or tip if no revision is checked out.
1109
1109
1110 Output may be to a file, in which case the name of the file is
1110 Output may be to a file, in which case the name of the file is
1111 given using a format string. The formatting rules are the same as
1111 given using a format string. The formatting rules are the same as
1112 for the export command, with the following additions:
1112 for the export command, with the following additions:
1113
1113
1114 :``%s``: basename of file being printed
1114 :``%s``: basename of file being printed
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1115 :``%d``: dirname of file being printed, or '.' if in repository root
1116 :``%p``: root-relative path name of file being printed
1116 :``%p``: root-relative path name of file being printed
1117
1117
1118 Returns 0 on success.
1118 Returns 0 on success.
1119 """
1119 """
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1120 ctx = scmutil.revsingle(repo, opts.get('rev'))
1121 err = 1
1121 err = 1
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1122 m = scmutil.match(ctx, (file1,) + pats, opts)
1123 for abs in ctx.walk(m):
1123 for abs in ctx.walk(m):
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1124 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1125 pathname=abs)
1125 pathname=abs)
1126 data = ctx[abs].data()
1126 data = ctx[abs].data()
1127 if opts.get('decode'):
1127 if opts.get('decode'):
1128 data = repo.wwritedata(abs, data)
1128 data = repo.wwritedata(abs, data)
1129 fp.write(data)
1129 fp.write(data)
1130 fp.close()
1130 fp.close()
1131 err = 0
1131 err = 0
1132 return err
1132 return err
1133
1133
1134 @command('^clone',
1134 @command('^clone',
1135 [('U', 'noupdate', None,
1135 [('U', 'noupdate', None,
1136 _('the clone will include an empty working copy (only a repository)')),
1136 _('the clone will include an empty working copy (only a repository)')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1137 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1138 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1139 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1140 ('', 'pull', None, _('use pull protocol to copy metadata')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1141 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1142 ] + remoteopts,
1142 ] + remoteopts,
1143 _('[OPTION]... SOURCE [DEST]'))
1143 _('[OPTION]... SOURCE [DEST]'))
1144 def clone(ui, source, dest=None, **opts):
1144 def clone(ui, source, dest=None, **opts):
1145 """make a copy of an existing repository
1145 """make a copy of an existing repository
1146
1146
1147 Create a copy of an existing repository in a new directory.
1147 Create a copy of an existing repository in a new directory.
1148
1148
1149 If no destination directory name is specified, it defaults to the
1149 If no destination directory name is specified, it defaults to the
1150 basename of the source.
1150 basename of the source.
1151
1151
1152 The location of the source is added to the new repository's
1152 The location of the source is added to the new repository's
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1153 ``.hg/hgrc`` file, as the default to be used for future pulls.
1154
1154
1155 Only local paths and ``ssh://`` URLs are supported as
1155 Only local paths and ``ssh://`` URLs are supported as
1156 destinations. For ``ssh://`` destinations, no working directory or
1156 destinations. For ``ssh://`` destinations, no working directory or
1157 ``.hg/hgrc`` will be created on the remote side.
1157 ``.hg/hgrc`` will be created on the remote side.
1158
1158
1159 To pull only a subset of changesets, specify one or more revisions
1159 To pull only a subset of changesets, specify one or more revisions
1160 identifiers with -r/--rev or branches with -b/--branch. The
1160 identifiers with -r/--rev or branches with -b/--branch. The
1161 resulting clone will contain only the specified changesets and
1161 resulting clone will contain only the specified changesets and
1162 their ancestors. These options (or 'clone src#rev dest') imply
1162 their ancestors. These options (or 'clone src#rev dest') imply
1163 --pull, even for local source repositories. Note that specifying a
1163 --pull, even for local source repositories. Note that specifying a
1164 tag will include the tagged changeset but not the changeset
1164 tag will include the tagged changeset but not the changeset
1165 containing the tag.
1165 containing the tag.
1166
1166
1167 If the source repository has a bookmark called '@' set, that
1167 If the source repository has a bookmark called '@' set, that
1168 revision will be checked out in the new repository by default.
1168 revision will be checked out in the new repository by default.
1169
1169
1170 To check out a particular version, use -u/--update, or
1170 To check out a particular version, use -u/--update, or
1171 -U/--noupdate to create a clone with no working directory.
1171 -U/--noupdate to create a clone with no working directory.
1172
1172
1173 .. container:: verbose
1173 .. container:: verbose
1174
1174
1175 For efficiency, hardlinks are used for cloning whenever the
1175 For efficiency, hardlinks are used for cloning whenever the
1176 source and destination are on the same filesystem (note this
1176 source and destination are on the same filesystem (note this
1177 applies only to the repository data, not to the working
1177 applies only to the repository data, not to the working
1178 directory). Some filesystems, such as AFS, implement hardlinking
1178 directory). Some filesystems, such as AFS, implement hardlinking
1179 incorrectly, but do not report errors. In these cases, use the
1179 incorrectly, but do not report errors. In these cases, use the
1180 --pull option to avoid hardlinking.
1180 --pull option to avoid hardlinking.
1181
1181
1182 In some cases, you can clone repositories and the working
1182 In some cases, you can clone repositories and the working
1183 directory using full hardlinks with ::
1183 directory using full hardlinks with ::
1184
1184
1185 $ cp -al REPO REPOCLONE
1185 $ cp -al REPO REPOCLONE
1186
1186
1187 This is the fastest way to clone, but it is not always safe. The
1187 This is the fastest way to clone, but it is not always safe. The
1188 operation is not atomic (making sure REPO is not modified during
1188 operation is not atomic (making sure REPO is not modified during
1189 the operation is up to you) and you have to make sure your
1189 the operation is up to you) and you have to make sure your
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1190 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1191 so). Also, this is not compatible with certain extensions that
1191 so). Also, this is not compatible with certain extensions that
1192 place their metadata under the .hg directory, such as mq.
1192 place their metadata under the .hg directory, such as mq.
1193
1193
1194 Mercurial will update the working directory to the first applicable
1194 Mercurial will update the working directory to the first applicable
1195 revision from this list:
1195 revision from this list:
1196
1196
1197 a) null if -U or the source repository has no changesets
1197 a) null if -U or the source repository has no changesets
1198 b) if -u . and the source repository is local, the first parent of
1198 b) if -u . and the source repository is local, the first parent of
1199 the source repository's working directory
1199 the source repository's working directory
1200 c) the changeset specified with -u (if a branch name, this means the
1200 c) the changeset specified with -u (if a branch name, this means the
1201 latest head of that branch)
1201 latest head of that branch)
1202 d) the changeset specified with -r
1202 d) the changeset specified with -r
1203 e) the tipmost head specified with -b
1203 e) the tipmost head specified with -b
1204 f) the tipmost head specified with the url#branch source syntax
1204 f) the tipmost head specified with the url#branch source syntax
1205 g) the revision marked with the '@' bookmark, if present
1205 g) the revision marked with the '@' bookmark, if present
1206 h) the tipmost head of the default branch
1206 h) the tipmost head of the default branch
1207 i) tip
1207 i) tip
1208
1208
1209 Examples:
1209 Examples:
1210
1210
1211 - clone a remote repository to a new directory named hg/::
1211 - clone a remote repository to a new directory named hg/::
1212
1212
1213 hg clone http://selenic.com/hg
1213 hg clone http://selenic.com/hg
1214
1214
1215 - create a lightweight local clone::
1215 - create a lightweight local clone::
1216
1216
1217 hg clone project/ project-feature/
1217 hg clone project/ project-feature/
1218
1218
1219 - clone from an absolute path on an ssh server (note double-slash)::
1219 - clone from an absolute path on an ssh server (note double-slash)::
1220
1220
1221 hg clone ssh://user@server//home/projects/alpha/
1221 hg clone ssh://user@server//home/projects/alpha/
1222
1222
1223 - do a high-speed clone over a LAN while checking out a
1223 - do a high-speed clone over a LAN while checking out a
1224 specified version::
1224 specified version::
1225
1225
1226 hg clone --uncompressed http://server/repo -u 1.5
1226 hg clone --uncompressed http://server/repo -u 1.5
1227
1227
1228 - create a repository without changesets after a particular revision::
1228 - create a repository without changesets after a particular revision::
1229
1229
1230 hg clone -r 04e544 experimental/ good/
1230 hg clone -r 04e544 experimental/ good/
1231
1231
1232 - clone (and track) a particular named branch::
1232 - clone (and track) a particular named branch::
1233
1233
1234 hg clone http://selenic.com/hg#stable
1234 hg clone http://selenic.com/hg#stable
1235
1235
1236 See :hg:`help urls` for details on specifying URLs.
1236 See :hg:`help urls` for details on specifying URLs.
1237
1237
1238 Returns 0 on success.
1238 Returns 0 on success.
1239 """
1239 """
1240 if opts.get('noupdate') and opts.get('updaterev'):
1240 if opts.get('noupdate') and opts.get('updaterev'):
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1241 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1242
1242
1243 r = hg.clone(ui, opts, source, dest,
1243 r = hg.clone(ui, opts, source, dest,
1244 pull=opts.get('pull'),
1244 pull=opts.get('pull'),
1245 stream=opts.get('uncompressed'),
1245 stream=opts.get('uncompressed'),
1246 rev=opts.get('rev'),
1246 rev=opts.get('rev'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1247 update=opts.get('updaterev') or not opts.get('noupdate'),
1248 branch=opts.get('branch'))
1248 branch=opts.get('branch'))
1249
1249
1250 return r is None
1250 return r is None
1251
1251
1252 @command('^commit|ci',
1252 @command('^commit|ci',
1253 [('A', 'addremove', None,
1253 [('A', 'addremove', None,
1254 _('mark new/missing files as added/removed before committing')),
1254 _('mark new/missing files as added/removed before committing')),
1255 ('', 'close-branch', None,
1255 ('', 'close-branch', None,
1256 _('mark a branch as closed, hiding it from the branch list')),
1256 _('mark a branch as closed, hiding it from the branch list')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1257 ('', 'amend', None, _('amend the parent of the working dir')),
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1258 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1259 _('[OPTION]... [FILE]...'))
1259 _('[OPTION]... [FILE]...'))
1260 def commit(ui, repo, *pats, **opts):
1260 def commit(ui, repo, *pats, **opts):
1261 """commit the specified files or all outstanding changes
1261 """commit the specified files or all outstanding changes
1262
1262
1263 Commit changes to the given files into the repository. Unlike a
1263 Commit changes to the given files into the repository. Unlike a
1264 centralized SCM, this operation is a local operation. See
1264 centralized SCM, this operation is a local operation. See
1265 :hg:`push` for a way to actively distribute your changes.
1265 :hg:`push` for a way to actively distribute your changes.
1266
1266
1267 If a list of files is omitted, all changes reported by :hg:`status`
1267 If a list of files is omitted, all changes reported by :hg:`status`
1268 will be committed.
1268 will be committed.
1269
1269
1270 If you are committing the result of a merge, do not provide any
1270 If you are committing the result of a merge, do not provide any
1271 filenames or -I/-X filters.
1271 filenames or -I/-X filters.
1272
1272
1273 If no commit message is specified, Mercurial starts your
1273 If no commit message is specified, Mercurial starts your
1274 configured editor where you can enter a message. In case your
1274 configured editor where you can enter a message. In case your
1275 commit fails, you will find a backup of your message in
1275 commit fails, you will find a backup of your message in
1276 ``.hg/last-message.txt``.
1276 ``.hg/last-message.txt``.
1277
1277
1278 The --amend flag can be used to amend the parent of the
1278 The --amend flag can be used to amend the parent of the
1279 working directory with a new commit that contains the changes
1279 working directory with a new commit that contains the changes
1280 in the parent in addition to those currently reported by :hg:`status`,
1280 in the parent in addition to those currently reported by :hg:`status`,
1281 if there are any. The old commit is stored in a backup bundle in
1281 if there are any. The old commit is stored in a backup bundle in
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1282 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1283 on how to restore it).
1283 on how to restore it).
1284
1284
1285 Message, user and date are taken from the amended commit unless
1285 Message, user and date are taken from the amended commit unless
1286 specified. When a message isn't specified on the command line,
1286 specified. When a message isn't specified on the command line,
1287 the editor will open with the message of the amended commit.
1287 the editor will open with the message of the amended commit.
1288
1288
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1289 It is not possible to amend public changesets (see :hg:`help phases`)
1290 or changesets that have children.
1290 or changesets that have children.
1291
1291
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1292 See :hg:`help dates` for a list of formats valid for -d/--date.
1293
1293
1294 Returns 0 on success, 1 if nothing changed.
1294 Returns 0 on success, 1 if nothing changed.
1295 """
1295 """
1296 if opts.get('subrepos'):
1296 if opts.get('subrepos'):
1297 # Let --subrepos on the command line override config setting.
1297 # Let --subrepos on the command line override config setting.
1298 ui.setconfig('ui', 'commitsubrepos', True)
1298 ui.setconfig('ui', 'commitsubrepos', True)
1299
1299
1300 extra = {}
1300 extra = {}
1301 if opts.get('close_branch'):
1301 if opts.get('close_branch'):
1302 extra['close'] = 1
1302 extra['close'] = 1
1303
1303
1304 branch = repo[None].branch()
1304 branch = repo[None].branch()
1305 bheads = repo.branchheads(branch)
1305 bheads = repo.branchheads(branch)
1306
1306
1307 if opts.get('amend'):
1307 if opts.get('amend'):
1308 if ui.configbool('ui', 'commitsubrepos'):
1308 if ui.configbool('ui', 'commitsubrepos'):
1309 raise util.Abort(_('cannot amend recursively'))
1309 raise util.Abort(_('cannot amend recursively'))
1310
1310
1311 old = repo['.']
1311 old = repo['.']
1312 if old.phase() == phases.public:
1312 if old.phase() == phases.public:
1313 raise util.Abort(_('cannot amend public changesets'))
1313 raise util.Abort(_('cannot amend public changesets'))
1314 if len(repo[None].parents()) > 1:
1314 if len(repo[None].parents()) > 1:
1315 raise util.Abort(_('cannot amend while merging'))
1315 raise util.Abort(_('cannot amend while merging'))
1316 if (not obsolete._enabled) and old.children():
1316 if (not obsolete._enabled) and old.children():
1317 raise util.Abort(_('cannot amend changeset with children'))
1317 raise util.Abort(_('cannot amend changeset with children'))
1318
1318
1319 e = cmdutil.commiteditor
1319 e = cmdutil.commiteditor
1320 if opts.get('force_editor'):
1320 if opts.get('force_editor'):
1321 e = cmdutil.commitforceeditor
1321 e = cmdutil.commitforceeditor
1322
1322
1323 def commitfunc(ui, repo, message, match, opts):
1323 def commitfunc(ui, repo, message, match, opts):
1324 editor = e
1324 editor = e
1325 # message contains text from -m or -l, if it's empty,
1325 # message contains text from -m or -l, if it's empty,
1326 # open the editor with the old message
1326 # open the editor with the old message
1327 if not message:
1327 if not message:
1328 message = old.description()
1328 message = old.description()
1329 editor = cmdutil.commitforceeditor
1329 editor = cmdutil.commitforceeditor
1330 return repo.commit(message,
1330 return repo.commit(message,
1331 opts.get('user') or old.user(),
1331 opts.get('user') or old.user(),
1332 opts.get('date') or old.date(),
1332 opts.get('date') or old.date(),
1333 match,
1333 match,
1334 editor=editor,
1334 editor=editor,
1335 extra=extra)
1335 extra=extra)
1336
1336
1337 current = repo._bookmarkcurrent
1337 current = repo._bookmarkcurrent
1338 marks = old.bookmarks()
1338 marks = old.bookmarks()
1339 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1339 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1340 if node == old.node():
1340 if node == old.node():
1341 ui.status(_("nothing changed\n"))
1341 ui.status(_("nothing changed\n"))
1342 return 1
1342 return 1
1343 elif marks:
1343 elif marks:
1344 ui.debug('moving bookmarks %r from %s to %s\n' %
1344 ui.debug('moving bookmarks %r from %s to %s\n' %
1345 (marks, old.hex(), hex(node)))
1345 (marks, old.hex(), hex(node)))
1346 newmarks = repo._bookmarks
1346 newmarks = repo._bookmarks
1347 for bm in marks:
1347 for bm in marks:
1348 newmarks[bm] = node
1348 newmarks[bm] = node
1349 if bm == current:
1349 if bm == current:
1350 bookmarks.setcurrent(repo, bm)
1350 bookmarks.setcurrent(repo, bm)
1351 newmarks.write()
1351 newmarks.write()
1352 else:
1352 else:
1353 e = cmdutil.commiteditor
1353 e = cmdutil.commiteditor
1354 if opts.get('force_editor'):
1354 if opts.get('force_editor'):
1355 e = cmdutil.commitforceeditor
1355 e = cmdutil.commitforceeditor
1356
1356
1357 def commitfunc(ui, repo, message, match, opts):
1357 def commitfunc(ui, repo, message, match, opts):
1358 return repo.commit(message, opts.get('user'), opts.get('date'),
1358 return repo.commit(message, opts.get('user'), opts.get('date'),
1359 match, editor=e, extra=extra)
1359 match, editor=e, extra=extra)
1360
1360
1361 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1361 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1362
1362
1363 if not node:
1363 if not node:
1364 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1364 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1365 if stat[3]:
1365 if stat[3]:
1366 ui.status(_("nothing changed (%d missing files, see "
1366 ui.status(_("nothing changed (%d missing files, see "
1367 "'hg status')\n") % len(stat[3]))
1367 "'hg status')\n") % len(stat[3]))
1368 else:
1368 else:
1369 ui.status(_("nothing changed\n"))
1369 ui.status(_("nothing changed\n"))
1370 return 1
1370 return 1
1371
1371
1372 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1372 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1373
1373
1374 @command('copy|cp',
1374 @command('copy|cp',
1375 [('A', 'after', None, _('record a copy that has already occurred')),
1375 [('A', 'after', None, _('record a copy that has already occurred')),
1376 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1376 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1377 ] + walkopts + dryrunopts,
1377 ] + walkopts + dryrunopts,
1378 _('[OPTION]... [SOURCE]... DEST'))
1378 _('[OPTION]... [SOURCE]... DEST'))
1379 def copy(ui, repo, *pats, **opts):
1379 def copy(ui, repo, *pats, **opts):
1380 """mark files as copied for the next commit
1380 """mark files as copied for the next commit
1381
1381
1382 Mark dest as having copies of source files. If dest is a
1382 Mark dest as having copies of source files. If dest is a
1383 directory, copies are put in that directory. If dest is a file,
1383 directory, copies are put in that directory. If dest is a file,
1384 the source must be a single file.
1384 the source must be a single file.
1385
1385
1386 By default, this command copies the contents of files as they
1386 By default, this command copies the contents of files as they
1387 exist in the working directory. If invoked with -A/--after, the
1387 exist in the working directory. If invoked with -A/--after, the
1388 operation is recorded, but no copying is performed.
1388 operation is recorded, but no copying is performed.
1389
1389
1390 This command takes effect with the next commit. To undo a copy
1390 This command takes effect with the next commit. To undo a copy
1391 before that, see :hg:`revert`.
1391 before that, see :hg:`revert`.
1392
1392
1393 Returns 0 on success, 1 if errors are encountered.
1393 Returns 0 on success, 1 if errors are encountered.
1394 """
1394 """
1395 wlock = repo.wlock(False)
1395 wlock = repo.wlock(False)
1396 try:
1396 try:
1397 return cmdutil.copy(ui, repo, pats, opts)
1397 return cmdutil.copy(ui, repo, pats, opts)
1398 finally:
1398 finally:
1399 wlock.release()
1399 wlock.release()
1400
1400
1401 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1401 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1402 def debugancestor(ui, repo, *args):
1402 def debugancestor(ui, repo, *args):
1403 """find the ancestor revision of two revisions in a given index"""
1403 """find the ancestor revision of two revisions in a given index"""
1404 if len(args) == 3:
1404 if len(args) == 3:
1405 index, rev1, rev2 = args
1405 index, rev1, rev2 = args
1406 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1406 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1407 lookup = r.lookup
1407 lookup = r.lookup
1408 elif len(args) == 2:
1408 elif len(args) == 2:
1409 if not repo:
1409 if not repo:
1410 raise util.Abort(_("there is no Mercurial repository here "
1410 raise util.Abort(_("there is no Mercurial repository here "
1411 "(.hg not found)"))
1411 "(.hg not found)"))
1412 rev1, rev2 = args
1412 rev1, rev2 = args
1413 r = repo.changelog
1413 r = repo.changelog
1414 lookup = repo.lookup
1414 lookup = repo.lookup
1415 else:
1415 else:
1416 raise util.Abort(_('either two or three arguments required'))
1416 raise util.Abort(_('either two or three arguments required'))
1417 a = r.ancestor(lookup(rev1), lookup(rev2))
1417 a = r.ancestor(lookup(rev1), lookup(rev2))
1418 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1418 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1419
1419
1420 @command('debugbuilddag',
1420 @command('debugbuilddag',
1421 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1421 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1422 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1422 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1423 ('n', 'new-file', None, _('add new file at each rev'))],
1423 ('n', 'new-file', None, _('add new file at each rev'))],
1424 _('[OPTION]... [TEXT]'))
1424 _('[OPTION]... [TEXT]'))
1425 def debugbuilddag(ui, repo, text=None,
1425 def debugbuilddag(ui, repo, text=None,
1426 mergeable_file=False,
1426 mergeable_file=False,
1427 overwritten_file=False,
1427 overwritten_file=False,
1428 new_file=False):
1428 new_file=False):
1429 """builds a repo with a given DAG from scratch in the current empty repo
1429 """builds a repo with a given DAG from scratch in the current empty repo
1430
1430
1431 The description of the DAG is read from stdin if not given on the
1431 The description of the DAG is read from stdin if not given on the
1432 command line.
1432 command line.
1433
1433
1434 Elements:
1434 Elements:
1435
1435
1436 - "+n" is a linear run of n nodes based on the current default parent
1436 - "+n" is a linear run of n nodes based on the current default parent
1437 - "." is a single node based on the current default parent
1437 - "." is a single node based on the current default parent
1438 - "$" resets the default parent to null (implied at the start);
1438 - "$" resets the default parent to null (implied at the start);
1439 otherwise the default parent is always the last node created
1439 otherwise the default parent is always the last node created
1440 - "<p" sets the default parent to the backref p
1440 - "<p" sets the default parent to the backref p
1441 - "*p" is a fork at parent p, which is a backref
1441 - "*p" is a fork at parent p, which is a backref
1442 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1442 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1443 - "/p2" is a merge of the preceding node and p2
1443 - "/p2" is a merge of the preceding node and p2
1444 - ":tag" defines a local tag for the preceding node
1444 - ":tag" defines a local tag for the preceding node
1445 - "@branch" sets the named branch for subsequent nodes
1445 - "@branch" sets the named branch for subsequent nodes
1446 - "#...\\n" is a comment up to the end of the line
1446 - "#...\\n" is a comment up to the end of the line
1447
1447
1448 Whitespace between the above elements is ignored.
1448 Whitespace between the above elements is ignored.
1449
1449
1450 A backref is either
1450 A backref is either
1451
1451
1452 - a number n, which references the node curr-n, where curr is the current
1452 - a number n, which references the node curr-n, where curr is the current
1453 node, or
1453 node, or
1454 - the name of a local tag you placed earlier using ":tag", or
1454 - the name of a local tag you placed earlier using ":tag", or
1455 - empty to denote the default parent.
1455 - empty to denote the default parent.
1456
1456
1457 All string valued-elements are either strictly alphanumeric, or must
1457 All string valued-elements are either strictly alphanumeric, or must
1458 be enclosed in double quotes ("..."), with "\\" as escape character.
1458 be enclosed in double quotes ("..."), with "\\" as escape character.
1459 """
1459 """
1460
1460
1461 if text is None:
1461 if text is None:
1462 ui.status(_("reading DAG from stdin\n"))
1462 ui.status(_("reading DAG from stdin\n"))
1463 text = ui.fin.read()
1463 text = ui.fin.read()
1464
1464
1465 cl = repo.changelog
1465 cl = repo.changelog
1466 if len(cl) > 0:
1466 if len(cl) > 0:
1467 raise util.Abort(_('repository is not empty'))
1467 raise util.Abort(_('repository is not empty'))
1468
1468
1469 # determine number of revs in DAG
1469 # determine number of revs in DAG
1470 total = 0
1470 total = 0
1471 for type, data in dagparser.parsedag(text):
1471 for type, data in dagparser.parsedag(text):
1472 if type == 'n':
1472 if type == 'n':
1473 total += 1
1473 total += 1
1474
1474
1475 if mergeable_file:
1475 if mergeable_file:
1476 linesperrev = 2
1476 linesperrev = 2
1477 # make a file with k lines per rev
1477 # make a file with k lines per rev
1478 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1478 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1479 initialmergedlines.append("")
1479 initialmergedlines.append("")
1480
1480
1481 tags = []
1481 tags = []
1482
1482
1483 lock = tr = None
1483 lock = tr = None
1484 try:
1484 try:
1485 lock = repo.lock()
1485 lock = repo.lock()
1486 tr = repo.transaction("builddag")
1486 tr = repo.transaction("builddag")
1487
1487
1488 at = -1
1488 at = -1
1489 atbranch = 'default'
1489 atbranch = 'default'
1490 nodeids = []
1490 nodeids = []
1491 id = 0
1491 id = 0
1492 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1492 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1493 for type, data in dagparser.parsedag(text):
1493 for type, data in dagparser.parsedag(text):
1494 if type == 'n':
1494 if type == 'n':
1495 ui.note(('node %s\n' % str(data)))
1495 ui.note(('node %s\n' % str(data)))
1496 id, ps = data
1496 id, ps = data
1497
1497
1498 files = []
1498 files = []
1499 fctxs = {}
1499 fctxs = {}
1500
1500
1501 p2 = None
1501 p2 = None
1502 if mergeable_file:
1502 if mergeable_file:
1503 fn = "mf"
1503 fn = "mf"
1504 p1 = repo[ps[0]]
1504 p1 = repo[ps[0]]
1505 if len(ps) > 1:
1505 if len(ps) > 1:
1506 p2 = repo[ps[1]]
1506 p2 = repo[ps[1]]
1507 pa = p1.ancestor(p2)
1507 pa = p1.ancestor(p2)
1508 base, local, other = [x[fn].data() for x in (pa, p1,
1508 base, local, other = [x[fn].data() for x in (pa, p1,
1509 p2)]
1509 p2)]
1510 m3 = simplemerge.Merge3Text(base, local, other)
1510 m3 = simplemerge.Merge3Text(base, local, other)
1511 ml = [l.strip() for l in m3.merge_lines()]
1511 ml = [l.strip() for l in m3.merge_lines()]
1512 ml.append("")
1512 ml.append("")
1513 elif at > 0:
1513 elif at > 0:
1514 ml = p1[fn].data().split("\n")
1514 ml = p1[fn].data().split("\n")
1515 else:
1515 else:
1516 ml = initialmergedlines
1516 ml = initialmergedlines
1517 ml[id * linesperrev] += " r%i" % id
1517 ml[id * linesperrev] += " r%i" % id
1518 mergedtext = "\n".join(ml)
1518 mergedtext = "\n".join(ml)
1519 files.append(fn)
1519 files.append(fn)
1520 fctxs[fn] = context.memfilectx(fn, mergedtext)
1520 fctxs[fn] = context.memfilectx(fn, mergedtext)
1521
1521
1522 if overwritten_file:
1522 if overwritten_file:
1523 fn = "of"
1523 fn = "of"
1524 files.append(fn)
1524 files.append(fn)
1525 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1525 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1526
1526
1527 if new_file:
1527 if new_file:
1528 fn = "nf%i" % id
1528 fn = "nf%i" % id
1529 files.append(fn)
1529 files.append(fn)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1530 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1531 if len(ps) > 1:
1531 if len(ps) > 1:
1532 if not p2:
1532 if not p2:
1533 p2 = repo[ps[1]]
1533 p2 = repo[ps[1]]
1534 for fn in p2:
1534 for fn in p2:
1535 if fn.startswith("nf"):
1535 if fn.startswith("nf"):
1536 files.append(fn)
1536 files.append(fn)
1537 fctxs[fn] = p2[fn]
1537 fctxs[fn] = p2[fn]
1538
1538
1539 def fctxfn(repo, cx, path):
1539 def fctxfn(repo, cx, path):
1540 return fctxs.get(path)
1540 return fctxs.get(path)
1541
1541
1542 if len(ps) == 0 or ps[0] < 0:
1542 if len(ps) == 0 or ps[0] < 0:
1543 pars = [None, None]
1543 pars = [None, None]
1544 elif len(ps) == 1:
1544 elif len(ps) == 1:
1545 pars = [nodeids[ps[0]], None]
1545 pars = [nodeids[ps[0]], None]
1546 else:
1546 else:
1547 pars = [nodeids[p] for p in ps]
1547 pars = [nodeids[p] for p in ps]
1548 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1548 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1549 date=(id, 0),
1549 date=(id, 0),
1550 user="debugbuilddag",
1550 user="debugbuilddag",
1551 extra={'branch': atbranch})
1551 extra={'branch': atbranch})
1552 nodeid = repo.commitctx(cx)
1552 nodeid = repo.commitctx(cx)
1553 nodeids.append(nodeid)
1553 nodeids.append(nodeid)
1554 at = id
1554 at = id
1555 elif type == 'l':
1555 elif type == 'l':
1556 id, name = data
1556 id, name = data
1557 ui.note(('tag %s\n' % name))
1557 ui.note(('tag %s\n' % name))
1558 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1558 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1559 elif type == 'a':
1559 elif type == 'a':
1560 ui.note(('branch %s\n' % data))
1560 ui.note(('branch %s\n' % data))
1561 atbranch = data
1561 atbranch = data
1562 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1562 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1563 tr.close()
1563 tr.close()
1564
1564
1565 if tags:
1565 if tags:
1566 repo.opener.write("localtags", "".join(tags))
1566 repo.opener.write("localtags", "".join(tags))
1567 finally:
1567 finally:
1568 ui.progress(_('building'), None)
1568 ui.progress(_('building'), None)
1569 release(tr, lock)
1569 release(tr, lock)
1570
1570
1571 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1571 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1572 def debugbundle(ui, bundlepath, all=None, **opts):
1572 def debugbundle(ui, bundlepath, all=None, **opts):
1573 """lists the contents of a bundle"""
1573 """lists the contents of a bundle"""
1574 f = hg.openpath(ui, bundlepath)
1574 f = hg.openpath(ui, bundlepath)
1575 try:
1575 try:
1576 gen = changegroup.readbundle(f, bundlepath)
1576 gen = changegroup.readbundle(f, bundlepath)
1577 if all:
1577 if all:
1578 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1578 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1579
1579
1580 def showchunks(named):
1580 def showchunks(named):
1581 ui.write("\n%s\n" % named)
1581 ui.write("\n%s\n" % named)
1582 chain = None
1582 chain = None
1583 while True:
1583 while True:
1584 chunkdata = gen.deltachunk(chain)
1584 chunkdata = gen.deltachunk(chain)
1585 if not chunkdata:
1585 if not chunkdata:
1586 break
1586 break
1587 node = chunkdata['node']
1587 node = chunkdata['node']
1588 p1 = chunkdata['p1']
1588 p1 = chunkdata['p1']
1589 p2 = chunkdata['p2']
1589 p2 = chunkdata['p2']
1590 cs = chunkdata['cs']
1590 cs = chunkdata['cs']
1591 deltabase = chunkdata['deltabase']
1591 deltabase = chunkdata['deltabase']
1592 delta = chunkdata['delta']
1592 delta = chunkdata['delta']
1593 ui.write("%s %s %s %s %s %s\n" %
1593 ui.write("%s %s %s %s %s %s\n" %
1594 (hex(node), hex(p1), hex(p2),
1594 (hex(node), hex(p1), hex(p2),
1595 hex(cs), hex(deltabase), len(delta)))
1595 hex(cs), hex(deltabase), len(delta)))
1596 chain = node
1596 chain = node
1597
1597
1598 chunkdata = gen.changelogheader()
1598 chunkdata = gen.changelogheader()
1599 showchunks("changelog")
1599 showchunks("changelog")
1600 chunkdata = gen.manifestheader()
1600 chunkdata = gen.manifestheader()
1601 showchunks("manifest")
1601 showchunks("manifest")
1602 while True:
1602 while True:
1603 chunkdata = gen.filelogheader()
1603 chunkdata = gen.filelogheader()
1604 if not chunkdata:
1604 if not chunkdata:
1605 break
1605 break
1606 fname = chunkdata['filename']
1606 fname = chunkdata['filename']
1607 showchunks(fname)
1607 showchunks(fname)
1608 else:
1608 else:
1609 chunkdata = gen.changelogheader()
1609 chunkdata = gen.changelogheader()
1610 chain = None
1610 chain = None
1611 while True:
1611 while True:
1612 chunkdata = gen.deltachunk(chain)
1612 chunkdata = gen.deltachunk(chain)
1613 if not chunkdata:
1613 if not chunkdata:
1614 break
1614 break
1615 node = chunkdata['node']
1615 node = chunkdata['node']
1616 ui.write("%s\n" % hex(node))
1616 ui.write("%s\n" % hex(node))
1617 chain = node
1617 chain = node
1618 finally:
1618 finally:
1619 f.close()
1619 f.close()
1620
1620
1621 @command('debugcheckstate', [], '')
1621 @command('debugcheckstate', [], '')
1622 def debugcheckstate(ui, repo):
1622 def debugcheckstate(ui, repo):
1623 """validate the correctness of the current dirstate"""
1623 """validate the correctness of the current dirstate"""
1624 parent1, parent2 = repo.dirstate.parents()
1624 parent1, parent2 = repo.dirstate.parents()
1625 m1 = repo[parent1].manifest()
1625 m1 = repo[parent1].manifest()
1626 m2 = repo[parent2].manifest()
1626 m2 = repo[parent2].manifest()
1627 errors = 0
1627 errors = 0
1628 for f in repo.dirstate:
1628 for f in repo.dirstate:
1629 state = repo.dirstate[f]
1629 state = repo.dirstate[f]
1630 if state in "nr" and f not in m1:
1630 if state in "nr" and f not in m1:
1631 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1631 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1632 errors += 1
1632 errors += 1
1633 if state in "a" and f in m1:
1633 if state in "a" and f in m1:
1634 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1634 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1635 errors += 1
1635 errors += 1
1636 if state in "m" and f not in m1 and f not in m2:
1636 if state in "m" and f not in m1 and f not in m2:
1637 ui.warn(_("%s in state %s, but not in either manifest\n") %
1637 ui.warn(_("%s in state %s, but not in either manifest\n") %
1638 (f, state))
1638 (f, state))
1639 errors += 1
1639 errors += 1
1640 for f in m1:
1640 for f in m1:
1641 state = repo.dirstate[f]
1641 state = repo.dirstate[f]
1642 if state not in "nrm":
1642 if state not in "nrm":
1643 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1643 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1644 errors += 1
1644 errors += 1
1645 if errors:
1645 if errors:
1646 error = _(".hg/dirstate inconsistent with current parent's manifest")
1646 error = _(".hg/dirstate inconsistent with current parent's manifest")
1647 raise util.Abort(error)
1647 raise util.Abort(error)
1648
1648
1649 @command('debugcommands', [], _('[COMMAND]'))
1649 @command('debugcommands', [], _('[COMMAND]'))
1650 def debugcommands(ui, cmd='', *args):
1650 def debugcommands(ui, cmd='', *args):
1651 """list all available commands and options"""
1651 """list all available commands and options"""
1652 for cmd, vals in sorted(table.iteritems()):
1652 for cmd, vals in sorted(table.iteritems()):
1653 cmd = cmd.split('|')[0].strip('^')
1653 cmd = cmd.split('|')[0].strip('^')
1654 opts = ', '.join([i[1] for i in vals[1]])
1654 opts = ', '.join([i[1] for i in vals[1]])
1655 ui.write('%s: %s\n' % (cmd, opts))
1655 ui.write('%s: %s\n' % (cmd, opts))
1656
1656
1657 @command('debugcomplete',
1657 @command('debugcomplete',
1658 [('o', 'options', None, _('show the command options'))],
1658 [('o', 'options', None, _('show the command options'))],
1659 _('[-o] CMD'))
1659 _('[-o] CMD'))
1660 def debugcomplete(ui, cmd='', **opts):
1660 def debugcomplete(ui, cmd='', **opts):
1661 """returns the completion list associated with the given command"""
1661 """returns the completion list associated with the given command"""
1662
1662
1663 if opts.get('options'):
1663 if opts.get('options'):
1664 options = []
1664 options = []
1665 otables = [globalopts]
1665 otables = [globalopts]
1666 if cmd:
1666 if cmd:
1667 aliases, entry = cmdutil.findcmd(cmd, table, False)
1667 aliases, entry = cmdutil.findcmd(cmd, table, False)
1668 otables.append(entry[1])
1668 otables.append(entry[1])
1669 for t in otables:
1669 for t in otables:
1670 for o in t:
1670 for o in t:
1671 if "(DEPRECATED)" in o[3]:
1671 if "(DEPRECATED)" in o[3]:
1672 continue
1672 continue
1673 if o[0]:
1673 if o[0]:
1674 options.append('-%s' % o[0])
1674 options.append('-%s' % o[0])
1675 options.append('--%s' % o[1])
1675 options.append('--%s' % o[1])
1676 ui.write("%s\n" % "\n".join(options))
1676 ui.write("%s\n" % "\n".join(options))
1677 return
1677 return
1678
1678
1679 cmdlist = cmdutil.findpossible(cmd, table)
1679 cmdlist = cmdutil.findpossible(cmd, table)
1680 if ui.verbose:
1680 if ui.verbose:
1681 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1681 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1682 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1682 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1683
1683
1684 @command('debugdag',
1684 @command('debugdag',
1685 [('t', 'tags', None, _('use tags as labels')),
1685 [('t', 'tags', None, _('use tags as labels')),
1686 ('b', 'branches', None, _('annotate with branch names')),
1686 ('b', 'branches', None, _('annotate with branch names')),
1687 ('', 'dots', None, _('use dots for runs')),
1687 ('', 'dots', None, _('use dots for runs')),
1688 ('s', 'spaces', None, _('separate elements by spaces'))],
1688 ('s', 'spaces', None, _('separate elements by spaces'))],
1689 _('[OPTION]... [FILE [REV]...]'))
1689 _('[OPTION]... [FILE [REV]...]'))
1690 def debugdag(ui, repo, file_=None, *revs, **opts):
1690 def debugdag(ui, repo, file_=None, *revs, **opts):
1691 """format the changelog or an index DAG as a concise textual description
1691 """format the changelog or an index DAG as a concise textual description
1692
1692
1693 If you pass a revlog index, the revlog's DAG is emitted. If you list
1693 If you pass a revlog index, the revlog's DAG is emitted. If you list
1694 revision numbers, they get labeled in the output as rN.
1694 revision numbers, they get labeled in the output as rN.
1695
1695
1696 Otherwise, the changelog DAG of the current repo is emitted.
1696 Otherwise, the changelog DAG of the current repo is emitted.
1697 """
1697 """
1698 spaces = opts.get('spaces')
1698 spaces = opts.get('spaces')
1699 dots = opts.get('dots')
1699 dots = opts.get('dots')
1700 if file_:
1700 if file_:
1701 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1701 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1702 revs = set((int(r) for r in revs))
1702 revs = set((int(r) for r in revs))
1703 def events():
1703 def events():
1704 for r in rlog:
1704 for r in rlog:
1705 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1705 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1706 if p != -1)))
1706 if p != -1)))
1707 if r in revs:
1707 if r in revs:
1708 yield 'l', (r, "r%i" % r)
1708 yield 'l', (r, "r%i" % r)
1709 elif repo:
1709 elif repo:
1710 cl = repo.changelog
1710 cl = repo.changelog
1711 tags = opts.get('tags')
1711 tags = opts.get('tags')
1712 branches = opts.get('branches')
1712 branches = opts.get('branches')
1713 if tags:
1713 if tags:
1714 labels = {}
1714 labels = {}
1715 for l, n in repo.tags().items():
1715 for l, n in repo.tags().items():
1716 labels.setdefault(cl.rev(n), []).append(l)
1716 labels.setdefault(cl.rev(n), []).append(l)
1717 def events():
1717 def events():
1718 b = "default"
1718 b = "default"
1719 for r in cl:
1719 for r in cl:
1720 if branches:
1720 if branches:
1721 newb = cl.read(cl.node(r))[5]['branch']
1721 newb = cl.read(cl.node(r))[5]['branch']
1722 if newb != b:
1722 if newb != b:
1723 yield 'a', newb
1723 yield 'a', newb
1724 b = newb
1724 b = newb
1725 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1725 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1726 if p != -1)))
1726 if p != -1)))
1727 if tags:
1727 if tags:
1728 ls = labels.get(r)
1728 ls = labels.get(r)
1729 if ls:
1729 if ls:
1730 for l in ls:
1730 for l in ls:
1731 yield 'l', (r, l)
1731 yield 'l', (r, l)
1732 else:
1732 else:
1733 raise util.Abort(_('need repo for changelog dag'))
1733 raise util.Abort(_('need repo for changelog dag'))
1734
1734
1735 for line in dagparser.dagtextlines(events(),
1735 for line in dagparser.dagtextlines(events(),
1736 addspaces=spaces,
1736 addspaces=spaces,
1737 wraplabels=True,
1737 wraplabels=True,
1738 wrapannotations=True,
1738 wrapannotations=True,
1739 wrapnonlinear=dots,
1739 wrapnonlinear=dots,
1740 usedots=dots,
1740 usedots=dots,
1741 maxlinewidth=70):
1741 maxlinewidth=70):
1742 ui.write(line)
1742 ui.write(line)
1743 ui.write("\n")
1743 ui.write("\n")
1744
1744
1745 @command('debugdata',
1745 @command('debugdata',
1746 [('c', 'changelog', False, _('open changelog')),
1746 [('c', 'changelog', False, _('open changelog')),
1747 ('m', 'manifest', False, _('open manifest'))],
1747 ('m', 'manifest', False, _('open manifest'))],
1748 _('-c|-m|FILE REV'))
1748 _('-c|-m|FILE REV'))
1749 def debugdata(ui, repo, file_, rev = None, **opts):
1749 def debugdata(ui, repo, file_, rev = None, **opts):
1750 """dump the contents of a data file revision"""
1750 """dump the contents of a data file revision"""
1751 if opts.get('changelog') or opts.get('manifest'):
1751 if opts.get('changelog') or opts.get('manifest'):
1752 file_, rev = None, file_
1752 file_, rev = None, file_
1753 elif rev is None:
1753 elif rev is None:
1754 raise error.CommandError('debugdata', _('invalid arguments'))
1754 raise error.CommandError('debugdata', _('invalid arguments'))
1755 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1755 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1756 try:
1756 try:
1757 ui.write(r.revision(r.lookup(rev)))
1757 ui.write(r.revision(r.lookup(rev)))
1758 except KeyError:
1758 except KeyError:
1759 raise util.Abort(_('invalid revision identifier %s') % rev)
1759 raise util.Abort(_('invalid revision identifier %s') % rev)
1760
1760
1761 @command('debugdate',
1761 @command('debugdate',
1762 [('e', 'extended', None, _('try extended date formats'))],
1762 [('e', 'extended', None, _('try extended date formats'))],
1763 _('[-e] DATE [RANGE]'))
1763 _('[-e] DATE [RANGE]'))
1764 def debugdate(ui, date, range=None, **opts):
1764 def debugdate(ui, date, range=None, **opts):
1765 """parse and display a date"""
1765 """parse and display a date"""
1766 if opts["extended"]:
1766 if opts["extended"]:
1767 d = util.parsedate(date, util.extendeddateformats)
1767 d = util.parsedate(date, util.extendeddateformats)
1768 else:
1768 else:
1769 d = util.parsedate(date)
1769 d = util.parsedate(date)
1770 ui.write(("internal: %s %s\n") % d)
1770 ui.write(("internal: %s %s\n") % d)
1771 ui.write(("standard: %s\n") % util.datestr(d))
1771 ui.write(("standard: %s\n") % util.datestr(d))
1772 if range:
1772 if range:
1773 m = util.matchdate(range)
1773 m = util.matchdate(range)
1774 ui.write(("match: %s\n") % m(d[0]))
1774 ui.write(("match: %s\n") % m(d[0]))
1775
1775
1776 @command('debugdiscovery',
1776 @command('debugdiscovery',
1777 [('', 'old', None, _('use old-style discovery')),
1777 [('', 'old', None, _('use old-style discovery')),
1778 ('', 'nonheads', None,
1778 ('', 'nonheads', None,
1779 _('use old-style discovery with non-heads included')),
1779 _('use old-style discovery with non-heads included')),
1780 ] + remoteopts,
1780 ] + remoteopts,
1781 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1781 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1782 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1782 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1783 """runs the changeset discovery protocol in isolation"""
1783 """runs the changeset discovery protocol in isolation"""
1784 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1784 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1785 opts.get('branch'))
1785 opts.get('branch'))
1786 remote = hg.peer(repo, opts, remoteurl)
1786 remote = hg.peer(repo, opts, remoteurl)
1787 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1787 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1788
1788
1789 # make sure tests are repeatable
1789 # make sure tests are repeatable
1790 random.seed(12323)
1790 random.seed(12323)
1791
1791
1792 def doit(localheads, remoteheads, remote=remote):
1792 def doit(localheads, remoteheads, remote=remote):
1793 if opts.get('old'):
1793 if opts.get('old'):
1794 if localheads:
1794 if localheads:
1795 raise util.Abort('cannot use localheads with old style '
1795 raise util.Abort('cannot use localheads with old style '
1796 'discovery')
1796 'discovery')
1797 if not util.safehasattr(remote, 'branches'):
1797 if not util.safehasattr(remote, 'branches'):
1798 # enable in-client legacy support
1798 # enable in-client legacy support
1799 remote = localrepo.locallegacypeer(remote.local())
1799 remote = localrepo.locallegacypeer(remote.local())
1800 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1800 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1801 force=True)
1801 force=True)
1802 common = set(common)
1802 common = set(common)
1803 if not opts.get('nonheads'):
1803 if not opts.get('nonheads'):
1804 ui.write(("unpruned common: %s\n") %
1804 ui.write(("unpruned common: %s\n") %
1805 " ".join(sorted(short(n) for n in common)))
1805 " ".join(sorted(short(n) for n in common)))
1806 dag = dagutil.revlogdag(repo.changelog)
1806 dag = dagutil.revlogdag(repo.changelog)
1807 all = dag.ancestorset(dag.internalizeall(common))
1807 all = dag.ancestorset(dag.internalizeall(common))
1808 common = dag.externalizeall(dag.headsetofconnecteds(all))
1808 common = dag.externalizeall(dag.headsetofconnecteds(all))
1809 else:
1809 else:
1810 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1810 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1811 common = set(common)
1811 common = set(common)
1812 rheads = set(hds)
1812 rheads = set(hds)
1813 lheads = set(repo.heads())
1813 lheads = set(repo.heads())
1814 ui.write(("common heads: %s\n") %
1814 ui.write(("common heads: %s\n") %
1815 " ".join(sorted(short(n) for n in common)))
1815 " ".join(sorted(short(n) for n in common)))
1816 if lheads <= common:
1816 if lheads <= common:
1817 ui.write(("local is subset\n"))
1817 ui.write(("local is subset\n"))
1818 elif rheads <= common:
1818 elif rheads <= common:
1819 ui.write(("remote is subset\n"))
1819 ui.write(("remote is subset\n"))
1820
1820
1821 serverlogs = opts.get('serverlog')
1821 serverlogs = opts.get('serverlog')
1822 if serverlogs:
1822 if serverlogs:
1823 for filename in serverlogs:
1823 for filename in serverlogs:
1824 logfile = open(filename, 'r')
1824 logfile = open(filename, 'r')
1825 try:
1825 try:
1826 line = logfile.readline()
1826 line = logfile.readline()
1827 while line:
1827 while line:
1828 parts = line.strip().split(';')
1828 parts = line.strip().split(';')
1829 op = parts[1]
1829 op = parts[1]
1830 if op == 'cg':
1830 if op == 'cg':
1831 pass
1831 pass
1832 elif op == 'cgss':
1832 elif op == 'cgss':
1833 doit(parts[2].split(' '), parts[3].split(' '))
1833 doit(parts[2].split(' '), parts[3].split(' '))
1834 elif op == 'unb':
1834 elif op == 'unb':
1835 doit(parts[3].split(' '), parts[2].split(' '))
1835 doit(parts[3].split(' '), parts[2].split(' '))
1836 line = logfile.readline()
1836 line = logfile.readline()
1837 finally:
1837 finally:
1838 logfile.close()
1838 logfile.close()
1839
1839
1840 else:
1840 else:
1841 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1841 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1842 opts.get('remote_head'))
1842 opts.get('remote_head'))
1843 localrevs = opts.get('local_head')
1843 localrevs = opts.get('local_head')
1844 doit(localrevs, remoterevs)
1844 doit(localrevs, remoterevs)
1845
1845
1846 @command('debugfileset',
1846 @command('debugfileset',
1847 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1847 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1848 _('[-r REV] FILESPEC'))
1848 _('[-r REV] FILESPEC'))
1849 def debugfileset(ui, repo, expr, **opts):
1849 def debugfileset(ui, repo, expr, **opts):
1850 '''parse and apply a fileset specification'''
1850 '''parse and apply a fileset specification'''
1851 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1851 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1852 if ui.verbose:
1852 if ui.verbose:
1853 tree = fileset.parse(expr)[0]
1853 tree = fileset.parse(expr)[0]
1854 ui.note(tree, "\n")
1854 ui.note(tree, "\n")
1855
1855
1856 for f in fileset.getfileset(ctx, expr):
1856 for f in fileset.getfileset(ctx, expr):
1857 ui.write("%s\n" % f)
1857 ui.write("%s\n" % f)
1858
1858
1859 @command('debugfsinfo', [], _('[PATH]'))
1859 @command('debugfsinfo', [], _('[PATH]'))
1860 def debugfsinfo(ui, path = "."):
1860 def debugfsinfo(ui, path = "."):
1861 """show information detected about current filesystem"""
1861 """show information detected about current filesystem"""
1862 util.writefile('.debugfsinfo', '')
1862 util.writefile('.debugfsinfo', '')
1863 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1863 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1864 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1864 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1865 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1865 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1866 and 'yes' or 'no'))
1866 and 'yes' or 'no'))
1867 os.unlink('.debugfsinfo')
1867 os.unlink('.debugfsinfo')
1868
1868
1869 @command('debuggetbundle',
1869 @command('debuggetbundle',
1870 [('H', 'head', [], _('id of head node'), _('ID')),
1870 [('H', 'head', [], _('id of head node'), _('ID')),
1871 ('C', 'common', [], _('id of common node'), _('ID')),
1871 ('C', 'common', [], _('id of common node'), _('ID')),
1872 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1872 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1873 _('REPO FILE [-H|-C ID]...'))
1873 _('REPO FILE [-H|-C ID]...'))
1874 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1874 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1875 """retrieves a bundle from a repo
1875 """retrieves a bundle from a repo
1876
1876
1877 Every ID must be a full-length hex node id string. Saves the bundle to the
1877 Every ID must be a full-length hex node id string. Saves the bundle to the
1878 given file.
1878 given file.
1879 """
1879 """
1880 repo = hg.peer(ui, opts, repopath)
1880 repo = hg.peer(ui, opts, repopath)
1881 if not repo.capable('getbundle'):
1881 if not repo.capable('getbundle'):
1882 raise util.Abort("getbundle() not supported by target repository")
1882 raise util.Abort("getbundle() not supported by target repository")
1883 args = {}
1883 args = {}
1884 if common:
1884 if common:
1885 args['common'] = [bin(s) for s in common]
1885 args['common'] = [bin(s) for s in common]
1886 if head:
1886 if head:
1887 args['heads'] = [bin(s) for s in head]
1887 args['heads'] = [bin(s) for s in head]
1888 bundle = repo.getbundle('debug', **args)
1888 bundle = repo.getbundle('debug', **args)
1889
1889
1890 bundletype = opts.get('type', 'bzip2').lower()
1890 bundletype = opts.get('type', 'bzip2').lower()
1891 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1891 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1892 bundletype = btypes.get(bundletype)
1892 bundletype = btypes.get(bundletype)
1893 if bundletype not in changegroup.bundletypes:
1893 if bundletype not in changegroup.bundletypes:
1894 raise util.Abort(_('unknown bundle type specified with --type'))
1894 raise util.Abort(_('unknown bundle type specified with --type'))
1895 changegroup.writebundle(bundle, bundlepath, bundletype)
1895 changegroup.writebundle(bundle, bundlepath, bundletype)
1896
1896
1897 @command('debugignore', [], '')
1897 @command('debugignore', [], '')
1898 def debugignore(ui, repo, *values, **opts):
1898 def debugignore(ui, repo, *values, **opts):
1899 """display the combined ignore pattern"""
1899 """display the combined ignore pattern"""
1900 ignore = repo.dirstate._ignore
1900 ignore = repo.dirstate._ignore
1901 includepat = getattr(ignore, 'includepat', None)
1901 includepat = getattr(ignore, 'includepat', None)
1902 if includepat is not None:
1902 if includepat is not None:
1903 ui.write("%s\n" % includepat)
1903 ui.write("%s\n" % includepat)
1904 else:
1904 else:
1905 raise util.Abort(_("no ignore patterns found"))
1905 raise util.Abort(_("no ignore patterns found"))
1906
1906
1907 @command('debugindex',
1907 @command('debugindex',
1908 [('c', 'changelog', False, _('open changelog')),
1908 [('c', 'changelog', False, _('open changelog')),
1909 ('m', 'manifest', False, _('open manifest')),
1909 ('m', 'manifest', False, _('open manifest')),
1910 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1910 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1911 _('[-f FORMAT] -c|-m|FILE'))
1911 _('[-f FORMAT] -c|-m|FILE'))
1912 def debugindex(ui, repo, file_ = None, **opts):
1912 def debugindex(ui, repo, file_ = None, **opts):
1913 """dump the contents of an index file"""
1913 """dump the contents of an index file"""
1914 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1914 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1915 format = opts.get('format', 0)
1915 format = opts.get('format', 0)
1916 if format not in (0, 1):
1916 if format not in (0, 1):
1917 raise util.Abort(_("unknown format %d") % format)
1917 raise util.Abort(_("unknown format %d") % format)
1918
1918
1919 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1919 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1920 if generaldelta:
1920 if generaldelta:
1921 basehdr = ' delta'
1921 basehdr = ' delta'
1922 else:
1922 else:
1923 basehdr = ' base'
1923 basehdr = ' base'
1924
1924
1925 if format == 0:
1925 if format == 0:
1926 ui.write(" rev offset length " + basehdr + " linkrev"
1926 ui.write(" rev offset length " + basehdr + " linkrev"
1927 " nodeid p1 p2\n")
1927 " nodeid p1 p2\n")
1928 elif format == 1:
1928 elif format == 1:
1929 ui.write(" rev flag offset length"
1929 ui.write(" rev flag offset length"
1930 " size " + basehdr + " link p1 p2"
1930 " size " + basehdr + " link p1 p2"
1931 " nodeid\n")
1931 " nodeid\n")
1932
1932
1933 for i in r:
1933 for i in r:
1934 node = r.node(i)
1934 node = r.node(i)
1935 if generaldelta:
1935 if generaldelta:
1936 base = r.deltaparent(i)
1936 base = r.deltaparent(i)
1937 else:
1937 else:
1938 base = r.chainbase(i)
1938 base = r.chainbase(i)
1939 if format == 0:
1939 if format == 0:
1940 try:
1940 try:
1941 pp = r.parents(node)
1941 pp = r.parents(node)
1942 except Exception:
1942 except Exception:
1943 pp = [nullid, nullid]
1943 pp = [nullid, nullid]
1944 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1944 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1945 i, r.start(i), r.length(i), base, r.linkrev(i),
1945 i, r.start(i), r.length(i), base, r.linkrev(i),
1946 short(node), short(pp[0]), short(pp[1])))
1946 short(node), short(pp[0]), short(pp[1])))
1947 elif format == 1:
1947 elif format == 1:
1948 pr = r.parentrevs(i)
1948 pr = r.parentrevs(i)
1949 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1949 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1950 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1950 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1951 base, r.linkrev(i), pr[0], pr[1], short(node)))
1951 base, r.linkrev(i), pr[0], pr[1], short(node)))
1952
1952
1953 @command('debugindexdot', [], _('FILE'))
1953 @command('debugindexdot', [], _('FILE'))
1954 def debugindexdot(ui, repo, file_):
1954 def debugindexdot(ui, repo, file_):
1955 """dump an index DAG as a graphviz dot file"""
1955 """dump an index DAG as a graphviz dot file"""
1956 r = None
1956 r = None
1957 if repo:
1957 if repo:
1958 filelog = repo.file(file_)
1958 filelog = repo.file(file_)
1959 if len(filelog):
1959 if len(filelog):
1960 r = filelog
1960 r = filelog
1961 if not r:
1961 if not r:
1962 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1962 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1963 ui.write(("digraph G {\n"))
1963 ui.write(("digraph G {\n"))
1964 for i in r:
1964 for i in r:
1965 node = r.node(i)
1965 node = r.node(i)
1966 pp = r.parents(node)
1966 pp = r.parents(node)
1967 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1967 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1968 if pp[1] != nullid:
1968 if pp[1] != nullid:
1969 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1969 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1970 ui.write("}\n")
1970 ui.write("}\n")
1971
1971
1972 @command('debuginstall', [], '')
1972 @command('debuginstall', [], '')
1973 def debuginstall(ui):
1973 def debuginstall(ui):
1974 '''test Mercurial installation
1974 '''test Mercurial installation
1975
1975
1976 Returns 0 on success.
1976 Returns 0 on success.
1977 '''
1977 '''
1978
1978
1979 def writetemp(contents):
1979 def writetemp(contents):
1980 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1980 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1981 f = os.fdopen(fd, "wb")
1981 f = os.fdopen(fd, "wb")
1982 f.write(contents)
1982 f.write(contents)
1983 f.close()
1983 f.close()
1984 return name
1984 return name
1985
1985
1986 problems = 0
1986 problems = 0
1987
1987
1988 # encoding
1988 # encoding
1989 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1989 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1990 try:
1990 try:
1991 encoding.fromlocal("test")
1991 encoding.fromlocal("test")
1992 except util.Abort, inst:
1992 except util.Abort, inst:
1993 ui.write(" %s\n" % inst)
1993 ui.write(" %s\n" % inst)
1994 ui.write(_(" (check that your locale is properly set)\n"))
1994 ui.write(_(" (check that your locale is properly set)\n"))
1995 problems += 1
1995 problems += 1
1996
1996
1997 # Python lib
1997 # Python lib
1998 ui.status(_("checking Python lib (%s)...\n")
1998 ui.status(_("checking Python lib (%s)...\n")
1999 % os.path.dirname(os.__file__))
1999 % os.path.dirname(os.__file__))
2000
2000
2001 # compiled modules
2001 # compiled modules
2002 ui.status(_("checking installed modules (%s)...\n")
2002 ui.status(_("checking installed modules (%s)...\n")
2003 % os.path.dirname(__file__))
2003 % os.path.dirname(__file__))
2004 try:
2004 try:
2005 import bdiff, mpatch, base85, osutil
2005 import bdiff, mpatch, base85, osutil
2006 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2006 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2007 except Exception, inst:
2007 except Exception, inst:
2008 ui.write(" %s\n" % inst)
2008 ui.write(" %s\n" % inst)
2009 ui.write(_(" One or more extensions could not be found"))
2009 ui.write(_(" One or more extensions could not be found"))
2010 ui.write(_(" (check that you compiled the extensions)\n"))
2010 ui.write(_(" (check that you compiled the extensions)\n"))
2011 problems += 1
2011 problems += 1
2012
2012
2013 # templates
2013 # templates
2014 import templater
2014 import templater
2015 p = templater.templatepath()
2015 p = templater.templatepath()
2016 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2016 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2017 try:
2017 try:
2018 templater.templater(templater.templatepath("map-cmdline.default"))
2018 templater.templater(templater.templatepath("map-cmdline.default"))
2019 except Exception, inst:
2019 except Exception, inst:
2020 ui.write(" %s\n" % inst)
2020 ui.write(" %s\n" % inst)
2021 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2021 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2022 problems += 1
2022 problems += 1
2023
2023
2024 # editor
2024 # editor
2025 ui.status(_("checking commit editor...\n"))
2025 ui.status(_("checking commit editor...\n"))
2026 editor = ui.geteditor()
2026 editor = ui.geteditor()
2027 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2027 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2028 if not cmdpath:
2028 if not cmdpath:
2029 if editor == 'vi':
2029 if editor == 'vi':
2030 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2030 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2031 ui.write(_(" (specify a commit editor in your configuration"
2031 ui.write(_(" (specify a commit editor in your configuration"
2032 " file)\n"))
2032 " file)\n"))
2033 else:
2033 else:
2034 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2034 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2035 ui.write(_(" (specify a commit editor in your configuration"
2035 ui.write(_(" (specify a commit editor in your configuration"
2036 " file)\n"))
2036 " file)\n"))
2037 problems += 1
2037 problems += 1
2038
2038
2039 # check username
2039 # check username
2040 ui.status(_("checking username...\n"))
2040 ui.status(_("checking username...\n"))
2041 try:
2041 try:
2042 ui.username()
2042 ui.username()
2043 except util.Abort, e:
2043 except util.Abort, e:
2044 ui.write(" %s\n" % e)
2044 ui.write(" %s\n" % e)
2045 ui.write(_(" (specify a username in your configuration file)\n"))
2045 ui.write(_(" (specify a username in your configuration file)\n"))
2046 problems += 1
2046 problems += 1
2047
2047
2048 if not problems:
2048 if not problems:
2049 ui.status(_("no problems detected\n"))
2049 ui.status(_("no problems detected\n"))
2050 else:
2050 else:
2051 ui.write(_("%s problems detected,"
2051 ui.write(_("%s problems detected,"
2052 " please check your install!\n") % problems)
2052 " please check your install!\n") % problems)
2053
2053
2054 return problems
2054 return problems
2055
2055
2056 @command('debugknown', [], _('REPO ID...'))
2056 @command('debugknown', [], _('REPO ID...'))
2057 def debugknown(ui, repopath, *ids, **opts):
2057 def debugknown(ui, repopath, *ids, **opts):
2058 """test whether node ids are known to a repo
2058 """test whether node ids are known to a repo
2059
2059
2060 Every ID must be a full-length hex node id string. Returns a list of 0s
2060 Every ID must be a full-length hex node id string. Returns a list of 0s
2061 and 1s indicating unknown/known.
2061 and 1s indicating unknown/known.
2062 """
2062 """
2063 repo = hg.peer(ui, opts, repopath)
2063 repo = hg.peer(ui, opts, repopath)
2064 if not repo.capable('known'):
2064 if not repo.capable('known'):
2065 raise util.Abort("known() not supported by target repository")
2065 raise util.Abort("known() not supported by target repository")
2066 flags = repo.known([bin(s) for s in ids])
2066 flags = repo.known([bin(s) for s in ids])
2067 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2067 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2068
2068
2069 @command('debuglabelcomplete', [], _('LABEL...'))
2069 @command('debuglabelcomplete', [], _('LABEL...'))
2070 def debuglabelcomplete(ui, repo, *args):
2070 def debuglabelcomplete(ui, repo, *args):
2071 '''complete "labels" - tags, open branch names, bookmark names'''
2071 '''complete "labels" - tags, open branch names, bookmark names'''
2072
2072
2073 labels = set()
2073 labels = set()
2074 labels.update(t[0] for t in repo.tagslist())
2074 labels.update(t[0] for t in repo.tagslist())
2075 labels.update(repo._bookmarks.keys())
2075 labels.update(repo._bookmarks.keys())
2076 for heads in repo.branchmap().itervalues():
2076 for heads in repo.branchmap().itervalues():
2077 for h in heads:
2077 for h in heads:
2078 ctx = repo[h]
2078 ctx = repo[h]
2079 if not ctx.closesbranch():
2079 if not ctx.closesbranch():
2080 labels.add(ctx.branch())
2080 labels.add(ctx.branch())
2081 completions = set()
2081 completions = set()
2082 if not args:
2082 if not args:
2083 args = ['']
2083 args = ['']
2084 for a in args:
2084 for a in args:
2085 completions.update(l for l in labels if l.startswith(a))
2085 completions.update(l for l in labels if l.startswith(a))
2086 ui.write('\n'.join(sorted(completions)))
2086 ui.write('\n'.join(sorted(completions)))
2087 ui.write('\n')
2087 ui.write('\n')
2088
2088
2089 @command('debugobsolete',
2089 @command('debugobsolete',
2090 [('', 'flags', 0, _('markers flag')),
2090 [('', 'flags', 0, _('markers flag')),
2091 ] + commitopts2,
2091 ] + commitopts2,
2092 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2092 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2093 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2093 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2094 """create arbitrary obsolete marker
2094 """create arbitrary obsolete marker
2095
2095
2096 With no arguments, displays the list of obsolescence markers."""
2096 With no arguments, displays the list of obsolescence markers."""
2097 def parsenodeid(s):
2097 def parsenodeid(s):
2098 try:
2098 try:
2099 # We do not use revsingle/revrange functions here to accept
2099 # We do not use revsingle/revrange functions here to accept
2100 # arbitrary node identifiers, possibly not present in the
2100 # arbitrary node identifiers, possibly not present in the
2101 # local repository.
2101 # local repository.
2102 n = bin(s)
2102 n = bin(s)
2103 if len(n) != len(nullid):
2103 if len(n) != len(nullid):
2104 raise TypeError()
2104 raise TypeError()
2105 return n
2105 return n
2106 except TypeError:
2106 except TypeError:
2107 raise util.Abort('changeset references must be full hexadecimal '
2107 raise util.Abort('changeset references must be full hexadecimal '
2108 'node identifiers')
2108 'node identifiers')
2109
2109
2110 if precursor is not None:
2110 if precursor is not None:
2111 metadata = {}
2111 metadata = {}
2112 if 'date' in opts:
2112 if 'date' in opts:
2113 metadata['date'] = opts['date']
2113 metadata['date'] = opts['date']
2114 metadata['user'] = opts['user'] or ui.username()
2114 metadata['user'] = opts['user'] or ui.username()
2115 succs = tuple(parsenodeid(succ) for succ in successors)
2115 succs = tuple(parsenodeid(succ) for succ in successors)
2116 l = repo.lock()
2116 l = repo.lock()
2117 try:
2117 try:
2118 tr = repo.transaction('debugobsolete')
2118 tr = repo.transaction('debugobsolete')
2119 try:
2119 try:
2120 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2120 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2121 opts['flags'], metadata)
2121 opts['flags'], metadata)
2122 tr.close()
2122 tr.close()
2123 finally:
2123 finally:
2124 tr.release()
2124 tr.release()
2125 finally:
2125 finally:
2126 l.release()
2126 l.release()
2127 else:
2127 else:
2128 for m in obsolete.allmarkers(repo):
2128 for m in obsolete.allmarkers(repo):
2129 ui.write(hex(m.precnode()))
2129 ui.write(hex(m.precnode()))
2130 for repl in m.succnodes():
2130 for repl in m.succnodes():
2131 ui.write(' ')
2131 ui.write(' ')
2132 ui.write(hex(repl))
2132 ui.write(hex(repl))
2133 ui.write(' %X ' % m._data[2])
2133 ui.write(' %X ' % m._data[2])
2134 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2134 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2135 sorted(m.metadata().items()))))
2135 sorted(m.metadata().items()))))
2136 ui.write('\n')
2136 ui.write('\n')
2137
2137
2138 @command('debugpathcomplete',
2138 @command('debugpathcomplete',
2139 [('f', 'full', None, _('complete an entire path')),
2139 [('f', 'full', None, _('complete an entire path')),
2140 ('n', 'normal', None, _('show only normal files')),
2140 ('n', 'normal', None, _('show only normal files')),
2141 ('a', 'added', None, _('show only added files')),
2141 ('a', 'added', None, _('show only added files')),
2142 ('r', 'removed', None, _('show only removed files'))],
2142 ('r', 'removed', None, _('show only removed files'))],
2143 _('FILESPEC...'))
2143 _('FILESPEC...'))
2144 def debugpathcomplete(ui, repo, *specs, **opts):
2144 def debugpathcomplete(ui, repo, *specs, **opts):
2145 '''complete part or all of a tracked path
2145 '''complete part or all of a tracked path
2146
2146
2147 This command supports shells that offer path name completion. It
2147 This command supports shells that offer path name completion. It
2148 currently completes only files already known to the dirstate.
2148 currently completes only files already known to the dirstate.
2149
2149
2150 Completion extends only to the next path segment unless
2150 Completion extends only to the next path segment unless
2151 --full is specified, in which case entire paths are used.'''
2151 --full is specified, in which case entire paths are used.'''
2152
2152
2153 def complete(path, acceptable):
2153 def complete(path, acceptable):
2154 dirstate = repo.dirstate
2154 dirstate = repo.dirstate
2155 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2155 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2156 rootdir = repo.root + os.sep
2156 rootdir = repo.root + os.sep
2157 if spec != repo.root and not spec.startswith(rootdir):
2157 if spec != repo.root and not spec.startswith(rootdir):
2158 return [], []
2158 return [], []
2159 if os.path.isdir(spec):
2159 if os.path.isdir(spec):
2160 spec += '/'
2160 spec += '/'
2161 spec = spec[len(rootdir):]
2161 spec = spec[len(rootdir):]
2162 fixpaths = os.sep != '/'
2162 fixpaths = os.sep != '/'
2163 if fixpaths:
2163 if fixpaths:
2164 spec = spec.replace(os.sep, '/')
2164 spec = spec.replace(os.sep, '/')
2165 speclen = len(spec)
2165 speclen = len(spec)
2166 fullpaths = opts['full']
2166 fullpaths = opts['full']
2167 files, dirs = set(), set()
2167 files, dirs = set(), set()
2168 adddir, addfile = dirs.add, files.add
2168 adddir, addfile = dirs.add, files.add
2169 for f, st in dirstate.iteritems():
2169 for f, st in dirstate.iteritems():
2170 if f.startswith(spec) and st[0] in acceptable:
2170 if f.startswith(spec) and st[0] in acceptable:
2171 if fixpaths:
2171 if fixpaths:
2172 f = f.replace('/', os.sep)
2172 f = f.replace('/', os.sep)
2173 if fullpaths:
2173 if fullpaths:
2174 addfile(f)
2174 addfile(f)
2175 continue
2175 continue
2176 s = f.find(os.sep, speclen)
2176 s = f.find(os.sep, speclen)
2177 if s >= 0:
2177 if s >= 0:
2178 adddir(f[:s + 1])
2178 adddir(f[:s + 1])
2179 else:
2179 else:
2180 addfile(f)
2180 addfile(f)
2181 return files, dirs
2181 return files, dirs
2182
2182
2183 acceptable = ''
2183 acceptable = ''
2184 if opts['normal']:
2184 if opts['normal']:
2185 acceptable += 'nm'
2185 acceptable += 'nm'
2186 if opts['added']:
2186 if opts['added']:
2187 acceptable += 'a'
2187 acceptable += 'a'
2188 if opts['removed']:
2188 if opts['removed']:
2189 acceptable += 'r'
2189 acceptable += 'r'
2190 cwd = repo.getcwd()
2190 cwd = repo.getcwd()
2191 if not specs:
2191 if not specs:
2192 specs = ['.']
2192 specs = ['.']
2193
2193
2194 files, dirs = set(), set()
2194 files, dirs = set(), set()
2195 for spec in specs:
2195 for spec in specs:
2196 f, d = complete(spec, acceptable or 'nmar')
2196 f, d = complete(spec, acceptable or 'nmar')
2197 files.update(f)
2197 files.update(f)
2198 dirs.update(d)
2198 dirs.update(d)
2199 if not files and len(dirs) == 1:
2199 if not files and len(dirs) == 1:
2200 # force the shell to consider a completion that matches one
2200 # force the shell to consider a completion that matches one
2201 # directory and zero files to be ambiguous
2201 # directory and zero files to be ambiguous
2202 dirs.add(iter(dirs).next() + '.')
2202 dirs.add(iter(dirs).next() + '.')
2203 files.update(dirs)
2203 files.update(dirs)
2204 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2204 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2205 ui.write('\n')
2205 ui.write('\n')
2206
2206
2207 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2207 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2208 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2208 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2209 '''access the pushkey key/value protocol
2209 '''access the pushkey key/value protocol
2210
2210
2211 With two args, list the keys in the given namespace.
2211 With two args, list the keys in the given namespace.
2212
2212
2213 With five args, set a key to new if it currently is set to old.
2213 With five args, set a key to new if it currently is set to old.
2214 Reports success or failure.
2214 Reports success or failure.
2215 '''
2215 '''
2216
2216
2217 target = hg.peer(ui, {}, repopath)
2217 target = hg.peer(ui, {}, repopath)
2218 if keyinfo:
2218 if keyinfo:
2219 key, old, new = keyinfo
2219 key, old, new = keyinfo
2220 r = target.pushkey(namespace, key, old, new)
2220 r = target.pushkey(namespace, key, old, new)
2221 ui.status(str(r) + '\n')
2221 ui.status(str(r) + '\n')
2222 return not r
2222 return not r
2223 else:
2223 else:
2224 for k, v in sorted(target.listkeys(namespace).iteritems()):
2224 for k, v in sorted(target.listkeys(namespace).iteritems()):
2225 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2225 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2226 v.encode('string-escape')))
2226 v.encode('string-escape')))
2227
2227
2228 @command('debugpvec', [], _('A B'))
2228 @command('debugpvec', [], _('A B'))
2229 def debugpvec(ui, repo, a, b=None):
2229 def debugpvec(ui, repo, a, b=None):
2230 ca = scmutil.revsingle(repo, a)
2230 ca = scmutil.revsingle(repo, a)
2231 cb = scmutil.revsingle(repo, b)
2231 cb = scmutil.revsingle(repo, b)
2232 pa = pvec.ctxpvec(ca)
2232 pa = pvec.ctxpvec(ca)
2233 pb = pvec.ctxpvec(cb)
2233 pb = pvec.ctxpvec(cb)
2234 if pa == pb:
2234 if pa == pb:
2235 rel = "="
2235 rel = "="
2236 elif pa > pb:
2236 elif pa > pb:
2237 rel = ">"
2237 rel = ">"
2238 elif pa < pb:
2238 elif pa < pb:
2239 rel = "<"
2239 rel = "<"
2240 elif pa | pb:
2240 elif pa | pb:
2241 rel = "|"
2241 rel = "|"
2242 ui.write(_("a: %s\n") % pa)
2242 ui.write(_("a: %s\n") % pa)
2243 ui.write(_("b: %s\n") % pb)
2243 ui.write(_("b: %s\n") % pb)
2244 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2244 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2245 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2245 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2246 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2246 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2247 pa.distance(pb), rel))
2247 pa.distance(pb), rel))
2248
2248
2249 @command('debugrebuilddirstate|debugrebuildstate',
2249 @command('debugrebuilddirstate|debugrebuildstate',
2250 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2250 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2251 _('[-r REV]'))
2251 _('[-r REV]'))
2252 def debugrebuilddirstate(ui, repo, rev):
2252 def debugrebuilddirstate(ui, repo, rev):
2253 """rebuild the dirstate as it would look like for the given revision
2253 """rebuild the dirstate as it would look like for the given revision
2254
2254
2255 If no revision is specified the first current parent will be used.
2255 If no revision is specified the first current parent will be used.
2256
2256
2257 The dirstate will be set to the files of the given revision.
2257 The dirstate will be set to the files of the given revision.
2258 The actual working directory content or existing dirstate
2258 The actual working directory content or existing dirstate
2259 information such as adds or removes is not considered.
2259 information such as adds or removes is not considered.
2260
2260
2261 One use of this command is to make the next :hg:`status` invocation
2261 One use of this command is to make the next :hg:`status` invocation
2262 check the actual file content.
2262 check the actual file content.
2263 """
2263 """
2264 ctx = scmutil.revsingle(repo, rev)
2264 ctx = scmutil.revsingle(repo, rev)
2265 wlock = repo.wlock()
2265 wlock = repo.wlock()
2266 try:
2266 try:
2267 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2267 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2268 finally:
2268 finally:
2269 wlock.release()
2269 wlock.release()
2270
2270
2271 @command('debugrename',
2271 @command('debugrename',
2272 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2272 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2273 _('[-r REV] FILE'))
2273 _('[-r REV] FILE'))
2274 def debugrename(ui, repo, file1, *pats, **opts):
2274 def debugrename(ui, repo, file1, *pats, **opts):
2275 """dump rename information"""
2275 """dump rename information"""
2276
2276
2277 ctx = scmutil.revsingle(repo, opts.get('rev'))
2277 ctx = scmutil.revsingle(repo, opts.get('rev'))
2278 m = scmutil.match(ctx, (file1,) + pats, opts)
2278 m = scmutil.match(ctx, (file1,) + pats, opts)
2279 for abs in ctx.walk(m):
2279 for abs in ctx.walk(m):
2280 fctx = ctx[abs]
2280 fctx = ctx[abs]
2281 o = fctx.filelog().renamed(fctx.filenode())
2281 o = fctx.filelog().renamed(fctx.filenode())
2282 rel = m.rel(abs)
2282 rel = m.rel(abs)
2283 if o:
2283 if o:
2284 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2284 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2285 else:
2285 else:
2286 ui.write(_("%s not renamed\n") % rel)
2286 ui.write(_("%s not renamed\n") % rel)
2287
2287
2288 @command('debugrevlog',
2288 @command('debugrevlog',
2289 [('c', 'changelog', False, _('open changelog')),
2289 [('c', 'changelog', False, _('open changelog')),
2290 ('m', 'manifest', False, _('open manifest')),
2290 ('m', 'manifest', False, _('open manifest')),
2291 ('d', 'dump', False, _('dump index data'))],
2291 ('d', 'dump', False, _('dump index data'))],
2292 _('-c|-m|FILE'))
2292 _('-c|-m|FILE'))
2293 def debugrevlog(ui, repo, file_ = None, **opts):
2293 def debugrevlog(ui, repo, file_ = None, **opts):
2294 """show data and statistics about a revlog"""
2294 """show data and statistics about a revlog"""
2295 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2295 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2296
2296
2297 if opts.get("dump"):
2297 if opts.get("dump"):
2298 numrevs = len(r)
2298 numrevs = len(r)
2299 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2299 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2300 " rawsize totalsize compression heads\n")
2300 " rawsize totalsize compression heads\n")
2301 ts = 0
2301 ts = 0
2302 heads = set()
2302 heads = set()
2303 for rev in xrange(numrevs):
2303 for rev in xrange(numrevs):
2304 dbase = r.deltaparent(rev)
2304 dbase = r.deltaparent(rev)
2305 if dbase == -1:
2305 if dbase == -1:
2306 dbase = rev
2306 dbase = rev
2307 cbase = r.chainbase(rev)
2307 cbase = r.chainbase(rev)
2308 p1, p2 = r.parentrevs(rev)
2308 p1, p2 = r.parentrevs(rev)
2309 rs = r.rawsize(rev)
2309 rs = r.rawsize(rev)
2310 ts = ts + rs
2310 ts = ts + rs
2311 heads -= set(r.parentrevs(rev))
2311 heads -= set(r.parentrevs(rev))
2312 heads.add(rev)
2312 heads.add(rev)
2313 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2313 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2314 (rev, p1, p2, r.start(rev), r.end(rev),
2314 (rev, p1, p2, r.start(rev), r.end(rev),
2315 r.start(dbase), r.start(cbase),
2315 r.start(dbase), r.start(cbase),
2316 r.start(p1), r.start(p2),
2316 r.start(p1), r.start(p2),
2317 rs, ts, ts / r.end(rev), len(heads)))
2317 rs, ts, ts / r.end(rev), len(heads)))
2318 return 0
2318 return 0
2319
2319
2320 v = r.version
2320 v = r.version
2321 format = v & 0xFFFF
2321 format = v & 0xFFFF
2322 flags = []
2322 flags = []
2323 gdelta = False
2323 gdelta = False
2324 if v & revlog.REVLOGNGINLINEDATA:
2324 if v & revlog.REVLOGNGINLINEDATA:
2325 flags.append('inline')
2325 flags.append('inline')
2326 if v & revlog.REVLOGGENERALDELTA:
2326 if v & revlog.REVLOGGENERALDELTA:
2327 gdelta = True
2327 gdelta = True
2328 flags.append('generaldelta')
2328 flags.append('generaldelta')
2329 if not flags:
2329 if not flags:
2330 flags = ['(none)']
2330 flags = ['(none)']
2331
2331
2332 nummerges = 0
2332 nummerges = 0
2333 numfull = 0
2333 numfull = 0
2334 numprev = 0
2334 numprev = 0
2335 nump1 = 0
2335 nump1 = 0
2336 nump2 = 0
2336 nump2 = 0
2337 numother = 0
2337 numother = 0
2338 nump1prev = 0
2338 nump1prev = 0
2339 nump2prev = 0
2339 nump2prev = 0
2340 chainlengths = []
2340 chainlengths = []
2341
2341
2342 datasize = [None, 0, 0L]
2342 datasize = [None, 0, 0L]
2343 fullsize = [None, 0, 0L]
2343 fullsize = [None, 0, 0L]
2344 deltasize = [None, 0, 0L]
2344 deltasize = [None, 0, 0L]
2345
2345
2346 def addsize(size, l):
2346 def addsize(size, l):
2347 if l[0] is None or size < l[0]:
2347 if l[0] is None or size < l[0]:
2348 l[0] = size
2348 l[0] = size
2349 if size > l[1]:
2349 if size > l[1]:
2350 l[1] = size
2350 l[1] = size
2351 l[2] += size
2351 l[2] += size
2352
2352
2353 numrevs = len(r)
2353 numrevs = len(r)
2354 for rev in xrange(numrevs):
2354 for rev in xrange(numrevs):
2355 p1, p2 = r.parentrevs(rev)
2355 p1, p2 = r.parentrevs(rev)
2356 delta = r.deltaparent(rev)
2356 delta = r.deltaparent(rev)
2357 if format > 0:
2357 if format > 0:
2358 addsize(r.rawsize(rev), datasize)
2358 addsize(r.rawsize(rev), datasize)
2359 if p2 != nullrev:
2359 if p2 != nullrev:
2360 nummerges += 1
2360 nummerges += 1
2361 size = r.length(rev)
2361 size = r.length(rev)
2362 if delta == nullrev:
2362 if delta == nullrev:
2363 chainlengths.append(0)
2363 chainlengths.append(0)
2364 numfull += 1
2364 numfull += 1
2365 addsize(size, fullsize)
2365 addsize(size, fullsize)
2366 else:
2366 else:
2367 chainlengths.append(chainlengths[delta] + 1)
2367 chainlengths.append(chainlengths[delta] + 1)
2368 addsize(size, deltasize)
2368 addsize(size, deltasize)
2369 if delta == rev - 1:
2369 if delta == rev - 1:
2370 numprev += 1
2370 numprev += 1
2371 if delta == p1:
2371 if delta == p1:
2372 nump1prev += 1
2372 nump1prev += 1
2373 elif delta == p2:
2373 elif delta == p2:
2374 nump2prev += 1
2374 nump2prev += 1
2375 elif delta == p1:
2375 elif delta == p1:
2376 nump1 += 1
2376 nump1 += 1
2377 elif delta == p2:
2377 elif delta == p2:
2378 nump2 += 1
2378 nump2 += 1
2379 elif delta != nullrev:
2379 elif delta != nullrev:
2380 numother += 1
2380 numother += 1
2381
2381
2382 # Adjust size min value for empty cases
2382 # Adjust size min value for empty cases
2383 for size in (datasize, fullsize, deltasize):
2383 for size in (datasize, fullsize, deltasize):
2384 if size[0] is None:
2384 if size[0] is None:
2385 size[0] = 0
2385 size[0] = 0
2386
2386
2387 numdeltas = numrevs - numfull
2387 numdeltas = numrevs - numfull
2388 numoprev = numprev - nump1prev - nump2prev
2388 numoprev = numprev - nump1prev - nump2prev
2389 totalrawsize = datasize[2]
2389 totalrawsize = datasize[2]
2390 datasize[2] /= numrevs
2390 datasize[2] /= numrevs
2391 fulltotal = fullsize[2]
2391 fulltotal = fullsize[2]
2392 fullsize[2] /= numfull
2392 fullsize[2] /= numfull
2393 deltatotal = deltasize[2]
2393 deltatotal = deltasize[2]
2394 if numrevs - numfull > 0:
2394 if numrevs - numfull > 0:
2395 deltasize[2] /= numrevs - numfull
2395 deltasize[2] /= numrevs - numfull
2396 totalsize = fulltotal + deltatotal
2396 totalsize = fulltotal + deltatotal
2397 avgchainlen = sum(chainlengths) / numrevs
2397 avgchainlen = sum(chainlengths) / numrevs
2398 compratio = totalrawsize / totalsize
2398 compratio = totalrawsize / totalsize
2399
2399
2400 basedfmtstr = '%%%dd\n'
2400 basedfmtstr = '%%%dd\n'
2401 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2401 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2402
2402
2403 def dfmtstr(max):
2403 def dfmtstr(max):
2404 return basedfmtstr % len(str(max))
2404 return basedfmtstr % len(str(max))
2405 def pcfmtstr(max, padding=0):
2405 def pcfmtstr(max, padding=0):
2406 return basepcfmtstr % (len(str(max)), ' ' * padding)
2406 return basepcfmtstr % (len(str(max)), ' ' * padding)
2407
2407
2408 def pcfmt(value, total):
2408 def pcfmt(value, total):
2409 return (value, 100 * float(value) / total)
2409 return (value, 100 * float(value) / total)
2410
2410
2411 ui.write(('format : %d\n') % format)
2411 ui.write(('format : %d\n') % format)
2412 ui.write(('flags : %s\n') % ', '.join(flags))
2412 ui.write(('flags : %s\n') % ', '.join(flags))
2413
2413
2414 ui.write('\n')
2414 ui.write('\n')
2415 fmt = pcfmtstr(totalsize)
2415 fmt = pcfmtstr(totalsize)
2416 fmt2 = dfmtstr(totalsize)
2416 fmt2 = dfmtstr(totalsize)
2417 ui.write(('revisions : ') + fmt2 % numrevs)
2417 ui.write(('revisions : ') + fmt2 % numrevs)
2418 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2418 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2419 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2419 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2420 ui.write(('revisions : ') + fmt2 % numrevs)
2420 ui.write(('revisions : ') + fmt2 % numrevs)
2421 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2421 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2422 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2422 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2423 ui.write(('revision size : ') + fmt2 % totalsize)
2423 ui.write(('revision size : ') + fmt2 % totalsize)
2424 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2424 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2425 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2425 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2426
2426
2427 ui.write('\n')
2427 ui.write('\n')
2428 fmt = dfmtstr(max(avgchainlen, compratio))
2428 fmt = dfmtstr(max(avgchainlen, compratio))
2429 ui.write(('avg chain length : ') + fmt % avgchainlen)
2429 ui.write(('avg chain length : ') + fmt % avgchainlen)
2430 ui.write(('compression ratio : ') + fmt % compratio)
2430 ui.write(('compression ratio : ') + fmt % compratio)
2431
2431
2432 if format > 0:
2432 if format > 0:
2433 ui.write('\n')
2433 ui.write('\n')
2434 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2434 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2435 % tuple(datasize))
2435 % tuple(datasize))
2436 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2436 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2437 % tuple(fullsize))
2437 % tuple(fullsize))
2438 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2438 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2439 % tuple(deltasize))
2439 % tuple(deltasize))
2440
2440
2441 if numdeltas > 0:
2441 if numdeltas > 0:
2442 ui.write('\n')
2442 ui.write('\n')
2443 fmt = pcfmtstr(numdeltas)
2443 fmt = pcfmtstr(numdeltas)
2444 fmt2 = pcfmtstr(numdeltas, 4)
2444 fmt2 = pcfmtstr(numdeltas, 4)
2445 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2445 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2446 if numprev > 0:
2446 if numprev > 0:
2447 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2447 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2448 numprev))
2448 numprev))
2449 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2449 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2450 numprev))
2450 numprev))
2451 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2451 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2452 numprev))
2452 numprev))
2453 if gdelta:
2453 if gdelta:
2454 ui.write(('deltas against p1 : ')
2454 ui.write(('deltas against p1 : ')
2455 + fmt % pcfmt(nump1, numdeltas))
2455 + fmt % pcfmt(nump1, numdeltas))
2456 ui.write(('deltas against p2 : ')
2456 ui.write(('deltas against p2 : ')
2457 + fmt % pcfmt(nump2, numdeltas))
2457 + fmt % pcfmt(nump2, numdeltas))
2458 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2458 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2459 numdeltas))
2459 numdeltas))
2460
2460
2461 @command('debugrevspec', [], ('REVSPEC'))
2461 @command('debugrevspec', [], ('REVSPEC'))
2462 def debugrevspec(ui, repo, expr):
2462 def debugrevspec(ui, repo, expr):
2463 """parse and apply a revision specification
2463 """parse and apply a revision specification
2464
2464
2465 Use --verbose to print the parsed tree before and after aliases
2465 Use --verbose to print the parsed tree before and after aliases
2466 expansion.
2466 expansion.
2467 """
2467 """
2468 if ui.verbose:
2468 if ui.verbose:
2469 tree = revset.parse(expr)[0]
2469 tree = revset.parse(expr)[0]
2470 ui.note(revset.prettyformat(tree), "\n")
2470 ui.note(revset.prettyformat(tree), "\n")
2471 newtree = revset.findaliases(ui, tree)
2471 newtree = revset.findaliases(ui, tree)
2472 if newtree != tree:
2472 if newtree != tree:
2473 ui.note(revset.prettyformat(newtree), "\n")
2473 ui.note(revset.prettyformat(newtree), "\n")
2474 func = revset.match(ui, expr)
2474 func = revset.match(ui, expr)
2475 for c in func(repo, range(len(repo))):
2475 for c in func(repo, range(len(repo))):
2476 ui.write("%s\n" % c)
2476 ui.write("%s\n" % c)
2477
2477
2478 @command('debugsetparents', [], _('REV1 [REV2]'))
2478 @command('debugsetparents', [], _('REV1 [REV2]'))
2479 def debugsetparents(ui, repo, rev1, rev2=None):
2479 def debugsetparents(ui, repo, rev1, rev2=None):
2480 """manually set the parents of the current working directory
2480 """manually set the parents of the current working directory
2481
2481
2482 This is useful for writing repository conversion tools, but should
2482 This is useful for writing repository conversion tools, but should
2483 be used with care.
2483 be used with care.
2484
2484
2485 Returns 0 on success.
2485 Returns 0 on success.
2486 """
2486 """
2487
2487
2488 r1 = scmutil.revsingle(repo, rev1).node()
2488 r1 = scmutil.revsingle(repo, rev1).node()
2489 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2489 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2490
2490
2491 wlock = repo.wlock()
2491 wlock = repo.wlock()
2492 try:
2492 try:
2493 repo.setparents(r1, r2)
2493 repo.setparents(r1, r2)
2494 finally:
2494 finally:
2495 wlock.release()
2495 wlock.release()
2496
2496
2497 @command('debugdirstate|debugstate',
2497 @command('debugdirstate|debugstate',
2498 [('', 'nodates', None, _('do not display the saved mtime')),
2498 [('', 'nodates', None, _('do not display the saved mtime')),
2499 ('', 'datesort', None, _('sort by saved mtime'))],
2499 ('', 'datesort', None, _('sort by saved mtime'))],
2500 _('[OPTION]...'))
2500 _('[OPTION]...'))
2501 def debugstate(ui, repo, nodates=None, datesort=None):
2501 def debugstate(ui, repo, nodates=None, datesort=None):
2502 """show the contents of the current dirstate"""
2502 """show the contents of the current dirstate"""
2503 timestr = ""
2503 timestr = ""
2504 showdate = not nodates
2504 showdate = not nodates
2505 if datesort:
2505 if datesort:
2506 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2506 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2507 else:
2507 else:
2508 keyfunc = None # sort by filename
2508 keyfunc = None # sort by filename
2509 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2509 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2510 if showdate:
2510 if showdate:
2511 if ent[3] == -1:
2511 if ent[3] == -1:
2512 # Pad or slice to locale representation
2512 # Pad or slice to locale representation
2513 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2513 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2514 time.localtime(0)))
2514 time.localtime(0)))
2515 timestr = 'unset'
2515 timestr = 'unset'
2516 timestr = (timestr[:locale_len] +
2516 timestr = (timestr[:locale_len] +
2517 ' ' * (locale_len - len(timestr)))
2517 ' ' * (locale_len - len(timestr)))
2518 else:
2518 else:
2519 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2519 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2520 time.localtime(ent[3]))
2520 time.localtime(ent[3]))
2521 if ent[1] & 020000:
2521 if ent[1] & 020000:
2522 mode = 'lnk'
2522 mode = 'lnk'
2523 else:
2523 else:
2524 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2524 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2525 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2525 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2526 for f in repo.dirstate.copies():
2526 for f in repo.dirstate.copies():
2527 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2527 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2528
2528
2529 @command('debugsub',
2529 @command('debugsub',
2530 [('r', 'rev', '',
2530 [('r', 'rev', '',
2531 _('revision to check'), _('REV'))],
2531 _('revision to check'), _('REV'))],
2532 _('[-r REV] [REV]'))
2532 _('[-r REV] [REV]'))
2533 def debugsub(ui, repo, rev=None):
2533 def debugsub(ui, repo, rev=None):
2534 ctx = scmutil.revsingle(repo, rev, None)
2534 ctx = scmutil.revsingle(repo, rev, None)
2535 for k, v in sorted(ctx.substate.items()):
2535 for k, v in sorted(ctx.substate.items()):
2536 ui.write(('path %s\n') % k)
2536 ui.write(('path %s\n') % k)
2537 ui.write((' source %s\n') % v[0])
2537 ui.write((' source %s\n') % v[0])
2538 ui.write((' revision %s\n') % v[1])
2538 ui.write((' revision %s\n') % v[1])
2539
2539
2540 @command('debugsuccessorssets',
2540 @command('debugsuccessorssets',
2541 [],
2541 [],
2542 _('[REV]'))
2542 _('[REV]'))
2543 def debugsuccessorssets(ui, repo, *revs):
2543 def debugsuccessorssets(ui, repo, *revs):
2544 """show set of successors for revision
2544 """show set of successors for revision
2545
2545
2546 A successors set of changeset A is a consistent group of revisions that
2546 A successors set of changeset A is a consistent group of revisions that
2547 succeed A. It contains non-obsolete changesets only.
2547 succeed A. It contains non-obsolete changesets only.
2548
2548
2549 In most cases a changeset A has a single successors set containing a single
2549 In most cases a changeset A has a single successors set containing a single
2550 successor (changeset A replaced by A').
2550 successor (changeset A replaced by A').
2551
2551
2552 A changeset that is made obsolete with no successors are called "pruned".
2552 A changeset that is made obsolete with no successors are called "pruned".
2553 Such changesets have no successors sets at all.
2553 Such changesets have no successors sets at all.
2554
2554
2555 A changeset that has been "split" will have a successors set containing
2555 A changeset that has been "split" will have a successors set containing
2556 more than one successor.
2556 more than one successor.
2557
2557
2558 A changeset that has been rewritten in multiple different ways is called
2558 A changeset that has been rewritten in multiple different ways is called
2559 "divergent". Such changesets have multiple successor sets (each of which
2559 "divergent". Such changesets have multiple successor sets (each of which
2560 may also be split, i.e. have multiple successors).
2560 may also be split, i.e. have multiple successors).
2561
2561
2562 Results are displayed as follows::
2562 Results are displayed as follows::
2563
2563
2564 <rev1>
2564 <rev1>
2565 <successors-1A>
2565 <successors-1A>
2566 <rev2>
2566 <rev2>
2567 <successors-2A>
2567 <successors-2A>
2568 <successors-2B1> <successors-2B2> <successors-2B3>
2568 <successors-2B1> <successors-2B2> <successors-2B3>
2569
2569
2570 Here rev2 has two possible (i.e. divergent) successors sets. The first
2570 Here rev2 has two possible (i.e. divergent) successors sets. The first
2571 holds one element, whereas the second holds three (i.e. the changeset has
2571 holds one element, whereas the second holds three (i.e. the changeset has
2572 been split).
2572 been split).
2573 """
2573 """
2574 # passed to successorssets caching computation from one call to another
2574 # passed to successorssets caching computation from one call to another
2575 cache = {}
2575 cache = {}
2576 ctx2str = str
2576 ctx2str = str
2577 node2str = short
2577 node2str = short
2578 if ui.debug():
2578 if ui.debug():
2579 def ctx2str(ctx):
2579 def ctx2str(ctx):
2580 return ctx.hex()
2580 return ctx.hex()
2581 node2str = hex
2581 node2str = hex
2582 for rev in scmutil.revrange(repo, revs):
2582 for rev in scmutil.revrange(repo, revs):
2583 ctx = repo[rev]
2583 ctx = repo[rev]
2584 ui.write('%s\n'% ctx2str(ctx))
2584 ui.write('%s\n'% ctx2str(ctx))
2585 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2585 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2586 if succsset:
2586 if succsset:
2587 ui.write(' ')
2587 ui.write(' ')
2588 ui.write(node2str(succsset[0]))
2588 ui.write(node2str(succsset[0]))
2589 for node in succsset[1:]:
2589 for node in succsset[1:]:
2590 ui.write(' ')
2590 ui.write(' ')
2591 ui.write(node2str(node))
2591 ui.write(node2str(node))
2592 ui.write('\n')
2592 ui.write('\n')
2593
2593
2594 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2594 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2595 def debugwalk(ui, repo, *pats, **opts):
2595 def debugwalk(ui, repo, *pats, **opts):
2596 """show how files match on given patterns"""
2596 """show how files match on given patterns"""
2597 m = scmutil.match(repo[None], pats, opts)
2597 m = scmutil.match(repo[None], pats, opts)
2598 items = list(repo.walk(m))
2598 items = list(repo.walk(m))
2599 if not items:
2599 if not items:
2600 return
2600 return
2601 f = lambda fn: fn
2601 f = lambda fn: fn
2602 if ui.configbool('ui', 'slash') and os.sep != '/':
2602 if ui.configbool('ui', 'slash') and os.sep != '/':
2603 f = lambda fn: util.normpath(fn)
2603 f = lambda fn: util.normpath(fn)
2604 fmt = 'f %%-%ds %%-%ds %%s' % (
2604 fmt = 'f %%-%ds %%-%ds %%s' % (
2605 max([len(abs) for abs in items]),
2605 max([len(abs) for abs in items]),
2606 max([len(m.rel(abs)) for abs in items]))
2606 max([len(m.rel(abs)) for abs in items]))
2607 for abs in items:
2607 for abs in items:
2608 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2608 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2609 ui.write("%s\n" % line.rstrip())
2609 ui.write("%s\n" % line.rstrip())
2610
2610
2611 @command('debugwireargs',
2611 @command('debugwireargs',
2612 [('', 'three', '', 'three'),
2612 [('', 'three', '', 'three'),
2613 ('', 'four', '', 'four'),
2613 ('', 'four', '', 'four'),
2614 ('', 'five', '', 'five'),
2614 ('', 'five', '', 'five'),
2615 ] + remoteopts,
2615 ] + remoteopts,
2616 _('REPO [OPTIONS]... [ONE [TWO]]'))
2616 _('REPO [OPTIONS]... [ONE [TWO]]'))
2617 def debugwireargs(ui, repopath, *vals, **opts):
2617 def debugwireargs(ui, repopath, *vals, **opts):
2618 repo = hg.peer(ui, opts, repopath)
2618 repo = hg.peer(ui, opts, repopath)
2619 for opt in remoteopts:
2619 for opt in remoteopts:
2620 del opts[opt[1]]
2620 del opts[opt[1]]
2621 args = {}
2621 args = {}
2622 for k, v in opts.iteritems():
2622 for k, v in opts.iteritems():
2623 if v:
2623 if v:
2624 args[k] = v
2624 args[k] = v
2625 # run twice to check that we don't mess up the stream for the next command
2625 # run twice to check that we don't mess up the stream for the next command
2626 res1 = repo.debugwireargs(*vals, **args)
2626 res1 = repo.debugwireargs(*vals, **args)
2627 res2 = repo.debugwireargs(*vals, **args)
2627 res2 = repo.debugwireargs(*vals, **args)
2628 ui.write("%s\n" % res1)
2628 ui.write("%s\n" % res1)
2629 if res1 != res2:
2629 if res1 != res2:
2630 ui.warn("%s\n" % res2)
2630 ui.warn("%s\n" % res2)
2631
2631
2632 @command('^diff',
2632 @command('^diff',
2633 [('r', 'rev', [], _('revision'), _('REV')),
2633 [('r', 'rev', [], _('revision'), _('REV')),
2634 ('c', 'change', '', _('change made by revision'), _('REV'))
2634 ('c', 'change', '', _('change made by revision'), _('REV'))
2635 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2635 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2636 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2636 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2637 def diff(ui, repo, *pats, **opts):
2637 def diff(ui, repo, *pats, **opts):
2638 """diff repository (or selected files)
2638 """diff repository (or selected files)
2639
2639
2640 Show differences between revisions for the specified files.
2640 Show differences between revisions for the specified files.
2641
2641
2642 Differences between files are shown using the unified diff format.
2642 Differences between files are shown using the unified diff format.
2643
2643
2644 .. note::
2644 .. note::
2645 diff may generate unexpected results for merges, as it will
2645 diff may generate unexpected results for merges, as it will
2646 default to comparing against the working directory's first
2646 default to comparing against the working directory's first
2647 parent changeset if no revisions are specified.
2647 parent changeset if no revisions are specified.
2648
2648
2649 When two revision arguments are given, then changes are shown
2649 When two revision arguments are given, then changes are shown
2650 between those revisions. If only one revision is specified then
2650 between those revisions. If only one revision is specified then
2651 that revision is compared to the working directory, and, when no
2651 that revision is compared to the working directory, and, when no
2652 revisions are specified, the working directory files are compared
2652 revisions are specified, the working directory files are compared
2653 to its parent.
2653 to its parent.
2654
2654
2655 Alternatively you can specify -c/--change with a revision to see
2655 Alternatively you can specify -c/--change with a revision to see
2656 the changes in that changeset relative to its first parent.
2656 the changes in that changeset relative to its first parent.
2657
2657
2658 Without the -a/--text option, diff will avoid generating diffs of
2658 Without the -a/--text option, diff will avoid generating diffs of
2659 files it detects as binary. With -a, diff will generate a diff
2659 files it detects as binary. With -a, diff will generate a diff
2660 anyway, probably with undesirable results.
2660 anyway, probably with undesirable results.
2661
2661
2662 Use the -g/--git option to generate diffs in the git extended diff
2662 Use the -g/--git option to generate diffs in the git extended diff
2663 format. For more information, read :hg:`help diffs`.
2663 format. For more information, read :hg:`help diffs`.
2664
2664
2665 .. container:: verbose
2665 .. container:: verbose
2666
2666
2667 Examples:
2667 Examples:
2668
2668
2669 - compare a file in the current working directory to its parent::
2669 - compare a file in the current working directory to its parent::
2670
2670
2671 hg diff foo.c
2671 hg diff foo.c
2672
2672
2673 - compare two historical versions of a directory, with rename info::
2673 - compare two historical versions of a directory, with rename info::
2674
2674
2675 hg diff --git -r 1.0:1.2 lib/
2675 hg diff --git -r 1.0:1.2 lib/
2676
2676
2677 - get change stats relative to the last change on some date::
2677 - get change stats relative to the last change on some date::
2678
2678
2679 hg diff --stat -r "date('may 2')"
2679 hg diff --stat -r "date('may 2')"
2680
2680
2681 - diff all newly-added files that contain a keyword::
2681 - diff all newly-added files that contain a keyword::
2682
2682
2683 hg diff "set:added() and grep(GNU)"
2683 hg diff "set:added() and grep(GNU)"
2684
2684
2685 - compare a revision and its parents::
2685 - compare a revision and its parents::
2686
2686
2687 hg diff -c 9353 # compare against first parent
2687 hg diff -c 9353 # compare against first parent
2688 hg diff -r 9353^:9353 # same using revset syntax
2688 hg diff -r 9353^:9353 # same using revset syntax
2689 hg diff -r 9353^2:9353 # compare against the second parent
2689 hg diff -r 9353^2:9353 # compare against the second parent
2690
2690
2691 Returns 0 on success.
2691 Returns 0 on success.
2692 """
2692 """
2693
2693
2694 revs = opts.get('rev')
2694 revs = opts.get('rev')
2695 change = opts.get('change')
2695 change = opts.get('change')
2696 stat = opts.get('stat')
2696 stat = opts.get('stat')
2697 reverse = opts.get('reverse')
2697 reverse = opts.get('reverse')
2698
2698
2699 if revs and change:
2699 if revs and change:
2700 msg = _('cannot specify --rev and --change at the same time')
2700 msg = _('cannot specify --rev and --change at the same time')
2701 raise util.Abort(msg)
2701 raise util.Abort(msg)
2702 elif change:
2702 elif change:
2703 node2 = scmutil.revsingle(repo, change, None).node()
2703 node2 = scmutil.revsingle(repo, change, None).node()
2704 node1 = repo[node2].p1().node()
2704 node1 = repo[node2].p1().node()
2705 else:
2705 else:
2706 node1, node2 = scmutil.revpair(repo, revs)
2706 node1, node2 = scmutil.revpair(repo, revs)
2707
2707
2708 if reverse:
2708 if reverse:
2709 node1, node2 = node2, node1
2709 node1, node2 = node2, node1
2710
2710
2711 diffopts = patch.diffopts(ui, opts)
2711 diffopts = patch.diffopts(ui, opts)
2712 m = scmutil.match(repo[node2], pats, opts)
2712 m = scmutil.match(repo[node2], pats, opts)
2713 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2713 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2714 listsubrepos=opts.get('subrepos'))
2714 listsubrepos=opts.get('subrepos'))
2715
2715
2716 @command('^export',
2716 @command('^export',
2717 [('o', 'output', '',
2717 [('o', 'output', '',
2718 _('print output to file with formatted name'), _('FORMAT')),
2718 _('print output to file with formatted name'), _('FORMAT')),
2719 ('', 'switch-parent', None, _('diff against the second parent')),
2719 ('', 'switch-parent', None, _('diff against the second parent')),
2720 ('r', 'rev', [], _('revisions to export'), _('REV')),
2720 ('r', 'rev', [], _('revisions to export'), _('REV')),
2721 ] + diffopts,
2721 ] + diffopts,
2722 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2722 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2723 def export(ui, repo, *changesets, **opts):
2723 def export(ui, repo, *changesets, **opts):
2724 """dump the header and diffs for one or more changesets
2724 """dump the header and diffs for one or more changesets
2725
2725
2726 Print the changeset header and diffs for one or more revisions.
2726 Print the changeset header and diffs for one or more revisions.
2727 If no revision is given, the parent of the working directory is used.
2727 If no revision is given, the parent of the working directory is used.
2728
2728
2729 The information shown in the changeset header is: author, date,
2729 The information shown in the changeset header is: author, date,
2730 branch name (if non-default), changeset hash, parent(s) and commit
2730 branch name (if non-default), changeset hash, parent(s) and commit
2731 comment.
2731 comment.
2732
2732
2733 .. note::
2733 .. note::
2734 export may generate unexpected diff output for merge
2734 export may generate unexpected diff output for merge
2735 changesets, as it will compare the merge changeset against its
2735 changesets, as it will compare the merge changeset against its
2736 first parent only.
2736 first parent only.
2737
2737
2738 Output may be to a file, in which case the name of the file is
2738 Output may be to a file, in which case the name of the file is
2739 given using a format string. The formatting rules are as follows:
2739 given using a format string. The formatting rules are as follows:
2740
2740
2741 :``%%``: literal "%" character
2741 :``%%``: literal "%" character
2742 :``%H``: changeset hash (40 hexadecimal digits)
2742 :``%H``: changeset hash (40 hexadecimal digits)
2743 :``%N``: number of patches being generated
2743 :``%N``: number of patches being generated
2744 :``%R``: changeset revision number
2744 :``%R``: changeset revision number
2745 :``%b``: basename of the exporting repository
2745 :``%b``: basename of the exporting repository
2746 :``%h``: short-form changeset hash (12 hexadecimal digits)
2746 :``%h``: short-form changeset hash (12 hexadecimal digits)
2747 :``%m``: first line of the commit message (only alphanumeric characters)
2747 :``%m``: first line of the commit message (only alphanumeric characters)
2748 :``%n``: zero-padded sequence number, starting at 1
2748 :``%n``: zero-padded sequence number, starting at 1
2749 :``%r``: zero-padded changeset revision number
2749 :``%r``: zero-padded changeset revision number
2750
2750
2751 Without the -a/--text option, export will avoid generating diffs
2751 Without the -a/--text option, export will avoid generating diffs
2752 of files it detects as binary. With -a, export will generate a
2752 of files it detects as binary. With -a, export will generate a
2753 diff anyway, probably with undesirable results.
2753 diff anyway, probably with undesirable results.
2754
2754
2755 Use the -g/--git option to generate diffs in the git extended diff
2755 Use the -g/--git option to generate diffs in the git extended diff
2756 format. See :hg:`help diffs` for more information.
2756 format. See :hg:`help diffs` for more information.
2757
2757
2758 With the --switch-parent option, the diff will be against the
2758 With the --switch-parent option, the diff will be against the
2759 second parent. It can be useful to review a merge.
2759 second parent. It can be useful to review a merge.
2760
2760
2761 .. container:: verbose
2761 .. container:: verbose
2762
2762
2763 Examples:
2763 Examples:
2764
2764
2765 - use export and import to transplant a bugfix to the current
2765 - use export and import to transplant a bugfix to the current
2766 branch::
2766 branch::
2767
2767
2768 hg export -r 9353 | hg import -
2768 hg export -r 9353 | hg import -
2769
2769
2770 - export all the changesets between two revisions to a file with
2770 - export all the changesets between two revisions to a file with
2771 rename information::
2771 rename information::
2772
2772
2773 hg export --git -r 123:150 > changes.txt
2773 hg export --git -r 123:150 > changes.txt
2774
2774
2775 - split outgoing changes into a series of patches with
2775 - split outgoing changes into a series of patches with
2776 descriptive names::
2776 descriptive names::
2777
2777
2778 hg export -r "outgoing()" -o "%n-%m.patch"
2778 hg export -r "outgoing()" -o "%n-%m.patch"
2779
2779
2780 Returns 0 on success.
2780 Returns 0 on success.
2781 """
2781 """
2782 changesets += tuple(opts.get('rev', []))
2782 changesets += tuple(opts.get('rev', []))
2783 if not changesets:
2783 if not changesets:
2784 changesets = ['.']
2784 changesets = ['.']
2785 revs = scmutil.revrange(repo, changesets)
2785 revs = scmutil.revrange(repo, changesets)
2786 if not revs:
2786 if not revs:
2787 raise util.Abort(_("export requires at least one changeset"))
2787 raise util.Abort(_("export requires at least one changeset"))
2788 if len(revs) > 1:
2788 if len(revs) > 1:
2789 ui.note(_('exporting patches:\n'))
2789 ui.note(_('exporting patches:\n'))
2790 else:
2790 else:
2791 ui.note(_('exporting patch:\n'))
2791 ui.note(_('exporting patch:\n'))
2792 cmdutil.export(repo, revs, template=opts.get('output'),
2792 cmdutil.export(repo, revs, template=opts.get('output'),
2793 switch_parent=opts.get('switch_parent'),
2793 switch_parent=opts.get('switch_parent'),
2794 opts=patch.diffopts(ui, opts))
2794 opts=patch.diffopts(ui, opts))
2795
2795
2796 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2796 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2797 def forget(ui, repo, *pats, **opts):
2797 def forget(ui, repo, *pats, **opts):
2798 """forget the specified files on the next commit
2798 """forget the specified files on the next commit
2799
2799
2800 Mark the specified files so they will no longer be tracked
2800 Mark the specified files so they will no longer be tracked
2801 after the next commit.
2801 after the next commit.
2802
2802
2803 This only removes files from the current branch, not from the
2803 This only removes files from the current branch, not from the
2804 entire project history, and it does not delete them from the
2804 entire project history, and it does not delete them from the
2805 working directory.
2805 working directory.
2806
2806
2807 To undo a forget before the next commit, see :hg:`add`.
2807 To undo a forget before the next commit, see :hg:`add`.
2808
2808
2809 .. container:: verbose
2809 .. container:: verbose
2810
2810
2811 Examples:
2811 Examples:
2812
2812
2813 - forget newly-added binary files::
2813 - forget newly-added binary files::
2814
2814
2815 hg forget "set:added() and binary()"
2815 hg forget "set:added() and binary()"
2816
2816
2817 - forget files that would be excluded by .hgignore::
2817 - forget files that would be excluded by .hgignore::
2818
2818
2819 hg forget "set:hgignore()"
2819 hg forget "set:hgignore()"
2820
2820
2821 Returns 0 on success.
2821 Returns 0 on success.
2822 """
2822 """
2823
2823
2824 if not pats:
2824 if not pats:
2825 raise util.Abort(_('no files specified'))
2825 raise util.Abort(_('no files specified'))
2826
2826
2827 m = scmutil.match(repo[None], pats, opts)
2827 m = scmutil.match(repo[None], pats, opts)
2828 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2828 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2829 return rejected and 1 or 0
2829 return rejected and 1 or 0
2830
2830
2831 @command(
2831 @command(
2832 'graft',
2832 'graft',
2833 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2833 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2834 ('c', 'continue', False, _('resume interrupted graft')),
2834 ('c', 'continue', False, _('resume interrupted graft')),
2835 ('e', 'edit', False, _('invoke editor on commit messages')),
2835 ('e', 'edit', False, _('invoke editor on commit messages')),
2836 ('', 'log', None, _('append graft info to log message')),
2836 ('', 'log', None, _('append graft info to log message')),
2837 ('D', 'currentdate', False,
2837 ('D', 'currentdate', False,
2838 _('record the current date as commit date')),
2838 _('record the current date as commit date')),
2839 ('U', 'currentuser', False,
2839 ('U', 'currentuser', False,
2840 _('record the current user as committer'), _('DATE'))]
2840 _('record the current user as committer'), _('DATE'))]
2841 + commitopts2 + mergetoolopts + dryrunopts,
2841 + commitopts2 + mergetoolopts + dryrunopts,
2842 _('[OPTION]... [-r] REV...'))
2842 _('[OPTION]... [-r] REV...'))
2843 def graft(ui, repo, *revs, **opts):
2843 def graft(ui, repo, *revs, **opts):
2844 '''copy changes from other branches onto the current branch
2844 '''copy changes from other branches onto the current branch
2845
2845
2846 This command uses Mercurial's merge logic to copy individual
2846 This command uses Mercurial's merge logic to copy individual
2847 changes from other branches without merging branches in the
2847 changes from other branches without merging branches in the
2848 history graph. This is sometimes known as 'backporting' or
2848 history graph. This is sometimes known as 'backporting' or
2849 'cherry-picking'. By default, graft will copy user, date, and
2849 'cherry-picking'. By default, graft will copy user, date, and
2850 description from the source changesets.
2850 description from the source changesets.
2851
2851
2852 Changesets that are ancestors of the current revision, that have
2852 Changesets that are ancestors of the current revision, that have
2853 already been grafted, or that are merges will be skipped.
2853 already been grafted, or that are merges will be skipped.
2854
2854
2855 If --log is specified, log messages will have a comment appended
2855 If --log is specified, log messages will have a comment appended
2856 of the form::
2856 of the form::
2857
2857
2858 (grafted from CHANGESETHASH)
2858 (grafted from CHANGESETHASH)
2859
2859
2860 If a graft merge results in conflicts, the graft process is
2860 If a graft merge results in conflicts, the graft process is
2861 interrupted so that the current merge can be manually resolved.
2861 interrupted so that the current merge can be manually resolved.
2862 Once all conflicts are addressed, the graft process can be
2862 Once all conflicts are addressed, the graft process can be
2863 continued with the -c/--continue option.
2863 continued with the -c/--continue option.
2864
2864
2865 .. note::
2865 .. note::
2866 The -c/--continue option does not reapply earlier options.
2866 The -c/--continue option does not reapply earlier options.
2867
2867
2868 .. container:: verbose
2868 .. container:: verbose
2869
2869
2870 Examples:
2870 Examples:
2871
2871
2872 - copy a single change to the stable branch and edit its description::
2872 - copy a single change to the stable branch and edit its description::
2873
2873
2874 hg update stable
2874 hg update stable
2875 hg graft --edit 9393
2875 hg graft --edit 9393
2876
2876
2877 - graft a range of changesets with one exception, updating dates::
2877 - graft a range of changesets with one exception, updating dates::
2878
2878
2879 hg graft -D "2085::2093 and not 2091"
2879 hg graft -D "2085::2093 and not 2091"
2880
2880
2881 - continue a graft after resolving conflicts::
2881 - continue a graft after resolving conflicts::
2882
2882
2883 hg graft -c
2883 hg graft -c
2884
2884
2885 - show the source of a grafted changeset::
2885 - show the source of a grafted changeset::
2886
2886
2887 hg log --debug -r tip
2887 hg log --debug -r tip
2888
2888
2889 Returns 0 on successful completion.
2889 Returns 0 on successful completion.
2890 '''
2890 '''
2891
2891
2892 revs = list(revs)
2892 revs = list(revs)
2893 revs.extend(opts['rev'])
2893 revs.extend(opts['rev'])
2894
2894
2895 if not opts.get('user') and opts.get('currentuser'):
2895 if not opts.get('user') and opts.get('currentuser'):
2896 opts['user'] = ui.username()
2896 opts['user'] = ui.username()
2897 if not opts.get('date') and opts.get('currentdate'):
2897 if not opts.get('date') and opts.get('currentdate'):
2898 opts['date'] = "%d %d" % util.makedate()
2898 opts['date'] = "%d %d" % util.makedate()
2899
2899
2900 editor = None
2900 editor = None
2901 if opts.get('edit'):
2901 if opts.get('edit'):
2902 editor = cmdutil.commitforceeditor
2902 editor = cmdutil.commitforceeditor
2903
2903
2904 cont = False
2904 cont = False
2905 if opts['continue']:
2905 if opts['continue']:
2906 cont = True
2906 cont = True
2907 if revs:
2907 if revs:
2908 raise util.Abort(_("can't specify --continue and revisions"))
2908 raise util.Abort(_("can't specify --continue and revisions"))
2909 # read in unfinished revisions
2909 # read in unfinished revisions
2910 try:
2910 try:
2911 nodes = repo.opener.read('graftstate').splitlines()
2911 nodes = repo.opener.read('graftstate').splitlines()
2912 revs = [repo[node].rev() for node in nodes]
2912 revs = [repo[node].rev() for node in nodes]
2913 except IOError, inst:
2913 except IOError, inst:
2914 if inst.errno != errno.ENOENT:
2914 if inst.errno != errno.ENOENT:
2915 raise
2915 raise
2916 raise util.Abort(_("no graft state found, can't continue"))
2916 raise util.Abort(_("no graft state found, can't continue"))
2917 else:
2917 else:
2918 cmdutil.bailifchanged(repo)
2918 cmdutil.bailifchanged(repo)
2919 if not revs:
2919 if not revs:
2920 raise util.Abort(_('no revisions specified'))
2920 raise util.Abort(_('no revisions specified'))
2921 revs = scmutil.revrange(repo, revs)
2921 revs = scmutil.revrange(repo, revs)
2922
2922
2923 # check for merges
2923 # check for merges
2924 for rev in repo.revs('%ld and merge()', revs):
2924 for rev in repo.revs('%ld and merge()', revs):
2925 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2925 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2926 revs.remove(rev)
2926 revs.remove(rev)
2927 if not revs:
2927 if not revs:
2928 return -1
2928 return -1
2929
2929
2930 # check for ancestors of dest branch
2930 # check for ancestors of dest branch
2931 crev = repo['.'].rev()
2931 crev = repo['.'].rev()
2932 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2932 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2933 # don't mutate while iterating, create a copy
2933 # don't mutate while iterating, create a copy
2934 for rev in list(revs):
2934 for rev in list(revs):
2935 if rev in ancestors:
2935 if rev in ancestors:
2936 ui.warn(_('skipping ancestor revision %s\n') % rev)
2936 ui.warn(_('skipping ancestor revision %s\n') % rev)
2937 revs.remove(rev)
2937 revs.remove(rev)
2938 if not revs:
2938 if not revs:
2939 return -1
2939 return -1
2940
2940
2941 # analyze revs for earlier grafts
2941 # analyze revs for earlier grafts
2942 ids = {}
2942 ids = {}
2943 for ctx in repo.set("%ld", revs):
2943 for ctx in repo.set("%ld", revs):
2944 ids[ctx.hex()] = ctx.rev()
2944 ids[ctx.hex()] = ctx.rev()
2945 n = ctx.extra().get('source')
2945 n = ctx.extra().get('source')
2946 if n:
2946 if n:
2947 ids[n] = ctx.rev()
2947 ids[n] = ctx.rev()
2948
2948
2949 # check ancestors for earlier grafts
2949 # check ancestors for earlier grafts
2950 ui.debug('scanning for duplicate grafts\n')
2950 ui.debug('scanning for duplicate grafts\n')
2951
2951
2952 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2952 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2953 ctx = repo[rev]
2953 ctx = repo[rev]
2954 n = ctx.extra().get('source')
2954 n = ctx.extra().get('source')
2955 if n in ids:
2955 if n in ids:
2956 r = repo[n].rev()
2956 r = repo[n].rev()
2957 if r in revs:
2957 if r in revs:
2958 ui.warn(_('skipping already grafted revision %s\n') % r)
2958 ui.warn(_('skipping already grafted revision %s\n') % r)
2959 revs.remove(r)
2959 revs.remove(r)
2960 elif ids[n] in revs:
2960 elif ids[n] in revs:
2961 ui.warn(_('skipping already grafted revision %s '
2961 ui.warn(_('skipping already grafted revision %s '
2962 '(same origin %d)\n') % (ids[n], r))
2962 '(same origin %d)\n') % (ids[n], r))
2963 revs.remove(ids[n])
2963 revs.remove(ids[n])
2964 elif ctx.hex() in ids:
2964 elif ctx.hex() in ids:
2965 r = ids[ctx.hex()]
2965 r = ids[ctx.hex()]
2966 ui.warn(_('skipping already grafted revision %s '
2966 ui.warn(_('skipping already grafted revision %s '
2967 '(was grafted from %d)\n') % (r, rev))
2967 '(was grafted from %d)\n') % (r, rev))
2968 revs.remove(r)
2968 revs.remove(r)
2969 if not revs:
2969 if not revs:
2970 return -1
2970 return -1
2971
2971
2972 wlock = repo.wlock()
2972 wlock = repo.wlock()
2973 try:
2973 try:
2974 current = repo['.']
2974 current = repo['.']
2975 for pos, ctx in enumerate(repo.set("%ld", revs)):
2975 for pos, ctx in enumerate(repo.set("%ld", revs)):
2976
2976
2977 ui.status(_('grafting revision %s\n') % ctx.rev())
2977 ui.status(_('grafting revision %s\n') % ctx.rev())
2978 if opts.get('dry_run'):
2978 if opts.get('dry_run'):
2979 continue
2979 continue
2980
2980
2981 source = ctx.extra().get('source')
2981 source = ctx.extra().get('source')
2982 if not source:
2982 if not source:
2983 source = ctx.hex()
2983 source = ctx.hex()
2984 extra = {'source': source}
2984 extra = {'source': source}
2985 user = ctx.user()
2985 user = ctx.user()
2986 if opts.get('user'):
2986 if opts.get('user'):
2987 user = opts['user']
2987 user = opts['user']
2988 date = ctx.date()
2988 date = ctx.date()
2989 if opts.get('date'):
2989 if opts.get('date'):
2990 date = opts['date']
2990 date = opts['date']
2991 message = ctx.description()
2991 message = ctx.description()
2992 if opts.get('log'):
2992 if opts.get('log'):
2993 message += '\n(grafted from %s)' % ctx.hex()
2993 message += '\n(grafted from %s)' % ctx.hex()
2994
2994
2995 # we don't merge the first commit when continuing
2995 # we don't merge the first commit when continuing
2996 if not cont:
2996 if not cont:
2997 # perform the graft merge with p1(rev) as 'ancestor'
2997 # perform the graft merge with p1(rev) as 'ancestor'
2998 try:
2998 try:
2999 # ui.forcemerge is an internal variable, do not document
2999 # ui.forcemerge is an internal variable, do not document
3000 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3000 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3001 stats = mergemod.update(repo, ctx.node(), True, True, False,
3001 stats = mergemod.update(repo, ctx.node(), True, True, False,
3002 ctx.p1().node())
3002 ctx.p1().node())
3003 finally:
3003 finally:
3004 repo.ui.setconfig('ui', 'forcemerge', '')
3004 repo.ui.setconfig('ui', 'forcemerge', '')
3005 # report any conflicts
3005 # report any conflicts
3006 if stats and stats[3] > 0:
3006 if stats and stats[3] > 0:
3007 # write out state for --continue
3007 # write out state for --continue
3008 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3008 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3009 repo.opener.write('graftstate', ''.join(nodelines))
3009 repo.opener.write('graftstate', ''.join(nodelines))
3010 raise util.Abort(
3010 raise util.Abort(
3011 _("unresolved conflicts, can't continue"),
3011 _("unresolved conflicts, can't continue"),
3012 hint=_('use hg resolve and hg graft --continue'))
3012 hint=_('use hg resolve and hg graft --continue'))
3013 else:
3013 else:
3014 cont = False
3014 cont = False
3015
3015
3016 # drop the second merge parent
3016 # drop the second merge parent
3017 repo.setparents(current.node(), nullid)
3017 repo.setparents(current.node(), nullid)
3018 repo.dirstate.write()
3018 repo.dirstate.write()
3019 # fix up dirstate for copies and renames
3019 # fix up dirstate for copies and renames
3020 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3020 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3021
3021
3022 # commit
3022 # commit
3023 node = repo.commit(text=message, user=user,
3023 node = repo.commit(text=message, user=user,
3024 date=date, extra=extra, editor=editor)
3024 date=date, extra=extra, editor=editor)
3025 if node is None:
3025 if node is None:
3026 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3026 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3027 else:
3027 else:
3028 current = repo[node]
3028 current = repo[node]
3029 finally:
3029 finally:
3030 wlock.release()
3030 wlock.release()
3031
3031
3032 # remove state when we complete successfully
3032 # remove state when we complete successfully
3033 if not opts.get('dry_run'):
3033 if not opts.get('dry_run'):
3034 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3034 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3035
3035
3036 return 0
3036 return 0
3037
3037
3038 @command('grep',
3038 @command('grep',
3039 [('0', 'print0', None, _('end fields with NUL')),
3039 [('0', 'print0', None, _('end fields with NUL')),
3040 ('', 'all', None, _('print all revisions that match')),
3040 ('', 'all', None, _('print all revisions that match')),
3041 ('a', 'text', None, _('treat all files as text')),
3041 ('a', 'text', None, _('treat all files as text')),
3042 ('f', 'follow', None,
3042 ('f', 'follow', None,
3043 _('follow changeset history,'
3043 _('follow changeset history,'
3044 ' or file history across copies and renames')),
3044 ' or file history across copies and renames')),
3045 ('i', 'ignore-case', None, _('ignore case when matching')),
3045 ('i', 'ignore-case', None, _('ignore case when matching')),
3046 ('l', 'files-with-matches', None,
3046 ('l', 'files-with-matches', None,
3047 _('print only filenames and revisions that match')),
3047 _('print only filenames and revisions that match')),
3048 ('n', 'line-number', None, _('print matching line numbers')),
3048 ('n', 'line-number', None, _('print matching line numbers')),
3049 ('r', 'rev', [],
3049 ('r', 'rev', [],
3050 _('only search files changed within revision range'), _('REV')),
3050 _('only search files changed within revision range'), _('REV')),
3051 ('u', 'user', None, _('list the author (long with -v)')),
3051 ('u', 'user', None, _('list the author (long with -v)')),
3052 ('d', 'date', None, _('list the date (short with -q)')),
3052 ('d', 'date', None, _('list the date (short with -q)')),
3053 ] + walkopts,
3053 ] + walkopts,
3054 _('[OPTION]... PATTERN [FILE]...'))
3054 _('[OPTION]... PATTERN [FILE]...'))
3055 def grep(ui, repo, pattern, *pats, **opts):
3055 def grep(ui, repo, pattern, *pats, **opts):
3056 """search for a pattern in specified files and revisions
3056 """search for a pattern in specified files and revisions
3057
3057
3058 Search revisions of files for a regular expression.
3058 Search revisions of files for a regular expression.
3059
3059
3060 This command behaves differently than Unix grep. It only accepts
3060 This command behaves differently than Unix grep. It only accepts
3061 Python/Perl regexps. It searches repository history, not the
3061 Python/Perl regexps. It searches repository history, not the
3062 working directory. It always prints the revision number in which a
3062 working directory. It always prints the revision number in which a
3063 match appears.
3063 match appears.
3064
3064
3065 By default, grep only prints output for the first revision of a
3065 By default, grep only prints output for the first revision of a
3066 file in which it finds a match. To get it to print every revision
3066 file in which it finds a match. To get it to print every revision
3067 that contains a change in match status ("-" for a match that
3067 that contains a change in match status ("-" for a match that
3068 becomes a non-match, or "+" for a non-match that becomes a match),
3068 becomes a non-match, or "+" for a non-match that becomes a match),
3069 use the --all flag.
3069 use the --all flag.
3070
3070
3071 Returns 0 if a match is found, 1 otherwise.
3071 Returns 0 if a match is found, 1 otherwise.
3072 """
3072 """
3073 reflags = re.M
3073 reflags = re.M
3074 if opts.get('ignore_case'):
3074 if opts.get('ignore_case'):
3075 reflags |= re.I
3075 reflags |= re.I
3076 try:
3076 try:
3077 regexp = util.compilere(pattern, reflags)
3077 regexp = util.compilere(pattern, reflags)
3078 except re.error, inst:
3078 except re.error, inst:
3079 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3079 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3080 return 1
3080 return 1
3081 sep, eol = ':', '\n'
3081 sep, eol = ':', '\n'
3082 if opts.get('print0'):
3082 if opts.get('print0'):
3083 sep = eol = '\0'
3083 sep = eol = '\0'
3084
3084
3085 getfile = util.lrucachefunc(repo.file)
3085 getfile = util.lrucachefunc(repo.file)
3086
3086
3087 def matchlines(body):
3087 def matchlines(body):
3088 begin = 0
3088 begin = 0
3089 linenum = 0
3089 linenum = 0
3090 while begin < len(body):
3090 while begin < len(body):
3091 match = regexp.search(body, begin)
3091 match = regexp.search(body, begin)
3092 if not match:
3092 if not match:
3093 break
3093 break
3094 mstart, mend = match.span()
3094 mstart, mend = match.span()
3095 linenum += body.count('\n', begin, mstart) + 1
3095 linenum += body.count('\n', begin, mstart) + 1
3096 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3096 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3097 begin = body.find('\n', mend) + 1 or len(body) + 1
3097 begin = body.find('\n', mend) + 1 or len(body) + 1
3098 lend = begin - 1
3098 lend = begin - 1
3099 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3099 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3100
3100
3101 class linestate(object):
3101 class linestate(object):
3102 def __init__(self, line, linenum, colstart, colend):
3102 def __init__(self, line, linenum, colstart, colend):
3103 self.line = line
3103 self.line = line
3104 self.linenum = linenum
3104 self.linenum = linenum
3105 self.colstart = colstart
3105 self.colstart = colstart
3106 self.colend = colend
3106 self.colend = colend
3107
3107
3108 def __hash__(self):
3108 def __hash__(self):
3109 return hash((self.linenum, self.line))
3109 return hash((self.linenum, self.line))
3110
3110
3111 def __eq__(self, other):
3111 def __eq__(self, other):
3112 return self.line == other.line
3112 return self.line == other.line
3113
3113
3114 matches = {}
3114 matches = {}
3115 copies = {}
3115 copies = {}
3116 def grepbody(fn, rev, body):
3116 def grepbody(fn, rev, body):
3117 matches[rev].setdefault(fn, [])
3117 matches[rev].setdefault(fn, [])
3118 m = matches[rev][fn]
3118 m = matches[rev][fn]
3119 for lnum, cstart, cend, line in matchlines(body):
3119 for lnum, cstart, cend, line in matchlines(body):
3120 s = linestate(line, lnum, cstart, cend)
3120 s = linestate(line, lnum, cstart, cend)
3121 m.append(s)
3121 m.append(s)
3122
3122
3123 def difflinestates(a, b):
3123 def difflinestates(a, b):
3124 sm = difflib.SequenceMatcher(None, a, b)
3124 sm = difflib.SequenceMatcher(None, a, b)
3125 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3125 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3126 if tag == 'insert':
3126 if tag == 'insert':
3127 for i in xrange(blo, bhi):
3127 for i in xrange(blo, bhi):
3128 yield ('+', b[i])
3128 yield ('+', b[i])
3129 elif tag == 'delete':
3129 elif tag == 'delete':
3130 for i in xrange(alo, ahi):
3130 for i in xrange(alo, ahi):
3131 yield ('-', a[i])
3131 yield ('-', a[i])
3132 elif tag == 'replace':
3132 elif tag == 'replace':
3133 for i in xrange(alo, ahi):
3133 for i in xrange(alo, ahi):
3134 yield ('-', a[i])
3134 yield ('-', a[i])
3135 for i in xrange(blo, bhi):
3135 for i in xrange(blo, bhi):
3136 yield ('+', b[i])
3136 yield ('+', b[i])
3137
3137
3138 def display(fn, ctx, pstates, states):
3138 def display(fn, ctx, pstates, states):
3139 rev = ctx.rev()
3139 rev = ctx.rev()
3140 datefunc = ui.quiet and util.shortdate or util.datestr
3140 datefunc = ui.quiet and util.shortdate or util.datestr
3141 found = False
3141 found = False
3142 filerevmatches = {}
3142 filerevmatches = {}
3143 def binary():
3143 def binary():
3144 flog = getfile(fn)
3144 flog = getfile(fn)
3145 return util.binary(flog.read(ctx.filenode(fn)))
3145 return util.binary(flog.read(ctx.filenode(fn)))
3146
3146
3147 if opts.get('all'):
3147 if opts.get('all'):
3148 iter = difflinestates(pstates, states)
3148 iter = difflinestates(pstates, states)
3149 else:
3149 else:
3150 iter = [('', l) for l in states]
3150 iter = [('', l) for l in states]
3151 for change, l in iter:
3151 for change, l in iter:
3152 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3152 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3153 before, match, after = None, None, None
3153 before, match, after = None, None, None
3154
3154
3155 if opts.get('line_number'):
3155 if opts.get('line_number'):
3156 cols.append((str(l.linenum), 'grep.linenumber'))
3156 cols.append((str(l.linenum), 'grep.linenumber'))
3157 if opts.get('all'):
3157 if opts.get('all'):
3158 cols.append((change, 'grep.change'))
3158 cols.append((change, 'grep.change'))
3159 if opts.get('user'):
3159 if opts.get('user'):
3160 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3160 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3161 if opts.get('date'):
3161 if opts.get('date'):
3162 cols.append((datefunc(ctx.date()), 'grep.date'))
3162 cols.append((datefunc(ctx.date()), 'grep.date'))
3163 if opts.get('files_with_matches'):
3163 if opts.get('files_with_matches'):
3164 c = (fn, rev)
3164 c = (fn, rev)
3165 if c in filerevmatches:
3165 if c in filerevmatches:
3166 continue
3166 continue
3167 filerevmatches[c] = 1
3167 filerevmatches[c] = 1
3168 else:
3168 else:
3169 before = l.line[:l.colstart]
3169 before = l.line[:l.colstart]
3170 match = l.line[l.colstart:l.colend]
3170 match = l.line[l.colstart:l.colend]
3171 after = l.line[l.colend:]
3171 after = l.line[l.colend:]
3172 for col, label in cols[:-1]:
3172 for col, label in cols[:-1]:
3173 ui.write(col, label=label)
3173 ui.write(col, label=label)
3174 ui.write(sep, label='grep.sep')
3174 ui.write(sep, label='grep.sep')
3175 ui.write(cols[-1][0], label=cols[-1][1])
3175 ui.write(cols[-1][0], label=cols[-1][1])
3176 if before is not None:
3176 if before is not None:
3177 ui.write(sep, label='grep.sep')
3177 ui.write(sep, label='grep.sep')
3178 if not opts.get('text') and binary():
3178 if not opts.get('text') and binary():
3179 ui.write(" Binary file matches")
3179 ui.write(" Binary file matches")
3180 else:
3180 else:
3181 ui.write(before)
3181 ui.write(before)
3182 ui.write(match, label='grep.match')
3182 ui.write(match, label='grep.match')
3183 ui.write(after)
3183 ui.write(after)
3184 ui.write(eol)
3184 ui.write(eol)
3185 found = True
3185 found = True
3186 return found
3186 return found
3187
3187
3188 skip = {}
3188 skip = {}
3189 revfiles = {}
3189 revfiles = {}
3190 matchfn = scmutil.match(repo[None], pats, opts)
3190 matchfn = scmutil.match(repo[None], pats, opts)
3191 found = False
3191 found = False
3192 follow = opts.get('follow')
3192 follow = opts.get('follow')
3193
3193
3194 def prep(ctx, fns):
3194 def prep(ctx, fns):
3195 rev = ctx.rev()
3195 rev = ctx.rev()
3196 pctx = ctx.p1()
3196 pctx = ctx.p1()
3197 parent = pctx.rev()
3197 parent = pctx.rev()
3198 matches.setdefault(rev, {})
3198 matches.setdefault(rev, {})
3199 matches.setdefault(parent, {})
3199 matches.setdefault(parent, {})
3200 files = revfiles.setdefault(rev, [])
3200 files = revfiles.setdefault(rev, [])
3201 for fn in fns:
3201 for fn in fns:
3202 flog = getfile(fn)
3202 flog = getfile(fn)
3203 try:
3203 try:
3204 fnode = ctx.filenode(fn)
3204 fnode = ctx.filenode(fn)
3205 except error.LookupError:
3205 except error.LookupError:
3206 continue
3206 continue
3207
3207
3208 copied = flog.renamed(fnode)
3208 copied = flog.renamed(fnode)
3209 copy = follow and copied and copied[0]
3209 copy = follow and copied and copied[0]
3210 if copy:
3210 if copy:
3211 copies.setdefault(rev, {})[fn] = copy
3211 copies.setdefault(rev, {})[fn] = copy
3212 if fn in skip:
3212 if fn in skip:
3213 if copy:
3213 if copy:
3214 skip[copy] = True
3214 skip[copy] = True
3215 continue
3215 continue
3216 files.append(fn)
3216 files.append(fn)
3217
3217
3218 if fn not in matches[rev]:
3218 if fn not in matches[rev]:
3219 grepbody(fn, rev, flog.read(fnode))
3219 grepbody(fn, rev, flog.read(fnode))
3220
3220
3221 pfn = copy or fn
3221 pfn = copy or fn
3222 if pfn not in matches[parent]:
3222 if pfn not in matches[parent]:
3223 try:
3223 try:
3224 fnode = pctx.filenode(pfn)
3224 fnode = pctx.filenode(pfn)
3225 grepbody(pfn, parent, flog.read(fnode))
3225 grepbody(pfn, parent, flog.read(fnode))
3226 except error.LookupError:
3226 except error.LookupError:
3227 pass
3227 pass
3228
3228
3229 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3229 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3230 rev = ctx.rev()
3230 rev = ctx.rev()
3231 parent = ctx.p1().rev()
3231 parent = ctx.p1().rev()
3232 for fn in sorted(revfiles.get(rev, [])):
3232 for fn in sorted(revfiles.get(rev, [])):
3233 states = matches[rev][fn]
3233 states = matches[rev][fn]
3234 copy = copies.get(rev, {}).get(fn)
3234 copy = copies.get(rev, {}).get(fn)
3235 if fn in skip:
3235 if fn in skip:
3236 if copy:
3236 if copy:
3237 skip[copy] = True
3237 skip[copy] = True
3238 continue
3238 continue
3239 pstates = matches.get(parent, {}).get(copy or fn, [])
3239 pstates = matches.get(parent, {}).get(copy or fn, [])
3240 if pstates or states:
3240 if pstates or states:
3241 r = display(fn, ctx, pstates, states)
3241 r = display(fn, ctx, pstates, states)
3242 found = found or r
3242 found = found or r
3243 if r and not opts.get('all'):
3243 if r and not opts.get('all'):
3244 skip[fn] = True
3244 skip[fn] = True
3245 if copy:
3245 if copy:
3246 skip[copy] = True
3246 skip[copy] = True
3247 del matches[rev]
3247 del matches[rev]
3248 del revfiles[rev]
3248 del revfiles[rev]
3249
3249
3250 return not found
3250 return not found
3251
3251
3252 @command('heads',
3252 @command('heads',
3253 [('r', 'rev', '',
3253 [('r', 'rev', '',
3254 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3254 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3255 ('t', 'topo', False, _('show topological heads only')),
3255 ('t', 'topo', False, _('show topological heads only')),
3256 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3256 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3257 ('c', 'closed', False, _('show normal and closed branch heads')),
3257 ('c', 'closed', False, _('show normal and closed branch heads')),
3258 ] + templateopts,
3258 ] + templateopts,
3259 _('[-ct] [-r STARTREV] [REV]...'))
3259 _('[-ct] [-r STARTREV] [REV]...'))
3260 def heads(ui, repo, *branchrevs, **opts):
3260 def heads(ui, repo, *branchrevs, **opts):
3261 """show current repository heads or show branch heads
3261 """show current repository heads or show branch heads
3262
3262
3263 With no arguments, show all repository branch heads.
3263 With no arguments, show all repository branch heads.
3264
3264
3265 Repository "heads" are changesets with no child changesets. They are
3265 Repository "heads" are changesets with no child changesets. They are
3266 where development generally takes place and are the usual targets
3266 where development generally takes place and are the usual targets
3267 for update and merge operations. Branch heads are changesets that have
3267 for update and merge operations. Branch heads are changesets that have
3268 no child changeset on the same branch.
3268 no child changeset on the same branch.
3269
3269
3270 If one or more REVs are given, only branch heads on the branches
3270 If one or more REVs are given, only branch heads on the branches
3271 associated with the specified changesets are shown. This means
3271 associated with the specified changesets are shown. This means
3272 that you can use :hg:`heads foo` to see the heads on a branch
3272 that you can use :hg:`heads foo` to see the heads on a branch
3273 named ``foo``.
3273 named ``foo``.
3274
3274
3275 If -c/--closed is specified, also show branch heads marked closed
3275 If -c/--closed is specified, also show branch heads marked closed
3276 (see :hg:`commit --close-branch`).
3276 (see :hg:`commit --close-branch`).
3277
3277
3278 If STARTREV is specified, only those heads that are descendants of
3278 If STARTREV is specified, only those heads that are descendants of
3279 STARTREV will be displayed.
3279 STARTREV will be displayed.
3280
3280
3281 If -t/--topo is specified, named branch mechanics will be ignored and only
3281 If -t/--topo is specified, named branch mechanics will be ignored and only
3282 changesets without children will be shown.
3282 changesets without children will be shown.
3283
3283
3284 Returns 0 if matching heads are found, 1 if not.
3284 Returns 0 if matching heads are found, 1 if not.
3285 """
3285 """
3286
3286
3287 start = None
3287 start = None
3288 if 'rev' in opts:
3288 if 'rev' in opts:
3289 start = scmutil.revsingle(repo, opts['rev'], None).node()
3289 start = scmutil.revsingle(repo, opts['rev'], None).node()
3290
3290
3291 if opts.get('topo'):
3291 if opts.get('topo'):
3292 heads = [repo[h] for h in repo.heads(start)]
3292 heads = [repo[h] for h in repo.heads(start)]
3293 else:
3293 else:
3294 heads = []
3294 heads = []
3295 for branch in repo.branchmap():
3295 for branch in repo.branchmap():
3296 heads += repo.branchheads(branch, start, opts.get('closed'))
3296 heads += repo.branchheads(branch, start, opts.get('closed'))
3297 heads = [repo[h] for h in heads]
3297 heads = [repo[h] for h in heads]
3298
3298
3299 if branchrevs:
3299 if branchrevs:
3300 branches = set(repo[br].branch() for br in branchrevs)
3300 branches = set(repo[br].branch() for br in branchrevs)
3301 heads = [h for h in heads if h.branch() in branches]
3301 heads = [h for h in heads if h.branch() in branches]
3302
3302
3303 if opts.get('active') and branchrevs:
3303 if opts.get('active') and branchrevs:
3304 dagheads = repo.heads(start)
3304 dagheads = repo.heads(start)
3305 heads = [h for h in heads if h.node() in dagheads]
3305 heads = [h for h in heads if h.node() in dagheads]
3306
3306
3307 if branchrevs:
3307 if branchrevs:
3308 haveheads = set(h.branch() for h in heads)
3308 haveheads = set(h.branch() for h in heads)
3309 if branches - haveheads:
3309 if branches - haveheads:
3310 headless = ', '.join(b for b in branches - haveheads)
3310 headless = ', '.join(b for b in branches - haveheads)
3311 msg = _('no open branch heads found on branches %s')
3311 msg = _('no open branch heads found on branches %s')
3312 if opts.get('rev'):
3312 if opts.get('rev'):
3313 msg += _(' (started at %s)') % opts['rev']
3313 msg += _(' (started at %s)') % opts['rev']
3314 ui.warn((msg + '\n') % headless)
3314 ui.warn((msg + '\n') % headless)
3315
3315
3316 if not heads:
3316 if not heads:
3317 return 1
3317 return 1
3318
3318
3319 heads = sorted(heads, key=lambda x: -x.rev())
3319 heads = sorted(heads, key=lambda x: -x.rev())
3320 displayer = cmdutil.show_changeset(ui, repo, opts)
3320 displayer = cmdutil.show_changeset(ui, repo, opts)
3321 for ctx in heads:
3321 for ctx in heads:
3322 displayer.show(ctx)
3322 displayer.show(ctx)
3323 displayer.close()
3323 displayer.close()
3324
3324
3325 @command('help',
3325 @command('help',
3326 [('e', 'extension', None, _('show only help for extensions')),
3326 [('e', 'extension', None, _('show only help for extensions')),
3327 ('c', 'command', None, _('show only help for commands')),
3327 ('c', 'command', None, _('show only help for commands')),
3328 ('k', 'keyword', '', _('show topics matching keyword')),
3328 ('k', 'keyword', '', _('show topics matching keyword')),
3329 ],
3329 ],
3330 _('[-ec] [TOPIC]'))
3330 _('[-ec] [TOPIC]'))
3331 def help_(ui, name=None, **opts):
3331 def help_(ui, name=None, **opts):
3332 """show help for a given topic or a help overview
3332 """show help for a given topic or a help overview
3333
3333
3334 With no arguments, print a list of commands with short help messages.
3334 With no arguments, print a list of commands with short help messages.
3335
3335
3336 Given a topic, extension, or command name, print help for that
3336 Given a topic, extension, or command name, print help for that
3337 topic.
3337 topic.
3338
3338
3339 Returns 0 if successful.
3339 Returns 0 if successful.
3340 """
3340 """
3341
3341
3342 textwidth = min(ui.termwidth(), 80) - 2
3342 textwidth = min(ui.termwidth(), 80) - 2
3343
3343
3344 keep = ui.verbose and ['verbose'] or []
3344 keep = ui.verbose and ['verbose'] or []
3345 text = help.help_(ui, name, **opts)
3345 text = help.help_(ui, name, **opts)
3346
3346
3347 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3347 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3348 if 'verbose' in pruned:
3348 if 'verbose' in pruned:
3349 keep.append('omitted')
3349 keep.append('omitted')
3350 else:
3350 else:
3351 keep.append('notomitted')
3351 keep.append('notomitted')
3352 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3352 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3353 ui.write(formatted)
3353 ui.write(formatted)
3354
3354
3355
3355
3356 @command('identify|id',
3356 @command('identify|id',
3357 [('r', 'rev', '',
3357 [('r', 'rev', '',
3358 _('identify the specified revision'), _('REV')),
3358 _('identify the specified revision'), _('REV')),
3359 ('n', 'num', None, _('show local revision number')),
3359 ('n', 'num', None, _('show local revision number')),
3360 ('i', 'id', None, _('show global revision id')),
3360 ('i', 'id', None, _('show global revision id')),
3361 ('b', 'branch', None, _('show branch')),
3361 ('b', 'branch', None, _('show branch')),
3362 ('t', 'tags', None, _('show tags')),
3362 ('t', 'tags', None, _('show tags')),
3363 ('B', 'bookmarks', None, _('show bookmarks')),
3363 ('B', 'bookmarks', None, _('show bookmarks')),
3364 ] + remoteopts,
3364 ] + remoteopts,
3365 _('[-nibtB] [-r REV] [SOURCE]'))
3365 _('[-nibtB] [-r REV] [SOURCE]'))
3366 def identify(ui, repo, source=None, rev=None,
3366 def identify(ui, repo, source=None, rev=None,
3367 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3367 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3368 """identify the working copy or specified revision
3368 """identify the working copy or specified revision
3369
3369
3370 Print a summary identifying the repository state at REV using one or
3370 Print a summary identifying the repository state at REV using one or
3371 two parent hash identifiers, followed by a "+" if the working
3371 two parent hash identifiers, followed by a "+" if the working
3372 directory has uncommitted changes, the branch name (if not default),
3372 directory has uncommitted changes, the branch name (if not default),
3373 a list of tags, and a list of bookmarks.
3373 a list of tags, and a list of bookmarks.
3374
3374
3375 When REV is not given, print a summary of the current state of the
3375 When REV is not given, print a summary of the current state of the
3376 repository.
3376 repository.
3377
3377
3378 Specifying a path to a repository root or Mercurial bundle will
3378 Specifying a path to a repository root or Mercurial bundle will
3379 cause lookup to operate on that repository/bundle.
3379 cause lookup to operate on that repository/bundle.
3380
3380
3381 .. container:: verbose
3381 .. container:: verbose
3382
3382
3383 Examples:
3383 Examples:
3384
3384
3385 - generate a build identifier for the working directory::
3385 - generate a build identifier for the working directory::
3386
3386
3387 hg id --id > build-id.dat
3387 hg id --id > build-id.dat
3388
3388
3389 - find the revision corresponding to a tag::
3389 - find the revision corresponding to a tag::
3390
3390
3391 hg id -n -r 1.3
3391 hg id -n -r 1.3
3392
3392
3393 - check the most recent revision of a remote repository::
3393 - check the most recent revision of a remote repository::
3394
3394
3395 hg id -r tip http://selenic.com/hg/
3395 hg id -r tip http://selenic.com/hg/
3396
3396
3397 Returns 0 if successful.
3397 Returns 0 if successful.
3398 """
3398 """
3399
3399
3400 if not repo and not source:
3400 if not repo and not source:
3401 raise util.Abort(_("there is no Mercurial repository here "
3401 raise util.Abort(_("there is no Mercurial repository here "
3402 "(.hg not found)"))
3402 "(.hg not found)"))
3403
3403
3404 hexfunc = ui.debugflag and hex or short
3404 hexfunc = ui.debugflag and hex or short
3405 default = not (num or id or branch or tags or bookmarks)
3405 default = not (num or id or branch or tags or bookmarks)
3406 output = []
3406 output = []
3407 revs = []
3407 revs = []
3408
3408
3409 if source:
3409 if source:
3410 source, branches = hg.parseurl(ui.expandpath(source))
3410 source, branches = hg.parseurl(ui.expandpath(source))
3411 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3411 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3412 repo = peer.local()
3412 repo = peer.local()
3413 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3413 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3414
3414
3415 if not repo:
3415 if not repo:
3416 if num or branch or tags:
3416 if num or branch or tags:
3417 raise util.Abort(
3417 raise util.Abort(
3418 _("can't query remote revision number, branch, or tags"))
3418 _("can't query remote revision number, branch, or tags"))
3419 if not rev and revs:
3419 if not rev and revs:
3420 rev = revs[0]
3420 rev = revs[0]
3421 if not rev:
3421 if not rev:
3422 rev = "tip"
3422 rev = "tip"
3423
3423
3424 remoterev = peer.lookup(rev)
3424 remoterev = peer.lookup(rev)
3425 if default or id:
3425 if default or id:
3426 output = [hexfunc(remoterev)]
3426 output = [hexfunc(remoterev)]
3427
3427
3428 def getbms():
3428 def getbms():
3429 bms = []
3429 bms = []
3430
3430
3431 if 'bookmarks' in peer.listkeys('namespaces'):
3431 if 'bookmarks' in peer.listkeys('namespaces'):
3432 hexremoterev = hex(remoterev)
3432 hexremoterev = hex(remoterev)
3433 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3433 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3434 if bmr == hexremoterev]
3434 if bmr == hexremoterev]
3435
3435
3436 return sorted(bms)
3436 return sorted(bms)
3437
3437
3438 if bookmarks:
3438 if bookmarks:
3439 output.extend(getbms())
3439 output.extend(getbms())
3440 elif default and not ui.quiet:
3440 elif default and not ui.quiet:
3441 # multiple bookmarks for a single parent separated by '/'
3441 # multiple bookmarks for a single parent separated by '/'
3442 bm = '/'.join(getbms())
3442 bm = '/'.join(getbms())
3443 if bm:
3443 if bm:
3444 output.append(bm)
3444 output.append(bm)
3445 else:
3445 else:
3446 if not rev:
3446 if not rev:
3447 ctx = repo[None]
3447 ctx = repo[None]
3448 parents = ctx.parents()
3448 parents = ctx.parents()
3449 changed = ""
3449 changed = ""
3450 if default or id or num:
3450 if default or id or num:
3451 if (util.any(repo.status())
3451 if (util.any(repo.status())
3452 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3452 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3453 changed = '+'
3453 changed = '+'
3454 if default or id:
3454 if default or id:
3455 output = ["%s%s" %
3455 output = ["%s%s" %
3456 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3456 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3457 if num:
3457 if num:
3458 output.append("%s%s" %
3458 output.append("%s%s" %
3459 ('+'.join([str(p.rev()) for p in parents]), changed))
3459 ('+'.join([str(p.rev()) for p in parents]), changed))
3460 else:
3460 else:
3461 ctx = scmutil.revsingle(repo, rev)
3461 ctx = scmutil.revsingle(repo, rev)
3462 if default or id:
3462 if default or id:
3463 output = [hexfunc(ctx.node())]
3463 output = [hexfunc(ctx.node())]
3464 if num:
3464 if num:
3465 output.append(str(ctx.rev()))
3465 output.append(str(ctx.rev()))
3466
3466
3467 if default and not ui.quiet:
3467 if default and not ui.quiet:
3468 b = ctx.branch()
3468 b = ctx.branch()
3469 if b != 'default':
3469 if b != 'default':
3470 output.append("(%s)" % b)
3470 output.append("(%s)" % b)
3471
3471
3472 # multiple tags for a single parent separated by '/'
3472 # multiple tags for a single parent separated by '/'
3473 t = '/'.join(ctx.tags())
3473 t = '/'.join(ctx.tags())
3474 if t:
3474 if t:
3475 output.append(t)
3475 output.append(t)
3476
3476
3477 # multiple bookmarks for a single parent separated by '/'
3477 # multiple bookmarks for a single parent separated by '/'
3478 bm = '/'.join(ctx.bookmarks())
3478 bm = '/'.join(ctx.bookmarks())
3479 if bm:
3479 if bm:
3480 output.append(bm)
3480 output.append(bm)
3481 else:
3481 else:
3482 if branch:
3482 if branch:
3483 output.append(ctx.branch())
3483 output.append(ctx.branch())
3484
3484
3485 if tags:
3485 if tags:
3486 output.extend(ctx.tags())
3486 output.extend(ctx.tags())
3487
3487
3488 if bookmarks:
3488 if bookmarks:
3489 output.extend(ctx.bookmarks())
3489 output.extend(ctx.bookmarks())
3490
3490
3491 ui.write("%s\n" % ' '.join(output))
3491 ui.write("%s\n" % ' '.join(output))
3492
3492
3493 @command('import|patch',
3493 @command('import|patch',
3494 [('p', 'strip', 1,
3494 [('p', 'strip', 1,
3495 _('directory strip option for patch. This has the same '
3495 _('directory strip option for patch. This has the same '
3496 'meaning as the corresponding patch option'), _('NUM')),
3496 'meaning as the corresponding patch option'), _('NUM')),
3497 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3497 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3498 ('e', 'edit', False, _('invoke editor on commit messages')),
3498 ('e', 'edit', False, _('invoke editor on commit messages')),
3499 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3499 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3500 ('', 'no-commit', None,
3500 ('', 'no-commit', None,
3501 _("don't commit, just update the working directory")),
3501 _("don't commit, just update the working directory")),
3502 ('', 'bypass', None,
3502 ('', 'bypass', None,
3503 _("apply patch without touching the working directory")),
3503 _("apply patch without touching the working directory")),
3504 ('', 'exact', None,
3504 ('', 'exact', None,
3505 _('apply patch to the nodes from which it was generated')),
3505 _('apply patch to the nodes from which it was generated')),
3506 ('', 'import-branch', None,
3506 ('', 'import-branch', None,
3507 _('use any branch information in patch (implied by --exact)'))] +
3507 _('use any branch information in patch (implied by --exact)'))] +
3508 commitopts + commitopts2 + similarityopts,
3508 commitopts + commitopts2 + similarityopts,
3509 _('[OPTION]... PATCH...'))
3509 _('[OPTION]... PATCH...'))
3510 def import_(ui, repo, patch1=None, *patches, **opts):
3510 def import_(ui, repo, patch1=None, *patches, **opts):
3511 """import an ordered set of patches
3511 """import an ordered set of patches
3512
3512
3513 Import a list of patches and commit them individually (unless
3513 Import a list of patches and commit them individually (unless
3514 --no-commit is specified).
3514 --no-commit is specified).
3515
3515
3516 If there are outstanding changes in the working directory, import
3516 If there are outstanding changes in the working directory, import
3517 will abort unless given the -f/--force flag.
3517 will abort unless given the -f/--force flag.
3518
3518
3519 You can import a patch straight from a mail message. Even patches
3519 You can import a patch straight from a mail message. Even patches
3520 as attachments work (to use the body part, it must have type
3520 as attachments work (to use the body part, it must have type
3521 text/plain or text/x-patch). From and Subject headers of email
3521 text/plain or text/x-patch). From and Subject headers of email
3522 message are used as default committer and commit message. All
3522 message are used as default committer and commit message. All
3523 text/plain body parts before first diff are added to commit
3523 text/plain body parts before first diff are added to commit
3524 message.
3524 message.
3525
3525
3526 If the imported patch was generated by :hg:`export`, user and
3526 If the imported patch was generated by :hg:`export`, user and
3527 description from patch override values from message headers and
3527 description from patch override values from message headers and
3528 body. Values given on command line with -m/--message and -u/--user
3528 body. Values given on command line with -m/--message and -u/--user
3529 override these.
3529 override these.
3530
3530
3531 If --exact is specified, import will set the working directory to
3531 If --exact is specified, import will set the working directory to
3532 the parent of each patch before applying it, and will abort if the
3532 the parent of each patch before applying it, and will abort if the
3533 resulting changeset has a different ID than the one recorded in
3533 resulting changeset has a different ID than the one recorded in
3534 the patch. This may happen due to character set problems or other
3534 the patch. This may happen due to character set problems or other
3535 deficiencies in the text patch format.
3535 deficiencies in the text patch format.
3536
3536
3537 Use --bypass to apply and commit patches directly to the
3537 Use --bypass to apply and commit patches directly to the
3538 repository, not touching the working directory. Without --exact,
3538 repository, not touching the working directory. Without --exact,
3539 patches will be applied on top of the working directory parent
3539 patches will be applied on top of the working directory parent
3540 revision.
3540 revision.
3541
3541
3542 With -s/--similarity, hg will attempt to discover renames and
3542 With -s/--similarity, hg will attempt to discover renames and
3543 copies in the patch in the same way as :hg:`addremove`.
3543 copies in the patch in the same way as :hg:`addremove`.
3544
3544
3545 To read a patch from standard input, use "-" as the patch name. If
3545 To read a patch from standard input, use "-" as the patch name. If
3546 a URL is specified, the patch will be downloaded from it.
3546 a URL is specified, the patch will be downloaded from it.
3547 See :hg:`help dates` for a list of formats valid for -d/--date.
3547 See :hg:`help dates` for a list of formats valid for -d/--date.
3548
3548
3549 .. container:: verbose
3549 .. container:: verbose
3550
3550
3551 Examples:
3551 Examples:
3552
3552
3553 - import a traditional patch from a website and detect renames::
3553 - import a traditional patch from a website and detect renames::
3554
3554
3555 hg import -s 80 http://example.com/bugfix.patch
3555 hg import -s 80 http://example.com/bugfix.patch
3556
3556
3557 - import a changeset from an hgweb server::
3557 - import a changeset from an hgweb server::
3558
3558
3559 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3559 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3560
3560
3561 - import all the patches in an Unix-style mbox::
3561 - import all the patches in an Unix-style mbox::
3562
3562
3563 hg import incoming-patches.mbox
3563 hg import incoming-patches.mbox
3564
3564
3565 - attempt to exactly restore an exported changeset (not always
3565 - attempt to exactly restore an exported changeset (not always
3566 possible)::
3566 possible)::
3567
3567
3568 hg import --exact proposed-fix.patch
3568 hg import --exact proposed-fix.patch
3569
3569
3570 Returns 0 on success.
3570 Returns 0 on success.
3571 """
3571 """
3572
3572
3573 if not patch1:
3573 if not patch1:
3574 raise util.Abort(_('need at least one patch to import'))
3574 raise util.Abort(_('need at least one patch to import'))
3575
3575
3576 patches = (patch1,) + patches
3576 patches = (patch1,) + patches
3577
3577
3578 date = opts.get('date')
3578 date = opts.get('date')
3579 if date:
3579 if date:
3580 opts['date'] = util.parsedate(date)
3580 opts['date'] = util.parsedate(date)
3581
3581
3582 editor = cmdutil.commiteditor
3582 editor = cmdutil.commiteditor
3583 if opts.get('edit'):
3583 if opts.get('edit'):
3584 editor = cmdutil.commitforceeditor
3584 editor = cmdutil.commitforceeditor
3585
3585
3586 update = not opts.get('bypass')
3586 update = not opts.get('bypass')
3587 if not update and opts.get('no_commit'):
3587 if not update and opts.get('no_commit'):
3588 raise util.Abort(_('cannot use --no-commit with --bypass'))
3588 raise util.Abort(_('cannot use --no-commit with --bypass'))
3589 try:
3589 try:
3590 sim = float(opts.get('similarity') or 0)
3590 sim = float(opts.get('similarity') or 0)
3591 except ValueError:
3591 except ValueError:
3592 raise util.Abort(_('similarity must be a number'))
3592 raise util.Abort(_('similarity must be a number'))
3593 if sim < 0 or sim > 100:
3593 if sim < 0 or sim > 100:
3594 raise util.Abort(_('similarity must be between 0 and 100'))
3594 raise util.Abort(_('similarity must be between 0 and 100'))
3595 if sim and not update:
3595 if sim and not update:
3596 raise util.Abort(_('cannot use --similarity with --bypass'))
3596 raise util.Abort(_('cannot use --similarity with --bypass'))
3597
3597
3598 if (opts.get('exact') or not opts.get('force')) and update:
3598 if (opts.get('exact') or not opts.get('force')) and update:
3599 cmdutil.bailifchanged(repo)
3599 cmdutil.bailifchanged(repo)
3600
3600
3601 base = opts["base"]
3601 base = opts["base"]
3602 strip = opts["strip"]
3602 strip = opts["strip"]
3603 wlock = lock = tr = None
3603 wlock = lock = tr = None
3604 msgs = []
3604 msgs = []
3605
3605
3606 def checkexact(repo, n, nodeid):
3606 def checkexact(repo, n, nodeid):
3607 if opts.get('exact') and hex(n) != nodeid:
3607 if opts.get('exact') and hex(n) != nodeid:
3608 raise util.Abort(_('patch is damaged or loses information'))
3608 raise util.Abort(_('patch is damaged or loses information'))
3609
3609
3610 def tryone(ui, hunk, parents):
3610 def tryone(ui, hunk, parents):
3611 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3611 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3612 patch.extract(ui, hunk)
3612 patch.extract(ui, hunk)
3613
3613
3614 if not tmpname:
3614 if not tmpname:
3615 return (None, None)
3615 return (None, None)
3616 msg = _('applied to working directory')
3616 msg = _('applied to working directory')
3617
3617
3618 try:
3618 try:
3619 cmdline_message = cmdutil.logmessage(ui, opts)
3619 cmdline_message = cmdutil.logmessage(ui, opts)
3620 if cmdline_message:
3620 if cmdline_message:
3621 # pickup the cmdline msg
3621 # pickup the cmdline msg
3622 message = cmdline_message
3622 message = cmdline_message
3623 elif message:
3623 elif message:
3624 # pickup the patch msg
3624 # pickup the patch msg
3625 message = message.strip()
3625 message = message.strip()
3626 else:
3626 else:
3627 # launch the editor
3627 # launch the editor
3628 message = None
3628 message = None
3629 ui.debug('message:\n%s\n' % message)
3629 ui.debug('message:\n%s\n' % message)
3630
3630
3631 if len(parents) == 1:
3631 if len(parents) == 1:
3632 parents.append(repo[nullid])
3632 parents.append(repo[nullid])
3633 if opts.get('exact'):
3633 if opts.get('exact'):
3634 if not nodeid or not p1:
3634 if not nodeid or not p1:
3635 raise util.Abort(_('not a Mercurial patch'))
3635 raise util.Abort(_('not a Mercurial patch'))
3636 p1 = repo[p1]
3636 p1 = repo[p1]
3637 p2 = repo[p2 or nullid]
3637 p2 = repo[p2 or nullid]
3638 elif p2:
3638 elif p2:
3639 try:
3639 try:
3640 p1 = repo[p1]
3640 p1 = repo[p1]
3641 p2 = repo[p2]
3641 p2 = repo[p2]
3642 # Without any options, consider p2 only if the
3642 # Without any options, consider p2 only if the
3643 # patch is being applied on top of the recorded
3643 # patch is being applied on top of the recorded
3644 # first parent.
3644 # first parent.
3645 if p1 != parents[0]:
3645 if p1 != parents[0]:
3646 p1 = parents[0]
3646 p1 = parents[0]
3647 p2 = repo[nullid]
3647 p2 = repo[nullid]
3648 except error.RepoError:
3648 except error.RepoError:
3649 p1, p2 = parents
3649 p1, p2 = parents
3650 else:
3650 else:
3651 p1, p2 = parents
3651 p1, p2 = parents
3652
3652
3653 n = None
3653 n = None
3654 if update:
3654 if update:
3655 if p1 != parents[0]:
3655 if p1 != parents[0]:
3656 hg.clean(repo, p1.node())
3656 hg.clean(repo, p1.node())
3657 if p2 != parents[1]:
3657 if p2 != parents[1]:
3658 repo.setparents(p1.node(), p2.node())
3658 repo.setparents(p1.node(), p2.node())
3659
3659
3660 if opts.get('exact') or opts.get('import_branch'):
3660 if opts.get('exact') or opts.get('import_branch'):
3661 repo.dirstate.setbranch(branch or 'default')
3661 repo.dirstate.setbranch(branch or 'default')
3662
3662
3663 files = set()
3663 files = set()
3664 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3664 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3665 eolmode=None, similarity=sim / 100.0)
3665 eolmode=None, similarity=sim / 100.0)
3666 files = list(files)
3666 files = list(files)
3667 if opts.get('no_commit'):
3667 if opts.get('no_commit'):
3668 if message:
3668 if message:
3669 msgs.append(message)
3669 msgs.append(message)
3670 else:
3670 else:
3671 if opts.get('exact') or p2:
3671 if opts.get('exact') or p2:
3672 # If you got here, you either use --force and know what
3672 # If you got here, you either use --force and know what
3673 # you are doing or used --exact or a merge patch while
3673 # you are doing or used --exact or a merge patch while
3674 # being updated to its first parent.
3674 # being updated to its first parent.
3675 m = None
3675 m = None
3676 else:
3676 else:
3677 m = scmutil.matchfiles(repo, files or [])
3677 m = scmutil.matchfiles(repo, files or [])
3678 n = repo.commit(message, opts.get('user') or user,
3678 n = repo.commit(message, opts.get('user') or user,
3679 opts.get('date') or date, match=m,
3679 opts.get('date') or date, match=m,
3680 editor=editor)
3680 editor=editor)
3681 checkexact(repo, n, nodeid)
3681 checkexact(repo, n, nodeid)
3682 else:
3682 else:
3683 if opts.get('exact') or opts.get('import_branch'):
3683 if opts.get('exact') or opts.get('import_branch'):
3684 branch = branch or 'default'
3684 branch = branch or 'default'
3685 else:
3685 else:
3686 branch = p1.branch()
3686 branch = p1.branch()
3687 store = patch.filestore()
3687 store = patch.filestore()
3688 try:
3688 try:
3689 files = set()
3689 files = set()
3690 try:
3690 try:
3691 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3691 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3692 files, eolmode=None)
3692 files, eolmode=None)
3693 except patch.PatchError, e:
3693 except patch.PatchError, e:
3694 raise util.Abort(str(e))
3694 raise util.Abort(str(e))
3695 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3695 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3696 message,
3696 message,
3697 opts.get('user') or user,
3697 opts.get('user') or user,
3698 opts.get('date') or date,
3698 opts.get('date') or date,
3699 branch, files, store,
3699 branch, files, store,
3700 editor=cmdutil.commiteditor)
3700 editor=cmdutil.commiteditor)
3701 repo.savecommitmessage(memctx.description())
3701 repo.savecommitmessage(memctx.description())
3702 n = memctx.commit()
3702 n = memctx.commit()
3703 checkexact(repo, n, nodeid)
3703 checkexact(repo, n, nodeid)
3704 finally:
3704 finally:
3705 store.close()
3705 store.close()
3706 if n:
3706 if n:
3707 # i18n: refers to a short changeset id
3707 # i18n: refers to a short changeset id
3708 msg = _('created %s') % short(n)
3708 msg = _('created %s') % short(n)
3709 return (msg, n)
3709 return (msg, n)
3710 finally:
3710 finally:
3711 os.unlink(tmpname)
3711 os.unlink(tmpname)
3712
3712
3713 try:
3713 try:
3714 try:
3714 try:
3715 wlock = repo.wlock()
3715 wlock = repo.wlock()
3716 if not opts.get('no_commit'):
3716 if not opts.get('no_commit'):
3717 lock = repo.lock()
3717 lock = repo.lock()
3718 tr = repo.transaction('import')
3718 tr = repo.transaction('import')
3719 parents = repo.parents()
3719 parents = repo.parents()
3720 for patchurl in patches:
3720 for patchurl in patches:
3721 if patchurl == '-':
3721 if patchurl == '-':
3722 ui.status(_('applying patch from stdin\n'))
3722 ui.status(_('applying patch from stdin\n'))
3723 patchfile = ui.fin
3723 patchfile = ui.fin
3724 patchurl = 'stdin' # for error message
3724 patchurl = 'stdin' # for error message
3725 else:
3725 else:
3726 patchurl = os.path.join(base, patchurl)
3726 patchurl = os.path.join(base, patchurl)
3727 ui.status(_('applying %s\n') % patchurl)
3727 ui.status(_('applying %s\n') % patchurl)
3728 patchfile = hg.openpath(ui, patchurl)
3728 patchfile = hg.openpath(ui, patchurl)
3729
3729
3730 haspatch = False
3730 haspatch = False
3731 for hunk in patch.split(patchfile):
3731 for hunk in patch.split(patchfile):
3732 (msg, node) = tryone(ui, hunk, parents)
3732 (msg, node) = tryone(ui, hunk, parents)
3733 if msg:
3733 if msg:
3734 haspatch = True
3734 haspatch = True
3735 ui.note(msg + '\n')
3735 ui.note(msg + '\n')
3736 if update or opts.get('exact'):
3736 if update or opts.get('exact'):
3737 parents = repo.parents()
3737 parents = repo.parents()
3738 else:
3738 else:
3739 parents = [repo[node]]
3739 parents = [repo[node]]
3740
3740
3741 if not haspatch:
3741 if not haspatch:
3742 raise util.Abort(_('%s: no diffs found') % patchurl)
3742 raise util.Abort(_('%s: no diffs found') % patchurl)
3743
3743
3744 if tr:
3744 if tr:
3745 tr.close()
3745 tr.close()
3746 if msgs:
3746 if msgs:
3747 repo.savecommitmessage('\n* * *\n'.join(msgs))
3747 repo.savecommitmessage('\n* * *\n'.join(msgs))
3748 except: # re-raises
3748 except: # re-raises
3749 # wlock.release() indirectly calls dirstate.write(): since
3749 # wlock.release() indirectly calls dirstate.write(): since
3750 # we're crashing, we do not want to change the working dir
3750 # we're crashing, we do not want to change the working dir
3751 # parent after all, so make sure it writes nothing
3751 # parent after all, so make sure it writes nothing
3752 repo.dirstate.invalidate()
3752 repo.dirstate.invalidate()
3753 raise
3753 raise
3754 finally:
3754 finally:
3755 if tr:
3755 if tr:
3756 tr.release()
3756 tr.release()
3757 release(lock, wlock)
3757 release(lock, wlock)
3758
3758
3759 @command('incoming|in',
3759 @command('incoming|in',
3760 [('f', 'force', None,
3760 [('f', 'force', None,
3761 _('run even if remote repository is unrelated')),
3761 _('run even if remote repository is unrelated')),
3762 ('n', 'newest-first', None, _('show newest record first')),
3762 ('n', 'newest-first', None, _('show newest record first')),
3763 ('', 'bundle', '',
3763 ('', 'bundle', '',
3764 _('file to store the bundles into'), _('FILE')),
3764 _('file to store the bundles into'), _('FILE')),
3765 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3765 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3766 ('B', 'bookmarks', False, _("compare bookmarks")),
3766 ('B', 'bookmarks', False, _("compare bookmarks")),
3767 ('b', 'branch', [],
3767 ('b', 'branch', [],
3768 _('a specific branch you would like to pull'), _('BRANCH')),
3768 _('a specific branch you would like to pull'), _('BRANCH')),
3769 ] + logopts + remoteopts + subrepoopts,
3769 ] + logopts + remoteopts + subrepoopts,
3770 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3770 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3771 def incoming(ui, repo, source="default", **opts):
3771 def incoming(ui, repo, source="default", **opts):
3772 """show new changesets found in source
3772 """show new changesets found in source
3773
3773
3774 Show new changesets found in the specified path/URL or the default
3774 Show new changesets found in the specified path/URL or the default
3775 pull location. These are the changesets that would have been pulled
3775 pull location. These are the changesets that would have been pulled
3776 if a pull at the time you issued this command.
3776 if a pull at the time you issued this command.
3777
3777
3778 For remote repository, using --bundle avoids downloading the
3778 For remote repository, using --bundle avoids downloading the
3779 changesets twice if the incoming is followed by a pull.
3779 changesets twice if the incoming is followed by a pull.
3780
3780
3781 See pull for valid source format details.
3781 See pull for valid source format details.
3782
3782
3783 Returns 0 if there are incoming changes, 1 otherwise.
3783 Returns 0 if there are incoming changes, 1 otherwise.
3784 """
3784 """
3785 if opts.get('graph'):
3785 if opts.get('graph'):
3786 cmdutil.checkunsupportedgraphflags([], opts)
3786 cmdutil.checkunsupportedgraphflags([], opts)
3787 def display(other, chlist, displayer):
3787 def display(other, chlist, displayer):
3788 revdag = cmdutil.graphrevs(other, chlist, opts)
3788 revdag = cmdutil.graphrevs(other, chlist, opts)
3789 showparents = [ctx.node() for ctx in repo[None].parents()]
3789 showparents = [ctx.node() for ctx in repo[None].parents()]
3790 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3790 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3791 graphmod.asciiedges)
3791 graphmod.asciiedges)
3792
3792
3793 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3793 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3794 return 0
3794 return 0
3795
3795
3796 if opts.get('bundle') and opts.get('subrepos'):
3796 if opts.get('bundle') and opts.get('subrepos'):
3797 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3797 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3798
3798
3799 if opts.get('bookmarks'):
3799 if opts.get('bookmarks'):
3800 source, branches = hg.parseurl(ui.expandpath(source),
3800 source, branches = hg.parseurl(ui.expandpath(source),
3801 opts.get('branch'))
3801 opts.get('branch'))
3802 other = hg.peer(repo, opts, source)
3802 other = hg.peer(repo, opts, source)
3803 if 'bookmarks' not in other.listkeys('namespaces'):
3803 if 'bookmarks' not in other.listkeys('namespaces'):
3804 ui.warn(_("remote doesn't support bookmarks\n"))
3804 ui.warn(_("remote doesn't support bookmarks\n"))
3805 return 0
3805 return 0
3806 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3806 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3807 return bookmarks.diff(ui, repo, other)
3807 return bookmarks.diff(ui, repo, other)
3808
3808
3809 repo._subtoppath = ui.expandpath(source)
3809 repo._subtoppath = ui.expandpath(source)
3810 try:
3810 try:
3811 return hg.incoming(ui, repo, source, opts)
3811 return hg.incoming(ui, repo, source, opts)
3812 finally:
3812 finally:
3813 del repo._subtoppath
3813 del repo._subtoppath
3814
3814
3815
3815
3816 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3816 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3817 def init(ui, dest=".", **opts):
3817 def init(ui, dest=".", **opts):
3818 """create a new repository in the given directory
3818 """create a new repository in the given directory
3819
3819
3820 Initialize a new repository in the given directory. If the given
3820 Initialize a new repository in the given directory. If the given
3821 directory does not exist, it will be created.
3821 directory does not exist, it will be created.
3822
3822
3823 If no directory is given, the current directory is used.
3823 If no directory is given, the current directory is used.
3824
3824
3825 It is possible to specify an ``ssh://`` URL as the destination.
3825 It is possible to specify an ``ssh://`` URL as the destination.
3826 See :hg:`help urls` for more information.
3826 See :hg:`help urls` for more information.
3827
3827
3828 Returns 0 on success.
3828 Returns 0 on success.
3829 """
3829 """
3830 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3830 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3831
3831
3832 @command('locate',
3832 @command('locate',
3833 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3833 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3834 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3834 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3835 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3835 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3836 ] + walkopts,
3836 ] + walkopts,
3837 _('[OPTION]... [PATTERN]...'))
3837 _('[OPTION]... [PATTERN]...'))
3838 def locate(ui, repo, *pats, **opts):
3838 def locate(ui, repo, *pats, **opts):
3839 """locate files matching specific patterns
3839 """locate files matching specific patterns
3840
3840
3841 Print files under Mercurial control in the working directory whose
3841 Print files under Mercurial control in the working directory whose
3842 names match the given patterns.
3842 names match the given patterns.
3843
3843
3844 By default, this command searches all directories in the working
3844 By default, this command searches all directories in the working
3845 directory. To search just the current directory and its
3845 directory. To search just the current directory and its
3846 subdirectories, use "--include .".
3846 subdirectories, use "--include .".
3847
3847
3848 If no patterns are given to match, this command prints the names
3848 If no patterns are given to match, this command prints the names
3849 of all files under Mercurial control in the working directory.
3849 of all files under Mercurial control in the working directory.
3850
3850
3851 If you want to feed the output of this command into the "xargs"
3851 If you want to feed the output of this command into the "xargs"
3852 command, use the -0 option to both this command and "xargs". This
3852 command, use the -0 option to both this command and "xargs". This
3853 will avoid the problem of "xargs" treating single filenames that
3853 will avoid the problem of "xargs" treating single filenames that
3854 contain whitespace as multiple filenames.
3854 contain whitespace as multiple filenames.
3855
3855
3856 Returns 0 if a match is found, 1 otherwise.
3856 Returns 0 if a match is found, 1 otherwise.
3857 """
3857 """
3858 end = opts.get('print0') and '\0' or '\n'
3858 end = opts.get('print0') and '\0' or '\n'
3859 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3859 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3860
3860
3861 ret = 1
3861 ret = 1
3862 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3862 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3863 m.bad = lambda x, y: False
3863 m.bad = lambda x, y: False
3864 for abs in repo[rev].walk(m):
3864 for abs in repo[rev].walk(m):
3865 if not rev and abs not in repo.dirstate:
3865 if not rev and abs not in repo.dirstate:
3866 continue
3866 continue
3867 if opts.get('fullpath'):
3867 if opts.get('fullpath'):
3868 ui.write(repo.wjoin(abs), end)
3868 ui.write(repo.wjoin(abs), end)
3869 else:
3869 else:
3870 ui.write(((pats and m.rel(abs)) or abs), end)
3870 ui.write(((pats and m.rel(abs)) or abs), end)
3871 ret = 0
3871 ret = 0
3872
3872
3873 return ret
3873 return ret
3874
3874
3875 @command('^log|history',
3875 @command('^log|history',
3876 [('f', 'follow', None,
3876 [('f', 'follow', None,
3877 _('follow changeset history, or file history across copies and renames')),
3877 _('follow changeset history, or file history across copies and renames')),
3878 ('', 'follow-first', None,
3878 ('', 'follow-first', None,
3879 _('only follow the first parent of merge changesets (DEPRECATED)')),
3879 _('only follow the first parent of merge changesets (DEPRECATED)')),
3880 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3880 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3881 ('C', 'copies', None, _('show copied files')),
3881 ('C', 'copies', None, _('show copied files')),
3882 ('k', 'keyword', [],
3882 ('k', 'keyword', [],
3883 _('do case-insensitive search for a given text'), _('TEXT')),
3883 _('do case-insensitive search for a given text'), _('TEXT')),
3884 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3884 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3885 ('', 'removed', None, _('include revisions where files were removed')),
3885 ('', 'removed', None, _('include revisions where files were removed')),
3886 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3886 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3887 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3887 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3888 ('', 'only-branch', [],
3888 ('', 'only-branch', [],
3889 _('show only changesets within the given named branch (DEPRECATED)'),
3889 _('show only changesets within the given named branch (DEPRECATED)'),
3890 _('BRANCH')),
3890 _('BRANCH')),
3891 ('b', 'branch', [],
3891 ('b', 'branch', [],
3892 _('show changesets within the given named branch'), _('BRANCH')),
3892 _('show changesets within the given named branch'), _('BRANCH')),
3893 ('P', 'prune', [],
3893 ('P', 'prune', [],
3894 _('do not display revision or any of its ancestors'), _('REV')),
3894 _('do not display revision or any of its ancestors'), _('REV')),
3895 ] + logopts + walkopts,
3895 ] + logopts + walkopts,
3896 _('[OPTION]... [FILE]'))
3896 _('[OPTION]... [FILE]'))
3897 def log(ui, repo, *pats, **opts):
3897 def log(ui, repo, *pats, **opts):
3898 """show revision history of entire repository or files
3898 """show revision history of entire repository or files
3899
3899
3900 Print the revision history of the specified files or the entire
3900 Print the revision history of the specified files or the entire
3901 project.
3901 project.
3902
3902
3903 If no revision range is specified, the default is ``tip:0`` unless
3903 If no revision range is specified, the default is ``tip:0`` unless
3904 --follow is set, in which case the working directory parent is
3904 --follow is set, in which case the working directory parent is
3905 used as the starting revision.
3905 used as the starting revision.
3906
3906
3907 File history is shown without following rename or copy history of
3907 File history is shown without following rename or copy history of
3908 files. Use -f/--follow with a filename to follow history across
3908 files. Use -f/--follow with a filename to follow history across
3909 renames and copies. --follow without a filename will only show
3909 renames and copies. --follow without a filename will only show
3910 ancestors or descendants of the starting revision.
3910 ancestors or descendants of the starting revision.
3911
3911
3912 By default this command prints revision number and changeset id,
3912 By default this command prints revision number and changeset id,
3913 tags, non-trivial parents, user, date and time, and a summary for
3913 tags, non-trivial parents, user, date and time, and a summary for
3914 each commit. When the -v/--verbose switch is used, the list of
3914 each commit. When the -v/--verbose switch is used, the list of
3915 changed files and full commit message are shown.
3915 changed files and full commit message are shown.
3916
3916
3917 .. note::
3917 .. note::
3918 log -p/--patch may generate unexpected diff output for merge
3918 log -p/--patch may generate unexpected diff output for merge
3919 changesets, as it will only compare the merge changeset against
3919 changesets, as it will only compare the merge changeset against
3920 its first parent. Also, only files different from BOTH parents
3920 its first parent. Also, only files different from BOTH parents
3921 will appear in files:.
3921 will appear in files:.
3922
3922
3923 .. note::
3923 .. note::
3924 for performance reasons, log FILE may omit duplicate changes
3924 for performance reasons, log FILE may omit duplicate changes
3925 made on branches and will not show deletions. To see all
3925 made on branches and will not show deletions. To see all
3926 changes including duplicates and deletions, use the --removed
3926 changes including duplicates and deletions, use the --removed
3927 switch.
3927 switch.
3928
3928
3929 .. container:: verbose
3929 .. container:: verbose
3930
3930
3931 Some examples:
3931 Some examples:
3932
3932
3933 - changesets with full descriptions and file lists::
3933 - changesets with full descriptions and file lists::
3934
3934
3935 hg log -v
3935 hg log -v
3936
3936
3937 - changesets ancestral to the working directory::
3937 - changesets ancestral to the working directory::
3938
3938
3939 hg log -f
3939 hg log -f
3940
3940
3941 - last 10 commits on the current branch::
3941 - last 10 commits on the current branch::
3942
3942
3943 hg log -l 10 -b .
3943 hg log -l 10 -b .
3944
3944
3945 - changesets showing all modifications of a file, including removals::
3945 - changesets showing all modifications of a file, including removals::
3946
3946
3947 hg log --removed file.c
3947 hg log --removed file.c
3948
3948
3949 - all changesets that touch a directory, with diffs, excluding merges::
3949 - all changesets that touch a directory, with diffs, excluding merges::
3950
3950
3951 hg log -Mp lib/
3951 hg log -Mp lib/
3952
3952
3953 - all revision numbers that match a keyword::
3953 - all revision numbers that match a keyword::
3954
3954
3955 hg log -k bug --template "{rev}\\n"
3955 hg log -k bug --template "{rev}\\n"
3956
3956
3957 - check if a given changeset is included is a tagged release::
3957 - check if a given changeset is included is a tagged release::
3958
3958
3959 hg log -r "a21ccf and ancestor(1.9)"
3959 hg log -r "a21ccf and ancestor(1.9)"
3960
3960
3961 - find all changesets by some user in a date range::
3961 - find all changesets by some user in a date range::
3962
3962
3963 hg log -k alice -d "may 2008 to jul 2008"
3963 hg log -k alice -d "may 2008 to jul 2008"
3964
3964
3965 - summary of all changesets after the last tag::
3965 - summary of all changesets after the last tag::
3966
3966
3967 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3967 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3968
3968
3969 See :hg:`help dates` for a list of formats valid for -d/--date.
3969 See :hg:`help dates` for a list of formats valid for -d/--date.
3970
3970
3971 See :hg:`help revisions` and :hg:`help revsets` for more about
3971 See :hg:`help revisions` and :hg:`help revsets` for more about
3972 specifying revisions.
3972 specifying revisions.
3973
3973
3974 See :hg:`help templates` for more about pre-packaged styles and
3974 See :hg:`help templates` for more about pre-packaged styles and
3975 specifying custom templates.
3975 specifying custom templates.
3976
3976
3977 Returns 0 on success.
3977 Returns 0 on success.
3978 """
3978 """
3979 if opts.get('graph'):
3979 if opts.get('graph'):
3980 return cmdutil.graphlog(ui, repo, *pats, **opts)
3980 return cmdutil.graphlog(ui, repo, *pats, **opts)
3981
3981
3982 matchfn = scmutil.match(repo[None], pats, opts)
3982 matchfn = scmutil.match(repo[None], pats, opts)
3983 limit = cmdutil.loglimit(opts)
3983 limit = cmdutil.loglimit(opts)
3984 count = 0
3984 count = 0
3985
3985
3986 getrenamed, endrev = None, None
3986 getrenamed, endrev = None, None
3987 if opts.get('copies'):
3987 if opts.get('copies'):
3988 if opts.get('rev'):
3988 if opts.get('rev'):
3989 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3989 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3990 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3990 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3991
3991
3992 df = False
3992 df = False
3993 if opts.get("date"):
3993 if opts.get("date"):
3994 df = util.matchdate(opts["date"])
3994 df = util.matchdate(opts["date"])
3995
3995
3996 branches = opts.get('branch', []) + opts.get('only_branch', [])
3996 branches = opts.get('branch', []) + opts.get('only_branch', [])
3997 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3997 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3998
3998
3999 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3999 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4000 def prep(ctx, fns):
4000 def prep(ctx, fns):
4001 rev = ctx.rev()
4001 rev = ctx.rev()
4002 parents = [p for p in repo.changelog.parentrevs(rev)
4002 parents = [p for p in repo.changelog.parentrevs(rev)
4003 if p != nullrev]
4003 if p != nullrev]
4004 if opts.get('no_merges') and len(parents) == 2:
4004 if opts.get('no_merges') and len(parents) == 2:
4005 return
4005 return
4006 if opts.get('only_merges') and len(parents) != 2:
4006 if opts.get('only_merges') and len(parents) != 2:
4007 return
4007 return
4008 if opts.get('branch') and ctx.branch() not in opts['branch']:
4008 if opts.get('branch') and ctx.branch() not in opts['branch']:
4009 return
4009 return
4010 if df and not df(ctx.date()[0]):
4010 if df and not df(ctx.date()[0]):
4011 return
4011 return
4012
4012
4013 lower = encoding.lower
4013 lower = encoding.lower
4014 if opts.get('user'):
4014 if opts.get('user'):
4015 luser = lower(ctx.user())
4015 luser = lower(ctx.user())
4016 for k in [lower(x) for x in opts['user']]:
4016 for k in [lower(x) for x in opts['user']]:
4017 if (k in luser):
4017 if (k in luser):
4018 break
4018 break
4019 else:
4019 else:
4020 return
4020 return
4021 if opts.get('keyword'):
4021 if opts.get('keyword'):
4022 luser = lower(ctx.user())
4022 luser = lower(ctx.user())
4023 ldesc = lower(ctx.description())
4023 ldesc = lower(ctx.description())
4024 lfiles = lower(" ".join(ctx.files()))
4024 lfiles = lower(" ".join(ctx.files()))
4025 for k in [lower(x) for x in opts['keyword']]:
4025 for k in [lower(x) for x in opts['keyword']]:
4026 if (k in luser or k in ldesc or k in lfiles):
4026 if (k in luser or k in ldesc or k in lfiles):
4027 break
4027 break
4028 else:
4028 else:
4029 return
4029 return
4030
4030
4031 copies = None
4031 copies = None
4032 if getrenamed is not None and rev:
4032 if getrenamed is not None and rev:
4033 copies = []
4033 copies = []
4034 for fn in ctx.files():
4034 for fn in ctx.files():
4035 rename = getrenamed(fn, rev)
4035 rename = getrenamed(fn, rev)
4036 if rename:
4036 if rename:
4037 copies.append((fn, rename[0]))
4037 copies.append((fn, rename[0]))
4038
4038
4039 revmatchfn = None
4039 revmatchfn = None
4040 if opts.get('patch') or opts.get('stat'):
4040 if opts.get('patch') or opts.get('stat'):
4041 if opts.get('follow') or opts.get('follow_first'):
4041 if opts.get('follow') or opts.get('follow_first'):
4042 # note: this might be wrong when following through merges
4042 # note: this might be wrong when following through merges
4043 revmatchfn = scmutil.match(repo[None], fns, default='path')
4043 revmatchfn = scmutil.match(repo[None], fns, default='path')
4044 else:
4044 else:
4045 revmatchfn = matchfn
4045 revmatchfn = matchfn
4046
4046
4047 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4047 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4048
4048
4049 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4049 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4050 if displayer.flush(ctx.rev()):
4050 if displayer.flush(ctx.rev()):
4051 count += 1
4051 count += 1
4052 if count == limit:
4052 if count == limit:
4053 break
4053 break
4054 displayer.close()
4054 displayer.close()
4055
4055
4056 @command('manifest',
4056 @command('manifest',
4057 [('r', 'rev', '', _('revision to display'), _('REV')),
4057 [('r', 'rev', '', _('revision to display'), _('REV')),
4058 ('', 'all', False, _("list files from all revisions"))],
4058 ('', 'all', False, _("list files from all revisions"))],
4059 _('[-r REV]'))
4059 _('[-r REV]'))
4060 def manifest(ui, repo, node=None, rev=None, **opts):
4060 def manifest(ui, repo, node=None, rev=None, **opts):
4061 """output the current or given revision of the project manifest
4061 """output the current or given revision of the project manifest
4062
4062
4063 Print a list of version controlled files for the given revision.
4063 Print a list of version controlled files for the given revision.
4064 If no revision is given, the first parent of the working directory
4064 If no revision is given, the first parent of the working directory
4065 is used, or the null revision if no revision is checked out.
4065 is used, or the null revision if no revision is checked out.
4066
4066
4067 With -v, print file permissions, symlink and executable bits.
4067 With -v, print file permissions, symlink and executable bits.
4068 With --debug, print file revision hashes.
4068 With --debug, print file revision hashes.
4069
4069
4070 If option --all is specified, the list of all files from all revisions
4070 If option --all is specified, the list of all files from all revisions
4071 is printed. This includes deleted and renamed files.
4071 is printed. This includes deleted and renamed files.
4072
4072
4073 Returns 0 on success.
4073 Returns 0 on success.
4074 """
4074 """
4075
4075
4076 fm = ui.formatter('manifest', opts)
4076 fm = ui.formatter('manifest', opts)
4077
4077
4078 if opts.get('all'):
4078 if opts.get('all'):
4079 if rev or node:
4079 if rev or node:
4080 raise util.Abort(_("can't specify a revision with --all"))
4080 raise util.Abort(_("can't specify a revision with --all"))
4081
4081
4082 res = []
4082 res = []
4083 prefix = "data/"
4083 prefix = "data/"
4084 suffix = ".i"
4084 suffix = ".i"
4085 plen = len(prefix)
4085 plen = len(prefix)
4086 slen = len(suffix)
4086 slen = len(suffix)
4087 lock = repo.lock()
4087 lock = repo.lock()
4088 try:
4088 try:
4089 for fn, b, size in repo.store.datafiles():
4089 for fn, b, size in repo.store.datafiles():
4090 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4090 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4091 res.append(fn[plen:-slen])
4091 res.append(fn[plen:-slen])
4092 finally:
4092 finally:
4093 lock.release()
4093 lock.release()
4094 for f in res:
4094 for f in res:
4095 fm.startitem()
4095 fm.startitem()
4096 fm.write("path", '%s\n', f)
4096 fm.write("path", '%s\n', f)
4097 fm.end()
4097 fm.end()
4098 return
4098 return
4099
4099
4100 if rev and node:
4100 if rev and node:
4101 raise util.Abort(_("please specify just one revision"))
4101 raise util.Abort(_("please specify just one revision"))
4102
4102
4103 if not node:
4103 if not node:
4104 node = rev
4104 node = rev
4105
4105
4106 char = {'l': '@', 'x': '*', '': ''}
4106 char = {'l': '@', 'x': '*', '': ''}
4107 mode = {'l': '644', 'x': '755', '': '644'}
4107 mode = {'l': '644', 'x': '755', '': '644'}
4108 ctx = scmutil.revsingle(repo, node)
4108 ctx = scmutil.revsingle(repo, node)
4109 mf = ctx.manifest()
4109 mf = ctx.manifest()
4110 for f in ctx:
4110 for f in ctx:
4111 fm.startitem()
4111 fm.startitem()
4112 fl = ctx[f].flags()
4112 fl = ctx[f].flags()
4113 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4113 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4114 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4114 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4115 fm.write('path', '%s\n', f)
4115 fm.write('path', '%s\n', f)
4116 fm.end()
4116 fm.end()
4117
4117
4118 @command('^merge',
4118 @command('^merge',
4119 [('f', 'force', None, _('force a merge with outstanding changes')),
4119 [('f', 'force', None, _('force a merge with outstanding changes')),
4120 ('r', 'rev', '', _('revision to merge'), _('REV')),
4120 ('r', 'rev', '', _('revision to merge'), _('REV')),
4121 ('P', 'preview', None,
4121 ('P', 'preview', None,
4122 _('review revisions to merge (no merge is performed)'))
4122 _('review revisions to merge (no merge is performed)'))
4123 ] + mergetoolopts,
4123 ] + mergetoolopts,
4124 _('[-P] [-f] [[-r] REV]'))
4124 _('[-P] [-f] [[-r] REV]'))
4125 def merge(ui, repo, node=None, **opts):
4125 def merge(ui, repo, node=None, **opts):
4126 """merge working directory with another revision
4126 """merge working directory with another revision
4127
4127
4128 The current working directory is updated with all changes made in
4128 The current working directory is updated with all changes made in
4129 the requested revision since the last common predecessor revision.
4129 the requested revision since the last common predecessor revision.
4130
4130
4131 Files that changed between either parent are marked as changed for
4131 Files that changed between either parent are marked as changed for
4132 the next commit and a commit must be performed before any further
4132 the next commit and a commit must be performed before any further
4133 updates to the repository are allowed. The next commit will have
4133 updates to the repository are allowed. The next commit will have
4134 two parents.
4134 two parents.
4135
4135
4136 ``--tool`` can be used to specify the merge tool used for file
4136 ``--tool`` can be used to specify the merge tool used for file
4137 merges. It overrides the HGMERGE environment variable and your
4137 merges. It overrides the HGMERGE environment variable and your
4138 configuration files. See :hg:`help merge-tools` for options.
4138 configuration files. See :hg:`help merge-tools` for options.
4139
4139
4140 If no revision is specified, the working directory's parent is a
4140 If no revision is specified, the working directory's parent is a
4141 head revision, and the current branch contains exactly one other
4141 head revision, and the current branch contains exactly one other
4142 head, the other head is merged with by default. Otherwise, an
4142 head, the other head is merged with by default. Otherwise, an
4143 explicit revision with which to merge with must be provided.
4143 explicit revision with which to merge with must be provided.
4144
4144
4145 :hg:`resolve` must be used to resolve unresolved files.
4145 :hg:`resolve` must be used to resolve unresolved files.
4146
4146
4147 To undo an uncommitted merge, use :hg:`update --clean .` which
4147 To undo an uncommitted merge, use :hg:`update --clean .` which
4148 will check out a clean copy of the original merge parent, losing
4148 will check out a clean copy of the original merge parent, losing
4149 all changes.
4149 all changes.
4150
4150
4151 Returns 0 on success, 1 if there are unresolved files.
4151 Returns 0 on success, 1 if there are unresolved files.
4152 """
4152 """
4153
4153
4154 if opts.get('rev') and node:
4154 if opts.get('rev') and node:
4155 raise util.Abort(_("please specify just one revision"))
4155 raise util.Abort(_("please specify just one revision"))
4156 if not node:
4156 if not node:
4157 node = opts.get('rev')
4157 node = opts.get('rev')
4158
4158
4159 if node:
4159 if node:
4160 node = scmutil.revsingle(repo, node).node()
4160 node = scmutil.revsingle(repo, node).node()
4161
4161
4162 if not node and repo._bookmarkcurrent:
4162 if not node and repo._bookmarkcurrent:
4163 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4163 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4164 curhead = repo[repo._bookmarkcurrent].node()
4164 curhead = repo[repo._bookmarkcurrent].node()
4165 if len(bmheads) == 2:
4165 if len(bmheads) == 2:
4166 if curhead == bmheads[0]:
4166 if curhead == bmheads[0]:
4167 node = bmheads[1]
4167 node = bmheads[1]
4168 else:
4168 else:
4169 node = bmheads[0]
4169 node = bmheads[0]
4170 elif len(bmheads) > 2:
4170 elif len(bmheads) > 2:
4171 raise util.Abort(_("multiple matching bookmarks to merge - "
4171 raise util.Abort(_("multiple matching bookmarks to merge - "
4172 "please merge with an explicit rev or bookmark"),
4172 "please merge with an explicit rev or bookmark"),
4173 hint=_("run 'hg heads' to see all heads"))
4173 hint=_("run 'hg heads' to see all heads"))
4174 elif len(bmheads) <= 1:
4174 elif len(bmheads) <= 1:
4175 raise util.Abort(_("no matching bookmark to merge - "
4175 raise util.Abort(_("no matching bookmark to merge - "
4176 "please merge with an explicit rev or bookmark"),
4176 "please merge with an explicit rev or bookmark"),
4177 hint=_("run 'hg heads' to see all heads"))
4177 hint=_("run 'hg heads' to see all heads"))
4178
4178
4179 if not node and not repo._bookmarkcurrent:
4179 if not node and not repo._bookmarkcurrent:
4180 branch = repo[None].branch()
4180 branch = repo[None].branch()
4181 bheads = repo.branchheads(branch)
4181 bheads = repo.branchheads(branch)
4182 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4182 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4183
4183
4184 if len(nbhs) > 2:
4184 if len(nbhs) > 2:
4185 raise util.Abort(_("branch '%s' has %d heads - "
4185 raise util.Abort(_("branch '%s' has %d heads - "
4186 "please merge with an explicit rev")
4186 "please merge with an explicit rev")
4187 % (branch, len(bheads)),
4187 % (branch, len(bheads)),
4188 hint=_("run 'hg heads .' to see heads"))
4188 hint=_("run 'hg heads .' to see heads"))
4189
4189
4190 parent = repo.dirstate.p1()
4190 parent = repo.dirstate.p1()
4191 if len(nbhs) <= 1:
4191 if len(nbhs) <= 1:
4192 if len(bheads) > 1:
4192 if len(bheads) > 1:
4193 raise util.Abort(_("heads are bookmarked - "
4193 raise util.Abort(_("heads are bookmarked - "
4194 "please merge with an explicit rev"),
4194 "please merge with an explicit rev"),
4195 hint=_("run 'hg heads' to see all heads"))
4195 hint=_("run 'hg heads' to see all heads"))
4196 if len(repo.heads()) > 1:
4196 if len(repo.heads()) > 1:
4197 raise util.Abort(_("branch '%s' has one head - "
4197 raise util.Abort(_("branch '%s' has one head - "
4198 "please merge with an explicit rev")
4198 "please merge with an explicit rev")
4199 % branch,
4199 % branch,
4200 hint=_("run 'hg heads' to see all heads"))
4200 hint=_("run 'hg heads' to see all heads"))
4201 msg, hint = _('nothing to merge'), None
4201 msg, hint = _('nothing to merge'), None
4202 if parent != repo.lookup(branch):
4202 if parent != repo.lookup(branch):
4203 hint = _("use 'hg update' instead")
4203 hint = _("use 'hg update' instead")
4204 raise util.Abort(msg, hint=hint)
4204 raise util.Abort(msg, hint=hint)
4205
4205
4206 if parent not in bheads:
4206 if parent not in bheads:
4207 raise util.Abort(_('working directory not at a head revision'),
4207 raise util.Abort(_('working directory not at a head revision'),
4208 hint=_("use 'hg update' or merge with an "
4208 hint=_("use 'hg update' or merge with an "
4209 "explicit revision"))
4209 "explicit revision"))
4210 if parent == nbhs[0]:
4210 if parent == nbhs[0]:
4211 node = nbhs[-1]
4211 node = nbhs[-1]
4212 else:
4212 else:
4213 node = nbhs[0]
4213 node = nbhs[0]
4214
4214
4215 if opts.get('preview'):
4215 if opts.get('preview'):
4216 # find nodes that are ancestors of p2 but not of p1
4216 # find nodes that are ancestors of p2 but not of p1
4217 p1 = repo.lookup('.')
4217 p1 = repo.lookup('.')
4218 p2 = repo.lookup(node)
4218 p2 = repo.lookup(node)
4219 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4219 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4220
4220
4221 displayer = cmdutil.show_changeset(ui, repo, opts)
4221 displayer = cmdutil.show_changeset(ui, repo, opts)
4222 for node in nodes:
4222 for node in nodes:
4223 displayer.show(repo[node])
4223 displayer.show(repo[node])
4224 displayer.close()
4224 displayer.close()
4225 return 0
4225 return 0
4226
4226
4227 try:
4227 try:
4228 # ui.forcemerge is an internal variable, do not document
4228 # ui.forcemerge is an internal variable, do not document
4229 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4229 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4230 return hg.merge(repo, node, force=opts.get('force'))
4230 return hg.merge(repo, node, force=opts.get('force'))
4231 finally:
4231 finally:
4232 ui.setconfig('ui', 'forcemerge', '')
4232 ui.setconfig('ui', 'forcemerge', '')
4233
4233
4234 @command('outgoing|out',
4234 @command('outgoing|out',
4235 [('f', 'force', None, _('run even when the destination is unrelated')),
4235 [('f', 'force', None, _('run even when the destination is unrelated')),
4236 ('r', 'rev', [],
4236 ('r', 'rev', [],
4237 _('a changeset intended to be included in the destination'), _('REV')),
4237 _('a changeset intended to be included in the destination'), _('REV')),
4238 ('n', 'newest-first', None, _('show newest record first')),
4238 ('n', 'newest-first', None, _('show newest record first')),
4239 ('B', 'bookmarks', False, _('compare bookmarks')),
4239 ('B', 'bookmarks', False, _('compare bookmarks')),
4240 ('b', 'branch', [], _('a specific branch you would like to push'),
4240 ('b', 'branch', [], _('a specific branch you would like to push'),
4241 _('BRANCH')),
4241 _('BRANCH')),
4242 ] + logopts + remoteopts + subrepoopts,
4242 ] + logopts + remoteopts + subrepoopts,
4243 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4243 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4244 def outgoing(ui, repo, dest=None, **opts):
4244 def outgoing(ui, repo, dest=None, **opts):
4245 """show changesets not found in the destination
4245 """show changesets not found in the destination
4246
4246
4247 Show changesets not found in the specified destination repository
4247 Show changesets not found in the specified destination repository
4248 or the default push location. These are the changesets that would
4248 or the default push location. These are the changesets that would
4249 be pushed if a push was requested.
4249 be pushed if a push was requested.
4250
4250
4251 See pull for details of valid destination formats.
4251 See pull for details of valid destination formats.
4252
4252
4253 Returns 0 if there are outgoing changes, 1 otherwise.
4253 Returns 0 if there are outgoing changes, 1 otherwise.
4254 """
4254 """
4255 if opts.get('graph'):
4255 if opts.get('graph'):
4256 cmdutil.checkunsupportedgraphflags([], opts)
4256 cmdutil.checkunsupportedgraphflags([], opts)
4257 o = hg._outgoing(ui, repo, dest, opts)
4257 o = hg._outgoing(ui, repo, dest, opts)
4258 if o is None:
4258 if o is None:
4259 return
4259 return
4260
4260
4261 revdag = cmdutil.graphrevs(repo, o, opts)
4261 revdag = cmdutil.graphrevs(repo, o, opts)
4262 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4262 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4263 showparents = [ctx.node() for ctx in repo[None].parents()]
4263 showparents = [ctx.node() for ctx in repo[None].parents()]
4264 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4264 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4265 graphmod.asciiedges)
4265 graphmod.asciiedges)
4266 return 0
4266 return 0
4267
4267
4268 if opts.get('bookmarks'):
4268 if opts.get('bookmarks'):
4269 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4269 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4270 dest, branches = hg.parseurl(dest, opts.get('branch'))
4270 dest, branches = hg.parseurl(dest, opts.get('branch'))
4271 other = hg.peer(repo, opts, dest)
4271 other = hg.peer(repo, opts, dest)
4272 if 'bookmarks' not in other.listkeys('namespaces'):
4272 if 'bookmarks' not in other.listkeys('namespaces'):
4273 ui.warn(_("remote doesn't support bookmarks\n"))
4273 ui.warn(_("remote doesn't support bookmarks\n"))
4274 return 0
4274 return 0
4275 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4275 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4276 return bookmarks.diff(ui, other, repo)
4276 return bookmarks.diff(ui, other, repo)
4277
4277
4278 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4278 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4279 try:
4279 try:
4280 return hg.outgoing(ui, repo, dest, opts)
4280 return hg.outgoing(ui, repo, dest, opts)
4281 finally:
4281 finally:
4282 del repo._subtoppath
4282 del repo._subtoppath
4283
4283
4284 @command('parents',
4284 @command('parents',
4285 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4285 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4286 ] + templateopts,
4286 ] + templateopts,
4287 _('[-r REV] [FILE]'))
4287 _('[-r REV] [FILE]'))
4288 def parents(ui, repo, file_=None, **opts):
4288 def parents(ui, repo, file_=None, **opts):
4289 """show the parents of the working directory or revision
4289 """show the parents of the working directory or revision
4290
4290
4291 Print the working directory's parent revisions. If a revision is
4291 Print the working directory's parent revisions. If a revision is
4292 given via -r/--rev, the parent of that revision will be printed.
4292 given via -r/--rev, the parent of that revision will be printed.
4293 If a file argument is given, the revision in which the file was
4293 If a file argument is given, the revision in which the file was
4294 last changed (before the working directory revision or the
4294 last changed (before the working directory revision or the
4295 argument to --rev if given) is printed.
4295 argument to --rev if given) is printed.
4296
4296
4297 Returns 0 on success.
4297 Returns 0 on success.
4298 """
4298 """
4299
4299
4300 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4300 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4301
4301
4302 if file_:
4302 if file_:
4303 m = scmutil.match(ctx, (file_,), opts)
4303 m = scmutil.match(ctx, (file_,), opts)
4304 if m.anypats() or len(m.files()) != 1:
4304 if m.anypats() or len(m.files()) != 1:
4305 raise util.Abort(_('can only specify an explicit filename'))
4305 raise util.Abort(_('can only specify an explicit filename'))
4306 file_ = m.files()[0]
4306 file_ = m.files()[0]
4307 filenodes = []
4307 filenodes = []
4308 for cp in ctx.parents():
4308 for cp in ctx.parents():
4309 if not cp:
4309 if not cp:
4310 continue
4310 continue
4311 try:
4311 try:
4312 filenodes.append(cp.filenode(file_))
4312 filenodes.append(cp.filenode(file_))
4313 except error.LookupError:
4313 except error.LookupError:
4314 pass
4314 pass
4315 if not filenodes:
4315 if not filenodes:
4316 raise util.Abort(_("'%s' not found in manifest!") % file_)
4316 raise util.Abort(_("'%s' not found in manifest!") % file_)
4317 fl = repo.file(file_)
4317 fl = repo.file(file_)
4318 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4318 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4319 else:
4319 else:
4320 p = [cp.node() for cp in ctx.parents()]
4320 p = [cp.node() for cp in ctx.parents()]
4321
4321
4322 displayer = cmdutil.show_changeset(ui, repo, opts)
4322 displayer = cmdutil.show_changeset(ui, repo, opts)
4323 for n in p:
4323 for n in p:
4324 if n != nullid:
4324 if n != nullid:
4325 displayer.show(repo[n])
4325 displayer.show(repo[n])
4326 displayer.close()
4326 displayer.close()
4327
4327
4328 @command('paths', [], _('[NAME]'))
4328 @command('paths', [], _('[NAME]'))
4329 def paths(ui, repo, search=None):
4329 def paths(ui, repo, search=None):
4330 """show aliases for remote repositories
4330 """show aliases for remote repositories
4331
4331
4332 Show definition of symbolic path name NAME. If no name is given,
4332 Show definition of symbolic path name NAME. If no name is given,
4333 show definition of all available names.
4333 show definition of all available names.
4334
4334
4335 Option -q/--quiet suppresses all output when searching for NAME
4335 Option -q/--quiet suppresses all output when searching for NAME
4336 and shows only the path names when listing all definitions.
4336 and shows only the path names when listing all definitions.
4337
4337
4338 Path names are defined in the [paths] section of your
4338 Path names are defined in the [paths] section of your
4339 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4339 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4340 repository, ``.hg/hgrc`` is used, too.
4340 repository, ``.hg/hgrc`` is used, too.
4341
4341
4342 The path names ``default`` and ``default-push`` have a special
4342 The path names ``default`` and ``default-push`` have a special
4343 meaning. When performing a push or pull operation, they are used
4343 meaning. When performing a push or pull operation, they are used
4344 as fallbacks if no location is specified on the command-line.
4344 as fallbacks if no location is specified on the command-line.
4345 When ``default-push`` is set, it will be used for push and
4345 When ``default-push`` is set, it will be used for push and
4346 ``default`` will be used for pull; otherwise ``default`` is used
4346 ``default`` will be used for pull; otherwise ``default`` is used
4347 as the fallback for both. When cloning a repository, the clone
4347 as the fallback for both. When cloning a repository, the clone
4348 source is written as ``default`` in ``.hg/hgrc``. Note that
4348 source is written as ``default`` in ``.hg/hgrc``. Note that
4349 ``default`` and ``default-push`` apply to all inbound (e.g.
4349 ``default`` and ``default-push`` apply to all inbound (e.g.
4350 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4350 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4351 :hg:`bundle`) operations.
4351 :hg:`bundle`) operations.
4352
4352
4353 See :hg:`help urls` for more information.
4353 See :hg:`help urls` for more information.
4354
4354
4355 Returns 0 on success.
4355 Returns 0 on success.
4356 """
4356 """
4357 if search:
4357 if search:
4358 for name, path in ui.configitems("paths"):
4358 for name, path in ui.configitems("paths"):
4359 if name == search:
4359 if name == search:
4360 ui.status("%s\n" % util.hidepassword(path))
4360 ui.status("%s\n" % util.hidepassword(path))
4361 return
4361 return
4362 if not ui.quiet:
4362 if not ui.quiet:
4363 ui.warn(_("not found!\n"))
4363 ui.warn(_("not found!\n"))
4364 return 1
4364 return 1
4365 else:
4365 else:
4366 for name, path in ui.configitems("paths"):
4366 for name, path in ui.configitems("paths"):
4367 if ui.quiet:
4367 if ui.quiet:
4368 ui.write("%s\n" % name)
4368 ui.write("%s\n" % name)
4369 else:
4369 else:
4370 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4370 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4371
4371
4372 @command('phase',
4372 @command('phase',
4373 [('p', 'public', False, _('set changeset phase to public')),
4373 [('p', 'public', False, _('set changeset phase to public')),
4374 ('d', 'draft', False, _('set changeset phase to draft')),
4374 ('d', 'draft', False, _('set changeset phase to draft')),
4375 ('s', 'secret', False, _('set changeset phase to secret')),
4375 ('s', 'secret', False, _('set changeset phase to secret')),
4376 ('f', 'force', False, _('allow to move boundary backward')),
4376 ('f', 'force', False, _('allow to move boundary backward')),
4377 ('r', 'rev', [], _('target revision'), _('REV')),
4377 ('r', 'rev', [], _('target revision'), _('REV')),
4378 ],
4378 ],
4379 _('[-p|-d|-s] [-f] [-r] REV...'))
4379 _('[-p|-d|-s] [-f] [-r] REV...'))
4380 def phase(ui, repo, *revs, **opts):
4380 def phase(ui, repo, *revs, **opts):
4381 """set or show the current phase name
4381 """set or show the current phase name
4382
4382
4383 With no argument, show the phase name of specified revisions.
4383 With no argument, show the phase name of specified revisions.
4384
4384
4385 With one of -p/--public, -d/--draft or -s/--secret, change the
4385 With one of -p/--public, -d/--draft or -s/--secret, change the
4386 phase value of the specified revisions.
4386 phase value of the specified revisions.
4387
4387
4388 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4388 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4389 lower phase to an higher phase. Phases are ordered as follows::
4389 lower phase to an higher phase. Phases are ordered as follows::
4390
4390
4391 public < draft < secret
4391 public < draft < secret
4392
4392
4393 Return 0 on success, 1 if no phases were changed or some could not
4393 Return 0 on success, 1 if no phases were changed or some could not
4394 be changed.
4394 be changed.
4395 """
4395 """
4396 # search for a unique phase argument
4396 # search for a unique phase argument
4397 targetphase = None
4397 targetphase = None
4398 for idx, name in enumerate(phases.phasenames):
4398 for idx, name in enumerate(phases.phasenames):
4399 if opts[name]:
4399 if opts[name]:
4400 if targetphase is not None:
4400 if targetphase is not None:
4401 raise util.Abort(_('only one phase can be specified'))
4401 raise util.Abort(_('only one phase can be specified'))
4402 targetphase = idx
4402 targetphase = idx
4403
4403
4404 # look for specified revision
4404 # look for specified revision
4405 revs = list(revs)
4405 revs = list(revs)
4406 revs.extend(opts['rev'])
4406 revs.extend(opts['rev'])
4407 if not revs:
4407 if not revs:
4408 raise util.Abort(_('no revisions specified'))
4408 raise util.Abort(_('no revisions specified'))
4409
4409
4410 revs = scmutil.revrange(repo, revs)
4410 revs = scmutil.revrange(repo, revs)
4411
4411
4412 lock = None
4412 lock = None
4413 ret = 0
4413 ret = 0
4414 if targetphase is None:
4414 if targetphase is None:
4415 # display
4415 # display
4416 for r in revs:
4416 for r in revs:
4417 ctx = repo[r]
4417 ctx = repo[r]
4418 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4418 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4419 else:
4419 else:
4420 lock = repo.lock()
4420 lock = repo.lock()
4421 try:
4421 try:
4422 # set phase
4422 # set phase
4423 if not revs:
4423 if not revs:
4424 raise util.Abort(_('empty revision set'))
4424 raise util.Abort(_('empty revision set'))
4425 nodes = [repo[r].node() for r in revs]
4425 nodes = [repo[r].node() for r in revs]
4426 olddata = repo._phasecache.getphaserevs(repo)[:]
4426 olddata = repo._phasecache.getphaserevs(repo)[:]
4427 phases.advanceboundary(repo, targetphase, nodes)
4427 phases.advanceboundary(repo, targetphase, nodes)
4428 if opts['force']:
4428 if opts['force']:
4429 phases.retractboundary(repo, targetphase, nodes)
4429 phases.retractboundary(repo, targetphase, nodes)
4430 finally:
4430 finally:
4431 lock.release()
4431 lock.release()
4432 # moving revision from public to draft may hide them
4432 # moving revision from public to draft may hide them
4433 # We have to check result on an unfiltered repository
4433 # We have to check result on an unfiltered repository
4434 unfi = repo.unfiltered()
4434 unfi = repo.unfiltered()
4435 newdata = repo._phasecache.getphaserevs(unfi)
4435 newdata = repo._phasecache.getphaserevs(unfi)
4436 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4436 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4437 cl = unfi.changelog
4437 cl = unfi.changelog
4438 rejected = [n for n in nodes
4438 rejected = [n for n in nodes
4439 if newdata[cl.rev(n)] < targetphase]
4439 if newdata[cl.rev(n)] < targetphase]
4440 if rejected:
4440 if rejected:
4441 ui.warn(_('cannot move %i changesets to a more permissive '
4441 ui.warn(_('cannot move %i changesets to a more permissive '
4442 'phase, use --force\n') % len(rejected))
4442 'phase, use --force\n') % len(rejected))
4443 ret = 1
4443 ret = 1
4444 if changes:
4444 if changes:
4445 msg = _('phase changed for %i changesets\n') % changes
4445 msg = _('phase changed for %i changesets\n') % changes
4446 if ret:
4446 if ret:
4447 ui.status(msg)
4447 ui.status(msg)
4448 else:
4448 else:
4449 ui.note(msg)
4449 ui.note(msg)
4450 else:
4450 else:
4451 ui.warn(_('no phases changed\n'))
4451 ui.warn(_('no phases changed\n'))
4452 ret = 1
4452 ret = 1
4453 return ret
4453 return ret
4454
4454
4455 def postincoming(ui, repo, modheads, optupdate, checkout):
4455 def postincoming(ui, repo, modheads, optupdate, checkout):
4456 if modheads == 0:
4456 if modheads == 0:
4457 return
4457 return
4458 if optupdate:
4458 if optupdate:
4459 movemarkfrom = repo['.'].node()
4459 movemarkfrom = repo['.'].node()
4460 try:
4460 try:
4461 ret = hg.update(repo, checkout)
4461 ret = hg.update(repo, checkout)
4462 except util.Abort, inst:
4462 except util.Abort, inst:
4463 ui.warn(_("not updating: %s\n") % str(inst))
4463 ui.warn(_("not updating: %s\n") % str(inst))
4464 return 0
4464 return 0
4465 if not ret and not checkout:
4465 if not ret and not checkout:
4466 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4466 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4467 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4467 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4468 return ret
4468 return ret
4469 if modheads > 1:
4469 if modheads > 1:
4470 currentbranchheads = len(repo.branchheads())
4470 currentbranchheads = len(repo.branchheads())
4471 if currentbranchheads == modheads:
4471 if currentbranchheads == modheads:
4472 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4472 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4473 elif currentbranchheads > 1:
4473 elif currentbranchheads > 1:
4474 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4474 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4475 "merge)\n"))
4475 "merge)\n"))
4476 else:
4476 else:
4477 ui.status(_("(run 'hg heads' to see heads)\n"))
4477 ui.status(_("(run 'hg heads' to see heads)\n"))
4478 else:
4478 else:
4479 ui.status(_("(run 'hg update' to get a working copy)\n"))
4479 ui.status(_("(run 'hg update' to get a working copy)\n"))
4480
4480
4481 @command('^pull',
4481 @command('^pull',
4482 [('u', 'update', None,
4482 [('u', 'update', None,
4483 _('update to new branch head if changesets were pulled')),
4483 _('update to new branch head if changesets were pulled')),
4484 ('f', 'force', None, _('run even when remote repository is unrelated')),
4484 ('f', 'force', None, _('run even when remote repository is unrelated')),
4485 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4485 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4486 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4486 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4487 ('b', 'branch', [], _('a specific branch you would like to pull'),
4487 ('b', 'branch', [], _('a specific branch you would like to pull'),
4488 _('BRANCH')),
4488 _('BRANCH')),
4489 ] + remoteopts,
4489 ] + remoteopts,
4490 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4490 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4491 def pull(ui, repo, source="default", **opts):
4491 def pull(ui, repo, source="default", **opts):
4492 """pull changes from the specified source
4492 """pull changes from the specified source
4493
4493
4494 Pull changes from a remote repository to a local one.
4494 Pull changes from a remote repository to a local one.
4495
4495
4496 This finds all changes from the repository at the specified path
4496 This finds all changes from the repository at the specified path
4497 or URL and adds them to a local repository (the current one unless
4497 or URL and adds them to a local repository (the current one unless
4498 -R is specified). By default, this does not update the copy of the
4498 -R is specified). By default, this does not update the copy of the
4499 project in the working directory.
4499 project in the working directory.
4500
4500
4501 Use :hg:`incoming` if you want to see what would have been added
4501 Use :hg:`incoming` if you want to see what would have been added
4502 by a pull at the time you issued this command. If you then decide
4502 by a pull at the time you issued this command. If you then decide
4503 to add those changes to the repository, you should use :hg:`pull
4503 to add those changes to the repository, you should use :hg:`pull
4504 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4504 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4505
4505
4506 If SOURCE is omitted, the 'default' path will be used.
4506 If SOURCE is omitted, the 'default' path will be used.
4507 See :hg:`help urls` for more information.
4507 See :hg:`help urls` for more information.
4508
4508
4509 Returns 0 on success, 1 if an update had unresolved files.
4509 Returns 0 on success, 1 if an update had unresolved files.
4510 """
4510 """
4511 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4511 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4512 other = hg.peer(repo, opts, source)
4512 other = hg.peer(repo, opts, source)
4513 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4513 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4514 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4514 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4515
4515
4516 remotebookmarks = other.listkeys('bookmarks')
4516 remotebookmarks = other.listkeys('bookmarks')
4517
4517
4518 if opts.get('bookmark'):
4518 if opts.get('bookmark'):
4519 if not revs:
4519 if not revs:
4520 revs = []
4520 revs = []
4521 for b in opts['bookmark']:
4521 for b in opts['bookmark']:
4522 if b not in remotebookmarks:
4522 if b not in remotebookmarks:
4523 raise util.Abort(_('remote bookmark %s not found!') % b)
4523 raise util.Abort(_('remote bookmark %s not found!') % b)
4524 revs.append(remotebookmarks[b])
4524 revs.append(remotebookmarks[b])
4525
4525
4526 if revs:
4526 if revs:
4527 try:
4527 try:
4528 revs = [other.lookup(rev) for rev in revs]
4528 revs = [other.lookup(rev) for rev in revs]
4529 except error.CapabilityError:
4529 except error.CapabilityError:
4530 err = _("other repository doesn't support revision lookup, "
4530 err = _("other repository doesn't support revision lookup, "
4531 "so a rev cannot be specified.")
4531 "so a rev cannot be specified.")
4532 raise util.Abort(err)
4532 raise util.Abort(err)
4533
4533
4534 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4534 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4535 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4535 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4536 if checkout:
4536 if checkout:
4537 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4537 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4538 repo._subtoppath = source
4538 repo._subtoppath = source
4539 try:
4539 try:
4540 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4540 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4541
4541
4542 finally:
4542 finally:
4543 del repo._subtoppath
4543 del repo._subtoppath
4544
4544
4545 # update specified bookmarks
4545 # update specified bookmarks
4546 if opts.get('bookmark'):
4546 if opts.get('bookmark'):
4547 marks = repo._bookmarks
4547 marks = repo._bookmarks
4548 for b in opts['bookmark']:
4548 for b in opts['bookmark']:
4549 # explicit pull overrides local bookmark if any
4549 # explicit pull overrides local bookmark if any
4550 ui.status(_("importing bookmark %s\n") % b)
4550 ui.status(_("importing bookmark %s\n") % b)
4551 marks[b] = repo[remotebookmarks[b]].node()
4551 marks[b] = repo[remotebookmarks[b]].node()
4552 marks.write()
4552 marks.write()
4553
4553
4554 return ret
4554 return ret
4555
4555
4556 @command('^push',
4556 @command('^push',
4557 [('f', 'force', None, _('force push')),
4557 [('f', 'force', None, _('force push')),
4558 ('r', 'rev', [],
4558 ('r', 'rev', [],
4559 _('a changeset intended to be included in the destination'),
4559 _('a changeset intended to be included in the destination'),
4560 _('REV')),
4560 _('REV')),
4561 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4561 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4562 ('b', 'branch', [],
4562 ('b', 'branch', [],
4563 _('a specific branch you would like to push'), _('BRANCH')),
4563 _('a specific branch you would like to push'), _('BRANCH')),
4564 ('', 'new-branch', False, _('allow pushing a new branch')),
4564 ('', 'new-branch', False, _('allow pushing a new branch')),
4565 ] + remoteopts,
4565 ] + remoteopts,
4566 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4566 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4567 def push(ui, repo, dest=None, **opts):
4567 def push(ui, repo, dest=None, **opts):
4568 """push changes to the specified destination
4568 """push changes to the specified destination
4569
4569
4570 Push changesets from the local repository to the specified
4570 Push changesets from the local repository to the specified
4571 destination.
4571 destination.
4572
4572
4573 This operation is symmetrical to pull: it is identical to a pull
4573 This operation is symmetrical to pull: it is identical to a pull
4574 in the destination repository from the current one.
4574 in the destination repository from the current one.
4575
4575
4576 By default, push will not allow creation of new heads at the
4576 By default, push will not allow creation of new heads at the
4577 destination, since multiple heads would make it unclear which head
4577 destination, since multiple heads would make it unclear which head
4578 to use. In this situation, it is recommended to pull and merge
4578 to use. In this situation, it is recommended to pull and merge
4579 before pushing.
4579 before pushing.
4580
4580
4581 Use --new-branch if you want to allow push to create a new named
4581 Use --new-branch if you want to allow push to create a new named
4582 branch that is not present at the destination. This allows you to
4582 branch that is not present at the destination. This allows you to
4583 only create a new branch without forcing other changes.
4583 only create a new branch without forcing other changes.
4584
4584
4585 Use -f/--force to override the default behavior and push all
4585 Use -f/--force to override the default behavior and push all
4586 changesets on all branches.
4586 changesets on all branches.
4587
4587
4588 If -r/--rev is used, the specified revision and all its ancestors
4588 If -r/--rev is used, the specified revision and all its ancestors
4589 will be pushed to the remote repository.
4589 will be pushed to the remote repository.
4590
4590
4591 If -B/--bookmark is used, the specified bookmarked revision, its
4591 If -B/--bookmark is used, the specified bookmarked revision, its
4592 ancestors, and the bookmark will be pushed to the remote
4592 ancestors, and the bookmark will be pushed to the remote
4593 repository.
4593 repository.
4594
4594
4595 Please see :hg:`help urls` for important details about ``ssh://``
4595 Please see :hg:`help urls` for important details about ``ssh://``
4596 URLs. If DESTINATION is omitted, a default path will be used.
4596 URLs. If DESTINATION is omitted, a default path will be used.
4597
4597
4598 Returns 0 if push was successful, 1 if nothing to push.
4598 Returns 0 if push was successful, 1 if nothing to push.
4599 """
4599 """
4600
4600
4601 if opts.get('bookmark'):
4601 if opts.get('bookmark'):
4602 for b in opts['bookmark']:
4602 for b in opts['bookmark']:
4603 # translate -B options to -r so changesets get pushed
4603 # translate -B options to -r so changesets get pushed
4604 if b in repo._bookmarks:
4604 if b in repo._bookmarks:
4605 opts.setdefault('rev', []).append(b)
4605 opts.setdefault('rev', []).append(b)
4606 else:
4606 else:
4607 # if we try to push a deleted bookmark, translate it to null
4607 # if we try to push a deleted bookmark, translate it to null
4608 # this lets simultaneous -r, -b options continue working
4608 # this lets simultaneous -r, -b options continue working
4609 opts.setdefault('rev', []).append("null")
4609 opts.setdefault('rev', []).append("null")
4610
4610
4611 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4611 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4612 dest, branches = hg.parseurl(dest, opts.get('branch'))
4612 dest, branches = hg.parseurl(dest, opts.get('branch'))
4613 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4613 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4614 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4614 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4615 other = hg.peer(repo, opts, dest)
4615 other = hg.peer(repo, opts, dest)
4616 if revs:
4616 if revs:
4617 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4617 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4618
4618
4619 repo._subtoppath = dest
4619 repo._subtoppath = dest
4620 try:
4620 try:
4621 # push subrepos depth-first for coherent ordering
4621 # push subrepos depth-first for coherent ordering
4622 c = repo['']
4622 c = repo['']
4623 subs = c.substate # only repos that are committed
4623 subs = c.substate # only repos that are committed
4624 for s in sorted(subs):
4624 for s in sorted(subs):
4625 if c.sub(s).push(opts) == 0:
4625 if c.sub(s).push(opts) == 0:
4626 return False
4626 return False
4627 finally:
4627 finally:
4628 del repo._subtoppath
4628 del repo._subtoppath
4629 result = repo.push(other, opts.get('force'), revs=revs,
4629 result = repo.push(other, opts.get('force'), revs=revs,
4630 newbranch=opts.get('new_branch'))
4630 newbranch=opts.get('new_branch'))
4631
4631
4632 result = not result
4632 result = not result
4633
4633
4634 if opts.get('bookmark'):
4634 if opts.get('bookmark'):
4635 rb = other.listkeys('bookmarks')
4635 rb = other.listkeys('bookmarks')
4636 for b in opts['bookmark']:
4636 for b in opts['bookmark']:
4637 # explicit push overrides remote bookmark if any
4637 # explicit push overrides remote bookmark if any
4638 if b in repo._bookmarks:
4638 if b in repo._bookmarks:
4639 ui.status(_("exporting bookmark %s\n") % b)
4639 ui.status(_("exporting bookmark %s\n") % b)
4640 new = repo[b].hex()
4640 new = repo[b].hex()
4641 elif b in rb:
4641 elif b in rb:
4642 ui.status(_("deleting remote bookmark %s\n") % b)
4642 ui.status(_("deleting remote bookmark %s\n") % b)
4643 new = '' # delete
4643 new = '' # delete
4644 else:
4644 else:
4645 ui.warn(_('bookmark %s does not exist on the local '
4645 ui.warn(_('bookmark %s does not exist on the local '
4646 'or remote repository!\n') % b)
4646 'or remote repository!\n') % b)
4647 return 2
4647 return 2
4648 old = rb.get(b, '')
4648 old = rb.get(b, '')
4649 r = other.pushkey('bookmarks', b, old, new)
4649 r = other.pushkey('bookmarks', b, old, new)
4650 if not r:
4650 if not r:
4651 ui.warn(_('updating bookmark %s failed!\n') % b)
4651 ui.warn(_('updating bookmark %s failed!\n') % b)
4652 if not result:
4652 if not result:
4653 result = 2
4653 result = 2
4654
4654
4655 return result
4655 return result
4656
4656
4657 @command('recover', [])
4657 @command('recover', [])
4658 def recover(ui, repo):
4658 def recover(ui, repo):
4659 """roll back an interrupted transaction
4659 """roll back an interrupted transaction
4660
4660
4661 Recover from an interrupted commit or pull.
4661 Recover from an interrupted commit or pull.
4662
4662
4663 This command tries to fix the repository status after an
4663 This command tries to fix the repository status after an
4664 interrupted operation. It should only be necessary when Mercurial
4664 interrupted operation. It should only be necessary when Mercurial
4665 suggests it.
4665 suggests it.
4666
4666
4667 Returns 0 if successful, 1 if nothing to recover or verify fails.
4667 Returns 0 if successful, 1 if nothing to recover or verify fails.
4668 """
4668 """
4669 if repo.recover():
4669 if repo.recover():
4670 return hg.verify(repo)
4670 return hg.verify(repo)
4671 return 1
4671 return 1
4672
4672
4673 @command('^remove|rm',
4673 @command('^remove|rm',
4674 [('A', 'after', None, _('record delete for missing files')),
4674 [('A', 'after', None, _('record delete for missing files')),
4675 ('f', 'force', None,
4675 ('f', 'force', None,
4676 _('remove (and delete) file even if added or modified')),
4676 _('remove (and delete) file even if added or modified')),
4677 ] + walkopts,
4677 ] + walkopts,
4678 _('[OPTION]... FILE...'))
4678 _('[OPTION]... FILE...'))
4679 def remove(ui, repo, *pats, **opts):
4679 def remove(ui, repo, *pats, **opts):
4680 """remove the specified files on the next commit
4680 """remove the specified files on the next commit
4681
4681
4682 Schedule the indicated files for removal from the current branch.
4682 Schedule the indicated files for removal from the current branch.
4683
4683
4684 This command schedules the files to be removed at the next commit.
4684 This command schedules the files to be removed at the next commit.
4685 To undo a remove before that, see :hg:`revert`. To undo added
4685 To undo a remove before that, see :hg:`revert`. To undo added
4686 files, see :hg:`forget`.
4686 files, see :hg:`forget`.
4687
4687
4688 .. container:: verbose
4688 .. container:: verbose
4689
4689
4690 -A/--after can be used to remove only files that have already
4690 -A/--after can be used to remove only files that have already
4691 been deleted, -f/--force can be used to force deletion, and -Af
4691 been deleted, -f/--force can be used to force deletion, and -Af
4692 can be used to remove files from the next revision without
4692 can be used to remove files from the next revision without
4693 deleting them from the working directory.
4693 deleting them from the working directory.
4694
4694
4695 The following table details the behavior of remove for different
4695 The following table details the behavior of remove for different
4696 file states (columns) and option combinations (rows). The file
4696 file states (columns) and option combinations (rows). The file
4697 states are Added [A], Clean [C], Modified [M] and Missing [!]
4697 states are Added [A], Clean [C], Modified [M] and Missing [!]
4698 (as reported by :hg:`status`). The actions are Warn, Remove
4698 (as reported by :hg:`status`). The actions are Warn, Remove
4699 (from branch) and Delete (from disk):
4699 (from branch) and Delete (from disk):
4700
4700
4701 ======= == == == ==
4701 ======= == == == ==
4702 A C M !
4702 A C M !
4703 ======= == == == ==
4703 ======= == == == ==
4704 none W RD W R
4704 none W RD W R
4705 -f R RD RD R
4705 -f R RD RD R
4706 -A W W W R
4706 -A W W W R
4707 -Af R R R R
4707 -Af R R R R
4708 ======= == == == ==
4708 ======= == == == ==
4709
4709
4710 Note that remove never deletes files in Added [A] state from the
4710 Note that remove never deletes files in Added [A] state from the
4711 working directory, not even if option --force is specified.
4711 working directory, not even if option --force is specified.
4712
4712
4713 Returns 0 on success, 1 if any warnings encountered.
4713 Returns 0 on success, 1 if any warnings encountered.
4714 """
4714 """
4715
4715
4716 ret = 0
4716 ret = 0
4717 after, force = opts.get('after'), opts.get('force')
4717 after, force = opts.get('after'), opts.get('force')
4718 if not pats and not after:
4718 if not pats and not after:
4719 raise util.Abort(_('no files specified'))
4719 raise util.Abort(_('no files specified'))
4720
4720
4721 m = scmutil.match(repo[None], pats, opts)
4721 m = scmutil.match(repo[None], pats, opts)
4722 s = repo.status(match=m, clean=True)
4722 s = repo.status(match=m, clean=True)
4723 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4723 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4724
4724
4725 # warn about failure to delete explicit files/dirs
4725 # warn about failure to delete explicit files/dirs
4726 wctx = repo[None]
4726 wctx = repo[None]
4727 for f in m.files():
4727 for f in m.files():
4728 if f in repo.dirstate or f in wctx.dirs():
4728 if f in repo.dirstate or f in wctx.dirs():
4729 continue
4729 continue
4730 if os.path.exists(m.rel(f)):
4730 if os.path.exists(m.rel(f)):
4731 if os.path.isdir(m.rel(f)):
4731 if os.path.isdir(m.rel(f)):
4732 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4732 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4733 else:
4733 else:
4734 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4734 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4735 # missing files will generate a warning elsewhere
4735 # missing files will generate a warning elsewhere
4736 ret = 1
4736 ret = 1
4737
4737
4738 if force:
4738 if force:
4739 list = modified + deleted + clean + added
4739 list = modified + deleted + clean + added
4740 elif after:
4740 elif after:
4741 list = deleted
4741 list = deleted
4742 for f in modified + added + clean:
4742 for f in modified + added + clean:
4743 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4743 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4744 ret = 1
4744 ret = 1
4745 else:
4745 else:
4746 list = deleted + clean
4746 list = deleted + clean
4747 for f in modified:
4747 for f in modified:
4748 ui.warn(_('not removing %s: file is modified (use -f'
4748 ui.warn(_('not removing %s: file is modified (use -f'
4749 ' to force removal)\n') % m.rel(f))
4749 ' to force removal)\n') % m.rel(f))
4750 ret = 1
4750 ret = 1
4751 for f in added:
4751 for f in added:
4752 ui.warn(_('not removing %s: file has been marked for add'
4752 ui.warn(_('not removing %s: file has been marked for add'
4753 ' (use forget to undo)\n') % m.rel(f))
4753 ' (use forget to undo)\n') % m.rel(f))
4754 ret = 1
4754 ret = 1
4755
4755
4756 for f in sorted(list):
4756 for f in sorted(list):
4757 if ui.verbose or not m.exact(f):
4757 if ui.verbose or not m.exact(f):
4758 ui.status(_('removing %s\n') % m.rel(f))
4758 ui.status(_('removing %s\n') % m.rel(f))
4759
4759
4760 wlock = repo.wlock()
4760 wlock = repo.wlock()
4761 try:
4761 try:
4762 if not after:
4762 if not after:
4763 for f in list:
4763 for f in list:
4764 if f in added:
4764 if f in added:
4765 continue # we never unlink added files on remove
4765 continue # we never unlink added files on remove
4766 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4766 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4767 repo[None].forget(list)
4767 repo[None].forget(list)
4768 finally:
4768 finally:
4769 wlock.release()
4769 wlock.release()
4770
4770
4771 return ret
4771 return ret
4772
4772
4773 @command('rename|move|mv',
4773 @command('rename|move|mv',
4774 [('A', 'after', None, _('record a rename that has already occurred')),
4774 [('A', 'after', None, _('record a rename that has already occurred')),
4775 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4775 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4776 ] + walkopts + dryrunopts,
4776 ] + walkopts + dryrunopts,
4777 _('[OPTION]... SOURCE... DEST'))
4777 _('[OPTION]... SOURCE... DEST'))
4778 def rename(ui, repo, *pats, **opts):
4778 def rename(ui, repo, *pats, **opts):
4779 """rename files; equivalent of copy + remove
4779 """rename files; equivalent of copy + remove
4780
4780
4781 Mark dest as copies of sources; mark sources for deletion. If dest
4781 Mark dest as copies of sources; mark sources for deletion. If dest
4782 is a directory, copies are put in that directory. If dest is a
4782 is a directory, copies are put in that directory. If dest is a
4783 file, there can only be one source.
4783 file, there can only be one source.
4784
4784
4785 By default, this command copies the contents of files as they
4785 By default, this command copies the contents of files as they
4786 exist in the working directory. If invoked with -A/--after, the
4786 exist in the working directory. If invoked with -A/--after, the
4787 operation is recorded, but no copying is performed.
4787 operation is recorded, but no copying is performed.
4788
4788
4789 This command takes effect at the next commit. To undo a rename
4789 This command takes effect at the next commit. To undo a rename
4790 before that, see :hg:`revert`.
4790 before that, see :hg:`revert`.
4791
4791
4792 Returns 0 on success, 1 if errors are encountered.
4792 Returns 0 on success, 1 if errors are encountered.
4793 """
4793 """
4794 wlock = repo.wlock(False)
4794 wlock = repo.wlock(False)
4795 try:
4795 try:
4796 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4796 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4797 finally:
4797 finally:
4798 wlock.release()
4798 wlock.release()
4799
4799
4800 @command('resolve',
4800 @command('resolve',
4801 [('a', 'all', None, _('select all unresolved files')),
4801 [('a', 'all', None, _('select all unresolved files')),
4802 ('l', 'list', None, _('list state of files needing merge')),
4802 ('l', 'list', None, _('list state of files needing merge')),
4803 ('m', 'mark', None, _('mark files as resolved')),
4803 ('m', 'mark', None, _('mark files as resolved')),
4804 ('u', 'unmark', None, _('mark files as unresolved')),
4804 ('u', 'unmark', None, _('mark files as unresolved')),
4805 ('n', 'no-status', None, _('hide status prefix'))]
4805 ('n', 'no-status', None, _('hide status prefix'))]
4806 + mergetoolopts + walkopts,
4806 + mergetoolopts + walkopts,
4807 _('[OPTION]... [FILE]...'))
4807 _('[OPTION]... [FILE]...'))
4808 def resolve(ui, repo, *pats, **opts):
4808 def resolve(ui, repo, *pats, **opts):
4809 """redo merges or set/view the merge status of files
4809 """redo merges or set/view the merge status of files
4810
4810
4811 Merges with unresolved conflicts are often the result of
4811 Merges with unresolved conflicts are often the result of
4812 non-interactive merging using the ``internal:merge`` configuration
4812 non-interactive merging using the ``internal:merge`` configuration
4813 setting, or a command-line merge tool like ``diff3``. The resolve
4813 setting, or a command-line merge tool like ``diff3``. The resolve
4814 command is used to manage the files involved in a merge, after
4814 command is used to manage the files involved in a merge, after
4815 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4815 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4816 working directory must have two parents). See :hg:`help
4816 working directory must have two parents). See :hg:`help
4817 merge-tools` for information on configuring merge tools.
4817 merge-tools` for information on configuring merge tools.
4818
4818
4819 The resolve command can be used in the following ways:
4819 The resolve command can be used in the following ways:
4820
4820
4821 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4821 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4822 files, discarding any previous merge attempts. Re-merging is not
4822 files, discarding any previous merge attempts. Re-merging is not
4823 performed for files already marked as resolved. Use ``--all/-a``
4823 performed for files already marked as resolved. Use ``--all/-a``
4824 to select all unresolved files. ``--tool`` can be used to specify
4824 to select all unresolved files. ``--tool`` can be used to specify
4825 the merge tool used for the given files. It overrides the HGMERGE
4825 the merge tool used for the given files. It overrides the HGMERGE
4826 environment variable and your configuration files. Previous file
4826 environment variable and your configuration files. Previous file
4827 contents are saved with a ``.orig`` suffix.
4827 contents are saved with a ``.orig`` suffix.
4828
4828
4829 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4829 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4830 (e.g. after having manually fixed-up the files). The default is
4830 (e.g. after having manually fixed-up the files). The default is
4831 to mark all unresolved files.
4831 to mark all unresolved files.
4832
4832
4833 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4833 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4834 default is to mark all resolved files.
4834 default is to mark all resolved files.
4835
4835
4836 - :hg:`resolve -l`: list files which had or still have conflicts.
4836 - :hg:`resolve -l`: list files which had or still have conflicts.
4837 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4837 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4838
4838
4839 Note that Mercurial will not let you commit files with unresolved
4839 Note that Mercurial will not let you commit files with unresolved
4840 merge conflicts. You must use :hg:`resolve -m ...` before you can
4840 merge conflicts. You must use :hg:`resolve -m ...` before you can
4841 commit after a conflicting merge.
4841 commit after a conflicting merge.
4842
4842
4843 Returns 0 on success, 1 if any files fail a resolve attempt.
4843 Returns 0 on success, 1 if any files fail a resolve attempt.
4844 """
4844 """
4845
4845
4846 all, mark, unmark, show, nostatus = \
4846 all, mark, unmark, show, nostatus = \
4847 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4847 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4848
4848
4849 if (show and (mark or unmark)) or (mark and unmark):
4849 if (show and (mark or unmark)) or (mark and unmark):
4850 raise util.Abort(_("too many options specified"))
4850 raise util.Abort(_("too many options specified"))
4851 if pats and all:
4851 if pats and all:
4852 raise util.Abort(_("can't specify --all and patterns"))
4852 raise util.Abort(_("can't specify --all and patterns"))
4853 if not (all or pats or show or mark or unmark):
4853 if not (all or pats or show or mark or unmark):
4854 raise util.Abort(_('no files or directories specified; '
4854 raise util.Abort(_('no files or directories specified; '
4855 'use --all to remerge all files'))
4855 'use --all to remerge all files'))
4856
4856
4857 ms = mergemod.mergestate(repo)
4857 ms = mergemod.mergestate(repo)
4858 m = scmutil.match(repo[None], pats, opts)
4858 m = scmutil.match(repo[None], pats, opts)
4859 ret = 0
4859 ret = 0
4860
4860
4861 for f in ms:
4861 for f in ms:
4862 if m(f):
4862 if m(f):
4863 if show:
4863 if show:
4864 if nostatus:
4864 if nostatus:
4865 ui.write("%s\n" % f)
4865 ui.write("%s\n" % f)
4866 else:
4866 else:
4867 ui.write("%s %s\n" % (ms[f].upper(), f),
4867 ui.write("%s %s\n" % (ms[f].upper(), f),
4868 label='resolve.' +
4868 label='resolve.' +
4869 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4869 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4870 elif mark:
4870 elif mark:
4871 ms.mark(f, "r")
4871 ms.mark(f, "r")
4872 elif unmark:
4872 elif unmark:
4873 ms.mark(f, "u")
4873 ms.mark(f, "u")
4874 else:
4874 else:
4875 wctx = repo[None]
4875 wctx = repo[None]
4876 mctx = wctx.parents()[-1]
4876 mctx = wctx.parents()[-1]
4877
4877
4878 # backup pre-resolve (merge uses .orig for its own purposes)
4878 # backup pre-resolve (merge uses .orig for its own purposes)
4879 a = repo.wjoin(f)
4879 a = repo.wjoin(f)
4880 util.copyfile(a, a + ".resolve")
4880 util.copyfile(a, a + ".resolve")
4881
4881
4882 try:
4882 try:
4883 # resolve file
4883 # resolve file
4884 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4884 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4885 if ms.resolve(f, wctx, mctx):
4885 if ms.resolve(f, wctx, mctx):
4886 ret = 1
4886 ret = 1
4887 finally:
4887 finally:
4888 ui.setconfig('ui', 'forcemerge', '')
4888 ui.setconfig('ui', 'forcemerge', '')
4889 ms.commit()
4889 ms.commit()
4890
4890
4891 # replace filemerge's .orig file with our resolve file
4891 # replace filemerge's .orig file with our resolve file
4892 util.rename(a + ".resolve", a + ".orig")
4892 util.rename(a + ".resolve", a + ".orig")
4893
4893
4894 ms.commit()
4894 ms.commit()
4895 return ret
4895 return ret
4896
4896
4897 @command('revert',
4897 @command('revert',
4898 [('a', 'all', None, _('revert all changes when no arguments given')),
4898 [('a', 'all', None, _('revert all changes when no arguments given')),
4899 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4899 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4900 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4900 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4901 ('C', 'no-backup', None, _('do not save backup copies of files')),
4901 ('C', 'no-backup', None, _('do not save backup copies of files')),
4902 ] + walkopts + dryrunopts,
4902 ] + walkopts + dryrunopts,
4903 _('[OPTION]... [-r REV] [NAME]...'))
4903 _('[OPTION]... [-r REV] [NAME]...'))
4904 def revert(ui, repo, *pats, **opts):
4904 def revert(ui, repo, *pats, **opts):
4905 """restore files to their checkout state
4905 """restore files to their checkout state
4906
4906
4907 .. note::
4907 .. note::
4908
4908
4909 To check out earlier revisions, you should use :hg:`update REV`.
4909 To check out earlier revisions, you should use :hg:`update REV`.
4910 To cancel an uncommitted merge (and lose your changes), use
4910 To cancel an uncommitted merge (and lose your changes), use
4911 :hg:`update --clean .`.
4911 :hg:`update --clean .`.
4912
4912
4913 With no revision specified, revert the specified files or directories
4913 With no revision specified, revert the specified files or directories
4914 to the contents they had in the parent of the working directory.
4914 to the contents they had in the parent of the working directory.
4915 This restores the contents of files to an unmodified
4915 This restores the contents of files to an unmodified
4916 state and unschedules adds, removes, copies, and renames. If the
4916 state and unschedules adds, removes, copies, and renames. If the
4917 working directory has two parents, you must explicitly specify a
4917 working directory has two parents, you must explicitly specify a
4918 revision.
4918 revision.
4919
4919
4920 Using the -r/--rev or -d/--date options, revert the given files or
4920 Using the -r/--rev or -d/--date options, revert the given files or
4921 directories to their states as of a specific revision. Because
4921 directories to their states as of a specific revision. Because
4922 revert does not change the working directory parents, this will
4922 revert does not change the working directory parents, this will
4923 cause these files to appear modified. This can be helpful to "back
4923 cause these files to appear modified. This can be helpful to "back
4924 out" some or all of an earlier change. See :hg:`backout` for a
4924 out" some or all of an earlier change. See :hg:`backout` for a
4925 related method.
4925 related method.
4926
4926
4927 Modified files are saved with a .orig suffix before reverting.
4927 Modified files are saved with a .orig suffix before reverting.
4928 To disable these backups, use --no-backup.
4928 To disable these backups, use --no-backup.
4929
4929
4930 See :hg:`help dates` for a list of formats valid for -d/--date.
4930 See :hg:`help dates` for a list of formats valid for -d/--date.
4931
4931
4932 Returns 0 on success.
4932 Returns 0 on success.
4933 """
4933 """
4934
4934
4935 if opts.get("date"):
4935 if opts.get("date"):
4936 if opts.get("rev"):
4936 if opts.get("rev"):
4937 raise util.Abort(_("you can't specify a revision and a date"))
4937 raise util.Abort(_("you can't specify a revision and a date"))
4938 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4938 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4939
4939
4940 parent, p2 = repo.dirstate.parents()
4940 parent, p2 = repo.dirstate.parents()
4941 if not opts.get('rev') and p2 != nullid:
4941 if not opts.get('rev') and p2 != nullid:
4942 # revert after merge is a trap for new users (issue2915)
4942 # revert after merge is a trap for new users (issue2915)
4943 raise util.Abort(_('uncommitted merge with no revision specified'),
4943 raise util.Abort(_('uncommitted merge with no revision specified'),
4944 hint=_('use "hg update" or see "hg help revert"'))
4944 hint=_('use "hg update" or see "hg help revert"'))
4945
4945
4946 ctx = scmutil.revsingle(repo, opts.get('rev'))
4946 ctx = scmutil.revsingle(repo, opts.get('rev'))
4947
4947
4948 if not pats and not opts.get('all'):
4948 if not pats and not opts.get('all'):
4949 msg = _("no files or directories specified")
4949 msg = _("no files or directories specified")
4950 if p2 != nullid:
4950 if p2 != nullid:
4951 hint = _("uncommitted merge, use --all to discard all changes,"
4951 hint = _("uncommitted merge, use --all to discard all changes,"
4952 " or 'hg update -C .' to abort the merge")
4952 " or 'hg update -C .' to abort the merge")
4953 raise util.Abort(msg, hint=hint)
4953 raise util.Abort(msg, hint=hint)
4954 dirty = util.any(repo.status())
4954 dirty = util.any(repo.status())
4955 node = ctx.node()
4955 node = ctx.node()
4956 if node != parent:
4956 if node != parent:
4957 if dirty:
4957 if dirty:
4958 hint = _("uncommitted changes, use --all to discard all"
4958 hint = _("uncommitted changes, use --all to discard all"
4959 " changes, or 'hg update %s' to update") % ctx.rev()
4959 " changes, or 'hg update %s' to update") % ctx.rev()
4960 else:
4960 else:
4961 hint = _("use --all to revert all files,"
4961 hint = _("use --all to revert all files,"
4962 " or 'hg update %s' to update") % ctx.rev()
4962 " or 'hg update %s' to update") % ctx.rev()
4963 elif dirty:
4963 elif dirty:
4964 hint = _("uncommitted changes, use --all to discard all changes")
4964 hint = _("uncommitted changes, use --all to discard all changes")
4965 else:
4965 else:
4966 hint = _("use --all to revert all files")
4966 hint = _("use --all to revert all files")
4967 raise util.Abort(msg, hint=hint)
4967 raise util.Abort(msg, hint=hint)
4968
4968
4969 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4969 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4970
4970
4971 @command('rollback', dryrunopts +
4971 @command('rollback', dryrunopts +
4972 [('f', 'force', False, _('ignore safety measures'))])
4972 [('f', 'force', False, _('ignore safety measures'))])
4973 def rollback(ui, repo, **opts):
4973 def rollback(ui, repo, **opts):
4974 """roll back the last transaction (dangerous)
4974 """roll back the last transaction (dangerous)
4975
4975
4976 This command should be used with care. There is only one level of
4976 This command should be used with care. There is only one level of
4977 rollback, and there is no way to undo a rollback. It will also
4977 rollback, and there is no way to undo a rollback. It will also
4978 restore the dirstate at the time of the last transaction, losing
4978 restore the dirstate at the time of the last transaction, losing
4979 any dirstate changes since that time. This command does not alter
4979 any dirstate changes since that time. This command does not alter
4980 the working directory.
4980 the working directory.
4981
4981
4982 Transactions are used to encapsulate the effects of all commands
4982 Transactions are used to encapsulate the effects of all commands
4983 that create new changesets or propagate existing changesets into a
4983 that create new changesets or propagate existing changesets into a
4984 repository.
4984 repository.
4985
4985
4986 .. container:: verbose
4986 .. container:: verbose
4987
4987
4988 For example, the following commands are transactional, and their
4988 For example, the following commands are transactional, and their
4989 effects can be rolled back:
4989 effects can be rolled back:
4990
4990
4991 - commit
4991 - commit
4992 - import
4992 - import
4993 - pull
4993 - pull
4994 - push (with this repository as the destination)
4994 - push (with this repository as the destination)
4995 - unbundle
4995 - unbundle
4996
4996
4997 To avoid permanent data loss, rollback will refuse to rollback a
4997 To avoid permanent data loss, rollback will refuse to rollback a
4998 commit transaction if it isn't checked out. Use --force to
4998 commit transaction if it isn't checked out. Use --force to
4999 override this protection.
4999 override this protection.
5000
5000
5001 This command is not intended for use on public repositories. Once
5001 This command is not intended for use on public repositories. Once
5002 changes are visible for pull by other users, rolling a transaction
5002 changes are visible for pull by other users, rolling a transaction
5003 back locally is ineffective (someone else may already have pulled
5003 back locally is ineffective (someone else may already have pulled
5004 the changes). Furthermore, a race is possible with readers of the
5004 the changes). Furthermore, a race is possible with readers of the
5005 repository; for example an in-progress pull from the repository
5005 repository; for example an in-progress pull from the repository
5006 may fail if a rollback is performed.
5006 may fail if a rollback is performed.
5007
5007
5008 Returns 0 on success, 1 if no rollback data is available.
5008 Returns 0 on success, 1 if no rollback data is available.
5009 """
5009 """
5010 return repo.rollback(dryrun=opts.get('dry_run'),
5010 return repo.rollback(dryrun=opts.get('dry_run'),
5011 force=opts.get('force'))
5011 force=opts.get('force'))
5012
5012
5013 @command('root', [])
5013 @command('root', [])
5014 def root(ui, repo):
5014 def root(ui, repo):
5015 """print the root (top) of the current working directory
5015 """print the root (top) of the current working directory
5016
5016
5017 Print the root directory of the current repository.
5017 Print the root directory of the current repository.
5018
5018
5019 Returns 0 on success.
5019 Returns 0 on success.
5020 """
5020 """
5021 ui.write(repo.root + "\n")
5021 ui.write(repo.root + "\n")
5022
5022
5023 @command('^serve',
5023 @command('^serve',
5024 [('A', 'accesslog', '', _('name of access log file to write to'),
5024 [('A', 'accesslog', '', _('name of access log file to write to'),
5025 _('FILE')),
5025 _('FILE')),
5026 ('d', 'daemon', None, _('run server in background')),
5026 ('d', 'daemon', None, _('run server in background')),
5027 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5027 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5028 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5028 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5029 # use string type, then we can check if something was passed
5029 # use string type, then we can check if something was passed
5030 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5030 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5031 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5031 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5032 _('ADDR')),
5032 _('ADDR')),
5033 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5033 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5034 _('PREFIX')),
5034 _('PREFIX')),
5035 ('n', 'name', '',
5035 ('n', 'name', '',
5036 _('name to show in web pages (default: working directory)'), _('NAME')),
5036 _('name to show in web pages (default: working directory)'), _('NAME')),
5037 ('', 'web-conf', '',
5037 ('', 'web-conf', '',
5038 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5038 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5039 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5039 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5040 _('FILE')),
5040 _('FILE')),
5041 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5041 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5042 ('', 'stdio', None, _('for remote clients')),
5042 ('', 'stdio', None, _('for remote clients')),
5043 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5043 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5044 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5044 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5045 ('', 'style', '', _('template style to use'), _('STYLE')),
5045 ('', 'style', '', _('template style to use'), _('STYLE')),
5046 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5046 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5047 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5047 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5048 _('[OPTION]...'))
5048 _('[OPTION]...'))
5049 def serve(ui, repo, **opts):
5049 def serve(ui, repo, **opts):
5050 """start stand-alone webserver
5050 """start stand-alone webserver
5051
5051
5052 Start a local HTTP repository browser and pull server. You can use
5052 Start a local HTTP repository browser and pull server. You can use
5053 this for ad-hoc sharing and browsing of repositories. It is
5053 this for ad-hoc sharing and browsing of repositories. It is
5054 recommended to use a real web server to serve a repository for
5054 recommended to use a real web server to serve a repository for
5055 longer periods of time.
5055 longer periods of time.
5056
5056
5057 Please note that the server does not implement access control.
5057 Please note that the server does not implement access control.
5058 This means that, by default, anybody can read from the server and
5058 This means that, by default, anybody can read from the server and
5059 nobody can write to it by default. Set the ``web.allow_push``
5059 nobody can write to it by default. Set the ``web.allow_push``
5060 option to ``*`` to allow everybody to push to the server. You
5060 option to ``*`` to allow everybody to push to the server. You
5061 should use a real web server if you need to authenticate users.
5061 should use a real web server if you need to authenticate users.
5062
5062
5063 By default, the server logs accesses to stdout and errors to
5063 By default, the server logs accesses to stdout and errors to
5064 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5064 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5065 files.
5065 files.
5066
5066
5067 To have the server choose a free port number to listen on, specify
5067 To have the server choose a free port number to listen on, specify
5068 a port number of 0; in this case, the server will print the port
5068 a port number of 0; in this case, the server will print the port
5069 number it uses.
5069 number it uses.
5070
5070
5071 Returns 0 on success.
5071 Returns 0 on success.
5072 """
5072 """
5073
5073
5074 if opts["stdio"] and opts["cmdserver"]:
5074 if opts["stdio"] and opts["cmdserver"]:
5075 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5075 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5076
5076
5077 def checkrepo():
5077 def checkrepo():
5078 if repo is None:
5078 if repo is None:
5079 raise error.RepoError(_("there is no Mercurial repository here"
5079 raise error.RepoError(_("there is no Mercurial repository here"
5080 " (.hg not found)"))
5080 " (.hg not found)"))
5081
5081
5082 if opts["stdio"]:
5082 if opts["stdio"]:
5083 checkrepo()
5083 checkrepo()
5084 s = sshserver.sshserver(ui, repo)
5084 s = sshserver.sshserver(ui, repo)
5085 s.serve_forever()
5085 s.serve_forever()
5086
5086
5087 if opts["cmdserver"]:
5087 if opts["cmdserver"]:
5088 checkrepo()
5088 checkrepo()
5089 s = commandserver.server(ui, repo, opts["cmdserver"])
5089 s = commandserver.server(ui, repo, opts["cmdserver"])
5090 return s.serve()
5090 return s.serve()
5091
5091
5092 # this way we can check if something was given in the command-line
5092 # this way we can check if something was given in the command-line
5093 if opts.get('port'):
5093 if opts.get('port'):
5094 opts['port'] = util.getport(opts.get('port'))
5094 opts['port'] = util.getport(opts.get('port'))
5095
5095
5096 baseui = repo and repo.baseui or ui
5096 baseui = repo and repo.baseui or ui
5097 optlist = ("name templates style address port prefix ipv6"
5097 optlist = ("name templates style address port prefix ipv6"
5098 " accesslog errorlog certificate encoding")
5098 " accesslog errorlog certificate encoding")
5099 for o in optlist.split():
5099 for o in optlist.split():
5100 val = opts.get(o, '')
5100 val = opts.get(o, '')
5101 if val in (None, ''): # should check against default options instead
5101 if val in (None, ''): # should check against default options instead
5102 continue
5102 continue
5103 baseui.setconfig("web", o, val)
5103 baseui.setconfig("web", o, val)
5104 if repo and repo.ui != baseui:
5104 if repo and repo.ui != baseui:
5105 repo.ui.setconfig("web", o, val)
5105 repo.ui.setconfig("web", o, val)
5106
5106
5107 o = opts.get('web_conf') or opts.get('webdir_conf')
5107 o = opts.get('web_conf') or opts.get('webdir_conf')
5108 if not o:
5108 if not o:
5109 if not repo:
5109 if not repo:
5110 raise error.RepoError(_("there is no Mercurial repository"
5110 raise error.RepoError(_("there is no Mercurial repository"
5111 " here (.hg not found)"))
5111 " here (.hg not found)"))
5112 o = repo
5112 o = repo
5113
5113
5114 app = hgweb.hgweb(o, baseui=baseui)
5114 app = hgweb.hgweb(o, baseui=baseui)
5115
5115
5116 class service(object):
5116 class service(object):
5117 def init(self):
5117 def init(self):
5118 util.setsignalhandler()
5118 util.setsignalhandler()
5119 self.httpd = hgweb.server.create_server(ui, app)
5119 self.httpd = hgweb.server.create_server(ui, app)
5120
5120
5121 if opts['port'] and not ui.verbose:
5121 if opts['port'] and not ui.verbose:
5122 return
5122 return
5123
5123
5124 if self.httpd.prefix:
5124 if self.httpd.prefix:
5125 prefix = self.httpd.prefix.strip('/') + '/'
5125 prefix = self.httpd.prefix.strip('/') + '/'
5126 else:
5126 else:
5127 prefix = ''
5127 prefix = ''
5128
5128
5129 port = ':%d' % self.httpd.port
5129 port = ':%d' % self.httpd.port
5130 if port == ':80':
5130 if port == ':80':
5131 port = ''
5131 port = ''
5132
5132
5133 bindaddr = self.httpd.addr
5133 bindaddr = self.httpd.addr
5134 if bindaddr == '0.0.0.0':
5134 if bindaddr == '0.0.0.0':
5135 bindaddr = '*'
5135 bindaddr = '*'
5136 elif ':' in bindaddr: # IPv6
5136 elif ':' in bindaddr: # IPv6
5137 bindaddr = '[%s]' % bindaddr
5137 bindaddr = '[%s]' % bindaddr
5138
5138
5139 fqaddr = self.httpd.fqaddr
5139 fqaddr = self.httpd.fqaddr
5140 if ':' in fqaddr:
5140 if ':' in fqaddr:
5141 fqaddr = '[%s]' % fqaddr
5141 fqaddr = '[%s]' % fqaddr
5142 if opts['port']:
5142 if opts['port']:
5143 write = ui.status
5143 write = ui.status
5144 else:
5144 else:
5145 write = ui.write
5145 write = ui.write
5146 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5146 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5147 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5147 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5148
5148
5149 def run(self):
5149 def run(self):
5150 self.httpd.serve_forever()
5150 self.httpd.serve_forever()
5151
5151
5152 service = service()
5152 service = service()
5153
5153
5154 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5154 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5155
5155
5156 @command('showconfig|debugconfig',
5156 @command('showconfig|debugconfig',
5157 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5157 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5158 _('[-u] [NAME]...'))
5158 _('[-u] [NAME]...'))
5159 def showconfig(ui, repo, *values, **opts):
5159 def showconfig(ui, repo, *values, **opts):
5160 """show combined config settings from all hgrc files
5160 """show combined config settings from all hgrc files
5161
5161
5162 With no arguments, print names and values of all config items.
5162 With no arguments, print names and values of all config items.
5163
5163
5164 With one argument of the form section.name, print just the value
5164 With one argument of the form section.name, print just the value
5165 of that config item.
5165 of that config item.
5166
5166
5167 With multiple arguments, print names and values of all config
5167 With multiple arguments, print names and values of all config
5168 items with matching section names.
5168 items with matching section names.
5169
5169
5170 With --debug, the source (filename and line number) is printed
5170 With --debug, the source (filename and line number) is printed
5171 for each config item.
5171 for each config item.
5172
5172
5173 Returns 0 on success.
5173 Returns 0 on success.
5174 """
5174 """
5175
5175
5176 for f in scmutil.rcpath():
5176 for f in scmutil.rcpath():
5177 ui.debug('read config from: %s\n' % f)
5177 ui.debug('read config from: %s\n' % f)
5178 untrusted = bool(opts.get('untrusted'))
5178 untrusted = bool(opts.get('untrusted'))
5179 if values:
5179 if values:
5180 sections = [v for v in values if '.' not in v]
5180 sections = [v for v in values if '.' not in v]
5181 items = [v for v in values if '.' in v]
5181 items = [v for v in values if '.' in v]
5182 if len(items) > 1 or items and sections:
5182 if len(items) > 1 or items and sections:
5183 raise util.Abort(_('only one config item permitted'))
5183 raise util.Abort(_('only one config item permitted'))
5184 for section, name, value in ui.walkconfig(untrusted=untrusted):
5184 for section, name, value in ui.walkconfig(untrusted=untrusted):
5185 value = str(value).replace('\n', '\\n')
5185 value = str(value).replace('\n', '\\n')
5186 sectname = section + '.' + name
5186 sectname = section + '.' + name
5187 if values:
5187 if values:
5188 for v in values:
5188 for v in values:
5189 if v == section:
5189 if v == section:
5190 ui.debug('%s: ' %
5190 ui.debug('%s: ' %
5191 ui.configsource(section, name, untrusted))
5191 ui.configsource(section, name, untrusted))
5192 ui.write('%s=%s\n' % (sectname, value))
5192 ui.write('%s=%s\n' % (sectname, value))
5193 elif v == sectname:
5193 elif v == sectname:
5194 ui.debug('%s: ' %
5194 ui.debug('%s: ' %
5195 ui.configsource(section, name, untrusted))
5195 ui.configsource(section, name, untrusted))
5196 ui.write(value, '\n')
5196 ui.write(value, '\n')
5197 else:
5197 else:
5198 ui.debug('%s: ' %
5198 ui.debug('%s: ' %
5199 ui.configsource(section, name, untrusted))
5199 ui.configsource(section, name, untrusted))
5200 ui.write('%s=%s\n' % (sectname, value))
5200 ui.write('%s=%s\n' % (sectname, value))
5201
5201
5202 @command('^status|st',
5202 @command('^status|st',
5203 [('A', 'all', None, _('show status of all files')),
5203 [('A', 'all', None, _('show status of all files')),
5204 ('m', 'modified', None, _('show only modified files')),
5204 ('m', 'modified', None, _('show only modified files')),
5205 ('a', 'added', None, _('show only added files')),
5205 ('a', 'added', None, _('show only added files')),
5206 ('r', 'removed', None, _('show only removed files')),
5206 ('r', 'removed', None, _('show only removed files')),
5207 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5207 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5208 ('c', 'clean', None, _('show only files without changes')),
5208 ('c', 'clean', None, _('show only files without changes')),
5209 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5209 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5210 ('i', 'ignored', None, _('show only ignored files')),
5210 ('i', 'ignored', None, _('show only ignored files')),
5211 ('n', 'no-status', None, _('hide status prefix')),
5211 ('n', 'no-status', None, _('hide status prefix')),
5212 ('C', 'copies', None, _('show source of copied files')),
5212 ('C', 'copies', None, _('show source of copied files')),
5213 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5213 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5214 ('', 'rev', [], _('show difference from revision'), _('REV')),
5214 ('', 'rev', [], _('show difference from revision'), _('REV')),
5215 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5215 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5216 ] + walkopts + subrepoopts,
5216 ] + walkopts + subrepoopts,
5217 _('[OPTION]... [FILE]...'))
5217 _('[OPTION]... [FILE]...'))
5218 def status(ui, repo, *pats, **opts):
5218 def status(ui, repo, *pats, **opts):
5219 """show changed files in the working directory
5219 """show changed files in the working directory
5220
5220
5221 Show status of files in the repository. If names are given, only
5221 Show status of files in the repository. If names are given, only
5222 files that match are shown. Files that are clean or ignored or
5222 files that match are shown. Files that are clean or ignored or
5223 the source of a copy/move operation, are not listed unless
5223 the source of a copy/move operation, are not listed unless
5224 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5224 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5225 Unless options described with "show only ..." are given, the
5225 Unless options described with "show only ..." are given, the
5226 options -mardu are used.
5226 options -mardu are used.
5227
5227
5228 Option -q/--quiet hides untracked (unknown and ignored) files
5228 Option -q/--quiet hides untracked (unknown and ignored) files
5229 unless explicitly requested with -u/--unknown or -i/--ignored.
5229 unless explicitly requested with -u/--unknown or -i/--ignored.
5230
5230
5231 .. note::
5231 .. note::
5232 status may appear to disagree with diff if permissions have
5232 status may appear to disagree with diff if permissions have
5233 changed or a merge has occurred. The standard diff format does
5233 changed or a merge has occurred. The standard diff format does
5234 not report permission changes and diff only reports changes
5234 not report permission changes and diff only reports changes
5235 relative to one merge parent.
5235 relative to one merge parent.
5236
5236
5237 If one revision is given, it is used as the base revision.
5237 If one revision is given, it is used as the base revision.
5238 If two revisions are given, the differences between them are
5238 If two revisions are given, the differences between them are
5239 shown. The --change option can also be used as a shortcut to list
5239 shown. The --change option can also be used as a shortcut to list
5240 the changed files of a revision from its first parent.
5240 the changed files of a revision from its first parent.
5241
5241
5242 The codes used to show the status of files are::
5242 The codes used to show the status of files are::
5243
5243
5244 M = modified
5244 M = modified
5245 A = added
5245 A = added
5246 R = removed
5246 R = removed
5247 C = clean
5247 C = clean
5248 ! = missing (deleted by non-hg command, but still tracked)
5248 ! = missing (deleted by non-hg command, but still tracked)
5249 ? = not tracked
5249 ? = not tracked
5250 I = ignored
5250 I = ignored
5251 = origin of the previous file listed as A (added)
5251 = origin of the previous file listed as A (added)
5252
5252
5253 .. container:: verbose
5253 .. container:: verbose
5254
5254
5255 Examples:
5255 Examples:
5256
5256
5257 - show changes in the working directory relative to a
5257 - show changes in the working directory relative to a
5258 changeset::
5258 changeset::
5259
5259
5260 hg status --rev 9353
5260 hg status --rev 9353
5261
5261
5262 - show all changes including copies in an existing changeset::
5262 - show all changes including copies in an existing changeset::
5263
5263
5264 hg status --copies --change 9353
5264 hg status --copies --change 9353
5265
5265
5266 - get a NUL separated list of added files, suitable for xargs::
5266 - get a NUL separated list of added files, suitable for xargs::
5267
5267
5268 hg status -an0
5268 hg status -an0
5269
5269
5270 Returns 0 on success.
5270 Returns 0 on success.
5271 """
5271 """
5272
5272
5273 revs = opts.get('rev')
5273 revs = opts.get('rev')
5274 change = opts.get('change')
5274 change = opts.get('change')
5275
5275
5276 if revs and change:
5276 if revs and change:
5277 msg = _('cannot specify --rev and --change at the same time')
5277 msg = _('cannot specify --rev and --change at the same time')
5278 raise util.Abort(msg)
5278 raise util.Abort(msg)
5279 elif change:
5279 elif change:
5280 node2 = scmutil.revsingle(repo, change, None).node()
5280 node2 = scmutil.revsingle(repo, change, None).node()
5281 node1 = repo[node2].p1().node()
5281 node1 = repo[node2].p1().node()
5282 else:
5282 else:
5283 node1, node2 = scmutil.revpair(repo, revs)
5283 node1, node2 = scmutil.revpair(repo, revs)
5284
5284
5285 cwd = (pats and repo.getcwd()) or ''
5285 cwd = (pats and repo.getcwd()) or ''
5286 end = opts.get('print0') and '\0' or '\n'
5286 end = opts.get('print0') and '\0' or '\n'
5287 copy = {}
5287 copy = {}
5288 states = 'modified added removed deleted unknown ignored clean'.split()
5288 states = 'modified added removed deleted unknown ignored clean'.split()
5289 show = [k for k in states if opts.get(k)]
5289 show = [k for k in states if opts.get(k)]
5290 if opts.get('all'):
5290 if opts.get('all'):
5291 show += ui.quiet and (states[:4] + ['clean']) or states
5291 show += ui.quiet and (states[:4] + ['clean']) or states
5292 if not show:
5292 if not show:
5293 show = ui.quiet and states[:4] or states[:5]
5293 show = ui.quiet and states[:4] or states[:5]
5294
5294
5295 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5295 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5296 'ignored' in show, 'clean' in show, 'unknown' in show,
5296 'ignored' in show, 'clean' in show, 'unknown' in show,
5297 opts.get('subrepos'))
5297 opts.get('subrepos'))
5298 changestates = zip(states, 'MAR!?IC', stat)
5298 changestates = zip(states, 'MAR!?IC', stat)
5299
5299
5300 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5300 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5301 copy = copies.pathcopies(repo[node1], repo[node2])
5301 copy = copies.pathcopies(repo[node1], repo[node2])
5302
5302
5303 fm = ui.formatter('status', opts)
5303 fm = ui.formatter('status', opts)
5304 fmt = '%s' + end
5304 fmt = '%s' + end
5305 showchar = not opts.get('no_status')
5305 showchar = not opts.get('no_status')
5306
5306
5307 for state, char, files in changestates:
5307 for state, char, files in changestates:
5308 if state in show:
5308 if state in show:
5309 label = 'status.' + state
5309 label = 'status.' + state
5310 for f in files:
5310 for f in files:
5311 fm.startitem()
5311 fm.startitem()
5312 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5312 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5313 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5313 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5314 if f in copy:
5314 if f in copy:
5315 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5315 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5316 label='status.copied')
5316 label='status.copied')
5317 fm.end()
5317 fm.end()
5318
5318
5319 @command('^summary|sum',
5319 @command('^summary|sum',
5320 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5320 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5321 def summary(ui, repo, **opts):
5321 def summary(ui, repo, **opts):
5322 """summarize working directory state
5322 """summarize working directory state
5323
5323
5324 This generates a brief summary of the working directory state,
5324 This generates a brief summary of the working directory state,
5325 including parents, branch, commit status, and available updates.
5325 including parents, branch, commit status, and available updates.
5326
5326
5327 With the --remote option, this will check the default paths for
5327 With the --remote option, this will check the default paths for
5328 incoming and outgoing changes. This can be time-consuming.
5328 incoming and outgoing changes. This can be time-consuming.
5329
5329
5330 Returns 0 on success.
5330 Returns 0 on success.
5331 """
5331 """
5332
5332
5333 ctx = repo[None]
5333 ctx = repo[None]
5334 parents = ctx.parents()
5334 parents = ctx.parents()
5335 pnode = parents[0].node()
5335 pnode = parents[0].node()
5336 marks = []
5336 marks = []
5337
5337
5338 for p in parents:
5338 for p in parents:
5339 # label with log.changeset (instead of log.parent) since this
5339 # label with log.changeset (instead of log.parent) since this
5340 # shows a working directory parent *changeset*:
5340 # shows a working directory parent *changeset*:
5341 # i18n: column positioning for "hg summary"
5341 # i18n: column positioning for "hg summary"
5342 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5342 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5343 label='log.changeset changeset.%s' % p.phasestr())
5343 label='log.changeset changeset.%s' % p.phasestr())
5344 ui.write(' '.join(p.tags()), label='log.tag')
5344 ui.write(' '.join(p.tags()), label='log.tag')
5345 if p.bookmarks():
5345 if p.bookmarks():
5346 marks.extend(p.bookmarks())
5346 marks.extend(p.bookmarks())
5347 if p.rev() == -1:
5347 if p.rev() == -1:
5348 if not len(repo):
5348 if not len(repo):
5349 ui.write(_(' (empty repository)'))
5349 ui.write(_(' (empty repository)'))
5350 else:
5350 else:
5351 ui.write(_(' (no revision checked out)'))
5351 ui.write(_(' (no revision checked out)'))
5352 ui.write('\n')
5352 ui.write('\n')
5353 if p.description():
5353 if p.description():
5354 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5354 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5355 label='log.summary')
5355 label='log.summary')
5356
5356
5357 branch = ctx.branch()
5357 branch = ctx.branch()
5358 bheads = repo.branchheads(branch)
5358 bheads = repo.branchheads(branch)
5359 # i18n: column positioning for "hg summary"
5359 # i18n: column positioning for "hg summary"
5360 m = _('branch: %s\n') % branch
5360 m = _('branch: %s\n') % branch
5361 if branch != 'default':
5361 if branch != 'default':
5362 ui.write(m, label='log.branch')
5362 ui.write(m, label='log.branch')
5363 else:
5363 else:
5364 ui.status(m, label='log.branch')
5364 ui.status(m, label='log.branch')
5365
5365
5366 if marks:
5366 if marks:
5367 current = repo._bookmarkcurrent
5367 current = repo._bookmarkcurrent
5368 # i18n: column positioning for "hg summary"
5368 # i18n: column positioning for "hg summary"
5369 ui.write(_('bookmarks:'), label='log.bookmark')
5369 ui.write(_('bookmarks:'), label='log.bookmark')
5370 if current is not None:
5370 if current is not None:
5371 if current in marks:
5371 if current in marks:
5372 ui.write(' *' + current, label='bookmarks.current')
5372 ui.write(' *' + current, label='bookmarks.current')
5373 marks.remove(current)
5373 marks.remove(current)
5374 else:
5374 else:
5375 ui.write(' [%s]' % current, label='bookmarks.current')
5375 ui.write(' [%s]' % current, label='bookmarks.current')
5376 for m in marks:
5376 for m in marks:
5377 ui.write(' ' + m, label='log.bookmark')
5377 ui.write(' ' + m, label='log.bookmark')
5378 ui.write('\n', label='log.bookmark')
5378 ui.write('\n', label='log.bookmark')
5379
5379
5380 st = list(repo.status(unknown=True))[:6]
5380 st = list(repo.status(unknown=True))[:6]
5381
5381
5382 c = repo.dirstate.copies()
5382 c = repo.dirstate.copies()
5383 copied, renamed = [], []
5383 copied, renamed = [], []
5384 for d, s in c.iteritems():
5384 for d, s in c.iteritems():
5385 if s in st[2]:
5385 if s in st[2]:
5386 st[2].remove(s)
5386 st[2].remove(s)
5387 renamed.append(d)
5387 renamed.append(d)
5388 else:
5388 else:
5389 copied.append(d)
5389 copied.append(d)
5390 if d in st[1]:
5390 if d in st[1]:
5391 st[1].remove(d)
5391 st[1].remove(d)
5392 st.insert(3, renamed)
5392 st.insert(3, renamed)
5393 st.insert(4, copied)
5393 st.insert(4, copied)
5394
5394
5395 ms = mergemod.mergestate(repo)
5395 ms = mergemod.mergestate(repo)
5396 st.append([f for f in ms if ms[f] == 'u'])
5396 st.append([f for f in ms if ms[f] == 'u'])
5397
5397
5398 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5398 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5399 st.append(subs)
5399 st.append(subs)
5400
5400
5401 labels = [ui.label(_('%d modified'), 'status.modified'),
5401 labels = [ui.label(_('%d modified'), 'status.modified'),
5402 ui.label(_('%d added'), 'status.added'),
5402 ui.label(_('%d added'), 'status.added'),
5403 ui.label(_('%d removed'), 'status.removed'),
5403 ui.label(_('%d removed'), 'status.removed'),
5404 ui.label(_('%d renamed'), 'status.copied'),
5404 ui.label(_('%d renamed'), 'status.copied'),
5405 ui.label(_('%d copied'), 'status.copied'),
5405 ui.label(_('%d copied'), 'status.copied'),
5406 ui.label(_('%d deleted'), 'status.deleted'),
5406 ui.label(_('%d deleted'), 'status.deleted'),
5407 ui.label(_('%d unknown'), 'status.unknown'),
5407 ui.label(_('%d unknown'), 'status.unknown'),
5408 ui.label(_('%d ignored'), 'status.ignored'),
5408 ui.label(_('%d ignored'), 'status.ignored'),
5409 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5409 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5410 ui.label(_('%d subrepos'), 'status.modified')]
5410 ui.label(_('%d subrepos'), 'status.modified')]
5411 t = []
5411 t = []
5412 for s, l in zip(st, labels):
5412 for s, l in zip(st, labels):
5413 if s:
5413 if s:
5414 t.append(l % len(s))
5414 t.append(l % len(s))
5415
5415
5416 t = ', '.join(t)
5416 t = ', '.join(t)
5417 cleanworkdir = False
5417 cleanworkdir = False
5418
5418
5419 if len(parents) > 1:
5419 if len(parents) > 1:
5420 t += _(' (merge)')
5420 t += _(' (merge)')
5421 elif branch != parents[0].branch():
5421 elif branch != parents[0].branch():
5422 t += _(' (new branch)')
5422 t += _(' (new branch)')
5423 elif (parents[0].closesbranch() and
5423 elif (parents[0].closesbranch() and
5424 pnode in repo.branchheads(branch, closed=True)):
5424 pnode in repo.branchheads(branch, closed=True)):
5425 t += _(' (head closed)')
5425 t += _(' (head closed)')
5426 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5426 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5427 t += _(' (clean)')
5427 t += _(' (clean)')
5428 cleanworkdir = True
5428 cleanworkdir = True
5429 elif pnode not in bheads:
5429 elif pnode not in bheads:
5430 t += _(' (new branch head)')
5430 t += _(' (new branch head)')
5431
5431
5432 if cleanworkdir:
5432 if cleanworkdir:
5433 # i18n: column positioning for "hg summary"
5433 # i18n: column positioning for "hg summary"
5434 ui.status(_('commit: %s\n') % t.strip())
5434 ui.status(_('commit: %s\n') % t.strip())
5435 else:
5435 else:
5436 # i18n: column positioning for "hg summary"
5436 # i18n: column positioning for "hg summary"
5437 ui.write(_('commit: %s\n') % t.strip())
5437 ui.write(_('commit: %s\n') % t.strip())
5438
5438
5439 # all ancestors of branch heads - all ancestors of parent = new csets
5439 # all ancestors of branch heads - all ancestors of parent = new csets
5440 new = [0] * len(repo)
5440 new = [0] * len(repo)
5441 cl = repo.changelog
5441 cl = repo.changelog
5442 for a in [cl.rev(n) for n in bheads]:
5442 for a in [cl.rev(n) for n in bheads]:
5443 new[a] = 1
5443 new[a] = 1
5444 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5444 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5445 new[a] = 1
5445 new[a] = 1
5446 for a in [p.rev() for p in parents]:
5446 for a in [p.rev() for p in parents]:
5447 if a >= 0:
5447 if a >= 0:
5448 new[a] = 0
5448 new[a] = 0
5449 for a in cl.ancestors([p.rev() for p in parents]):
5449 for a in cl.ancestors([p.rev() for p in parents]):
5450 new[a] = 0
5450 new[a] = 0
5451 new = sum(new)
5451 new = sum(new)
5452
5452
5453 if new == 0:
5453 if new == 0:
5454 # i18n: column positioning for "hg summary"
5454 # i18n: column positioning for "hg summary"
5455 ui.status(_('update: (current)\n'))
5455 ui.status(_('update: (current)\n'))
5456 elif pnode not in bheads:
5456 elif pnode not in bheads:
5457 # i18n: column positioning for "hg summary"
5457 # i18n: column positioning for "hg summary"
5458 ui.write(_('update: %d new changesets (update)\n') % new)
5458 ui.write(_('update: %d new changesets (update)\n') % new)
5459 else:
5459 else:
5460 # i18n: column positioning for "hg summary"
5460 # i18n: column positioning for "hg summary"
5461 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5461 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5462 (new, len(bheads)))
5462 (new, len(bheads)))
5463
5463
5464 if opts.get('remote'):
5464 if opts.get('remote'):
5465 t = []
5465 t = []
5466 source, branches = hg.parseurl(ui.expandpath('default'))
5466 source, branches = hg.parseurl(ui.expandpath('default'))
5467 sbranch = branches[0]
5467 other = hg.peer(repo, {}, source)
5468 other = hg.peer(repo, {}, source)
5468 revs, checkout = hg.addbranchrevs(repo, other, branches,
5469 revs, checkout = hg.addbranchrevs(repo, other, branches,
5469 opts.get('rev'))
5470 opts.get('rev'))
5470 if revs:
5471 if revs:
5471 revs = [other.lookup(rev) for rev in revs]
5472 revs = [other.lookup(rev) for rev in revs]
5472 ui.debug('comparing with %s\n' % util.hidepassword(source))
5473 ui.debug('comparing with %s\n' % util.hidepassword(source))
5473 repo.ui.pushbuffer()
5474 repo.ui.pushbuffer()
5474 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5475 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5475 _common, incoming, _rheads = commoninc
5476 _common, incoming, _rheads = commoninc
5476 repo.ui.popbuffer()
5477 repo.ui.popbuffer()
5477 if incoming:
5478 if incoming:
5478 t.append(_('1 or more incoming'))
5479 t.append(_('1 or more incoming'))
5479
5480
5480 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5481 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5482 dbranch = branches[0]
5481 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5483 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5482 if source != dest:
5484 if source != dest:
5483 other = hg.peer(repo, {}, dest)
5485 other = hg.peer(repo, {}, dest)
5486 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5487 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5484 commoninc = None
5488 commoninc = None
5485 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5486 if revs:
5489 if revs:
5487 revs = [repo.lookup(rev) for rev in revs]
5490 revs = [repo.lookup(rev) for rev in revs]
5488 repo.ui.pushbuffer()
5491 repo.ui.pushbuffer()
5489 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5492 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5490 commoninc=commoninc)
5493 commoninc=commoninc)
5491 repo.ui.popbuffer()
5494 repo.ui.popbuffer()
5492 o = outgoing.missing
5495 o = outgoing.missing
5493 if o:
5496 if o:
5494 t.append(_('%d outgoing') % len(o))
5497 t.append(_('%d outgoing') % len(o))
5495 if 'bookmarks' in other.listkeys('namespaces'):
5498 if 'bookmarks' in other.listkeys('namespaces'):
5496 lmarks = repo.listkeys('bookmarks')
5499 lmarks = repo.listkeys('bookmarks')
5497 rmarks = other.listkeys('bookmarks')
5500 rmarks = other.listkeys('bookmarks')
5498 diff = set(rmarks) - set(lmarks)
5501 diff = set(rmarks) - set(lmarks)
5499 if len(diff) > 0:
5502 if len(diff) > 0:
5500 t.append(_('%d incoming bookmarks') % len(diff))
5503 t.append(_('%d incoming bookmarks') % len(diff))
5501 diff = set(lmarks) - set(rmarks)
5504 diff = set(lmarks) - set(rmarks)
5502 if len(diff) > 0:
5505 if len(diff) > 0:
5503 t.append(_('%d outgoing bookmarks') % len(diff))
5506 t.append(_('%d outgoing bookmarks') % len(diff))
5504
5507
5505 if t:
5508 if t:
5506 # i18n: column positioning for "hg summary"
5509 # i18n: column positioning for "hg summary"
5507 ui.write(_('remote: %s\n') % (', '.join(t)))
5510 ui.write(_('remote: %s\n') % (', '.join(t)))
5508 else:
5511 else:
5509 # i18n: column positioning for "hg summary"
5512 # i18n: column positioning for "hg summary"
5510 ui.status(_('remote: (synced)\n'))
5513 ui.status(_('remote: (synced)\n'))
5511
5514
5512 @command('tag',
5515 @command('tag',
5513 [('f', 'force', None, _('force tag')),
5516 [('f', 'force', None, _('force tag')),
5514 ('l', 'local', None, _('make the tag local')),
5517 ('l', 'local', None, _('make the tag local')),
5515 ('r', 'rev', '', _('revision to tag'), _('REV')),
5518 ('r', 'rev', '', _('revision to tag'), _('REV')),
5516 ('', 'remove', None, _('remove a tag')),
5519 ('', 'remove', None, _('remove a tag')),
5517 # -l/--local is already there, commitopts cannot be used
5520 # -l/--local is already there, commitopts cannot be used
5518 ('e', 'edit', None, _('edit commit message')),
5521 ('e', 'edit', None, _('edit commit message')),
5519 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5522 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5520 ] + commitopts2,
5523 ] + commitopts2,
5521 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5524 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5522 def tag(ui, repo, name1, *names, **opts):
5525 def tag(ui, repo, name1, *names, **opts):
5523 """add one or more tags for the current or given revision
5526 """add one or more tags for the current or given revision
5524
5527
5525 Name a particular revision using <name>.
5528 Name a particular revision using <name>.
5526
5529
5527 Tags are used to name particular revisions of the repository and are
5530 Tags are used to name particular revisions of the repository and are
5528 very useful to compare different revisions, to go back to significant
5531 very useful to compare different revisions, to go back to significant
5529 earlier versions or to mark branch points as releases, etc. Changing
5532 earlier versions or to mark branch points as releases, etc. Changing
5530 an existing tag is normally disallowed; use -f/--force to override.
5533 an existing tag is normally disallowed; use -f/--force to override.
5531
5534
5532 If no revision is given, the parent of the working directory is
5535 If no revision is given, the parent of the working directory is
5533 used, or tip if no revision is checked out.
5536 used, or tip if no revision is checked out.
5534
5537
5535 To facilitate version control, distribution, and merging of tags,
5538 To facilitate version control, distribution, and merging of tags,
5536 they are stored as a file named ".hgtags" which is managed similarly
5539 they are stored as a file named ".hgtags" which is managed similarly
5537 to other project files and can be hand-edited if necessary. This
5540 to other project files and can be hand-edited if necessary. This
5538 also means that tagging creates a new commit. The file
5541 also means that tagging creates a new commit. The file
5539 ".hg/localtags" is used for local tags (not shared among
5542 ".hg/localtags" is used for local tags (not shared among
5540 repositories).
5543 repositories).
5541
5544
5542 Tag commits are usually made at the head of a branch. If the parent
5545 Tag commits are usually made at the head of a branch. If the parent
5543 of the working directory is not a branch head, :hg:`tag` aborts; use
5546 of the working directory is not a branch head, :hg:`tag` aborts; use
5544 -f/--force to force the tag commit to be based on a non-head
5547 -f/--force to force the tag commit to be based on a non-head
5545 changeset.
5548 changeset.
5546
5549
5547 See :hg:`help dates` for a list of formats valid for -d/--date.
5550 See :hg:`help dates` for a list of formats valid for -d/--date.
5548
5551
5549 Since tag names have priority over branch names during revision
5552 Since tag names have priority over branch names during revision
5550 lookup, using an existing branch name as a tag name is discouraged.
5553 lookup, using an existing branch name as a tag name is discouraged.
5551
5554
5552 Returns 0 on success.
5555 Returns 0 on success.
5553 """
5556 """
5554 wlock = lock = None
5557 wlock = lock = None
5555 try:
5558 try:
5556 wlock = repo.wlock()
5559 wlock = repo.wlock()
5557 lock = repo.lock()
5560 lock = repo.lock()
5558 rev_ = "."
5561 rev_ = "."
5559 names = [t.strip() for t in (name1,) + names]
5562 names = [t.strip() for t in (name1,) + names]
5560 if len(names) != len(set(names)):
5563 if len(names) != len(set(names)):
5561 raise util.Abort(_('tag names must be unique'))
5564 raise util.Abort(_('tag names must be unique'))
5562 for n in names:
5565 for n in names:
5563 scmutil.checknewlabel(repo, n, 'tag')
5566 scmutil.checknewlabel(repo, n, 'tag')
5564 if not n:
5567 if not n:
5565 raise util.Abort(_('tag names cannot consist entirely of '
5568 raise util.Abort(_('tag names cannot consist entirely of '
5566 'whitespace'))
5569 'whitespace'))
5567 if opts.get('rev') and opts.get('remove'):
5570 if opts.get('rev') and opts.get('remove'):
5568 raise util.Abort(_("--rev and --remove are incompatible"))
5571 raise util.Abort(_("--rev and --remove are incompatible"))
5569 if opts.get('rev'):
5572 if opts.get('rev'):
5570 rev_ = opts['rev']
5573 rev_ = opts['rev']
5571 message = opts.get('message')
5574 message = opts.get('message')
5572 if opts.get('remove'):
5575 if opts.get('remove'):
5573 expectedtype = opts.get('local') and 'local' or 'global'
5576 expectedtype = opts.get('local') and 'local' or 'global'
5574 for n in names:
5577 for n in names:
5575 if not repo.tagtype(n):
5578 if not repo.tagtype(n):
5576 raise util.Abort(_("tag '%s' does not exist") % n)
5579 raise util.Abort(_("tag '%s' does not exist") % n)
5577 if repo.tagtype(n) != expectedtype:
5580 if repo.tagtype(n) != expectedtype:
5578 if expectedtype == 'global':
5581 if expectedtype == 'global':
5579 raise util.Abort(_("tag '%s' is not a global tag") % n)
5582 raise util.Abort(_("tag '%s' is not a global tag") % n)
5580 else:
5583 else:
5581 raise util.Abort(_("tag '%s' is not a local tag") % n)
5584 raise util.Abort(_("tag '%s' is not a local tag") % n)
5582 rev_ = nullid
5585 rev_ = nullid
5583 if not message:
5586 if not message:
5584 # we don't translate commit messages
5587 # we don't translate commit messages
5585 message = 'Removed tag %s' % ', '.join(names)
5588 message = 'Removed tag %s' % ', '.join(names)
5586 elif not opts.get('force'):
5589 elif not opts.get('force'):
5587 for n in names:
5590 for n in names:
5588 if n in repo.tags():
5591 if n in repo.tags():
5589 raise util.Abort(_("tag '%s' already exists "
5592 raise util.Abort(_("tag '%s' already exists "
5590 "(use -f to force)") % n)
5593 "(use -f to force)") % n)
5591 if not opts.get('local'):
5594 if not opts.get('local'):
5592 p1, p2 = repo.dirstate.parents()
5595 p1, p2 = repo.dirstate.parents()
5593 if p2 != nullid:
5596 if p2 != nullid:
5594 raise util.Abort(_('uncommitted merge'))
5597 raise util.Abort(_('uncommitted merge'))
5595 bheads = repo.branchheads()
5598 bheads = repo.branchheads()
5596 if not opts.get('force') and bheads and p1 not in bheads:
5599 if not opts.get('force') and bheads and p1 not in bheads:
5597 raise util.Abort(_('not at a branch head (use -f to force)'))
5600 raise util.Abort(_('not at a branch head (use -f to force)'))
5598 r = scmutil.revsingle(repo, rev_).node()
5601 r = scmutil.revsingle(repo, rev_).node()
5599
5602
5600 if not message:
5603 if not message:
5601 # we don't translate commit messages
5604 # we don't translate commit messages
5602 message = ('Added tag %s for changeset %s' %
5605 message = ('Added tag %s for changeset %s' %
5603 (', '.join(names), short(r)))
5606 (', '.join(names), short(r)))
5604
5607
5605 date = opts.get('date')
5608 date = opts.get('date')
5606 if date:
5609 if date:
5607 date = util.parsedate(date)
5610 date = util.parsedate(date)
5608
5611
5609 if opts.get('edit'):
5612 if opts.get('edit'):
5610 message = ui.edit(message, ui.username())
5613 message = ui.edit(message, ui.username())
5611
5614
5612 # don't allow tagging the null rev
5615 # don't allow tagging the null rev
5613 if (not opts.get('remove') and
5616 if (not opts.get('remove') and
5614 scmutil.revsingle(repo, rev_).rev() == nullrev):
5617 scmutil.revsingle(repo, rev_).rev() == nullrev):
5615 raise util.Abort(_("cannot tag null revision"))
5618 raise util.Abort(_("cannot tag null revision"))
5616
5619
5617 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5620 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5618 finally:
5621 finally:
5619 release(lock, wlock)
5622 release(lock, wlock)
5620
5623
5621 @command('tags', [], '')
5624 @command('tags', [], '')
5622 def tags(ui, repo, **opts):
5625 def tags(ui, repo, **opts):
5623 """list repository tags
5626 """list repository tags
5624
5627
5625 This lists both regular and local tags. When the -v/--verbose
5628 This lists both regular and local tags. When the -v/--verbose
5626 switch is used, a third column "local" is printed for local tags.
5629 switch is used, a third column "local" is printed for local tags.
5627
5630
5628 Returns 0 on success.
5631 Returns 0 on success.
5629 """
5632 """
5630
5633
5631 fm = ui.formatter('tags', opts)
5634 fm = ui.formatter('tags', opts)
5632 hexfunc = ui.debugflag and hex or short
5635 hexfunc = ui.debugflag and hex or short
5633 tagtype = ""
5636 tagtype = ""
5634
5637
5635 for t, n in reversed(repo.tagslist()):
5638 for t, n in reversed(repo.tagslist()):
5636 hn = hexfunc(n)
5639 hn = hexfunc(n)
5637 label = 'tags.normal'
5640 label = 'tags.normal'
5638 tagtype = ''
5641 tagtype = ''
5639 if repo.tagtype(t) == 'local':
5642 if repo.tagtype(t) == 'local':
5640 label = 'tags.local'
5643 label = 'tags.local'
5641 tagtype = 'local'
5644 tagtype = 'local'
5642
5645
5643 fm.startitem()
5646 fm.startitem()
5644 fm.write('tag', '%s', t, label=label)
5647 fm.write('tag', '%s', t, label=label)
5645 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5648 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5646 fm.condwrite(not ui.quiet, 'rev id', fmt,
5649 fm.condwrite(not ui.quiet, 'rev id', fmt,
5647 repo.changelog.rev(n), hn, label=label)
5650 repo.changelog.rev(n), hn, label=label)
5648 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5651 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5649 tagtype, label=label)
5652 tagtype, label=label)
5650 fm.plain('\n')
5653 fm.plain('\n')
5651 fm.end()
5654 fm.end()
5652
5655
5653 @command('tip',
5656 @command('tip',
5654 [('p', 'patch', None, _('show patch')),
5657 [('p', 'patch', None, _('show patch')),
5655 ('g', 'git', None, _('use git extended diff format')),
5658 ('g', 'git', None, _('use git extended diff format')),
5656 ] + templateopts,
5659 ] + templateopts,
5657 _('[-p] [-g]'))
5660 _('[-p] [-g]'))
5658 def tip(ui, repo, **opts):
5661 def tip(ui, repo, **opts):
5659 """show the tip revision
5662 """show the tip revision
5660
5663
5661 The tip revision (usually just called the tip) is the changeset
5664 The tip revision (usually just called the tip) is the changeset
5662 most recently added to the repository (and therefore the most
5665 most recently added to the repository (and therefore the most
5663 recently changed head).
5666 recently changed head).
5664
5667
5665 If you have just made a commit, that commit will be the tip. If
5668 If you have just made a commit, that commit will be the tip. If
5666 you have just pulled changes from another repository, the tip of
5669 you have just pulled changes from another repository, the tip of
5667 that repository becomes the current tip. The "tip" tag is special
5670 that repository becomes the current tip. The "tip" tag is special
5668 and cannot be renamed or assigned to a different changeset.
5671 and cannot be renamed or assigned to a different changeset.
5669
5672
5670 Returns 0 on success.
5673 Returns 0 on success.
5671 """
5674 """
5672 displayer = cmdutil.show_changeset(ui, repo, opts)
5675 displayer = cmdutil.show_changeset(ui, repo, opts)
5673 displayer.show(repo['tip'])
5676 displayer.show(repo['tip'])
5674 displayer.close()
5677 displayer.close()
5675
5678
5676 @command('unbundle',
5679 @command('unbundle',
5677 [('u', 'update', None,
5680 [('u', 'update', None,
5678 _('update to new branch head if changesets were unbundled'))],
5681 _('update to new branch head if changesets were unbundled'))],
5679 _('[-u] FILE...'))
5682 _('[-u] FILE...'))
5680 def unbundle(ui, repo, fname1, *fnames, **opts):
5683 def unbundle(ui, repo, fname1, *fnames, **opts):
5681 """apply one or more changegroup files
5684 """apply one or more changegroup files
5682
5685
5683 Apply one or more compressed changegroup files generated by the
5686 Apply one or more compressed changegroup files generated by the
5684 bundle command.
5687 bundle command.
5685
5688
5686 Returns 0 on success, 1 if an update has unresolved files.
5689 Returns 0 on success, 1 if an update has unresolved files.
5687 """
5690 """
5688 fnames = (fname1,) + fnames
5691 fnames = (fname1,) + fnames
5689
5692
5690 lock = repo.lock()
5693 lock = repo.lock()
5691 wc = repo['.']
5694 wc = repo['.']
5692 try:
5695 try:
5693 for fname in fnames:
5696 for fname in fnames:
5694 f = hg.openpath(ui, fname)
5697 f = hg.openpath(ui, fname)
5695 gen = changegroup.readbundle(f, fname)
5698 gen = changegroup.readbundle(f, fname)
5696 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5699 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5697 finally:
5700 finally:
5698 lock.release()
5701 lock.release()
5699 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5702 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5700 return postincoming(ui, repo, modheads, opts.get('update'), None)
5703 return postincoming(ui, repo, modheads, opts.get('update'), None)
5701
5704
5702 @command('^update|up|checkout|co',
5705 @command('^update|up|checkout|co',
5703 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5706 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5704 ('c', 'check', None,
5707 ('c', 'check', None,
5705 _('update across branches if no uncommitted changes')),
5708 _('update across branches if no uncommitted changes')),
5706 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5709 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5707 ('r', 'rev', '', _('revision'), _('REV'))],
5710 ('r', 'rev', '', _('revision'), _('REV'))],
5708 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5711 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5709 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5712 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5710 """update working directory (or switch revisions)
5713 """update working directory (or switch revisions)
5711
5714
5712 Update the repository's working directory to the specified
5715 Update the repository's working directory to the specified
5713 changeset. If no changeset is specified, update to the tip of the
5716 changeset. If no changeset is specified, update to the tip of the
5714 current named branch and move the current bookmark (see :hg:`help
5717 current named branch and move the current bookmark (see :hg:`help
5715 bookmarks`).
5718 bookmarks`).
5716
5719
5717 Update sets the working directory's parent revision to the specified
5720 Update sets the working directory's parent revision to the specified
5718 changeset (see :hg:`help parents`).
5721 changeset (see :hg:`help parents`).
5719
5722
5720 If the changeset is not a descendant or ancestor of the working
5723 If the changeset is not a descendant or ancestor of the working
5721 directory's parent, the update is aborted. With the -c/--check
5724 directory's parent, the update is aborted. With the -c/--check
5722 option, the working directory is checked for uncommitted changes; if
5725 option, the working directory is checked for uncommitted changes; if
5723 none are found, the working directory is updated to the specified
5726 none are found, the working directory is updated to the specified
5724 changeset.
5727 changeset.
5725
5728
5726 .. container:: verbose
5729 .. container:: verbose
5727
5730
5728 The following rules apply when the working directory contains
5731 The following rules apply when the working directory contains
5729 uncommitted changes:
5732 uncommitted changes:
5730
5733
5731 1. If neither -c/--check nor -C/--clean is specified, and if
5734 1. If neither -c/--check nor -C/--clean is specified, and if
5732 the requested changeset is an ancestor or descendant of
5735 the requested changeset is an ancestor or descendant of
5733 the working directory's parent, the uncommitted changes
5736 the working directory's parent, the uncommitted changes
5734 are merged into the requested changeset and the merged
5737 are merged into the requested changeset and the merged
5735 result is left uncommitted. If the requested changeset is
5738 result is left uncommitted. If the requested changeset is
5736 not an ancestor or descendant (that is, it is on another
5739 not an ancestor or descendant (that is, it is on another
5737 branch), the update is aborted and the uncommitted changes
5740 branch), the update is aborted and the uncommitted changes
5738 are preserved.
5741 are preserved.
5739
5742
5740 2. With the -c/--check option, the update is aborted and the
5743 2. With the -c/--check option, the update is aborted and the
5741 uncommitted changes are preserved.
5744 uncommitted changes are preserved.
5742
5745
5743 3. With the -C/--clean option, uncommitted changes are discarded and
5746 3. With the -C/--clean option, uncommitted changes are discarded and
5744 the working directory is updated to the requested changeset.
5747 the working directory is updated to the requested changeset.
5745
5748
5746 To cancel an uncommitted merge (and lose your changes), use
5749 To cancel an uncommitted merge (and lose your changes), use
5747 :hg:`update --clean .`.
5750 :hg:`update --clean .`.
5748
5751
5749 Use null as the changeset to remove the working directory (like
5752 Use null as the changeset to remove the working directory (like
5750 :hg:`clone -U`).
5753 :hg:`clone -U`).
5751
5754
5752 If you want to revert just one file to an older revision, use
5755 If you want to revert just one file to an older revision, use
5753 :hg:`revert [-r REV] NAME`.
5756 :hg:`revert [-r REV] NAME`.
5754
5757
5755 See :hg:`help dates` for a list of formats valid for -d/--date.
5758 See :hg:`help dates` for a list of formats valid for -d/--date.
5756
5759
5757 Returns 0 on success, 1 if there are unresolved files.
5760 Returns 0 on success, 1 if there are unresolved files.
5758 """
5761 """
5759 if rev and node:
5762 if rev and node:
5760 raise util.Abort(_("please specify just one revision"))
5763 raise util.Abort(_("please specify just one revision"))
5761
5764
5762 if rev is None or rev == '':
5765 if rev is None or rev == '':
5763 rev = node
5766 rev = node
5764
5767
5765 # with no argument, we also move the current bookmark, if any
5768 # with no argument, we also move the current bookmark, if any
5766 movemarkfrom = None
5769 movemarkfrom = None
5767 if rev is None:
5770 if rev is None:
5768 curmark = repo._bookmarkcurrent
5771 curmark = repo._bookmarkcurrent
5769 if bookmarks.iscurrent(repo):
5772 if bookmarks.iscurrent(repo):
5770 movemarkfrom = repo['.'].node()
5773 movemarkfrom = repo['.'].node()
5771 elif curmark:
5774 elif curmark:
5772 ui.status(_("updating to active bookmark %s\n") % curmark)
5775 ui.status(_("updating to active bookmark %s\n") % curmark)
5773 rev = curmark
5776 rev = curmark
5774
5777
5775 # if we defined a bookmark, we have to remember the original bookmark name
5778 # if we defined a bookmark, we have to remember the original bookmark name
5776 brev = rev
5779 brev = rev
5777 rev = scmutil.revsingle(repo, rev, rev).rev()
5780 rev = scmutil.revsingle(repo, rev, rev).rev()
5778
5781
5779 if check and clean:
5782 if check and clean:
5780 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5783 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5781
5784
5782 if date:
5785 if date:
5783 if rev is not None:
5786 if rev is not None:
5784 raise util.Abort(_("you can't specify a revision and a date"))
5787 raise util.Abort(_("you can't specify a revision and a date"))
5785 rev = cmdutil.finddate(ui, repo, date)
5788 rev = cmdutil.finddate(ui, repo, date)
5786
5789
5787 if check:
5790 if check:
5788 c = repo[None]
5791 c = repo[None]
5789 if c.dirty(merge=False, branch=False, missing=True):
5792 if c.dirty(merge=False, branch=False, missing=True):
5790 raise util.Abort(_("uncommitted local changes"))
5793 raise util.Abort(_("uncommitted local changes"))
5791 if rev is None:
5794 if rev is None:
5792 rev = repo[repo[None].branch()].rev()
5795 rev = repo[repo[None].branch()].rev()
5793 mergemod._checkunknown(repo, repo[None], repo[rev])
5796 mergemod._checkunknown(repo, repo[None], repo[rev])
5794
5797
5795 if clean:
5798 if clean:
5796 ret = hg.clean(repo, rev)
5799 ret = hg.clean(repo, rev)
5797 else:
5800 else:
5798 ret = hg.update(repo, rev)
5801 ret = hg.update(repo, rev)
5799
5802
5800 if not ret and movemarkfrom:
5803 if not ret and movemarkfrom:
5801 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5804 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5802 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5805 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5803 elif brev in repo._bookmarks:
5806 elif brev in repo._bookmarks:
5804 bookmarks.setcurrent(repo, brev)
5807 bookmarks.setcurrent(repo, brev)
5805 elif brev:
5808 elif brev:
5806 bookmarks.unsetcurrent(repo)
5809 bookmarks.unsetcurrent(repo)
5807
5810
5808 return ret
5811 return ret
5809
5812
5810 @command('verify', [])
5813 @command('verify', [])
5811 def verify(ui, repo):
5814 def verify(ui, repo):
5812 """verify the integrity of the repository
5815 """verify the integrity of the repository
5813
5816
5814 Verify the integrity of the current repository.
5817 Verify the integrity of the current repository.
5815
5818
5816 This will perform an extensive check of the repository's
5819 This will perform an extensive check of the repository's
5817 integrity, validating the hashes and checksums of each entry in
5820 integrity, validating the hashes and checksums of each entry in
5818 the changelog, manifest, and tracked files, as well as the
5821 the changelog, manifest, and tracked files, as well as the
5819 integrity of their crosslinks and indices.
5822 integrity of their crosslinks and indices.
5820
5823
5821 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5824 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5822 for more information about recovery from corruption of the
5825 for more information about recovery from corruption of the
5823 repository.
5826 repository.
5824
5827
5825 Returns 0 on success, 1 if errors are encountered.
5828 Returns 0 on success, 1 if errors are encountered.
5826 """
5829 """
5827 return hg.verify(repo)
5830 return hg.verify(repo)
5828
5831
5829 @command('version', [])
5832 @command('version', [])
5830 def version_(ui):
5833 def version_(ui):
5831 """output version and copyright information"""
5834 """output version and copyright information"""
5832 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5835 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5833 % util.version())
5836 % util.version())
5834 ui.status(_(
5837 ui.status(_(
5835 "(see http://mercurial.selenic.com for more information)\n"
5838 "(see http://mercurial.selenic.com for more information)\n"
5836 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5839 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5837 "This is free software; see the source for copying conditions. "
5840 "This is free software; see the source for copying conditions. "
5838 "There is NO\nwarranty; "
5841 "There is NO\nwarranty; "
5839 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5842 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5840 ))
5843 ))
5841
5844
5842 norepo = ("clone init version help debugcommands debugcomplete"
5845 norepo = ("clone init version help debugcommands debugcomplete"
5843 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5846 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5844 " debugknown debuggetbundle debugbundle")
5847 " debugknown debuggetbundle debugbundle")
5845 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5848 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5846 " debugdata debugindex debugindexdot debugrevlog")
5849 " debugdata debugindex debugindexdot debugrevlog")
5847 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5850 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5848 " remove resolve status debugwalk")
5851 " remove resolve status debugwalk")
@@ -1,247 +1,304 b''
1 Test basic functionality of url#rev syntax
1 Test basic functionality of url#rev syntax
2
2
3 $ hg init repo
3 $ hg init repo
4 $ cd repo
4 $ cd repo
5 $ echo a > a
5 $ echo a > a
6 $ hg ci -qAm 'add a'
6 $ hg ci -qAm 'add a'
7 $ hg branch foo
7 $ hg branch foo
8 marked working directory as branch foo
8 marked working directory as branch foo
9 (branches are permanent and global, did you want a bookmark?)
9 (branches are permanent and global, did you want a bookmark?)
10 $ echo >> a
10 $ echo >> a
11 $ hg ci -m 'change a'
11 $ hg ci -m 'change a'
12 $ cd ..
12 $ cd ..
13
13
14 $ hg clone 'repo#foo' clone
14 $ hg clone 'repo#foo' clone
15 adding changesets
15 adding changesets
16 adding manifests
16 adding manifests
17 adding file changes
17 adding file changes
18 added 2 changesets with 2 changes to 1 files
18 added 2 changesets with 2 changes to 1 files
19 updating to branch foo
19 updating to branch foo
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21
21
22 $ hg --cwd clone heads
22 $ hg --cwd clone heads
23 changeset: 1:cd2a86ecc814
23 changeset: 1:cd2a86ecc814
24 branch: foo
24 branch: foo
25 tag: tip
25 tag: tip
26 user: test
26 user: test
27 date: Thu Jan 01 00:00:00 1970 +0000
27 date: Thu Jan 01 00:00:00 1970 +0000
28 summary: change a
28 summary: change a
29
29
30 changeset: 0:1f0dee641bb7
30 changeset: 0:1f0dee641bb7
31 user: test
31 user: test
32 date: Thu Jan 01 00:00:00 1970 +0000
32 date: Thu Jan 01 00:00:00 1970 +0000
33 summary: add a
33 summary: add a
34
34
35 $ hg --cwd clone parents
35 $ hg --cwd clone parents
36 changeset: 1:cd2a86ecc814
36 changeset: 1:cd2a86ecc814
37 branch: foo
37 branch: foo
38 tag: tip
38 tag: tip
39 user: test
39 user: test
40 date: Thu Jan 01 00:00:00 1970 +0000
40 date: Thu Jan 01 00:00:00 1970 +0000
41 summary: change a
41 summary: change a
42
42
43 $ cat clone/.hg/hgrc
43 $ cat clone/.hg/hgrc
44 [paths]
44 [paths]
45 default = $TESTTMP/repo#foo (glob)
45 default = $TESTTMP/repo#foo (glob)
46
46
47 Changing original repo:
47 Changing original repo:
48
48
49 $ cd repo
49 $ cd repo
50
50
51 $ echo >> a
51 $ echo >> a
52 $ hg ci -m 'new head of branch foo'
52 $ hg ci -m 'new head of branch foo'
53
53
54 $ hg up -qC default
54 $ hg up -qC default
55 $ echo bar > bar
55 $ echo bar > bar
56 $ hg ci -qAm 'add bar'
56 $ hg ci -qAm 'add bar'
57
57
58 $ hg log
58 $ hg log
59 changeset: 3:4cd725637392
59 changeset: 3:4cd725637392
60 tag: tip
60 tag: tip
61 parent: 0:1f0dee641bb7
61 parent: 0:1f0dee641bb7
62 user: test
62 user: test
63 date: Thu Jan 01 00:00:00 1970 +0000
63 date: Thu Jan 01 00:00:00 1970 +0000
64 summary: add bar
64 summary: add bar
65
65
66 changeset: 2:faba9097cad4
66 changeset: 2:faba9097cad4
67 branch: foo
67 branch: foo
68 user: test
68 user: test
69 date: Thu Jan 01 00:00:00 1970 +0000
69 date: Thu Jan 01 00:00:00 1970 +0000
70 summary: new head of branch foo
70 summary: new head of branch foo
71
71
72 changeset: 1:cd2a86ecc814
72 changeset: 1:cd2a86ecc814
73 branch: foo
73 branch: foo
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: change a
76 summary: change a
77
77
78 changeset: 0:1f0dee641bb7
78 changeset: 0:1f0dee641bb7
79 user: test
79 user: test
80 date: Thu Jan 01 00:00:00 1970 +0000
80 date: Thu Jan 01 00:00:00 1970 +0000
81 summary: add a
81 summary: add a
82
82
83 $ hg -q outgoing '../clone'
83 $ hg -q outgoing '../clone'
84 2:faba9097cad4
84 2:faba9097cad4
85 3:4cd725637392
85 3:4cd725637392
86 $ hg summary --remote --config paths.default='../clone'
86 $ hg summary --remote --config paths.default='../clone'
87 parent: 3:4cd725637392 tip
87 parent: 3:4cd725637392 tip
88 add bar
88 add bar
89 branch: default
89 branch: default
90 commit: (clean)
90 commit: (clean)
91 update: (current)
91 update: (current)
92 remote: 2 outgoing
92 remote: 2 outgoing
93 $ hg -q outgoing '../clone#foo'
93 $ hg -q outgoing '../clone#foo'
94 2:faba9097cad4
94 2:faba9097cad4
95 $ hg summary --remote --config paths.default='../clone#foo'
95 $ hg summary --remote --config paths.default='../clone#foo'
96 parent: 3:4cd725637392 tip
96 parent: 3:4cd725637392 tip
97 add bar
97 add bar
98 branch: default
98 branch: default
99 commit: (clean)
99 commit: (clean)
100 update: (current)
100 update: (current)
101 remote: 1 outgoing
101 remote: 1 outgoing
102
102
103 $ hg -q --cwd ../clone incoming '../repo#foo'
103 $ hg -q --cwd ../clone incoming '../repo#foo'
104 2:faba9097cad4
104 2:faba9097cad4
105 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
105 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
106 parent: 1:cd2a86ecc814 tip
106 parent: 1:cd2a86ecc814 tip
107 change a
107 change a
108 branch: foo
108 branch: foo
109 commit: (clean)
109 commit: (clean)
110 update: (current)
110 update: (current)
111 remote: 1 or more incoming
111 remote: 1 or more incoming
112
112
113 $ hg -q push '../clone#foo'
113 $ hg -q push '../clone#foo'
114
114
115 $ hg --cwd ../clone heads
115 $ hg --cwd ../clone heads
116 changeset: 2:faba9097cad4
116 changeset: 2:faba9097cad4
117 branch: foo
117 branch: foo
118 tag: tip
118 tag: tip
119 user: test
119 user: test
120 date: Thu Jan 01 00:00:00 1970 +0000
120 date: Thu Jan 01 00:00:00 1970 +0000
121 summary: new head of branch foo
121 summary: new head of branch foo
122
122
123 changeset: 0:1f0dee641bb7
123 changeset: 0:1f0dee641bb7
124 user: test
124 user: test
125 date: Thu Jan 01 00:00:00 1970 +0000
125 date: Thu Jan 01 00:00:00 1970 +0000
126 summary: add a
126 summary: add a
127
127
128 $ hg -q --cwd ../clone incoming '../repo#foo'
128 $ hg -q --cwd ../clone incoming '../repo#foo'
129 [1]
129 [1]
130 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
130 $ hg --cwd ../clone summary --remote --config paths.default='../repo#foo'
131 parent: 1:cd2a86ecc814
131 parent: 1:cd2a86ecc814
132 change a
132 change a
133 branch: foo
133 branch: foo
134 commit: (clean)
134 commit: (clean)
135 update: 1 new changesets (update)
135 update: 1 new changesets (update)
136 remote: (synced)
136 remote: (synced)
137
137
138 $ cd ..
138 $ cd ..
139
139
140 $ cd clone
140 $ cd clone
141 $ hg rollback
141 $ hg rollback
142 repository tip rolled back to revision 1 (undo push)
142 repository tip rolled back to revision 1 (undo push)
143
143
144 $ hg -q incoming
144 $ hg -q incoming
145 2:faba9097cad4
145 2:faba9097cad4
146
146
147 $ hg -q pull
147 $ hg -q pull
148
148
149 $ hg heads
149 $ hg heads
150 changeset: 2:faba9097cad4
150 changeset: 2:faba9097cad4
151 branch: foo
151 branch: foo
152 tag: tip
152 tag: tip
153 user: test
153 user: test
154 date: Thu Jan 01 00:00:00 1970 +0000
154 date: Thu Jan 01 00:00:00 1970 +0000
155 summary: new head of branch foo
155 summary: new head of branch foo
156
156
157 changeset: 0:1f0dee641bb7
157 changeset: 0:1f0dee641bb7
158 user: test
158 user: test
159 date: Thu Jan 01 00:00:00 1970 +0000
159 date: Thu Jan 01 00:00:00 1970 +0000
160 summary: add a
160 summary: add a
161
161
162 Pull should not have updated:
162 Pull should not have updated:
163
163
164 $ hg parents -q
164 $ hg parents -q
165 1:cd2a86ecc814
165 1:cd2a86ecc814
166
166
167 Going back to the default branch:
167 Going back to the default branch:
168
168
169 $ hg up -C 0
169 $ hg up -C 0
170 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
171
171
172 $ hg parents
172 $ hg parents
173 changeset: 0:1f0dee641bb7
173 changeset: 0:1f0dee641bb7
174 user: test
174 user: test
175 date: Thu Jan 01 00:00:00 1970 +0000
175 date: Thu Jan 01 00:00:00 1970 +0000
176 summary: add a
176 summary: add a
177
177
178 No new revs, no update:
178 No new revs, no update:
179
179
180 $ hg pull -qu
180 $ hg pull -qu
181
181
182 $ hg parents -q
182 $ hg parents -q
183 0:1f0dee641bb7
183 0:1f0dee641bb7
184
184
185 $ hg rollback
185 $ hg rollback
186 repository tip rolled back to revision 1 (undo pull)
186 repository tip rolled back to revision 1 (undo pull)
187
187
188 $ hg parents -q
188 $ hg parents -q
189 0:1f0dee641bb7
189 0:1f0dee641bb7
190
190
191 Pull -u takes us back to branch foo:
191 Pull -u takes us back to branch foo:
192
192
193 $ hg pull -qu
193 $ hg pull -qu
194
194
195 $ hg parents
195 $ hg parents
196 changeset: 2:faba9097cad4
196 changeset: 2:faba9097cad4
197 branch: foo
197 branch: foo
198 tag: tip
198 tag: tip
199 user: test
199 user: test
200 date: Thu Jan 01 00:00:00 1970 +0000
200 date: Thu Jan 01 00:00:00 1970 +0000
201 summary: new head of branch foo
201 summary: new head of branch foo
202
202
203 $ hg rollback
203 $ hg rollback
204 repository tip rolled back to revision 1 (undo pull)
204 repository tip rolled back to revision 1 (undo pull)
205 working directory now based on revision 0
205 working directory now based on revision 0
206
206
207 $ hg up -C 0
207 $ hg up -C 0
208 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
208 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
209
209
210 $ hg parents -q
210 $ hg parents -q
211 0:1f0dee641bb7
211 0:1f0dee641bb7
212
212
213 $ hg heads -q
213 $ hg heads -q
214 1:cd2a86ecc814
214 1:cd2a86ecc814
215 0:1f0dee641bb7
215 0:1f0dee641bb7
216
216
217 $ hg pull -qur default default
217 $ hg pull -qur default default
218
218
219 $ hg parents
219 $ hg parents
220 changeset: 3:4cd725637392
220 changeset: 3:4cd725637392
221 tag: tip
221 tag: tip
222 parent: 0:1f0dee641bb7
222 parent: 0:1f0dee641bb7
223 user: test
223 user: test
224 date: Thu Jan 01 00:00:00 1970 +0000
224 date: Thu Jan 01 00:00:00 1970 +0000
225 summary: add bar
225 summary: add bar
226
226
227 $ hg heads
227 $ hg heads
228 changeset: 3:4cd725637392
228 changeset: 3:4cd725637392
229 tag: tip
229 tag: tip
230 parent: 0:1f0dee641bb7
230 parent: 0:1f0dee641bb7
231 user: test
231 user: test
232 date: Thu Jan 01 00:00:00 1970 +0000
232 date: Thu Jan 01 00:00:00 1970 +0000
233 summary: add bar
233 summary: add bar
234
234
235 changeset: 2:faba9097cad4
235 changeset: 2:faba9097cad4
236 branch: foo
236 branch: foo
237 user: test
237 user: test
238 date: Thu Jan 01 00:00:00 1970 +0000
238 date: Thu Jan 01 00:00:00 1970 +0000
239 summary: new head of branch foo
239 summary: new head of branch foo
240
240
241 Test handling of invalid urls
241 Test handling of invalid urls
242
242
243 $ hg id http://foo/?bar
243 $ hg id http://foo/?bar
244 abort: unsupported URL component: "bar"
244 abort: unsupported URL component: "bar"
245 [255]
245 [255]
246
246
247 $ cd ..
247 $ cd ..
248
249 Test handling common incoming revisions between "default" and
250 "default-push"
251
252 $ hg -R clone rollback
253 repository tip rolled back to revision 1 (undo pull)
254 working directory now based on revision 0
255
256 $ cd repo
257
258 $ hg update -q -C default
259 $ echo modified >> bar
260 $ hg commit -m "new head to push current default head"
261 $ hg -q push -r ".^1" '../clone'
262
263 $ hg -q outgoing '../clone'
264 2:faba9097cad4
265 4:d515801a8f3d
266
267 $ hg summary --remote --config paths.default='../clone#default' --config paths.default-push='../clone#foo'
268 parent: 4:d515801a8f3d tip
269 new head to push current default head
270 branch: default
271 commit: (clean)
272 update: (current)
273 remote: 1 outgoing
274
275 $ hg summary --remote --config paths.default='../clone#foo' --config paths.default-push='../clone'
276 parent: 4:d515801a8f3d tip
277 new head to push current default head
278 branch: default
279 commit: (clean)
280 update: (current)
281 remote: 2 outgoing
282
283 $ hg summary --remote --config paths.default='../clone' --config paths.default-push='../clone#foo'
284 parent: 4:d515801a8f3d tip
285 new head to push current default head
286 branch: default
287 commit: (clean)
288 update: (current)
289 remote: 1 outgoing
290
291 $ hg clone -q -r 0 . ../another
292 $ hg -q outgoing '../another#default'
293 3:4cd725637392
294 4:d515801a8f3d
295
296 $ hg summary --remote --config paths.default='../another#default' --config paths.default-push='../clone#default'
297 parent: 4:d515801a8f3d tip
298 new head to push current default head
299 branch: default
300 commit: (clean)
301 update: (current)
302 remote: 1 outgoing
303
304 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now