##// END OF EJS Templates
debugobsolete: use the new date argument on obsstore.create...
Pierre-Yves David -
r22218:b629397c default
parent child Browse files
Show More
@@ -1,6063 +1,6067 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, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys
12 import sys
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 import extensions
17 import extensions
18 from hgweb import server as hgweb_server
18 from hgweb import server as hgweb_server
19 import merge as mergemod
19 import merge as mergemod
20 import minirst, revset, fileset
20 import minirst, revset, fileset
21 import dagparser, context, simplemerge, graphmod
21 import dagparser, context, simplemerge, graphmod
22 import random
22 import random
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 import phases, obsolete, exchange
24 import phases, obsolete, exchange
25
25
26 table = {}
26 table = {}
27
27
28 command = cmdutil.command(table)
28 command = cmdutil.command(table)
29
29
30 # Space delimited list of commands that don't require local repositories.
30 # Space delimited list of commands that don't require local repositories.
31 # This should be populated by passing norepo=True into the @command decorator.
31 # This should be populated by passing norepo=True into the @command decorator.
32 norepo = ''
32 norepo = ''
33 # Space delimited list of commands that optionally require local repositories.
33 # Space delimited list of commands that optionally require local repositories.
34 # This should be populated by passing optionalrepo=True into the @command
34 # This should be populated by passing optionalrepo=True into the @command
35 # decorator.
35 # decorator.
36 optionalrepo = ''
36 optionalrepo = ''
37 # Space delimited list of commands that will examine arguments looking for
37 # Space delimited list of commands that will examine arguments looking for
38 # a repository. This should be populated by passing inferrepo=True into the
38 # a repository. This should be populated by passing inferrepo=True into the
39 # @command decorator.
39 # @command decorator.
40 inferrepo = ''
40 inferrepo = ''
41
41
42 # common command options
42 # common command options
43
43
44 globalopts = [
44 globalopts = [
45 ('R', 'repository', '',
45 ('R', 'repository', '',
46 _('repository root directory or name of overlay bundle file'),
46 _('repository root directory or name of overlay bundle file'),
47 _('REPO')),
47 _('REPO')),
48 ('', 'cwd', '',
48 ('', 'cwd', '',
49 _('change working directory'), _('DIR')),
49 _('change working directory'), _('DIR')),
50 ('y', 'noninteractive', None,
50 ('y', 'noninteractive', None,
51 _('do not prompt, automatically pick the first choice for all prompts')),
51 _('do not prompt, automatically pick the first choice for all prompts')),
52 ('q', 'quiet', None, _('suppress output')),
52 ('q', 'quiet', None, _('suppress output')),
53 ('v', 'verbose', None, _('enable additional output')),
53 ('v', 'verbose', None, _('enable additional output')),
54 ('', 'config', [],
54 ('', 'config', [],
55 _('set/override config option (use \'section.name=value\')'),
55 _('set/override config option (use \'section.name=value\')'),
56 _('CONFIG')),
56 _('CONFIG')),
57 ('', 'debug', None, _('enable debugging output')),
57 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debugger', None, _('start debugger')),
58 ('', 'debugger', None, _('start debugger')),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 _('ENCODE')),
60 _('ENCODE')),
61 ('', 'encodingmode', encoding.encodingmode,
61 ('', 'encodingmode', encoding.encodingmode,
62 _('set the charset encoding mode'), _('MODE')),
62 _('set the charset encoding mode'), _('MODE')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'time', None, _('time how long the command takes')),
64 ('', 'time', None, _('time how long the command takes')),
65 ('', 'profile', None, _('print command execution profile')),
65 ('', 'profile', None, _('print command execution profile')),
66 ('', 'version', None, _('output version information and exit')),
66 ('', 'version', None, _('output version information and exit')),
67 ('h', 'help', None, _('display help and exit')),
67 ('h', 'help', None, _('display help and exit')),
68 ('', 'hidden', False, _('consider hidden changesets')),
68 ('', 'hidden', False, _('consider hidden changesets')),
69 ]
69 ]
70
70
71 dryrunopts = [('n', 'dry-run', None,
71 dryrunopts = [('n', 'dry-run', None,
72 _('do not perform actions, just print output'))]
72 _('do not perform actions, just print output'))]
73
73
74 remoteopts = [
74 remoteopts = [
75 ('e', 'ssh', '',
75 ('e', 'ssh', '',
76 _('specify ssh command to use'), _('CMD')),
76 _('specify ssh command to use'), _('CMD')),
77 ('', 'remotecmd', '',
77 ('', 'remotecmd', '',
78 _('specify hg command to run on the remote side'), _('CMD')),
78 _('specify hg command to run on the remote side'), _('CMD')),
79 ('', 'insecure', None,
79 ('', 'insecure', None,
80 _('do not verify server certificate (ignoring web.cacerts config)')),
80 _('do not verify server certificate (ignoring web.cacerts config)')),
81 ]
81 ]
82
82
83 walkopts = [
83 walkopts = [
84 ('I', 'include', [],
84 ('I', 'include', [],
85 _('include names matching the given patterns'), _('PATTERN')),
85 _('include names matching the given patterns'), _('PATTERN')),
86 ('X', 'exclude', [],
86 ('X', 'exclude', [],
87 _('exclude names matching the given patterns'), _('PATTERN')),
87 _('exclude names matching the given patterns'), _('PATTERN')),
88 ]
88 ]
89
89
90 commitopts = [
90 commitopts = [
91 ('m', 'message', '',
91 ('m', 'message', '',
92 _('use text as commit message'), _('TEXT')),
92 _('use text as commit message'), _('TEXT')),
93 ('l', 'logfile', '',
93 ('l', 'logfile', '',
94 _('read commit message from file'), _('FILE')),
94 _('read commit message from file'), _('FILE')),
95 ]
95 ]
96
96
97 commitopts2 = [
97 commitopts2 = [
98 ('d', 'date', '',
98 ('d', 'date', '',
99 _('record the specified date as commit date'), _('DATE')),
99 _('record the specified date as commit date'), _('DATE')),
100 ('u', 'user', '',
100 ('u', 'user', '',
101 _('record the specified user as committer'), _('USER')),
101 _('record the specified user as committer'), _('USER')),
102 ]
102 ]
103
103
104 templateopts = [
104 templateopts = [
105 ('', 'style', '',
105 ('', 'style', '',
106 _('display using template map file (DEPRECATED)'), _('STYLE')),
106 _('display using template map file (DEPRECATED)'), _('STYLE')),
107 ('T', 'template', '',
107 ('T', 'template', '',
108 _('display with template'), _('TEMPLATE')),
108 _('display with template'), _('TEMPLATE')),
109 ]
109 ]
110
110
111 logopts = [
111 logopts = [
112 ('p', 'patch', None, _('show patch')),
112 ('p', 'patch', None, _('show patch')),
113 ('g', 'git', None, _('use git extended diff format')),
113 ('g', 'git', None, _('use git extended diff format')),
114 ('l', 'limit', '',
114 ('l', 'limit', '',
115 _('limit number of changes displayed'), _('NUM')),
115 _('limit number of changes displayed'), _('NUM')),
116 ('M', 'no-merges', None, _('do not show merges')),
116 ('M', 'no-merges', None, _('do not show merges')),
117 ('', 'stat', None, _('output diffstat-style summary of changes')),
117 ('', 'stat', None, _('output diffstat-style summary of changes')),
118 ('G', 'graph', None, _("show the revision DAG")),
118 ('G', 'graph', None, _("show the revision DAG")),
119 ] + templateopts
119 ] + templateopts
120
120
121 diffopts = [
121 diffopts = [
122 ('a', 'text', None, _('treat all files as text')),
122 ('a', 'text', None, _('treat all files as text')),
123 ('g', 'git', None, _('use git extended diff format')),
123 ('g', 'git', None, _('use git extended diff format')),
124 ('', 'nodates', None, _('omit dates from diff headers'))
124 ('', 'nodates', None, _('omit dates from diff headers'))
125 ]
125 ]
126
126
127 diffwsopts = [
127 diffwsopts = [
128 ('w', 'ignore-all-space', None,
128 ('w', 'ignore-all-space', None,
129 _('ignore white space when comparing lines')),
129 _('ignore white space when comparing lines')),
130 ('b', 'ignore-space-change', None,
130 ('b', 'ignore-space-change', None,
131 _('ignore changes in the amount of white space')),
131 _('ignore changes in the amount of white space')),
132 ('B', 'ignore-blank-lines', None,
132 ('B', 'ignore-blank-lines', None,
133 _('ignore changes whose lines are all blank')),
133 _('ignore changes whose lines are all blank')),
134 ]
134 ]
135
135
136 diffopts2 = [
136 diffopts2 = [
137 ('p', 'show-function', None, _('show which function each change is in')),
137 ('p', 'show-function', None, _('show which function each change is in')),
138 ('', 'reverse', None, _('produce a diff that undoes the changes')),
138 ('', 'reverse', None, _('produce a diff that undoes the changes')),
139 ] + diffwsopts + [
139 ] + diffwsopts + [
140 ('U', 'unified', '',
140 ('U', 'unified', '',
141 _('number of lines of context to show'), _('NUM')),
141 _('number of lines of context to show'), _('NUM')),
142 ('', 'stat', None, _('output diffstat-style summary of changes')),
142 ('', 'stat', None, _('output diffstat-style summary of changes')),
143 ]
143 ]
144
144
145 mergetoolopts = [
145 mergetoolopts = [
146 ('t', 'tool', '', _('specify merge tool')),
146 ('t', 'tool', '', _('specify merge tool')),
147 ]
147 ]
148
148
149 similarityopts = [
149 similarityopts = [
150 ('s', 'similarity', '',
150 ('s', 'similarity', '',
151 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
151 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
152 ]
152 ]
153
153
154 subrepoopts = [
154 subrepoopts = [
155 ('S', 'subrepos', None,
155 ('S', 'subrepos', None,
156 _('recurse into subrepositories'))
156 _('recurse into subrepositories'))
157 ]
157 ]
158
158
159 # Commands start here, listed alphabetically
159 # Commands start here, listed alphabetically
160
160
161 @command('^add',
161 @command('^add',
162 walkopts + subrepoopts + dryrunopts,
162 walkopts + subrepoopts + dryrunopts,
163 _('[OPTION]... [FILE]...'),
163 _('[OPTION]... [FILE]...'),
164 inferrepo=True)
164 inferrepo=True)
165 def add(ui, repo, *pats, **opts):
165 def add(ui, repo, *pats, **opts):
166 """add the specified files on the next commit
166 """add the specified files on the next commit
167
167
168 Schedule files to be version controlled and added to the
168 Schedule files to be version controlled and added to the
169 repository.
169 repository.
170
170
171 The files will be added to the repository at the next commit. To
171 The files will be added to the repository at the next commit. To
172 undo an add before that, see :hg:`forget`.
172 undo an add before that, see :hg:`forget`.
173
173
174 If no names are given, add all files to the repository.
174 If no names are given, add all files to the repository.
175
175
176 .. container:: verbose
176 .. container:: verbose
177
177
178 An example showing how new (unknown) files are added
178 An example showing how new (unknown) files are added
179 automatically by :hg:`add`::
179 automatically by :hg:`add`::
180
180
181 $ ls
181 $ ls
182 foo.c
182 foo.c
183 $ hg status
183 $ hg status
184 ? foo.c
184 ? foo.c
185 $ hg add
185 $ hg add
186 adding foo.c
186 adding foo.c
187 $ hg status
187 $ hg status
188 A foo.c
188 A foo.c
189
189
190 Returns 0 if all files are successfully added.
190 Returns 0 if all files are successfully added.
191 """
191 """
192
192
193 m = scmutil.match(repo[None], pats, opts)
193 m = scmutil.match(repo[None], pats, opts)
194 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
194 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
195 opts.get('subrepos'), prefix="", explicitonly=False)
195 opts.get('subrepos'), prefix="", explicitonly=False)
196 return rejected and 1 or 0
196 return rejected and 1 or 0
197
197
198 @command('addremove',
198 @command('addremove',
199 similarityopts + walkopts + dryrunopts,
199 similarityopts + walkopts + dryrunopts,
200 _('[OPTION]... [FILE]...'),
200 _('[OPTION]... [FILE]...'),
201 inferrepo=True)
201 inferrepo=True)
202 def addremove(ui, repo, *pats, **opts):
202 def addremove(ui, repo, *pats, **opts):
203 """add all new files, delete all missing files
203 """add all new files, delete all missing files
204
204
205 Add all new files and remove all missing files from the
205 Add all new files and remove all missing files from the
206 repository.
206 repository.
207
207
208 New files are ignored if they match any of the patterns in
208 New files are ignored if they match any of the patterns in
209 ``.hgignore``. As with add, these changes take effect at the next
209 ``.hgignore``. As with add, these changes take effect at the next
210 commit.
210 commit.
211
211
212 Use the -s/--similarity option to detect renamed files. This
212 Use the -s/--similarity option to detect renamed files. This
213 option takes a percentage between 0 (disabled) and 100 (files must
213 option takes a percentage between 0 (disabled) and 100 (files must
214 be identical) as its parameter. With a parameter greater than 0,
214 be identical) as its parameter. With a parameter greater than 0,
215 this compares every removed file with every added file and records
215 this compares every removed file with every added file and records
216 those similar enough as renames. Detecting renamed files this way
216 those similar enough as renames. Detecting renamed files this way
217 can be expensive. After using this option, :hg:`status -C` can be
217 can be expensive. After using this option, :hg:`status -C` can be
218 used to check which files were identified as moved or renamed. If
218 used to check which files were identified as moved or renamed. If
219 not specified, -s/--similarity defaults to 100 and only renames of
219 not specified, -s/--similarity defaults to 100 and only renames of
220 identical files are detected.
220 identical files are detected.
221
221
222 Returns 0 if all files are successfully added.
222 Returns 0 if all files are successfully added.
223 """
223 """
224 try:
224 try:
225 sim = float(opts.get('similarity') or 100)
225 sim = float(opts.get('similarity') or 100)
226 except ValueError:
226 except ValueError:
227 raise util.Abort(_('similarity must be a number'))
227 raise util.Abort(_('similarity must be a number'))
228 if sim < 0 or sim > 100:
228 if sim < 0 or sim > 100:
229 raise util.Abort(_('similarity must be between 0 and 100'))
229 raise util.Abort(_('similarity must be between 0 and 100'))
230 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
230 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
231
231
232 @command('^annotate|blame',
232 @command('^annotate|blame',
233 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
233 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
234 ('', 'follow', None,
234 ('', 'follow', None,
235 _('follow copies/renames and list the filename (DEPRECATED)')),
235 _('follow copies/renames and list the filename (DEPRECATED)')),
236 ('', 'no-follow', None, _("don't follow copies and renames")),
236 ('', 'no-follow', None, _("don't follow copies and renames")),
237 ('a', 'text', None, _('treat all files as text')),
237 ('a', 'text', None, _('treat all files as text')),
238 ('u', 'user', None, _('list the author (long with -v)')),
238 ('u', 'user', None, _('list the author (long with -v)')),
239 ('f', 'file', None, _('list the filename')),
239 ('f', 'file', None, _('list the filename')),
240 ('d', 'date', None, _('list the date (short with -q)')),
240 ('d', 'date', None, _('list the date (short with -q)')),
241 ('n', 'number', None, _('list the revision number (default)')),
241 ('n', 'number', None, _('list the revision number (default)')),
242 ('c', 'changeset', None, _('list the changeset')),
242 ('c', 'changeset', None, _('list the changeset')),
243 ('l', 'line-number', None, _('show line number at the first appearance'))
243 ('l', 'line-number', None, _('show line number at the first appearance'))
244 ] + diffwsopts + walkopts,
244 ] + diffwsopts + walkopts,
245 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
245 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
246 inferrepo=True)
246 inferrepo=True)
247 def annotate(ui, repo, *pats, **opts):
247 def annotate(ui, repo, *pats, **opts):
248 """show changeset information by line for each file
248 """show changeset information by line for each file
249
249
250 List changes in files, showing the revision id responsible for
250 List changes in files, showing the revision id responsible for
251 each line
251 each line
252
252
253 This command is useful for discovering when a change was made and
253 This command is useful for discovering when a change was made and
254 by whom.
254 by whom.
255
255
256 Without the -a/--text option, annotate will avoid processing files
256 Without the -a/--text option, annotate will avoid processing files
257 it detects as binary. With -a, annotate will annotate the file
257 it detects as binary. With -a, annotate will annotate the file
258 anyway, although the results will probably be neither useful
258 anyway, although the results will probably be neither useful
259 nor desirable.
259 nor desirable.
260
260
261 Returns 0 on success.
261 Returns 0 on success.
262 """
262 """
263 if opts.get('follow'):
263 if opts.get('follow'):
264 # --follow is deprecated and now just an alias for -f/--file
264 # --follow is deprecated and now just an alias for -f/--file
265 # to mimic the behavior of Mercurial before version 1.5
265 # to mimic the behavior of Mercurial before version 1.5
266 opts['file'] = True
266 opts['file'] = True
267
267
268 datefunc = ui.quiet and util.shortdate or util.datestr
268 datefunc = ui.quiet and util.shortdate or util.datestr
269 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
269 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
270
270
271 if not pats:
271 if not pats:
272 raise util.Abort(_('at least one filename or pattern is required'))
272 raise util.Abort(_('at least one filename or pattern is required'))
273
273
274 hexfn = ui.debugflag and hex or short
274 hexfn = ui.debugflag and hex or short
275
275
276 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
276 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
277 ('number', ' ', lambda x: str(x[0].rev())),
277 ('number', ' ', lambda x: str(x[0].rev())),
278 ('changeset', ' ', lambda x: hexfn(x[0].node())),
278 ('changeset', ' ', lambda x: hexfn(x[0].node())),
279 ('date', ' ', getdate),
279 ('date', ' ', getdate),
280 ('file', ' ', lambda x: x[0].path()),
280 ('file', ' ', lambda x: x[0].path()),
281 ('line_number', ':', lambda x: str(x[1])),
281 ('line_number', ':', lambda x: str(x[1])),
282 ]
282 ]
283
283
284 if (not opts.get('user') and not opts.get('changeset')
284 if (not opts.get('user') and not opts.get('changeset')
285 and not opts.get('date') and not opts.get('file')):
285 and not opts.get('date') and not opts.get('file')):
286 opts['number'] = True
286 opts['number'] = True
287
287
288 linenumber = opts.get('line_number') is not None
288 linenumber = opts.get('line_number') is not None
289 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
289 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
290 raise util.Abort(_('at least one of -n/-c is required for -l'))
290 raise util.Abort(_('at least one of -n/-c is required for -l'))
291
291
292 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
292 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
293 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
293 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
294
294
295 def bad(x, y):
295 def bad(x, y):
296 raise util.Abort("%s: %s" % (x, y))
296 raise util.Abort("%s: %s" % (x, y))
297
297
298 ctx = scmutil.revsingle(repo, opts.get('rev'))
298 ctx = scmutil.revsingle(repo, opts.get('rev'))
299 m = scmutil.match(ctx, pats, opts)
299 m = scmutil.match(ctx, pats, opts)
300 m.bad = bad
300 m.bad = bad
301 follow = not opts.get('no_follow')
301 follow = not opts.get('no_follow')
302 diffopts = patch.diffopts(ui, opts, section='annotate')
302 diffopts = patch.diffopts(ui, opts, section='annotate')
303 for abs in ctx.walk(m):
303 for abs in ctx.walk(m):
304 fctx = ctx[abs]
304 fctx = ctx[abs]
305 if not opts.get('text') and util.binary(fctx.data()):
305 if not opts.get('text') and util.binary(fctx.data()):
306 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
306 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
307 continue
307 continue
308
308
309 lines = fctx.annotate(follow=follow, linenumber=linenumber,
309 lines = fctx.annotate(follow=follow, linenumber=linenumber,
310 diffopts=diffopts)
310 diffopts=diffopts)
311 pieces = []
311 pieces = []
312
312
313 for f, sep in funcmap:
313 for f, sep in funcmap:
314 l = [f(n) for n, dummy in lines]
314 l = [f(n) for n, dummy in lines]
315 if l:
315 if l:
316 sized = [(x, encoding.colwidth(x)) for x in l]
316 sized = [(x, encoding.colwidth(x)) for x in l]
317 ml = max([w for x, w in sized])
317 ml = max([w for x, w in sized])
318 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
318 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
319 for x, w in sized])
319 for x, w in sized])
320
320
321 if pieces:
321 if pieces:
322 for p, l in zip(zip(*pieces), lines):
322 for p, l in zip(zip(*pieces), lines):
323 ui.write("%s: %s" % ("".join(p), l[1]))
323 ui.write("%s: %s" % ("".join(p), l[1]))
324
324
325 if lines and not lines[-1][1].endswith('\n'):
325 if lines and not lines[-1][1].endswith('\n'):
326 ui.write('\n')
326 ui.write('\n')
327
327
328 @command('archive',
328 @command('archive',
329 [('', 'no-decode', None, _('do not pass files through decoders')),
329 [('', 'no-decode', None, _('do not pass files through decoders')),
330 ('p', 'prefix', '', _('directory prefix for files in archive'),
330 ('p', 'prefix', '', _('directory prefix for files in archive'),
331 _('PREFIX')),
331 _('PREFIX')),
332 ('r', 'rev', '', _('revision to distribute'), _('REV')),
332 ('r', 'rev', '', _('revision to distribute'), _('REV')),
333 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
333 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
334 ] + subrepoopts + walkopts,
334 ] + subrepoopts + walkopts,
335 _('[OPTION]... DEST'))
335 _('[OPTION]... DEST'))
336 def archive(ui, repo, dest, **opts):
336 def archive(ui, repo, dest, **opts):
337 '''create an unversioned archive of a repository revision
337 '''create an unversioned archive of a repository revision
338
338
339 By default, the revision used is the parent of the working
339 By default, the revision used is the parent of the working
340 directory; use -r/--rev to specify a different revision.
340 directory; use -r/--rev to specify a different revision.
341
341
342 The archive type is automatically detected based on file
342 The archive type is automatically detected based on file
343 extension (or override using -t/--type).
343 extension (or override using -t/--type).
344
344
345 .. container:: verbose
345 .. container:: verbose
346
346
347 Examples:
347 Examples:
348
348
349 - create a zip file containing the 1.0 release::
349 - create a zip file containing the 1.0 release::
350
350
351 hg archive -r 1.0 project-1.0.zip
351 hg archive -r 1.0 project-1.0.zip
352
352
353 - create a tarball excluding .hg files::
353 - create a tarball excluding .hg files::
354
354
355 hg archive project.tar.gz -X ".hg*"
355 hg archive project.tar.gz -X ".hg*"
356
356
357 Valid types are:
357 Valid types are:
358
358
359 :``files``: a directory full of files (default)
359 :``files``: a directory full of files (default)
360 :``tar``: tar archive, uncompressed
360 :``tar``: tar archive, uncompressed
361 :``tbz2``: tar archive, compressed using bzip2
361 :``tbz2``: tar archive, compressed using bzip2
362 :``tgz``: tar archive, compressed using gzip
362 :``tgz``: tar archive, compressed using gzip
363 :``uzip``: zip archive, uncompressed
363 :``uzip``: zip archive, uncompressed
364 :``zip``: zip archive, compressed using deflate
364 :``zip``: zip archive, compressed using deflate
365
365
366 The exact name of the destination archive or directory is given
366 The exact name of the destination archive or directory is given
367 using a format string; see :hg:`help export` for details.
367 using a format string; see :hg:`help export` for details.
368
368
369 Each member added to an archive file has a directory prefix
369 Each member added to an archive file has a directory prefix
370 prepended. Use -p/--prefix to specify a format string for the
370 prepended. Use -p/--prefix to specify a format string for the
371 prefix. The default is the basename of the archive, with suffixes
371 prefix. The default is the basename of the archive, with suffixes
372 removed.
372 removed.
373
373
374 Returns 0 on success.
374 Returns 0 on success.
375 '''
375 '''
376
376
377 ctx = scmutil.revsingle(repo, opts.get('rev'))
377 ctx = scmutil.revsingle(repo, opts.get('rev'))
378 if not ctx:
378 if not ctx:
379 raise util.Abort(_('no working directory: please specify a revision'))
379 raise util.Abort(_('no working directory: please specify a revision'))
380 node = ctx.node()
380 node = ctx.node()
381 dest = cmdutil.makefilename(repo, dest, node)
381 dest = cmdutil.makefilename(repo, dest, node)
382 if os.path.realpath(dest) == repo.root:
382 if os.path.realpath(dest) == repo.root:
383 raise util.Abort(_('repository root cannot be destination'))
383 raise util.Abort(_('repository root cannot be destination'))
384
384
385 kind = opts.get('type') or archival.guesskind(dest) or 'files'
385 kind = opts.get('type') or archival.guesskind(dest) or 'files'
386 prefix = opts.get('prefix')
386 prefix = opts.get('prefix')
387
387
388 if dest == '-':
388 if dest == '-':
389 if kind == 'files':
389 if kind == 'files':
390 raise util.Abort(_('cannot archive plain files to stdout'))
390 raise util.Abort(_('cannot archive plain files to stdout'))
391 dest = cmdutil.makefileobj(repo, dest)
391 dest = cmdutil.makefileobj(repo, dest)
392 if not prefix:
392 if not prefix:
393 prefix = os.path.basename(repo.root) + '-%h'
393 prefix = os.path.basename(repo.root) + '-%h'
394
394
395 prefix = cmdutil.makefilename(repo, prefix, node)
395 prefix = cmdutil.makefilename(repo, prefix, node)
396 matchfn = scmutil.match(ctx, [], opts)
396 matchfn = scmutil.match(ctx, [], opts)
397 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
397 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
398 matchfn, prefix, subrepos=opts.get('subrepos'))
398 matchfn, prefix, subrepos=opts.get('subrepos'))
399
399
400 @command('backout',
400 @command('backout',
401 [('', 'merge', None, _('merge with old dirstate parent after backout')),
401 [('', 'merge', None, _('merge with old dirstate parent after backout')),
402 ('', 'parent', '',
402 ('', 'parent', '',
403 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
403 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
404 ('r', 'rev', '', _('revision to backout'), _('REV')),
404 ('r', 'rev', '', _('revision to backout'), _('REV')),
405 ('e', 'edit', False, _('invoke editor on commit messages')),
405 ('e', 'edit', False, _('invoke editor on commit messages')),
406 ] + mergetoolopts + walkopts + commitopts + commitopts2,
406 ] + mergetoolopts + walkopts + commitopts + commitopts2,
407 _('[OPTION]... [-r] REV'))
407 _('[OPTION]... [-r] REV'))
408 def backout(ui, repo, node=None, rev=None, **opts):
408 def backout(ui, repo, node=None, rev=None, **opts):
409 '''reverse effect of earlier changeset
409 '''reverse effect of earlier changeset
410
410
411 Prepare a new changeset with the effect of REV undone in the
411 Prepare a new changeset with the effect of REV undone in the
412 current working directory.
412 current working directory.
413
413
414 If REV is the parent of the working directory, then this new changeset
414 If REV is the parent of the working directory, then this new changeset
415 is committed automatically. Otherwise, hg needs to merge the
415 is committed automatically. Otherwise, hg needs to merge the
416 changes and the merged result is left uncommitted.
416 changes and the merged result is left uncommitted.
417
417
418 .. note::
418 .. note::
419
419
420 backout cannot be used to fix either an unwanted or
420 backout cannot be used to fix either an unwanted or
421 incorrect merge.
421 incorrect merge.
422
422
423 .. container:: verbose
423 .. container:: verbose
424
424
425 By default, the pending changeset will have one parent,
425 By default, the pending changeset will have one parent,
426 maintaining a linear history. With --merge, the pending
426 maintaining a linear history. With --merge, the pending
427 changeset will instead have two parents: the old parent of the
427 changeset will instead have two parents: the old parent of the
428 working directory and a new child of REV that simply undoes REV.
428 working directory and a new child of REV that simply undoes REV.
429
429
430 Before version 1.7, the behavior without --merge was equivalent
430 Before version 1.7, the behavior without --merge was equivalent
431 to specifying --merge followed by :hg:`update --clean .` to
431 to specifying --merge followed by :hg:`update --clean .` to
432 cancel the merge and leave the child of REV as a head to be
432 cancel the merge and leave the child of REV as a head to be
433 merged separately.
433 merged separately.
434
434
435 See :hg:`help dates` for a list of formats valid for -d/--date.
435 See :hg:`help dates` for a list of formats valid for -d/--date.
436
436
437 Returns 0 on success, 1 if nothing to backout or there are unresolved
437 Returns 0 on success, 1 if nothing to backout or there are unresolved
438 files.
438 files.
439 '''
439 '''
440 if rev and node:
440 if rev and node:
441 raise util.Abort(_("please specify just one revision"))
441 raise util.Abort(_("please specify just one revision"))
442
442
443 if not rev:
443 if not rev:
444 rev = node
444 rev = node
445
445
446 if not rev:
446 if not rev:
447 raise util.Abort(_("please specify a revision to backout"))
447 raise util.Abort(_("please specify a revision to backout"))
448
448
449 date = opts.get('date')
449 date = opts.get('date')
450 if date:
450 if date:
451 opts['date'] = util.parsedate(date)
451 opts['date'] = util.parsedate(date)
452
452
453 cmdutil.checkunfinished(repo)
453 cmdutil.checkunfinished(repo)
454 cmdutil.bailifchanged(repo)
454 cmdutil.bailifchanged(repo)
455 node = scmutil.revsingle(repo, rev).node()
455 node = scmutil.revsingle(repo, rev).node()
456
456
457 op1, op2 = repo.dirstate.parents()
457 op1, op2 = repo.dirstate.parents()
458 if node not in repo.changelog.commonancestorsheads(op1, node):
458 if node not in repo.changelog.commonancestorsheads(op1, node):
459 raise util.Abort(_('cannot backout change that is not an ancestor'))
459 raise util.Abort(_('cannot backout change that is not an ancestor'))
460
460
461 p1, p2 = repo.changelog.parents(node)
461 p1, p2 = repo.changelog.parents(node)
462 if p1 == nullid:
462 if p1 == nullid:
463 raise util.Abort(_('cannot backout a change with no parents'))
463 raise util.Abort(_('cannot backout a change with no parents'))
464 if p2 != nullid:
464 if p2 != nullid:
465 if not opts.get('parent'):
465 if not opts.get('parent'):
466 raise util.Abort(_('cannot backout a merge changeset'))
466 raise util.Abort(_('cannot backout a merge changeset'))
467 p = repo.lookup(opts['parent'])
467 p = repo.lookup(opts['parent'])
468 if p not in (p1, p2):
468 if p not in (p1, p2):
469 raise util.Abort(_('%s is not a parent of %s') %
469 raise util.Abort(_('%s is not a parent of %s') %
470 (short(p), short(node)))
470 (short(p), short(node)))
471 parent = p
471 parent = p
472 else:
472 else:
473 if opts.get('parent'):
473 if opts.get('parent'):
474 raise util.Abort(_('cannot use --parent on non-merge changeset'))
474 raise util.Abort(_('cannot use --parent on non-merge changeset'))
475 parent = p1
475 parent = p1
476
476
477 # the backout should appear on the same branch
477 # the backout should appear on the same branch
478 wlock = repo.wlock()
478 wlock = repo.wlock()
479 try:
479 try:
480 branch = repo.dirstate.branch()
480 branch = repo.dirstate.branch()
481 bheads = repo.branchheads(branch)
481 bheads = repo.branchheads(branch)
482 rctx = scmutil.revsingle(repo, hex(parent))
482 rctx = scmutil.revsingle(repo, hex(parent))
483 if not opts.get('merge') and op1 != node:
483 if not opts.get('merge') and op1 != node:
484 try:
484 try:
485 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
485 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
486 'backout')
486 'backout')
487 stats = mergemod.update(repo, parent, True, True, False,
487 stats = mergemod.update(repo, parent, True, True, False,
488 node, False)
488 node, False)
489 repo.setparents(op1, op2)
489 repo.setparents(op1, op2)
490 hg._showstats(repo, stats)
490 hg._showstats(repo, stats)
491 if stats[3]:
491 if stats[3]:
492 repo.ui.status(_("use 'hg resolve' to retry unresolved "
492 repo.ui.status(_("use 'hg resolve' to retry unresolved "
493 "file merges\n"))
493 "file merges\n"))
494 else:
494 else:
495 msg = _("changeset %s backed out, "
495 msg = _("changeset %s backed out, "
496 "don't forget to commit.\n")
496 "don't forget to commit.\n")
497 ui.status(msg % short(node))
497 ui.status(msg % short(node))
498 return stats[3] > 0
498 return stats[3] > 0
499 finally:
499 finally:
500 ui.setconfig('ui', 'forcemerge', '', '')
500 ui.setconfig('ui', 'forcemerge', '', '')
501 else:
501 else:
502 hg.clean(repo, node, show_stats=False)
502 hg.clean(repo, node, show_stats=False)
503 repo.dirstate.setbranch(branch)
503 repo.dirstate.setbranch(branch)
504 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
504 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
505
505
506
506
507 def commitfunc(ui, repo, message, match, opts):
507 def commitfunc(ui, repo, message, match, opts):
508 editform = 'backout'
508 editform = 'backout'
509 e = cmdutil.getcommiteditor(editform=editform, **opts)
509 e = cmdutil.getcommiteditor(editform=editform, **opts)
510 if not message:
510 if not message:
511 # we don't translate commit messages
511 # we don't translate commit messages
512 message = "Backed out changeset %s" % short(node)
512 message = "Backed out changeset %s" % short(node)
513 e = cmdutil.getcommiteditor(edit=True, editform=editform)
513 e = cmdutil.getcommiteditor(edit=True, editform=editform)
514 return repo.commit(message, opts.get('user'), opts.get('date'),
514 return repo.commit(message, opts.get('user'), opts.get('date'),
515 match, editor=e)
515 match, editor=e)
516 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
516 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
517 if not newnode:
517 if not newnode:
518 ui.status(_("nothing changed\n"))
518 ui.status(_("nothing changed\n"))
519 return 1
519 return 1
520 cmdutil.commitstatus(repo, newnode, branch, bheads)
520 cmdutil.commitstatus(repo, newnode, branch, bheads)
521
521
522 def nice(node):
522 def nice(node):
523 return '%d:%s' % (repo.changelog.rev(node), short(node))
523 return '%d:%s' % (repo.changelog.rev(node), short(node))
524 ui.status(_('changeset %s backs out changeset %s\n') %
524 ui.status(_('changeset %s backs out changeset %s\n') %
525 (nice(repo.changelog.tip()), nice(node)))
525 (nice(repo.changelog.tip()), nice(node)))
526 if opts.get('merge') and op1 != node:
526 if opts.get('merge') and op1 != node:
527 hg.clean(repo, op1, show_stats=False)
527 hg.clean(repo, op1, show_stats=False)
528 ui.status(_('merging with changeset %s\n')
528 ui.status(_('merging with changeset %s\n')
529 % nice(repo.changelog.tip()))
529 % nice(repo.changelog.tip()))
530 try:
530 try:
531 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
531 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
532 'backout')
532 'backout')
533 return hg.merge(repo, hex(repo.changelog.tip()))
533 return hg.merge(repo, hex(repo.changelog.tip()))
534 finally:
534 finally:
535 ui.setconfig('ui', 'forcemerge', '', '')
535 ui.setconfig('ui', 'forcemerge', '', '')
536 finally:
536 finally:
537 wlock.release()
537 wlock.release()
538 return 0
538 return 0
539
539
540 @command('bisect',
540 @command('bisect',
541 [('r', 'reset', False, _('reset bisect state')),
541 [('r', 'reset', False, _('reset bisect state')),
542 ('g', 'good', False, _('mark changeset good')),
542 ('g', 'good', False, _('mark changeset good')),
543 ('b', 'bad', False, _('mark changeset bad')),
543 ('b', 'bad', False, _('mark changeset bad')),
544 ('s', 'skip', False, _('skip testing changeset')),
544 ('s', 'skip', False, _('skip testing changeset')),
545 ('e', 'extend', False, _('extend the bisect range')),
545 ('e', 'extend', False, _('extend the bisect range')),
546 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
546 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
547 ('U', 'noupdate', False, _('do not update to target'))],
547 ('U', 'noupdate', False, _('do not update to target'))],
548 _("[-gbsr] [-U] [-c CMD] [REV]"))
548 _("[-gbsr] [-U] [-c CMD] [REV]"))
549 def bisect(ui, repo, rev=None, extra=None, command=None,
549 def bisect(ui, repo, rev=None, extra=None, command=None,
550 reset=None, good=None, bad=None, skip=None, extend=None,
550 reset=None, good=None, bad=None, skip=None, extend=None,
551 noupdate=None):
551 noupdate=None):
552 """subdivision search of changesets
552 """subdivision search of changesets
553
553
554 This command helps to find changesets which introduce problems. To
554 This command helps to find changesets which introduce problems. To
555 use, mark the earliest changeset you know exhibits the problem as
555 use, mark the earliest changeset you know exhibits the problem as
556 bad, then mark the latest changeset which is free from the problem
556 bad, then mark the latest changeset which is free from the problem
557 as good. Bisect will update your working directory to a revision
557 as good. Bisect will update your working directory to a revision
558 for testing (unless the -U/--noupdate option is specified). Once
558 for testing (unless the -U/--noupdate option is specified). Once
559 you have performed tests, mark the working directory as good or
559 you have performed tests, mark the working directory as good or
560 bad, and bisect will either update to another candidate changeset
560 bad, and bisect will either update to another candidate changeset
561 or announce that it has found the bad revision.
561 or announce that it has found the bad revision.
562
562
563 As a shortcut, you can also use the revision argument to mark a
563 As a shortcut, you can also use the revision argument to mark a
564 revision as good or bad without checking it out first.
564 revision as good or bad without checking it out first.
565
565
566 If you supply a command, it will be used for automatic bisection.
566 If you supply a command, it will be used for automatic bisection.
567 The environment variable HG_NODE will contain the ID of the
567 The environment variable HG_NODE will contain the ID of the
568 changeset being tested. The exit status of the command will be
568 changeset being tested. The exit status of the command will be
569 used to mark revisions as good or bad: status 0 means good, 125
569 used to mark revisions as good or bad: status 0 means good, 125
570 means to skip the revision, 127 (command not found) will abort the
570 means to skip the revision, 127 (command not found) will abort the
571 bisection, and any other non-zero exit status means the revision
571 bisection, and any other non-zero exit status means the revision
572 is bad.
572 is bad.
573
573
574 .. container:: verbose
574 .. container:: verbose
575
575
576 Some examples:
576 Some examples:
577
577
578 - start a bisection with known bad revision 34, and good revision 12::
578 - start a bisection with known bad revision 34, and good revision 12::
579
579
580 hg bisect --bad 34
580 hg bisect --bad 34
581 hg bisect --good 12
581 hg bisect --good 12
582
582
583 - advance the current bisection by marking current revision as good or
583 - advance the current bisection by marking current revision as good or
584 bad::
584 bad::
585
585
586 hg bisect --good
586 hg bisect --good
587 hg bisect --bad
587 hg bisect --bad
588
588
589 - mark the current revision, or a known revision, to be skipped (e.g. if
589 - mark the current revision, or a known revision, to be skipped (e.g. if
590 that revision is not usable because of another issue)::
590 that revision is not usable because of another issue)::
591
591
592 hg bisect --skip
592 hg bisect --skip
593 hg bisect --skip 23
593 hg bisect --skip 23
594
594
595 - skip all revisions that do not touch directories ``foo`` or ``bar``::
595 - skip all revisions that do not touch directories ``foo`` or ``bar``::
596
596
597 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
597 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
598
598
599 - forget the current bisection::
599 - forget the current bisection::
600
600
601 hg bisect --reset
601 hg bisect --reset
602
602
603 - use 'make && make tests' to automatically find the first broken
603 - use 'make && make tests' to automatically find the first broken
604 revision::
604 revision::
605
605
606 hg bisect --reset
606 hg bisect --reset
607 hg bisect --bad 34
607 hg bisect --bad 34
608 hg bisect --good 12
608 hg bisect --good 12
609 hg bisect --command "make && make tests"
609 hg bisect --command "make && make tests"
610
610
611 - see all changesets whose states are already known in the current
611 - see all changesets whose states are already known in the current
612 bisection::
612 bisection::
613
613
614 hg log -r "bisect(pruned)"
614 hg log -r "bisect(pruned)"
615
615
616 - see the changeset currently being bisected (especially useful
616 - see the changeset currently being bisected (especially useful
617 if running with -U/--noupdate)::
617 if running with -U/--noupdate)::
618
618
619 hg log -r "bisect(current)"
619 hg log -r "bisect(current)"
620
620
621 - see all changesets that took part in the current bisection::
621 - see all changesets that took part in the current bisection::
622
622
623 hg log -r "bisect(range)"
623 hg log -r "bisect(range)"
624
624
625 - you can even get a nice graph::
625 - you can even get a nice graph::
626
626
627 hg log --graph -r "bisect(range)"
627 hg log --graph -r "bisect(range)"
628
628
629 See :hg:`help revsets` for more about the `bisect()` keyword.
629 See :hg:`help revsets` for more about the `bisect()` keyword.
630
630
631 Returns 0 on success.
631 Returns 0 on success.
632 """
632 """
633 def extendbisectrange(nodes, good):
633 def extendbisectrange(nodes, good):
634 # bisect is incomplete when it ends on a merge node and
634 # bisect is incomplete when it ends on a merge node and
635 # one of the parent was not checked.
635 # one of the parent was not checked.
636 parents = repo[nodes[0]].parents()
636 parents = repo[nodes[0]].parents()
637 if len(parents) > 1:
637 if len(parents) > 1:
638 side = good and state['bad'] or state['good']
638 side = good and state['bad'] or state['good']
639 num = len(set(i.node() for i in parents) & set(side))
639 num = len(set(i.node() for i in parents) & set(side))
640 if num == 1:
640 if num == 1:
641 return parents[0].ancestor(parents[1])
641 return parents[0].ancestor(parents[1])
642 return None
642 return None
643
643
644 def print_result(nodes, good):
644 def print_result(nodes, good):
645 displayer = cmdutil.show_changeset(ui, repo, {})
645 displayer = cmdutil.show_changeset(ui, repo, {})
646 if len(nodes) == 1:
646 if len(nodes) == 1:
647 # narrowed it down to a single revision
647 # narrowed it down to a single revision
648 if good:
648 if good:
649 ui.write(_("The first good revision is:\n"))
649 ui.write(_("The first good revision is:\n"))
650 else:
650 else:
651 ui.write(_("The first bad revision is:\n"))
651 ui.write(_("The first bad revision is:\n"))
652 displayer.show(repo[nodes[0]])
652 displayer.show(repo[nodes[0]])
653 extendnode = extendbisectrange(nodes, good)
653 extendnode = extendbisectrange(nodes, good)
654 if extendnode is not None:
654 if extendnode is not None:
655 ui.write(_('Not all ancestors of this changeset have been'
655 ui.write(_('Not all ancestors of this changeset have been'
656 ' checked.\nUse bisect --extend to continue the '
656 ' checked.\nUse bisect --extend to continue the '
657 'bisection from\nthe common ancestor, %s.\n')
657 'bisection from\nthe common ancestor, %s.\n')
658 % extendnode)
658 % extendnode)
659 else:
659 else:
660 # multiple possible revisions
660 # multiple possible revisions
661 if good:
661 if good:
662 ui.write(_("Due to skipped revisions, the first "
662 ui.write(_("Due to skipped revisions, the first "
663 "good revision could be any of:\n"))
663 "good revision could be any of:\n"))
664 else:
664 else:
665 ui.write(_("Due to skipped revisions, the first "
665 ui.write(_("Due to skipped revisions, the first "
666 "bad revision could be any of:\n"))
666 "bad revision could be any of:\n"))
667 for n in nodes:
667 for n in nodes:
668 displayer.show(repo[n])
668 displayer.show(repo[n])
669 displayer.close()
669 displayer.close()
670
670
671 def check_state(state, interactive=True):
671 def check_state(state, interactive=True):
672 if not state['good'] or not state['bad']:
672 if not state['good'] or not state['bad']:
673 if (good or bad or skip or reset) and interactive:
673 if (good or bad or skip or reset) and interactive:
674 return
674 return
675 if not state['good']:
675 if not state['good']:
676 raise util.Abort(_('cannot bisect (no known good revisions)'))
676 raise util.Abort(_('cannot bisect (no known good revisions)'))
677 else:
677 else:
678 raise util.Abort(_('cannot bisect (no known bad revisions)'))
678 raise util.Abort(_('cannot bisect (no known bad revisions)'))
679 return True
679 return True
680
680
681 # backward compatibility
681 # backward compatibility
682 if rev in "good bad reset init".split():
682 if rev in "good bad reset init".split():
683 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
683 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
684 cmd, rev, extra = rev, extra, None
684 cmd, rev, extra = rev, extra, None
685 if cmd == "good":
685 if cmd == "good":
686 good = True
686 good = True
687 elif cmd == "bad":
687 elif cmd == "bad":
688 bad = True
688 bad = True
689 else:
689 else:
690 reset = True
690 reset = True
691 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
691 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
692 raise util.Abort(_('incompatible arguments'))
692 raise util.Abort(_('incompatible arguments'))
693
693
694 cmdutil.checkunfinished(repo)
694 cmdutil.checkunfinished(repo)
695
695
696 if reset:
696 if reset:
697 p = repo.join("bisect.state")
697 p = repo.join("bisect.state")
698 if os.path.exists(p):
698 if os.path.exists(p):
699 os.unlink(p)
699 os.unlink(p)
700 return
700 return
701
701
702 state = hbisect.load_state(repo)
702 state = hbisect.load_state(repo)
703
703
704 if command:
704 if command:
705 changesets = 1
705 changesets = 1
706 if noupdate:
706 if noupdate:
707 try:
707 try:
708 node = state['current'][0]
708 node = state['current'][0]
709 except LookupError:
709 except LookupError:
710 raise util.Abort(_('current bisect revision is unknown - '
710 raise util.Abort(_('current bisect revision is unknown - '
711 'start a new bisect to fix'))
711 'start a new bisect to fix'))
712 else:
712 else:
713 node, p2 = repo.dirstate.parents()
713 node, p2 = repo.dirstate.parents()
714 if p2 != nullid:
714 if p2 != nullid:
715 raise util.Abort(_('current bisect revision is a merge'))
715 raise util.Abort(_('current bisect revision is a merge'))
716 try:
716 try:
717 while changesets:
717 while changesets:
718 # update state
718 # update state
719 state['current'] = [node]
719 state['current'] = [node]
720 hbisect.save_state(repo, state)
720 hbisect.save_state(repo, state)
721 status = util.system(command,
721 status = util.system(command,
722 environ={'HG_NODE': hex(node)},
722 environ={'HG_NODE': hex(node)},
723 out=ui.fout)
723 out=ui.fout)
724 if status == 125:
724 if status == 125:
725 transition = "skip"
725 transition = "skip"
726 elif status == 0:
726 elif status == 0:
727 transition = "good"
727 transition = "good"
728 # status < 0 means process was killed
728 # status < 0 means process was killed
729 elif status == 127:
729 elif status == 127:
730 raise util.Abort(_("failed to execute %s") % command)
730 raise util.Abort(_("failed to execute %s") % command)
731 elif status < 0:
731 elif status < 0:
732 raise util.Abort(_("%s killed") % command)
732 raise util.Abort(_("%s killed") % command)
733 else:
733 else:
734 transition = "bad"
734 transition = "bad"
735 ctx = scmutil.revsingle(repo, rev, node)
735 ctx = scmutil.revsingle(repo, rev, node)
736 rev = None # clear for future iterations
736 rev = None # clear for future iterations
737 state[transition].append(ctx.node())
737 state[transition].append(ctx.node())
738 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
738 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
739 check_state(state, interactive=False)
739 check_state(state, interactive=False)
740 # bisect
740 # bisect
741 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
741 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
742 # update to next check
742 # update to next check
743 node = nodes[0]
743 node = nodes[0]
744 if not noupdate:
744 if not noupdate:
745 cmdutil.bailifchanged(repo)
745 cmdutil.bailifchanged(repo)
746 hg.clean(repo, node, show_stats=False)
746 hg.clean(repo, node, show_stats=False)
747 finally:
747 finally:
748 state['current'] = [node]
748 state['current'] = [node]
749 hbisect.save_state(repo, state)
749 hbisect.save_state(repo, state)
750 print_result(nodes, bgood)
750 print_result(nodes, bgood)
751 return
751 return
752
752
753 # update state
753 # update state
754
754
755 if rev:
755 if rev:
756 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
756 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
757 else:
757 else:
758 nodes = [repo.lookup('.')]
758 nodes = [repo.lookup('.')]
759
759
760 if good or bad or skip:
760 if good or bad or skip:
761 if good:
761 if good:
762 state['good'] += nodes
762 state['good'] += nodes
763 elif bad:
763 elif bad:
764 state['bad'] += nodes
764 state['bad'] += nodes
765 elif skip:
765 elif skip:
766 state['skip'] += nodes
766 state['skip'] += nodes
767 hbisect.save_state(repo, state)
767 hbisect.save_state(repo, state)
768
768
769 if not check_state(state):
769 if not check_state(state):
770 return
770 return
771
771
772 # actually bisect
772 # actually bisect
773 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
773 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
774 if extend:
774 if extend:
775 if not changesets:
775 if not changesets:
776 extendnode = extendbisectrange(nodes, good)
776 extendnode = extendbisectrange(nodes, good)
777 if extendnode is not None:
777 if extendnode is not None:
778 ui.write(_("Extending search to changeset %d:%s\n")
778 ui.write(_("Extending search to changeset %d:%s\n")
779 % (extendnode.rev(), extendnode))
779 % (extendnode.rev(), extendnode))
780 state['current'] = [extendnode.node()]
780 state['current'] = [extendnode.node()]
781 hbisect.save_state(repo, state)
781 hbisect.save_state(repo, state)
782 if noupdate:
782 if noupdate:
783 return
783 return
784 cmdutil.bailifchanged(repo)
784 cmdutil.bailifchanged(repo)
785 return hg.clean(repo, extendnode.node())
785 return hg.clean(repo, extendnode.node())
786 raise util.Abort(_("nothing to extend"))
786 raise util.Abort(_("nothing to extend"))
787
787
788 if changesets == 0:
788 if changesets == 0:
789 print_result(nodes, good)
789 print_result(nodes, good)
790 else:
790 else:
791 assert len(nodes) == 1 # only a single node can be tested next
791 assert len(nodes) == 1 # only a single node can be tested next
792 node = nodes[0]
792 node = nodes[0]
793 # compute the approximate number of remaining tests
793 # compute the approximate number of remaining tests
794 tests, size = 0, 2
794 tests, size = 0, 2
795 while size <= changesets:
795 while size <= changesets:
796 tests, size = tests + 1, size * 2
796 tests, size = tests + 1, size * 2
797 rev = repo.changelog.rev(node)
797 rev = repo.changelog.rev(node)
798 ui.write(_("Testing changeset %d:%s "
798 ui.write(_("Testing changeset %d:%s "
799 "(%d changesets remaining, ~%d tests)\n")
799 "(%d changesets remaining, ~%d tests)\n")
800 % (rev, short(node), changesets, tests))
800 % (rev, short(node), changesets, tests))
801 state['current'] = [node]
801 state['current'] = [node]
802 hbisect.save_state(repo, state)
802 hbisect.save_state(repo, state)
803 if not noupdate:
803 if not noupdate:
804 cmdutil.bailifchanged(repo)
804 cmdutil.bailifchanged(repo)
805 return hg.clean(repo, node)
805 return hg.clean(repo, node)
806
806
807 @command('bookmarks|bookmark',
807 @command('bookmarks|bookmark',
808 [('f', 'force', False, _('force')),
808 [('f', 'force', False, _('force')),
809 ('r', 'rev', '', _('revision'), _('REV')),
809 ('r', 'rev', '', _('revision'), _('REV')),
810 ('d', 'delete', False, _('delete a given bookmark')),
810 ('d', 'delete', False, _('delete a given bookmark')),
811 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
811 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
812 ('i', 'inactive', False, _('mark a bookmark inactive'))],
812 ('i', 'inactive', False, _('mark a bookmark inactive'))],
813 _('hg bookmarks [OPTIONS]... [NAME]...'))
813 _('hg bookmarks [OPTIONS]... [NAME]...'))
814 def bookmark(ui, repo, *names, **opts):
814 def bookmark(ui, repo, *names, **opts):
815 '''create a new bookmark or list existing bookmarks
815 '''create a new bookmark or list existing bookmarks
816
816
817 Bookmarks are labels on changesets to help track lines of development.
817 Bookmarks are labels on changesets to help track lines of development.
818 Bookmarks are unversioned and can be moved, renamed and deleted.
818 Bookmarks are unversioned and can be moved, renamed and deleted.
819 Deleting or moving a bookmark has no effect on the associated changesets.
819 Deleting or moving a bookmark has no effect on the associated changesets.
820
820
821 Creating or updating to a bookmark causes it to be marked as 'active'.
821 Creating or updating to a bookmark causes it to be marked as 'active'.
822 Active bookmarks are indicated with a '*'.
822 Active bookmarks are indicated with a '*'.
823 When a commit is made, an active bookmark will advance to the new commit.
823 When a commit is made, an active bookmark will advance to the new commit.
824 A plain :hg:`update` will also advance an active bookmark, if possible.
824 A plain :hg:`update` will also advance an active bookmark, if possible.
825 Updating away from a bookmark will cause it to be deactivated.
825 Updating away from a bookmark will cause it to be deactivated.
826
826
827 Bookmarks can be pushed and pulled between repositories (see
827 Bookmarks can be pushed and pulled between repositories (see
828 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
828 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
829 diverged, a new 'divergent bookmark' of the form 'name@path' will
829 diverged, a new 'divergent bookmark' of the form 'name@path' will
830 be created. Using :hg:'merge' will resolve the divergence.
830 be created. Using :hg:'merge' will resolve the divergence.
831
831
832 A bookmark named '@' has the special property that :hg:`clone` will
832 A bookmark named '@' has the special property that :hg:`clone` will
833 check it out by default if it exists.
833 check it out by default if it exists.
834
834
835 .. container:: verbose
835 .. container:: verbose
836
836
837 Examples:
837 Examples:
838
838
839 - create an active bookmark for a new line of development::
839 - create an active bookmark for a new line of development::
840
840
841 hg book new-feature
841 hg book new-feature
842
842
843 - create an inactive bookmark as a place marker::
843 - create an inactive bookmark as a place marker::
844
844
845 hg book -i reviewed
845 hg book -i reviewed
846
846
847 - create an inactive bookmark on another changeset::
847 - create an inactive bookmark on another changeset::
848
848
849 hg book -r .^ tested
849 hg book -r .^ tested
850
850
851 - move the '@' bookmark from another branch::
851 - move the '@' bookmark from another branch::
852
852
853 hg book -f @
853 hg book -f @
854 '''
854 '''
855 force = opts.get('force')
855 force = opts.get('force')
856 rev = opts.get('rev')
856 rev = opts.get('rev')
857 delete = opts.get('delete')
857 delete = opts.get('delete')
858 rename = opts.get('rename')
858 rename = opts.get('rename')
859 inactive = opts.get('inactive')
859 inactive = opts.get('inactive')
860
860
861 def checkformat(mark):
861 def checkformat(mark):
862 mark = mark.strip()
862 mark = mark.strip()
863 if not mark:
863 if not mark:
864 raise util.Abort(_("bookmark names cannot consist entirely of "
864 raise util.Abort(_("bookmark names cannot consist entirely of "
865 "whitespace"))
865 "whitespace"))
866 scmutil.checknewlabel(repo, mark, 'bookmark')
866 scmutil.checknewlabel(repo, mark, 'bookmark')
867 return mark
867 return mark
868
868
869 def checkconflict(repo, mark, cur, force=False, target=None):
869 def checkconflict(repo, mark, cur, force=False, target=None):
870 if mark in marks and not force:
870 if mark in marks and not force:
871 if target:
871 if target:
872 if marks[mark] == target and target == cur:
872 if marks[mark] == target and target == cur:
873 # re-activating a bookmark
873 # re-activating a bookmark
874 return
874 return
875 anc = repo.changelog.ancestors([repo[target].rev()])
875 anc = repo.changelog.ancestors([repo[target].rev()])
876 bmctx = repo[marks[mark]]
876 bmctx = repo[marks[mark]]
877 divs = [repo[b].node() for b in marks
877 divs = [repo[b].node() for b in marks
878 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
878 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
879
879
880 # allow resolving a single divergent bookmark even if moving
880 # allow resolving a single divergent bookmark even if moving
881 # the bookmark across branches when a revision is specified
881 # the bookmark across branches when a revision is specified
882 # that contains a divergent bookmark
882 # that contains a divergent bookmark
883 if bmctx.rev() not in anc and target in divs:
883 if bmctx.rev() not in anc and target in divs:
884 bookmarks.deletedivergent(repo, [target], mark)
884 bookmarks.deletedivergent(repo, [target], mark)
885 return
885 return
886
886
887 deletefrom = [b for b in divs
887 deletefrom = [b for b in divs
888 if repo[b].rev() in anc or b == target]
888 if repo[b].rev() in anc or b == target]
889 bookmarks.deletedivergent(repo, deletefrom, mark)
889 bookmarks.deletedivergent(repo, deletefrom, mark)
890 if bookmarks.validdest(repo, bmctx, repo[target]):
890 if bookmarks.validdest(repo, bmctx, repo[target]):
891 ui.status(_("moving bookmark '%s' forward from %s\n") %
891 ui.status(_("moving bookmark '%s' forward from %s\n") %
892 (mark, short(bmctx.node())))
892 (mark, short(bmctx.node())))
893 return
893 return
894 raise util.Abort(_("bookmark '%s' already exists "
894 raise util.Abort(_("bookmark '%s' already exists "
895 "(use -f to force)") % mark)
895 "(use -f to force)") % mark)
896 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
896 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
897 and not force):
897 and not force):
898 raise util.Abort(
898 raise util.Abort(
899 _("a bookmark cannot have the name of an existing branch"))
899 _("a bookmark cannot have the name of an existing branch"))
900
900
901 if delete and rename:
901 if delete and rename:
902 raise util.Abort(_("--delete and --rename are incompatible"))
902 raise util.Abort(_("--delete and --rename are incompatible"))
903 if delete and rev:
903 if delete and rev:
904 raise util.Abort(_("--rev is incompatible with --delete"))
904 raise util.Abort(_("--rev is incompatible with --delete"))
905 if rename and rev:
905 if rename and rev:
906 raise util.Abort(_("--rev is incompatible with --rename"))
906 raise util.Abort(_("--rev is incompatible with --rename"))
907 if not names and (delete or rev):
907 if not names and (delete or rev):
908 raise util.Abort(_("bookmark name required"))
908 raise util.Abort(_("bookmark name required"))
909
909
910 if delete or rename or names or inactive:
910 if delete or rename or names or inactive:
911 wlock = repo.wlock()
911 wlock = repo.wlock()
912 try:
912 try:
913 cur = repo.changectx('.').node()
913 cur = repo.changectx('.').node()
914 marks = repo._bookmarks
914 marks = repo._bookmarks
915 if delete:
915 if delete:
916 for mark in names:
916 for mark in names:
917 if mark not in marks:
917 if mark not in marks:
918 raise util.Abort(_("bookmark '%s' does not exist") %
918 raise util.Abort(_("bookmark '%s' does not exist") %
919 mark)
919 mark)
920 if mark == repo._bookmarkcurrent:
920 if mark == repo._bookmarkcurrent:
921 bookmarks.unsetcurrent(repo)
921 bookmarks.unsetcurrent(repo)
922 del marks[mark]
922 del marks[mark]
923 marks.write()
923 marks.write()
924
924
925 elif rename:
925 elif rename:
926 if not names:
926 if not names:
927 raise util.Abort(_("new bookmark name required"))
927 raise util.Abort(_("new bookmark name required"))
928 elif len(names) > 1:
928 elif len(names) > 1:
929 raise util.Abort(_("only one new bookmark name allowed"))
929 raise util.Abort(_("only one new bookmark name allowed"))
930 mark = checkformat(names[0])
930 mark = checkformat(names[0])
931 if rename not in marks:
931 if rename not in marks:
932 raise util.Abort(_("bookmark '%s' does not exist") % rename)
932 raise util.Abort(_("bookmark '%s' does not exist") % rename)
933 checkconflict(repo, mark, cur, force)
933 checkconflict(repo, mark, cur, force)
934 marks[mark] = marks[rename]
934 marks[mark] = marks[rename]
935 if repo._bookmarkcurrent == rename and not inactive:
935 if repo._bookmarkcurrent == rename and not inactive:
936 bookmarks.setcurrent(repo, mark)
936 bookmarks.setcurrent(repo, mark)
937 del marks[rename]
937 del marks[rename]
938 marks.write()
938 marks.write()
939
939
940 elif names:
940 elif names:
941 newact = None
941 newact = None
942 for mark in names:
942 for mark in names:
943 mark = checkformat(mark)
943 mark = checkformat(mark)
944 if newact is None:
944 if newact is None:
945 newact = mark
945 newact = mark
946 if inactive and mark == repo._bookmarkcurrent:
946 if inactive and mark == repo._bookmarkcurrent:
947 bookmarks.unsetcurrent(repo)
947 bookmarks.unsetcurrent(repo)
948 return
948 return
949 tgt = cur
949 tgt = cur
950 if rev:
950 if rev:
951 tgt = scmutil.revsingle(repo, rev).node()
951 tgt = scmutil.revsingle(repo, rev).node()
952 checkconflict(repo, mark, cur, force, tgt)
952 checkconflict(repo, mark, cur, force, tgt)
953 marks[mark] = tgt
953 marks[mark] = tgt
954 if not inactive and cur == marks[newact] and not rev:
954 if not inactive and cur == marks[newact] and not rev:
955 bookmarks.setcurrent(repo, newact)
955 bookmarks.setcurrent(repo, newact)
956 elif cur != tgt and newact == repo._bookmarkcurrent:
956 elif cur != tgt and newact == repo._bookmarkcurrent:
957 bookmarks.unsetcurrent(repo)
957 bookmarks.unsetcurrent(repo)
958 marks.write()
958 marks.write()
959
959
960 elif inactive:
960 elif inactive:
961 if len(marks) == 0:
961 if len(marks) == 0:
962 ui.status(_("no bookmarks set\n"))
962 ui.status(_("no bookmarks set\n"))
963 elif not repo._bookmarkcurrent:
963 elif not repo._bookmarkcurrent:
964 ui.status(_("no active bookmark\n"))
964 ui.status(_("no active bookmark\n"))
965 else:
965 else:
966 bookmarks.unsetcurrent(repo)
966 bookmarks.unsetcurrent(repo)
967 finally:
967 finally:
968 wlock.release()
968 wlock.release()
969 else: # show bookmarks
969 else: # show bookmarks
970 hexfn = ui.debugflag and hex or short
970 hexfn = ui.debugflag and hex or short
971 marks = repo._bookmarks
971 marks = repo._bookmarks
972 if len(marks) == 0:
972 if len(marks) == 0:
973 ui.status(_("no bookmarks set\n"))
973 ui.status(_("no bookmarks set\n"))
974 else:
974 else:
975 for bmark, n in sorted(marks.iteritems()):
975 for bmark, n in sorted(marks.iteritems()):
976 current = repo._bookmarkcurrent
976 current = repo._bookmarkcurrent
977 if bmark == current:
977 if bmark == current:
978 prefix, label = '*', 'bookmarks.current'
978 prefix, label = '*', 'bookmarks.current'
979 else:
979 else:
980 prefix, label = ' ', ''
980 prefix, label = ' ', ''
981
981
982 if ui.quiet:
982 if ui.quiet:
983 ui.write("%s\n" % bmark, label=label)
983 ui.write("%s\n" % bmark, label=label)
984 else:
984 else:
985 pad = " " * (25 - encoding.colwidth(bmark))
985 pad = " " * (25 - encoding.colwidth(bmark))
986 ui.write(" %s %s%s %d:%s\n" % (
986 ui.write(" %s %s%s %d:%s\n" % (
987 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
987 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
988 label=label)
988 label=label)
989
989
990 @command('branch',
990 @command('branch',
991 [('f', 'force', None,
991 [('f', 'force', None,
992 _('set branch name even if it shadows an existing branch')),
992 _('set branch name even if it shadows an existing branch')),
993 ('C', 'clean', None, _('reset branch name to parent branch name'))],
993 ('C', 'clean', None, _('reset branch name to parent branch name'))],
994 _('[-fC] [NAME]'))
994 _('[-fC] [NAME]'))
995 def branch(ui, repo, label=None, **opts):
995 def branch(ui, repo, label=None, **opts):
996 """set or show the current branch name
996 """set or show the current branch name
997
997
998 .. note::
998 .. note::
999
999
1000 Branch names are permanent and global. Use :hg:`bookmark` to create a
1000 Branch names are permanent and global. Use :hg:`bookmark` to create a
1001 light-weight bookmark instead. See :hg:`help glossary` for more
1001 light-weight bookmark instead. See :hg:`help glossary` for more
1002 information about named branches and bookmarks.
1002 information about named branches and bookmarks.
1003
1003
1004 With no argument, show the current branch name. With one argument,
1004 With no argument, show the current branch name. With one argument,
1005 set the working directory branch name (the branch will not exist
1005 set the working directory branch name (the branch will not exist
1006 in the repository until the next commit). Standard practice
1006 in the repository until the next commit). Standard practice
1007 recommends that primary development take place on the 'default'
1007 recommends that primary development take place on the 'default'
1008 branch.
1008 branch.
1009
1009
1010 Unless -f/--force is specified, branch will not let you set a
1010 Unless -f/--force is specified, branch will not let you set a
1011 branch name that already exists, even if it's inactive.
1011 branch name that already exists, even if it's inactive.
1012
1012
1013 Use -C/--clean to reset the working directory branch to that of
1013 Use -C/--clean to reset the working directory branch to that of
1014 the parent of the working directory, negating a previous branch
1014 the parent of the working directory, negating a previous branch
1015 change.
1015 change.
1016
1016
1017 Use the command :hg:`update` to switch to an existing branch. Use
1017 Use the command :hg:`update` to switch to an existing branch. Use
1018 :hg:`commit --close-branch` to mark this branch as closed.
1018 :hg:`commit --close-branch` to mark this branch as closed.
1019
1019
1020 Returns 0 on success.
1020 Returns 0 on success.
1021 """
1021 """
1022 if label:
1022 if label:
1023 label = label.strip()
1023 label = label.strip()
1024
1024
1025 if not opts.get('clean') and not label:
1025 if not opts.get('clean') and not label:
1026 ui.write("%s\n" % repo.dirstate.branch())
1026 ui.write("%s\n" % repo.dirstate.branch())
1027 return
1027 return
1028
1028
1029 wlock = repo.wlock()
1029 wlock = repo.wlock()
1030 try:
1030 try:
1031 if opts.get('clean'):
1031 if opts.get('clean'):
1032 label = repo[None].p1().branch()
1032 label = repo[None].p1().branch()
1033 repo.dirstate.setbranch(label)
1033 repo.dirstate.setbranch(label)
1034 ui.status(_('reset working directory to branch %s\n') % label)
1034 ui.status(_('reset working directory to branch %s\n') % label)
1035 elif label:
1035 elif label:
1036 if not opts.get('force') and label in repo.branchmap():
1036 if not opts.get('force') and label in repo.branchmap():
1037 if label not in [p.branch() for p in repo.parents()]:
1037 if label not in [p.branch() for p in repo.parents()]:
1038 raise util.Abort(_('a branch of the same name already'
1038 raise util.Abort(_('a branch of the same name already'
1039 ' exists'),
1039 ' exists'),
1040 # i18n: "it" refers to an existing branch
1040 # i18n: "it" refers to an existing branch
1041 hint=_("use 'hg update' to switch to it"))
1041 hint=_("use 'hg update' to switch to it"))
1042 scmutil.checknewlabel(repo, label, 'branch')
1042 scmutil.checknewlabel(repo, label, 'branch')
1043 repo.dirstate.setbranch(label)
1043 repo.dirstate.setbranch(label)
1044 ui.status(_('marked working directory as branch %s\n') % label)
1044 ui.status(_('marked working directory as branch %s\n') % label)
1045 ui.status(_('(branches are permanent and global, '
1045 ui.status(_('(branches are permanent and global, '
1046 'did you want a bookmark?)\n'))
1046 'did you want a bookmark?)\n'))
1047 finally:
1047 finally:
1048 wlock.release()
1048 wlock.release()
1049
1049
1050 @command('branches',
1050 @command('branches',
1051 [('a', 'active', False, _('show only branches that have unmerged heads')),
1051 [('a', 'active', False, _('show only branches that have unmerged heads')),
1052 ('c', 'closed', False, _('show normal and closed branches'))],
1052 ('c', 'closed', False, _('show normal and closed branches'))],
1053 _('[-ac]'))
1053 _('[-ac]'))
1054 def branches(ui, repo, active=False, closed=False):
1054 def branches(ui, repo, active=False, closed=False):
1055 """list repository named branches
1055 """list repository named branches
1056
1056
1057 List the repository's named branches, indicating which ones are
1057 List the repository's named branches, indicating which ones are
1058 inactive. If -c/--closed is specified, also list branches which have
1058 inactive. If -c/--closed is specified, also list branches which have
1059 been marked closed (see :hg:`commit --close-branch`).
1059 been marked closed (see :hg:`commit --close-branch`).
1060
1060
1061 If -a/--active is specified, only show active branches. A branch
1061 If -a/--active is specified, only show active branches. A branch
1062 is considered active if it contains repository heads.
1062 is considered active if it contains repository heads.
1063
1063
1064 Use the command :hg:`update` to switch to an existing branch.
1064 Use the command :hg:`update` to switch to an existing branch.
1065
1065
1066 Returns 0.
1066 Returns 0.
1067 """
1067 """
1068
1068
1069 hexfunc = ui.debugflag and hex or short
1069 hexfunc = ui.debugflag and hex or short
1070
1070
1071 allheads = set(repo.heads())
1071 allheads = set(repo.heads())
1072 branches = []
1072 branches = []
1073 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1073 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1074 isactive = not isclosed and bool(set(heads) & allheads)
1074 isactive = not isclosed and bool(set(heads) & allheads)
1075 branches.append((tag, repo[tip], isactive, not isclosed))
1075 branches.append((tag, repo[tip], isactive, not isclosed))
1076 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1076 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1077 reverse=True)
1077 reverse=True)
1078
1078
1079 for tag, ctx, isactive, isopen in branches:
1079 for tag, ctx, isactive, isopen in branches:
1080 if (not active) or isactive:
1080 if (not active) or isactive:
1081 if isactive:
1081 if isactive:
1082 label = 'branches.active'
1082 label = 'branches.active'
1083 notice = ''
1083 notice = ''
1084 elif not isopen:
1084 elif not isopen:
1085 if not closed:
1085 if not closed:
1086 continue
1086 continue
1087 label = 'branches.closed'
1087 label = 'branches.closed'
1088 notice = _(' (closed)')
1088 notice = _(' (closed)')
1089 else:
1089 else:
1090 label = 'branches.inactive'
1090 label = 'branches.inactive'
1091 notice = _(' (inactive)')
1091 notice = _(' (inactive)')
1092 if tag == repo.dirstate.branch():
1092 if tag == repo.dirstate.branch():
1093 label = 'branches.current'
1093 label = 'branches.current'
1094 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1094 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1095 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1095 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1096 'log.changeset changeset.%s' % ctx.phasestr())
1096 'log.changeset changeset.%s' % ctx.phasestr())
1097 labeledtag = ui.label(tag, label)
1097 labeledtag = ui.label(tag, label)
1098 if ui.quiet:
1098 if ui.quiet:
1099 ui.write("%s\n" % labeledtag)
1099 ui.write("%s\n" % labeledtag)
1100 else:
1100 else:
1101 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1101 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1102
1102
1103 @command('bundle',
1103 @command('bundle',
1104 [('f', 'force', None, _('run even when the destination is unrelated')),
1104 [('f', 'force', None, _('run even when the destination is unrelated')),
1105 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1105 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1106 _('REV')),
1106 _('REV')),
1107 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1107 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1108 _('BRANCH')),
1108 _('BRANCH')),
1109 ('', 'base', [],
1109 ('', 'base', [],
1110 _('a base changeset assumed to be available at the destination'),
1110 _('a base changeset assumed to be available at the destination'),
1111 _('REV')),
1111 _('REV')),
1112 ('a', 'all', None, _('bundle all changesets in the repository')),
1112 ('a', 'all', None, _('bundle all changesets in the repository')),
1113 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1113 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1114 ] + remoteopts,
1114 ] + remoteopts,
1115 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1115 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1116 def bundle(ui, repo, fname, dest=None, **opts):
1116 def bundle(ui, repo, fname, dest=None, **opts):
1117 """create a changegroup file
1117 """create a changegroup file
1118
1118
1119 Generate a compressed changegroup file collecting changesets not
1119 Generate a compressed changegroup file collecting changesets not
1120 known to be in another repository.
1120 known to be in another repository.
1121
1121
1122 If you omit the destination repository, then hg assumes the
1122 If you omit the destination repository, then hg assumes the
1123 destination will have all the nodes you specify with --base
1123 destination will have all the nodes you specify with --base
1124 parameters. To create a bundle containing all changesets, use
1124 parameters. To create a bundle containing all changesets, use
1125 -a/--all (or --base null).
1125 -a/--all (or --base null).
1126
1126
1127 You can change compression method with the -t/--type option.
1127 You can change compression method with the -t/--type option.
1128 The available compression methods are: none, bzip2, and
1128 The available compression methods are: none, bzip2, and
1129 gzip (by default, bundles are compressed using bzip2).
1129 gzip (by default, bundles are compressed using bzip2).
1130
1130
1131 The bundle file can then be transferred using conventional means
1131 The bundle file can then be transferred using conventional means
1132 and applied to another repository with the unbundle or pull
1132 and applied to another repository with the unbundle or pull
1133 command. This is useful when direct push and pull are not
1133 command. This is useful when direct push and pull are not
1134 available or when exporting an entire repository is undesirable.
1134 available or when exporting an entire repository is undesirable.
1135
1135
1136 Applying bundles preserves all changeset contents including
1136 Applying bundles preserves all changeset contents including
1137 permissions, copy/rename information, and revision history.
1137 permissions, copy/rename information, and revision history.
1138
1138
1139 Returns 0 on success, 1 if no changes found.
1139 Returns 0 on success, 1 if no changes found.
1140 """
1140 """
1141 revs = None
1141 revs = None
1142 if 'rev' in opts:
1142 if 'rev' in opts:
1143 revs = scmutil.revrange(repo, opts['rev'])
1143 revs = scmutil.revrange(repo, opts['rev'])
1144
1144
1145 bundletype = opts.get('type', 'bzip2').lower()
1145 bundletype = opts.get('type', 'bzip2').lower()
1146 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1146 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1147 bundletype = btypes.get(bundletype)
1147 bundletype = btypes.get(bundletype)
1148 if bundletype not in changegroup.bundletypes:
1148 if bundletype not in changegroup.bundletypes:
1149 raise util.Abort(_('unknown bundle type specified with --type'))
1149 raise util.Abort(_('unknown bundle type specified with --type'))
1150
1150
1151 if opts.get('all'):
1151 if opts.get('all'):
1152 base = ['null']
1152 base = ['null']
1153 else:
1153 else:
1154 base = scmutil.revrange(repo, opts.get('base'))
1154 base = scmutil.revrange(repo, opts.get('base'))
1155 # TODO: get desired bundlecaps from command line.
1155 # TODO: get desired bundlecaps from command line.
1156 bundlecaps = None
1156 bundlecaps = None
1157 if base:
1157 if base:
1158 if dest:
1158 if dest:
1159 raise util.Abort(_("--base is incompatible with specifying "
1159 raise util.Abort(_("--base is incompatible with specifying "
1160 "a destination"))
1160 "a destination"))
1161 common = [repo.lookup(rev) for rev in base]
1161 common = [repo.lookup(rev) for rev in base]
1162 heads = revs and map(repo.lookup, revs) or revs
1162 heads = revs and map(repo.lookup, revs) or revs
1163 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1163 cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
1164 bundlecaps=bundlecaps)
1164 bundlecaps=bundlecaps)
1165 outgoing = None
1165 outgoing = None
1166 else:
1166 else:
1167 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1167 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1168 dest, branches = hg.parseurl(dest, opts.get('branch'))
1168 dest, branches = hg.parseurl(dest, opts.get('branch'))
1169 other = hg.peer(repo, opts, dest)
1169 other = hg.peer(repo, opts, dest)
1170 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1170 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1171 heads = revs and map(repo.lookup, revs) or revs
1171 heads = revs and map(repo.lookup, revs) or revs
1172 outgoing = discovery.findcommonoutgoing(repo, other,
1172 outgoing = discovery.findcommonoutgoing(repo, other,
1173 onlyheads=heads,
1173 onlyheads=heads,
1174 force=opts.get('force'),
1174 force=opts.get('force'),
1175 portable=True)
1175 portable=True)
1176 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1176 cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
1177 if not cg:
1177 if not cg:
1178 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1178 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1179 return 1
1179 return 1
1180
1180
1181 changegroup.writebundle(cg, fname, bundletype)
1181 changegroup.writebundle(cg, fname, bundletype)
1182
1182
1183 @command('cat',
1183 @command('cat',
1184 [('o', 'output', '',
1184 [('o', 'output', '',
1185 _('print output to file with formatted name'), _('FORMAT')),
1185 _('print output to file with formatted name'), _('FORMAT')),
1186 ('r', 'rev', '', _('print the given revision'), _('REV')),
1186 ('r', 'rev', '', _('print the given revision'), _('REV')),
1187 ('', 'decode', None, _('apply any matching decode filter')),
1187 ('', 'decode', None, _('apply any matching decode filter')),
1188 ] + walkopts,
1188 ] + walkopts,
1189 _('[OPTION]... FILE...'),
1189 _('[OPTION]... FILE...'),
1190 inferrepo=True)
1190 inferrepo=True)
1191 def cat(ui, repo, file1, *pats, **opts):
1191 def cat(ui, repo, file1, *pats, **opts):
1192 """output the current or given revision of files
1192 """output the current or given revision of files
1193
1193
1194 Print the specified files as they were at the given revision. If
1194 Print the specified files as they were at the given revision. If
1195 no revision is given, the parent of the working directory is used.
1195 no revision is given, the parent of the working directory is used.
1196
1196
1197 Output may be to a file, in which case the name of the file is
1197 Output may be to a file, in which case the name of the file is
1198 given using a format string. The formatting rules as follows:
1198 given using a format string. The formatting rules as follows:
1199
1199
1200 :``%%``: literal "%" character
1200 :``%%``: literal "%" character
1201 :``%s``: basename of file being printed
1201 :``%s``: basename of file being printed
1202 :``%d``: dirname of file being printed, or '.' if in repository root
1202 :``%d``: dirname of file being printed, or '.' if in repository root
1203 :``%p``: root-relative path name of file being printed
1203 :``%p``: root-relative path name of file being printed
1204 :``%H``: changeset hash (40 hexadecimal digits)
1204 :``%H``: changeset hash (40 hexadecimal digits)
1205 :``%R``: changeset revision number
1205 :``%R``: changeset revision number
1206 :``%h``: short-form changeset hash (12 hexadecimal digits)
1206 :``%h``: short-form changeset hash (12 hexadecimal digits)
1207 :``%r``: zero-padded changeset revision number
1207 :``%r``: zero-padded changeset revision number
1208 :``%b``: basename of the exporting repository
1208 :``%b``: basename of the exporting repository
1209
1209
1210 Returns 0 on success.
1210 Returns 0 on success.
1211 """
1211 """
1212 ctx = scmutil.revsingle(repo, opts.get('rev'))
1212 ctx = scmutil.revsingle(repo, opts.get('rev'))
1213 m = scmutil.match(ctx, (file1,) + pats, opts)
1213 m = scmutil.match(ctx, (file1,) + pats, opts)
1214
1214
1215 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1215 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1216
1216
1217 @command('^clone',
1217 @command('^clone',
1218 [('U', 'noupdate', None,
1218 [('U', 'noupdate', None,
1219 _('the clone will include an empty working copy (only a repository)')),
1219 _('the clone will include an empty working copy (only a repository)')),
1220 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1220 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1221 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1221 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1222 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1222 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1223 ('', 'pull', None, _('use pull protocol to copy metadata')),
1223 ('', 'pull', None, _('use pull protocol to copy metadata')),
1224 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1224 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1225 ] + remoteopts,
1225 ] + remoteopts,
1226 _('[OPTION]... SOURCE [DEST]'),
1226 _('[OPTION]... SOURCE [DEST]'),
1227 norepo=True)
1227 norepo=True)
1228 def clone(ui, source, dest=None, **opts):
1228 def clone(ui, source, dest=None, **opts):
1229 """make a copy of an existing repository
1229 """make a copy of an existing repository
1230
1230
1231 Create a copy of an existing repository in a new directory.
1231 Create a copy of an existing repository in a new directory.
1232
1232
1233 If no destination directory name is specified, it defaults to the
1233 If no destination directory name is specified, it defaults to the
1234 basename of the source.
1234 basename of the source.
1235
1235
1236 The location of the source is added to the new repository's
1236 The location of the source is added to the new repository's
1237 ``.hg/hgrc`` file, as the default to be used for future pulls.
1237 ``.hg/hgrc`` file, as the default to be used for future pulls.
1238
1238
1239 Only local paths and ``ssh://`` URLs are supported as
1239 Only local paths and ``ssh://`` URLs are supported as
1240 destinations. For ``ssh://`` destinations, no working directory or
1240 destinations. For ``ssh://`` destinations, no working directory or
1241 ``.hg/hgrc`` will be created on the remote side.
1241 ``.hg/hgrc`` will be created on the remote side.
1242
1242
1243 To pull only a subset of changesets, specify one or more revisions
1243 To pull only a subset of changesets, specify one or more revisions
1244 identifiers with -r/--rev or branches with -b/--branch. The
1244 identifiers with -r/--rev or branches with -b/--branch. The
1245 resulting clone will contain only the specified changesets and
1245 resulting clone will contain only the specified changesets and
1246 their ancestors. These options (or 'clone src#rev dest') imply
1246 their ancestors. These options (or 'clone src#rev dest') imply
1247 --pull, even for local source repositories. Note that specifying a
1247 --pull, even for local source repositories. Note that specifying a
1248 tag will include the tagged changeset but not the changeset
1248 tag will include the tagged changeset but not the changeset
1249 containing the tag.
1249 containing the tag.
1250
1250
1251 If the source repository has a bookmark called '@' set, that
1251 If the source repository has a bookmark called '@' set, that
1252 revision will be checked out in the new repository by default.
1252 revision will be checked out in the new repository by default.
1253
1253
1254 To check out a particular version, use -u/--update, or
1254 To check out a particular version, use -u/--update, or
1255 -U/--noupdate to create a clone with no working directory.
1255 -U/--noupdate to create a clone with no working directory.
1256
1256
1257 .. container:: verbose
1257 .. container:: verbose
1258
1258
1259 For efficiency, hardlinks are used for cloning whenever the
1259 For efficiency, hardlinks are used for cloning whenever the
1260 source and destination are on the same filesystem (note this
1260 source and destination are on the same filesystem (note this
1261 applies only to the repository data, not to the working
1261 applies only to the repository data, not to the working
1262 directory). Some filesystems, such as AFS, implement hardlinking
1262 directory). Some filesystems, such as AFS, implement hardlinking
1263 incorrectly, but do not report errors. In these cases, use the
1263 incorrectly, but do not report errors. In these cases, use the
1264 --pull option to avoid hardlinking.
1264 --pull option to avoid hardlinking.
1265
1265
1266 In some cases, you can clone repositories and the working
1266 In some cases, you can clone repositories and the working
1267 directory using full hardlinks with ::
1267 directory using full hardlinks with ::
1268
1268
1269 $ cp -al REPO REPOCLONE
1269 $ cp -al REPO REPOCLONE
1270
1270
1271 This is the fastest way to clone, but it is not always safe. The
1271 This is the fastest way to clone, but it is not always safe. The
1272 operation is not atomic (making sure REPO is not modified during
1272 operation is not atomic (making sure REPO is not modified during
1273 the operation is up to you) and you have to make sure your
1273 the operation is up to you) and you have to make sure your
1274 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1274 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1275 so). Also, this is not compatible with certain extensions that
1275 so). Also, this is not compatible with certain extensions that
1276 place their metadata under the .hg directory, such as mq.
1276 place their metadata under the .hg directory, such as mq.
1277
1277
1278 Mercurial will update the working directory to the first applicable
1278 Mercurial will update the working directory to the first applicable
1279 revision from this list:
1279 revision from this list:
1280
1280
1281 a) null if -U or the source repository has no changesets
1281 a) null if -U or the source repository has no changesets
1282 b) if -u . and the source repository is local, the first parent of
1282 b) if -u . and the source repository is local, the first parent of
1283 the source repository's working directory
1283 the source repository's working directory
1284 c) the changeset specified with -u (if a branch name, this means the
1284 c) the changeset specified with -u (if a branch name, this means the
1285 latest head of that branch)
1285 latest head of that branch)
1286 d) the changeset specified with -r
1286 d) the changeset specified with -r
1287 e) the tipmost head specified with -b
1287 e) the tipmost head specified with -b
1288 f) the tipmost head specified with the url#branch source syntax
1288 f) the tipmost head specified with the url#branch source syntax
1289 g) the revision marked with the '@' bookmark, if present
1289 g) the revision marked with the '@' bookmark, if present
1290 h) the tipmost head of the default branch
1290 h) the tipmost head of the default branch
1291 i) tip
1291 i) tip
1292
1292
1293 Examples:
1293 Examples:
1294
1294
1295 - clone a remote repository to a new directory named hg/::
1295 - clone a remote repository to a new directory named hg/::
1296
1296
1297 hg clone http://selenic.com/hg
1297 hg clone http://selenic.com/hg
1298
1298
1299 - create a lightweight local clone::
1299 - create a lightweight local clone::
1300
1300
1301 hg clone project/ project-feature/
1301 hg clone project/ project-feature/
1302
1302
1303 - clone from an absolute path on an ssh server (note double-slash)::
1303 - clone from an absolute path on an ssh server (note double-slash)::
1304
1304
1305 hg clone ssh://user@server//home/projects/alpha/
1305 hg clone ssh://user@server//home/projects/alpha/
1306
1306
1307 - do a high-speed clone over a LAN while checking out a
1307 - do a high-speed clone over a LAN while checking out a
1308 specified version::
1308 specified version::
1309
1309
1310 hg clone --uncompressed http://server/repo -u 1.5
1310 hg clone --uncompressed http://server/repo -u 1.5
1311
1311
1312 - create a repository without changesets after a particular revision::
1312 - create a repository without changesets after a particular revision::
1313
1313
1314 hg clone -r 04e544 experimental/ good/
1314 hg clone -r 04e544 experimental/ good/
1315
1315
1316 - clone (and track) a particular named branch::
1316 - clone (and track) a particular named branch::
1317
1317
1318 hg clone http://selenic.com/hg#stable
1318 hg clone http://selenic.com/hg#stable
1319
1319
1320 See :hg:`help urls` for details on specifying URLs.
1320 See :hg:`help urls` for details on specifying URLs.
1321
1321
1322 Returns 0 on success.
1322 Returns 0 on success.
1323 """
1323 """
1324 if opts.get('noupdate') and opts.get('updaterev'):
1324 if opts.get('noupdate') and opts.get('updaterev'):
1325 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1325 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1326
1326
1327 r = hg.clone(ui, opts, source, dest,
1327 r = hg.clone(ui, opts, source, dest,
1328 pull=opts.get('pull'),
1328 pull=opts.get('pull'),
1329 stream=opts.get('uncompressed'),
1329 stream=opts.get('uncompressed'),
1330 rev=opts.get('rev'),
1330 rev=opts.get('rev'),
1331 update=opts.get('updaterev') or not opts.get('noupdate'),
1331 update=opts.get('updaterev') or not opts.get('noupdate'),
1332 branch=opts.get('branch'))
1332 branch=opts.get('branch'))
1333
1333
1334 return r is None
1334 return r is None
1335
1335
1336 @command('^commit|ci',
1336 @command('^commit|ci',
1337 [('A', 'addremove', None,
1337 [('A', 'addremove', None,
1338 _('mark new/missing files as added/removed before committing')),
1338 _('mark new/missing files as added/removed before committing')),
1339 ('', 'close-branch', None,
1339 ('', 'close-branch', None,
1340 _('mark a branch as closed, hiding it from the branch list')),
1340 _('mark a branch as closed, hiding it from the branch list')),
1341 ('', 'amend', None, _('amend the parent of the working dir')),
1341 ('', 'amend', None, _('amend the parent of the working dir')),
1342 ('s', 'secret', None, _('use the secret phase for committing')),
1342 ('s', 'secret', None, _('use the secret phase for committing')),
1343 ('e', 'edit', None, _('invoke editor on commit messages')),
1343 ('e', 'edit', None, _('invoke editor on commit messages')),
1344 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1344 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1345 _('[OPTION]... [FILE]...'),
1345 _('[OPTION]... [FILE]...'),
1346 inferrepo=True)
1346 inferrepo=True)
1347 def commit(ui, repo, *pats, **opts):
1347 def commit(ui, repo, *pats, **opts):
1348 """commit the specified files or all outstanding changes
1348 """commit the specified files or all outstanding changes
1349
1349
1350 Commit changes to the given files into the repository. Unlike a
1350 Commit changes to the given files into the repository. Unlike a
1351 centralized SCM, this operation is a local operation. See
1351 centralized SCM, this operation is a local operation. See
1352 :hg:`push` for a way to actively distribute your changes.
1352 :hg:`push` for a way to actively distribute your changes.
1353
1353
1354 If a list of files is omitted, all changes reported by :hg:`status`
1354 If a list of files is omitted, all changes reported by :hg:`status`
1355 will be committed.
1355 will be committed.
1356
1356
1357 If you are committing the result of a merge, do not provide any
1357 If you are committing the result of a merge, do not provide any
1358 filenames or -I/-X filters.
1358 filenames or -I/-X filters.
1359
1359
1360 If no commit message is specified, Mercurial starts your
1360 If no commit message is specified, Mercurial starts your
1361 configured editor where you can enter a message. In case your
1361 configured editor where you can enter a message. In case your
1362 commit fails, you will find a backup of your message in
1362 commit fails, you will find a backup of your message in
1363 ``.hg/last-message.txt``.
1363 ``.hg/last-message.txt``.
1364
1364
1365 The --amend flag can be used to amend the parent of the
1365 The --amend flag can be used to amend the parent of the
1366 working directory with a new commit that contains the changes
1366 working directory with a new commit that contains the changes
1367 in the parent in addition to those currently reported by :hg:`status`,
1367 in the parent in addition to those currently reported by :hg:`status`,
1368 if there are any. The old commit is stored in a backup bundle in
1368 if there are any. The old commit is stored in a backup bundle in
1369 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1369 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1370 on how to restore it).
1370 on how to restore it).
1371
1371
1372 Message, user and date are taken from the amended commit unless
1372 Message, user and date are taken from the amended commit unless
1373 specified. When a message isn't specified on the command line,
1373 specified. When a message isn't specified on the command line,
1374 the editor will open with the message of the amended commit.
1374 the editor will open with the message of the amended commit.
1375
1375
1376 It is not possible to amend public changesets (see :hg:`help phases`)
1376 It is not possible to amend public changesets (see :hg:`help phases`)
1377 or changesets that have children.
1377 or changesets that have children.
1378
1378
1379 See :hg:`help dates` for a list of formats valid for -d/--date.
1379 See :hg:`help dates` for a list of formats valid for -d/--date.
1380
1380
1381 Returns 0 on success, 1 if nothing changed.
1381 Returns 0 on success, 1 if nothing changed.
1382 """
1382 """
1383 if opts.get('subrepos'):
1383 if opts.get('subrepos'):
1384 if opts.get('amend'):
1384 if opts.get('amend'):
1385 raise util.Abort(_('cannot amend with --subrepos'))
1385 raise util.Abort(_('cannot amend with --subrepos'))
1386 # Let --subrepos on the command line override config setting.
1386 # Let --subrepos on the command line override config setting.
1387 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1387 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1388
1388
1389 cmdutil.checkunfinished(repo, commit=True)
1389 cmdutil.checkunfinished(repo, commit=True)
1390
1390
1391 branch = repo[None].branch()
1391 branch = repo[None].branch()
1392 bheads = repo.branchheads(branch)
1392 bheads = repo.branchheads(branch)
1393
1393
1394 extra = {}
1394 extra = {}
1395 if opts.get('close_branch'):
1395 if opts.get('close_branch'):
1396 extra['close'] = 1
1396 extra['close'] = 1
1397
1397
1398 if not bheads:
1398 if not bheads:
1399 raise util.Abort(_('can only close branch heads'))
1399 raise util.Abort(_('can only close branch heads'))
1400 elif opts.get('amend'):
1400 elif opts.get('amend'):
1401 if repo.parents()[0].p1().branch() != branch and \
1401 if repo.parents()[0].p1().branch() != branch and \
1402 repo.parents()[0].p2().branch() != branch:
1402 repo.parents()[0].p2().branch() != branch:
1403 raise util.Abort(_('can only close branch heads'))
1403 raise util.Abort(_('can only close branch heads'))
1404
1404
1405 if opts.get('amend'):
1405 if opts.get('amend'):
1406 if ui.configbool('ui', 'commitsubrepos'):
1406 if ui.configbool('ui', 'commitsubrepos'):
1407 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1407 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1408
1408
1409 old = repo['.']
1409 old = repo['.']
1410 if old.phase() == phases.public:
1410 if old.phase() == phases.public:
1411 raise util.Abort(_('cannot amend public changesets'))
1411 raise util.Abort(_('cannot amend public changesets'))
1412 if len(repo[None].parents()) > 1:
1412 if len(repo[None].parents()) > 1:
1413 raise util.Abort(_('cannot amend while merging'))
1413 raise util.Abort(_('cannot amend while merging'))
1414 if (not obsolete._enabled) and old.children():
1414 if (not obsolete._enabled) and old.children():
1415 raise util.Abort(_('cannot amend changeset with children'))
1415 raise util.Abort(_('cannot amend changeset with children'))
1416
1416
1417 # commitfunc is used only for temporary amend commit by cmdutil.amend
1417 # commitfunc is used only for temporary amend commit by cmdutil.amend
1418 def commitfunc(ui, repo, message, match, opts):
1418 def commitfunc(ui, repo, message, match, opts):
1419 return repo.commit(message,
1419 return repo.commit(message,
1420 opts.get('user') or old.user(),
1420 opts.get('user') or old.user(),
1421 opts.get('date') or old.date(),
1421 opts.get('date') or old.date(),
1422 match,
1422 match,
1423 extra=extra)
1423 extra=extra)
1424
1424
1425 current = repo._bookmarkcurrent
1425 current = repo._bookmarkcurrent
1426 marks = old.bookmarks()
1426 marks = old.bookmarks()
1427 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1427 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1428 if node == old.node():
1428 if node == old.node():
1429 ui.status(_("nothing changed\n"))
1429 ui.status(_("nothing changed\n"))
1430 return 1
1430 return 1
1431 elif marks:
1431 elif marks:
1432 ui.debug('moving bookmarks %r from %s to %s\n' %
1432 ui.debug('moving bookmarks %r from %s to %s\n' %
1433 (marks, old.hex(), hex(node)))
1433 (marks, old.hex(), hex(node)))
1434 newmarks = repo._bookmarks
1434 newmarks = repo._bookmarks
1435 for bm in marks:
1435 for bm in marks:
1436 newmarks[bm] = node
1436 newmarks[bm] = node
1437 if bm == current:
1437 if bm == current:
1438 bookmarks.setcurrent(repo, bm)
1438 bookmarks.setcurrent(repo, bm)
1439 newmarks.write()
1439 newmarks.write()
1440 else:
1440 else:
1441 def commitfunc(ui, repo, message, match, opts):
1441 def commitfunc(ui, repo, message, match, opts):
1442 backup = ui.backupconfig('phases', 'new-commit')
1442 backup = ui.backupconfig('phases', 'new-commit')
1443 baseui = repo.baseui
1443 baseui = repo.baseui
1444 basebackup = baseui.backupconfig('phases', 'new-commit')
1444 basebackup = baseui.backupconfig('phases', 'new-commit')
1445 try:
1445 try:
1446 if opts.get('secret'):
1446 if opts.get('secret'):
1447 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1447 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1448 # Propagate to subrepos
1448 # Propagate to subrepos
1449 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1449 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1450
1450
1451 editform = 'commit.normal'
1451 editform = 'commit.normal'
1452 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1452 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1453 return repo.commit(message, opts.get('user'), opts.get('date'),
1453 return repo.commit(message, opts.get('user'), opts.get('date'),
1454 match,
1454 match,
1455 editor=editor,
1455 editor=editor,
1456 extra=extra)
1456 extra=extra)
1457 finally:
1457 finally:
1458 ui.restoreconfig(backup)
1458 ui.restoreconfig(backup)
1459 repo.baseui.restoreconfig(basebackup)
1459 repo.baseui.restoreconfig(basebackup)
1460
1460
1461
1461
1462 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1462 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1463
1463
1464 if not node:
1464 if not node:
1465 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1465 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1466 if stat[3]:
1466 if stat[3]:
1467 ui.status(_("nothing changed (%d missing files, see "
1467 ui.status(_("nothing changed (%d missing files, see "
1468 "'hg status')\n") % len(stat[3]))
1468 "'hg status')\n") % len(stat[3]))
1469 else:
1469 else:
1470 ui.status(_("nothing changed\n"))
1470 ui.status(_("nothing changed\n"))
1471 return 1
1471 return 1
1472
1472
1473 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1473 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1474
1474
1475 @command('config|showconfig|debugconfig',
1475 @command('config|showconfig|debugconfig',
1476 [('u', 'untrusted', None, _('show untrusted configuration options')),
1476 [('u', 'untrusted', None, _('show untrusted configuration options')),
1477 ('e', 'edit', None, _('edit user config')),
1477 ('e', 'edit', None, _('edit user config')),
1478 ('l', 'local', None, _('edit repository config')),
1478 ('l', 'local', None, _('edit repository config')),
1479 ('g', 'global', None, _('edit global config'))],
1479 ('g', 'global', None, _('edit global config'))],
1480 _('[-u] [NAME]...'),
1480 _('[-u] [NAME]...'),
1481 optionalrepo=True)
1481 optionalrepo=True)
1482 def config(ui, repo, *values, **opts):
1482 def config(ui, repo, *values, **opts):
1483 """show combined config settings from all hgrc files
1483 """show combined config settings from all hgrc files
1484
1484
1485 With no arguments, print names and values of all config items.
1485 With no arguments, print names and values of all config items.
1486
1486
1487 With one argument of the form section.name, print just the value
1487 With one argument of the form section.name, print just the value
1488 of that config item.
1488 of that config item.
1489
1489
1490 With multiple arguments, print names and values of all config
1490 With multiple arguments, print names and values of all config
1491 items with matching section names.
1491 items with matching section names.
1492
1492
1493 With --edit, start an editor on the user-level config file. With
1493 With --edit, start an editor on the user-level config file. With
1494 --global, edit the system-wide config file. With --local, edit the
1494 --global, edit the system-wide config file. With --local, edit the
1495 repository-level config file.
1495 repository-level config file.
1496
1496
1497 With --debug, the source (filename and line number) is printed
1497 With --debug, the source (filename and line number) is printed
1498 for each config item.
1498 for each config item.
1499
1499
1500 See :hg:`help config` for more information about config files.
1500 See :hg:`help config` for more information about config files.
1501
1501
1502 Returns 0 on success.
1502 Returns 0 on success.
1503
1503
1504 """
1504 """
1505
1505
1506 if opts.get('edit') or opts.get('local') or opts.get('global'):
1506 if opts.get('edit') or opts.get('local') or opts.get('global'):
1507 if opts.get('local') and opts.get('global'):
1507 if opts.get('local') and opts.get('global'):
1508 raise util.Abort(_("can't use --local and --global together"))
1508 raise util.Abort(_("can't use --local and --global together"))
1509
1509
1510 if opts.get('local'):
1510 if opts.get('local'):
1511 if not repo:
1511 if not repo:
1512 raise util.Abort(_("can't use --local outside a repository"))
1512 raise util.Abort(_("can't use --local outside a repository"))
1513 paths = [repo.join('hgrc')]
1513 paths = [repo.join('hgrc')]
1514 elif opts.get('global'):
1514 elif opts.get('global'):
1515 paths = scmutil.systemrcpath()
1515 paths = scmutil.systemrcpath()
1516 else:
1516 else:
1517 paths = scmutil.userrcpath()
1517 paths = scmutil.userrcpath()
1518
1518
1519 for f in paths:
1519 for f in paths:
1520 if os.path.exists(f):
1520 if os.path.exists(f):
1521 break
1521 break
1522 else:
1522 else:
1523 f = paths[0]
1523 f = paths[0]
1524 fp = open(f, "w")
1524 fp = open(f, "w")
1525 fp.write(
1525 fp.write(
1526 '# example config (see "hg help config" for more info)\n'
1526 '# example config (see "hg help config" for more info)\n'
1527 '\n'
1527 '\n'
1528 '[ui]\n'
1528 '[ui]\n'
1529 '# name and email, e.g.\n'
1529 '# name and email, e.g.\n'
1530 '# username = Jane Doe <jdoe@example.com>\n'
1530 '# username = Jane Doe <jdoe@example.com>\n'
1531 'username =\n'
1531 'username =\n'
1532 '\n'
1532 '\n'
1533 '[extensions]\n'
1533 '[extensions]\n'
1534 '# uncomment these lines to enable some popular extensions\n'
1534 '# uncomment these lines to enable some popular extensions\n'
1535 '# (see "hg help extensions" for more info)\n'
1535 '# (see "hg help extensions" for more info)\n'
1536 '# pager =\n'
1536 '# pager =\n'
1537 '# progress =\n'
1537 '# progress =\n'
1538 '# color =\n')
1538 '# color =\n')
1539 fp.close()
1539 fp.close()
1540
1540
1541 editor = ui.geteditor()
1541 editor = ui.geteditor()
1542 util.system("%s \"%s\"" % (editor, f),
1542 util.system("%s \"%s\"" % (editor, f),
1543 onerr=util.Abort, errprefix=_("edit failed"),
1543 onerr=util.Abort, errprefix=_("edit failed"),
1544 out=ui.fout)
1544 out=ui.fout)
1545 return
1545 return
1546
1546
1547 for f in scmutil.rcpath():
1547 for f in scmutil.rcpath():
1548 ui.debug('read config from: %s\n' % f)
1548 ui.debug('read config from: %s\n' % f)
1549 untrusted = bool(opts.get('untrusted'))
1549 untrusted = bool(opts.get('untrusted'))
1550 if values:
1550 if values:
1551 sections = [v for v in values if '.' not in v]
1551 sections = [v for v in values if '.' not in v]
1552 items = [v for v in values if '.' in v]
1552 items = [v for v in values if '.' in v]
1553 if len(items) > 1 or items and sections:
1553 if len(items) > 1 or items and sections:
1554 raise util.Abort(_('only one config item permitted'))
1554 raise util.Abort(_('only one config item permitted'))
1555 for section, name, value in ui.walkconfig(untrusted=untrusted):
1555 for section, name, value in ui.walkconfig(untrusted=untrusted):
1556 value = str(value).replace('\n', '\\n')
1556 value = str(value).replace('\n', '\\n')
1557 sectname = section + '.' + name
1557 sectname = section + '.' + name
1558 if values:
1558 if values:
1559 for v in values:
1559 for v in values:
1560 if v == section:
1560 if v == section:
1561 ui.debug('%s: ' %
1561 ui.debug('%s: ' %
1562 ui.configsource(section, name, untrusted))
1562 ui.configsource(section, name, untrusted))
1563 ui.write('%s=%s\n' % (sectname, value))
1563 ui.write('%s=%s\n' % (sectname, value))
1564 elif v == sectname:
1564 elif v == sectname:
1565 ui.debug('%s: ' %
1565 ui.debug('%s: ' %
1566 ui.configsource(section, name, untrusted))
1566 ui.configsource(section, name, untrusted))
1567 ui.write(value, '\n')
1567 ui.write(value, '\n')
1568 else:
1568 else:
1569 ui.debug('%s: ' %
1569 ui.debug('%s: ' %
1570 ui.configsource(section, name, untrusted))
1570 ui.configsource(section, name, untrusted))
1571 ui.write('%s=%s\n' % (sectname, value))
1571 ui.write('%s=%s\n' % (sectname, value))
1572
1572
1573 @command('copy|cp',
1573 @command('copy|cp',
1574 [('A', 'after', None, _('record a copy that has already occurred')),
1574 [('A', 'after', None, _('record a copy that has already occurred')),
1575 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1575 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1576 ] + walkopts + dryrunopts,
1576 ] + walkopts + dryrunopts,
1577 _('[OPTION]... [SOURCE]... DEST'))
1577 _('[OPTION]... [SOURCE]... DEST'))
1578 def copy(ui, repo, *pats, **opts):
1578 def copy(ui, repo, *pats, **opts):
1579 """mark files as copied for the next commit
1579 """mark files as copied for the next commit
1580
1580
1581 Mark dest as having copies of source files. If dest is a
1581 Mark dest as having copies of source files. If dest is a
1582 directory, copies are put in that directory. If dest is a file,
1582 directory, copies are put in that directory. If dest is a file,
1583 the source must be a single file.
1583 the source must be a single file.
1584
1584
1585 By default, this command copies the contents of files as they
1585 By default, this command copies the contents of files as they
1586 exist in the working directory. If invoked with -A/--after, the
1586 exist in the working directory. If invoked with -A/--after, the
1587 operation is recorded, but no copying is performed.
1587 operation is recorded, but no copying is performed.
1588
1588
1589 This command takes effect with the next commit. To undo a copy
1589 This command takes effect with the next commit. To undo a copy
1590 before that, see :hg:`revert`.
1590 before that, see :hg:`revert`.
1591
1591
1592 Returns 0 on success, 1 if errors are encountered.
1592 Returns 0 on success, 1 if errors are encountered.
1593 """
1593 """
1594 wlock = repo.wlock(False)
1594 wlock = repo.wlock(False)
1595 try:
1595 try:
1596 return cmdutil.copy(ui, repo, pats, opts)
1596 return cmdutil.copy(ui, repo, pats, opts)
1597 finally:
1597 finally:
1598 wlock.release()
1598 wlock.release()
1599
1599
1600 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1600 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1601 def debugancestor(ui, repo, *args):
1601 def debugancestor(ui, repo, *args):
1602 """find the ancestor revision of two revisions in a given index"""
1602 """find the ancestor revision of two revisions in a given index"""
1603 if len(args) == 3:
1603 if len(args) == 3:
1604 index, rev1, rev2 = args
1604 index, rev1, rev2 = args
1605 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1605 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1606 lookup = r.lookup
1606 lookup = r.lookup
1607 elif len(args) == 2:
1607 elif len(args) == 2:
1608 if not repo:
1608 if not repo:
1609 raise util.Abort(_("there is no Mercurial repository here "
1609 raise util.Abort(_("there is no Mercurial repository here "
1610 "(.hg not found)"))
1610 "(.hg not found)"))
1611 rev1, rev2 = args
1611 rev1, rev2 = args
1612 r = repo.changelog
1612 r = repo.changelog
1613 lookup = repo.lookup
1613 lookup = repo.lookup
1614 else:
1614 else:
1615 raise util.Abort(_('either two or three arguments required'))
1615 raise util.Abort(_('either two or three arguments required'))
1616 a = r.ancestor(lookup(rev1), lookup(rev2))
1616 a = r.ancestor(lookup(rev1), lookup(rev2))
1617 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1617 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1618
1618
1619 @command('debugbuilddag',
1619 @command('debugbuilddag',
1620 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1620 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1621 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1621 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1622 ('n', 'new-file', None, _('add new file at each rev'))],
1622 ('n', 'new-file', None, _('add new file at each rev'))],
1623 _('[OPTION]... [TEXT]'))
1623 _('[OPTION]... [TEXT]'))
1624 def debugbuilddag(ui, repo, text=None,
1624 def debugbuilddag(ui, repo, text=None,
1625 mergeable_file=False,
1625 mergeable_file=False,
1626 overwritten_file=False,
1626 overwritten_file=False,
1627 new_file=False):
1627 new_file=False):
1628 """builds a repo with a given DAG from scratch in the current empty repo
1628 """builds a repo with a given DAG from scratch in the current empty repo
1629
1629
1630 The description of the DAG is read from stdin if not given on the
1630 The description of the DAG is read from stdin if not given on the
1631 command line.
1631 command line.
1632
1632
1633 Elements:
1633 Elements:
1634
1634
1635 - "+n" is a linear run of n nodes based on the current default parent
1635 - "+n" is a linear run of n nodes based on the current default parent
1636 - "." is a single node based on the current default parent
1636 - "." is a single node based on the current default parent
1637 - "$" resets the default parent to null (implied at the start);
1637 - "$" resets the default parent to null (implied at the start);
1638 otherwise the default parent is always the last node created
1638 otherwise the default parent is always the last node created
1639 - "<p" sets the default parent to the backref p
1639 - "<p" sets the default parent to the backref p
1640 - "*p" is a fork at parent p, which is a backref
1640 - "*p" is a fork at parent p, which is a backref
1641 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1641 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1642 - "/p2" is a merge of the preceding node and p2
1642 - "/p2" is a merge of the preceding node and p2
1643 - ":tag" defines a local tag for the preceding node
1643 - ":tag" defines a local tag for the preceding node
1644 - "@branch" sets the named branch for subsequent nodes
1644 - "@branch" sets the named branch for subsequent nodes
1645 - "#...\\n" is a comment up to the end of the line
1645 - "#...\\n" is a comment up to the end of the line
1646
1646
1647 Whitespace between the above elements is ignored.
1647 Whitespace between the above elements is ignored.
1648
1648
1649 A backref is either
1649 A backref is either
1650
1650
1651 - a number n, which references the node curr-n, where curr is the current
1651 - a number n, which references the node curr-n, where curr is the current
1652 node, or
1652 node, or
1653 - the name of a local tag you placed earlier using ":tag", or
1653 - the name of a local tag you placed earlier using ":tag", or
1654 - empty to denote the default parent.
1654 - empty to denote the default parent.
1655
1655
1656 All string valued-elements are either strictly alphanumeric, or must
1656 All string valued-elements are either strictly alphanumeric, or must
1657 be enclosed in double quotes ("..."), with "\\" as escape character.
1657 be enclosed in double quotes ("..."), with "\\" as escape character.
1658 """
1658 """
1659
1659
1660 if text is None:
1660 if text is None:
1661 ui.status(_("reading DAG from stdin\n"))
1661 ui.status(_("reading DAG from stdin\n"))
1662 text = ui.fin.read()
1662 text = ui.fin.read()
1663
1663
1664 cl = repo.changelog
1664 cl = repo.changelog
1665 if len(cl) > 0:
1665 if len(cl) > 0:
1666 raise util.Abort(_('repository is not empty'))
1666 raise util.Abort(_('repository is not empty'))
1667
1667
1668 # determine number of revs in DAG
1668 # determine number of revs in DAG
1669 total = 0
1669 total = 0
1670 for type, data in dagparser.parsedag(text):
1670 for type, data in dagparser.parsedag(text):
1671 if type == 'n':
1671 if type == 'n':
1672 total += 1
1672 total += 1
1673
1673
1674 if mergeable_file:
1674 if mergeable_file:
1675 linesperrev = 2
1675 linesperrev = 2
1676 # make a file with k lines per rev
1676 # make a file with k lines per rev
1677 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1677 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1678 initialmergedlines.append("")
1678 initialmergedlines.append("")
1679
1679
1680 tags = []
1680 tags = []
1681
1681
1682 lock = tr = None
1682 lock = tr = None
1683 try:
1683 try:
1684 lock = repo.lock()
1684 lock = repo.lock()
1685 tr = repo.transaction("builddag")
1685 tr = repo.transaction("builddag")
1686
1686
1687 at = -1
1687 at = -1
1688 atbranch = 'default'
1688 atbranch = 'default'
1689 nodeids = []
1689 nodeids = []
1690 id = 0
1690 id = 0
1691 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1691 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1692 for type, data in dagparser.parsedag(text):
1692 for type, data in dagparser.parsedag(text):
1693 if type == 'n':
1693 if type == 'n':
1694 ui.note(('node %s\n' % str(data)))
1694 ui.note(('node %s\n' % str(data)))
1695 id, ps = data
1695 id, ps = data
1696
1696
1697 files = []
1697 files = []
1698 fctxs = {}
1698 fctxs = {}
1699
1699
1700 p2 = None
1700 p2 = None
1701 if mergeable_file:
1701 if mergeable_file:
1702 fn = "mf"
1702 fn = "mf"
1703 p1 = repo[ps[0]]
1703 p1 = repo[ps[0]]
1704 if len(ps) > 1:
1704 if len(ps) > 1:
1705 p2 = repo[ps[1]]
1705 p2 = repo[ps[1]]
1706 pa = p1.ancestor(p2)
1706 pa = p1.ancestor(p2)
1707 base, local, other = [x[fn].data() for x in (pa, p1,
1707 base, local, other = [x[fn].data() for x in (pa, p1,
1708 p2)]
1708 p2)]
1709 m3 = simplemerge.Merge3Text(base, local, other)
1709 m3 = simplemerge.Merge3Text(base, local, other)
1710 ml = [l.strip() for l in m3.merge_lines()]
1710 ml = [l.strip() for l in m3.merge_lines()]
1711 ml.append("")
1711 ml.append("")
1712 elif at > 0:
1712 elif at > 0:
1713 ml = p1[fn].data().split("\n")
1713 ml = p1[fn].data().split("\n")
1714 else:
1714 else:
1715 ml = initialmergedlines
1715 ml = initialmergedlines
1716 ml[id * linesperrev] += " r%i" % id
1716 ml[id * linesperrev] += " r%i" % id
1717 mergedtext = "\n".join(ml)
1717 mergedtext = "\n".join(ml)
1718 files.append(fn)
1718 files.append(fn)
1719 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1719 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1720
1720
1721 if overwritten_file:
1721 if overwritten_file:
1722 fn = "of"
1722 fn = "of"
1723 files.append(fn)
1723 files.append(fn)
1724 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1724 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1725
1725
1726 if new_file:
1726 if new_file:
1727 fn = "nf%i" % id
1727 fn = "nf%i" % id
1728 files.append(fn)
1728 files.append(fn)
1729 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1729 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1730 if len(ps) > 1:
1730 if len(ps) > 1:
1731 if not p2:
1731 if not p2:
1732 p2 = repo[ps[1]]
1732 p2 = repo[ps[1]]
1733 for fn in p2:
1733 for fn in p2:
1734 if fn.startswith("nf"):
1734 if fn.startswith("nf"):
1735 files.append(fn)
1735 files.append(fn)
1736 fctxs[fn] = p2[fn]
1736 fctxs[fn] = p2[fn]
1737
1737
1738 def fctxfn(repo, cx, path):
1738 def fctxfn(repo, cx, path):
1739 return fctxs.get(path)
1739 return fctxs.get(path)
1740
1740
1741 if len(ps) == 0 or ps[0] < 0:
1741 if len(ps) == 0 or ps[0] < 0:
1742 pars = [None, None]
1742 pars = [None, None]
1743 elif len(ps) == 1:
1743 elif len(ps) == 1:
1744 pars = [nodeids[ps[0]], None]
1744 pars = [nodeids[ps[0]], None]
1745 else:
1745 else:
1746 pars = [nodeids[p] for p in ps]
1746 pars = [nodeids[p] for p in ps]
1747 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1747 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1748 date=(id, 0),
1748 date=(id, 0),
1749 user="debugbuilddag",
1749 user="debugbuilddag",
1750 extra={'branch': atbranch})
1750 extra={'branch': atbranch})
1751 nodeid = repo.commitctx(cx)
1751 nodeid = repo.commitctx(cx)
1752 nodeids.append(nodeid)
1752 nodeids.append(nodeid)
1753 at = id
1753 at = id
1754 elif type == 'l':
1754 elif type == 'l':
1755 id, name = data
1755 id, name = data
1756 ui.note(('tag %s\n' % name))
1756 ui.note(('tag %s\n' % name))
1757 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1757 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1758 elif type == 'a':
1758 elif type == 'a':
1759 ui.note(('branch %s\n' % data))
1759 ui.note(('branch %s\n' % data))
1760 atbranch = data
1760 atbranch = data
1761 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1761 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1762 tr.close()
1762 tr.close()
1763
1763
1764 if tags:
1764 if tags:
1765 repo.opener.write("localtags", "".join(tags))
1765 repo.opener.write("localtags", "".join(tags))
1766 finally:
1766 finally:
1767 ui.progress(_('building'), None)
1767 ui.progress(_('building'), None)
1768 release(tr, lock)
1768 release(tr, lock)
1769
1769
1770 @command('debugbundle',
1770 @command('debugbundle',
1771 [('a', 'all', None, _('show all details'))],
1771 [('a', 'all', None, _('show all details'))],
1772 _('FILE'),
1772 _('FILE'),
1773 norepo=True)
1773 norepo=True)
1774 def debugbundle(ui, bundlepath, all=None, **opts):
1774 def debugbundle(ui, bundlepath, all=None, **opts):
1775 """lists the contents of a bundle"""
1775 """lists the contents of a bundle"""
1776 f = hg.openpath(ui, bundlepath)
1776 f = hg.openpath(ui, bundlepath)
1777 try:
1777 try:
1778 gen = exchange.readbundle(ui, f, bundlepath)
1778 gen = exchange.readbundle(ui, f, bundlepath)
1779 if all:
1779 if all:
1780 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1780 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1781
1781
1782 def showchunks(named):
1782 def showchunks(named):
1783 ui.write("\n%s\n" % named)
1783 ui.write("\n%s\n" % named)
1784 chain = None
1784 chain = None
1785 while True:
1785 while True:
1786 chunkdata = gen.deltachunk(chain)
1786 chunkdata = gen.deltachunk(chain)
1787 if not chunkdata:
1787 if not chunkdata:
1788 break
1788 break
1789 node = chunkdata['node']
1789 node = chunkdata['node']
1790 p1 = chunkdata['p1']
1790 p1 = chunkdata['p1']
1791 p2 = chunkdata['p2']
1791 p2 = chunkdata['p2']
1792 cs = chunkdata['cs']
1792 cs = chunkdata['cs']
1793 deltabase = chunkdata['deltabase']
1793 deltabase = chunkdata['deltabase']
1794 delta = chunkdata['delta']
1794 delta = chunkdata['delta']
1795 ui.write("%s %s %s %s %s %s\n" %
1795 ui.write("%s %s %s %s %s %s\n" %
1796 (hex(node), hex(p1), hex(p2),
1796 (hex(node), hex(p1), hex(p2),
1797 hex(cs), hex(deltabase), len(delta)))
1797 hex(cs), hex(deltabase), len(delta)))
1798 chain = node
1798 chain = node
1799
1799
1800 chunkdata = gen.changelogheader()
1800 chunkdata = gen.changelogheader()
1801 showchunks("changelog")
1801 showchunks("changelog")
1802 chunkdata = gen.manifestheader()
1802 chunkdata = gen.manifestheader()
1803 showchunks("manifest")
1803 showchunks("manifest")
1804 while True:
1804 while True:
1805 chunkdata = gen.filelogheader()
1805 chunkdata = gen.filelogheader()
1806 if not chunkdata:
1806 if not chunkdata:
1807 break
1807 break
1808 fname = chunkdata['filename']
1808 fname = chunkdata['filename']
1809 showchunks(fname)
1809 showchunks(fname)
1810 else:
1810 else:
1811 chunkdata = gen.changelogheader()
1811 chunkdata = gen.changelogheader()
1812 chain = None
1812 chain = None
1813 while True:
1813 while True:
1814 chunkdata = gen.deltachunk(chain)
1814 chunkdata = gen.deltachunk(chain)
1815 if not chunkdata:
1815 if not chunkdata:
1816 break
1816 break
1817 node = chunkdata['node']
1817 node = chunkdata['node']
1818 ui.write("%s\n" % hex(node))
1818 ui.write("%s\n" % hex(node))
1819 chain = node
1819 chain = node
1820 finally:
1820 finally:
1821 f.close()
1821 f.close()
1822
1822
1823 @command('debugcheckstate', [], '')
1823 @command('debugcheckstate', [], '')
1824 def debugcheckstate(ui, repo):
1824 def debugcheckstate(ui, repo):
1825 """validate the correctness of the current dirstate"""
1825 """validate the correctness of the current dirstate"""
1826 parent1, parent2 = repo.dirstate.parents()
1826 parent1, parent2 = repo.dirstate.parents()
1827 m1 = repo[parent1].manifest()
1827 m1 = repo[parent1].manifest()
1828 m2 = repo[parent2].manifest()
1828 m2 = repo[parent2].manifest()
1829 errors = 0
1829 errors = 0
1830 for f in repo.dirstate:
1830 for f in repo.dirstate:
1831 state = repo.dirstate[f]
1831 state = repo.dirstate[f]
1832 if state in "nr" and f not in m1:
1832 if state in "nr" and f not in m1:
1833 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1833 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1834 errors += 1
1834 errors += 1
1835 if state in "a" and f in m1:
1835 if state in "a" and f in m1:
1836 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1836 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1837 errors += 1
1837 errors += 1
1838 if state in "m" and f not in m1 and f not in m2:
1838 if state in "m" and f not in m1 and f not in m2:
1839 ui.warn(_("%s in state %s, but not in either manifest\n") %
1839 ui.warn(_("%s in state %s, but not in either manifest\n") %
1840 (f, state))
1840 (f, state))
1841 errors += 1
1841 errors += 1
1842 for f in m1:
1842 for f in m1:
1843 state = repo.dirstate[f]
1843 state = repo.dirstate[f]
1844 if state not in "nrm":
1844 if state not in "nrm":
1845 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1845 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1846 errors += 1
1846 errors += 1
1847 if errors:
1847 if errors:
1848 error = _(".hg/dirstate inconsistent with current parent's manifest")
1848 error = _(".hg/dirstate inconsistent with current parent's manifest")
1849 raise util.Abort(error)
1849 raise util.Abort(error)
1850
1850
1851 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1851 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1852 def debugcommands(ui, cmd='', *args):
1852 def debugcommands(ui, cmd='', *args):
1853 """list all available commands and options"""
1853 """list all available commands and options"""
1854 for cmd, vals in sorted(table.iteritems()):
1854 for cmd, vals in sorted(table.iteritems()):
1855 cmd = cmd.split('|')[0].strip('^')
1855 cmd = cmd.split('|')[0].strip('^')
1856 opts = ', '.join([i[1] for i in vals[1]])
1856 opts = ', '.join([i[1] for i in vals[1]])
1857 ui.write('%s: %s\n' % (cmd, opts))
1857 ui.write('%s: %s\n' % (cmd, opts))
1858
1858
1859 @command('debugcomplete',
1859 @command('debugcomplete',
1860 [('o', 'options', None, _('show the command options'))],
1860 [('o', 'options', None, _('show the command options'))],
1861 _('[-o] CMD'),
1861 _('[-o] CMD'),
1862 norepo=True)
1862 norepo=True)
1863 def debugcomplete(ui, cmd='', **opts):
1863 def debugcomplete(ui, cmd='', **opts):
1864 """returns the completion list associated with the given command"""
1864 """returns the completion list associated with the given command"""
1865
1865
1866 if opts.get('options'):
1866 if opts.get('options'):
1867 options = []
1867 options = []
1868 otables = [globalopts]
1868 otables = [globalopts]
1869 if cmd:
1869 if cmd:
1870 aliases, entry = cmdutil.findcmd(cmd, table, False)
1870 aliases, entry = cmdutil.findcmd(cmd, table, False)
1871 otables.append(entry[1])
1871 otables.append(entry[1])
1872 for t in otables:
1872 for t in otables:
1873 for o in t:
1873 for o in t:
1874 if "(DEPRECATED)" in o[3]:
1874 if "(DEPRECATED)" in o[3]:
1875 continue
1875 continue
1876 if o[0]:
1876 if o[0]:
1877 options.append('-%s' % o[0])
1877 options.append('-%s' % o[0])
1878 options.append('--%s' % o[1])
1878 options.append('--%s' % o[1])
1879 ui.write("%s\n" % "\n".join(options))
1879 ui.write("%s\n" % "\n".join(options))
1880 return
1880 return
1881
1881
1882 cmdlist = cmdutil.findpossible(cmd, table)
1882 cmdlist = cmdutil.findpossible(cmd, table)
1883 if ui.verbose:
1883 if ui.verbose:
1884 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1884 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1885 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1885 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1886
1886
1887 @command('debugdag',
1887 @command('debugdag',
1888 [('t', 'tags', None, _('use tags as labels')),
1888 [('t', 'tags', None, _('use tags as labels')),
1889 ('b', 'branches', None, _('annotate with branch names')),
1889 ('b', 'branches', None, _('annotate with branch names')),
1890 ('', 'dots', None, _('use dots for runs')),
1890 ('', 'dots', None, _('use dots for runs')),
1891 ('s', 'spaces', None, _('separate elements by spaces'))],
1891 ('s', 'spaces', None, _('separate elements by spaces'))],
1892 _('[OPTION]... [FILE [REV]...]'),
1892 _('[OPTION]... [FILE [REV]...]'),
1893 optionalrepo=True)
1893 optionalrepo=True)
1894 def debugdag(ui, repo, file_=None, *revs, **opts):
1894 def debugdag(ui, repo, file_=None, *revs, **opts):
1895 """format the changelog or an index DAG as a concise textual description
1895 """format the changelog or an index DAG as a concise textual description
1896
1896
1897 If you pass a revlog index, the revlog's DAG is emitted. If you list
1897 If you pass a revlog index, the revlog's DAG is emitted. If you list
1898 revision numbers, they get labeled in the output as rN.
1898 revision numbers, they get labeled in the output as rN.
1899
1899
1900 Otherwise, the changelog DAG of the current repo is emitted.
1900 Otherwise, the changelog DAG of the current repo is emitted.
1901 """
1901 """
1902 spaces = opts.get('spaces')
1902 spaces = opts.get('spaces')
1903 dots = opts.get('dots')
1903 dots = opts.get('dots')
1904 if file_:
1904 if file_:
1905 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1905 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1906 revs = set((int(r) for r in revs))
1906 revs = set((int(r) for r in revs))
1907 def events():
1907 def events():
1908 for r in rlog:
1908 for r in rlog:
1909 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1909 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1910 if p != -1)))
1910 if p != -1)))
1911 if r in revs:
1911 if r in revs:
1912 yield 'l', (r, "r%i" % r)
1912 yield 'l', (r, "r%i" % r)
1913 elif repo:
1913 elif repo:
1914 cl = repo.changelog
1914 cl = repo.changelog
1915 tags = opts.get('tags')
1915 tags = opts.get('tags')
1916 branches = opts.get('branches')
1916 branches = opts.get('branches')
1917 if tags:
1917 if tags:
1918 labels = {}
1918 labels = {}
1919 for l, n in repo.tags().items():
1919 for l, n in repo.tags().items():
1920 labels.setdefault(cl.rev(n), []).append(l)
1920 labels.setdefault(cl.rev(n), []).append(l)
1921 def events():
1921 def events():
1922 b = "default"
1922 b = "default"
1923 for r in cl:
1923 for r in cl:
1924 if branches:
1924 if branches:
1925 newb = cl.read(cl.node(r))[5]['branch']
1925 newb = cl.read(cl.node(r))[5]['branch']
1926 if newb != b:
1926 if newb != b:
1927 yield 'a', newb
1927 yield 'a', newb
1928 b = newb
1928 b = newb
1929 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1929 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1930 if p != -1)))
1930 if p != -1)))
1931 if tags:
1931 if tags:
1932 ls = labels.get(r)
1932 ls = labels.get(r)
1933 if ls:
1933 if ls:
1934 for l in ls:
1934 for l in ls:
1935 yield 'l', (r, l)
1935 yield 'l', (r, l)
1936 else:
1936 else:
1937 raise util.Abort(_('need repo for changelog dag'))
1937 raise util.Abort(_('need repo for changelog dag'))
1938
1938
1939 for line in dagparser.dagtextlines(events(),
1939 for line in dagparser.dagtextlines(events(),
1940 addspaces=spaces,
1940 addspaces=spaces,
1941 wraplabels=True,
1941 wraplabels=True,
1942 wrapannotations=True,
1942 wrapannotations=True,
1943 wrapnonlinear=dots,
1943 wrapnonlinear=dots,
1944 usedots=dots,
1944 usedots=dots,
1945 maxlinewidth=70):
1945 maxlinewidth=70):
1946 ui.write(line)
1946 ui.write(line)
1947 ui.write("\n")
1947 ui.write("\n")
1948
1948
1949 @command('debugdata',
1949 @command('debugdata',
1950 [('c', 'changelog', False, _('open changelog')),
1950 [('c', 'changelog', False, _('open changelog')),
1951 ('m', 'manifest', False, _('open manifest'))],
1951 ('m', 'manifest', False, _('open manifest'))],
1952 _('-c|-m|FILE REV'))
1952 _('-c|-m|FILE REV'))
1953 def debugdata(ui, repo, file_, rev=None, **opts):
1953 def debugdata(ui, repo, file_, rev=None, **opts):
1954 """dump the contents of a data file revision"""
1954 """dump the contents of a data file revision"""
1955 if opts.get('changelog') or opts.get('manifest'):
1955 if opts.get('changelog') or opts.get('manifest'):
1956 file_, rev = None, file_
1956 file_, rev = None, file_
1957 elif rev is None:
1957 elif rev is None:
1958 raise error.CommandError('debugdata', _('invalid arguments'))
1958 raise error.CommandError('debugdata', _('invalid arguments'))
1959 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1959 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1960 try:
1960 try:
1961 ui.write(r.revision(r.lookup(rev)))
1961 ui.write(r.revision(r.lookup(rev)))
1962 except KeyError:
1962 except KeyError:
1963 raise util.Abort(_('invalid revision identifier %s') % rev)
1963 raise util.Abort(_('invalid revision identifier %s') % rev)
1964
1964
1965 @command('debugdate',
1965 @command('debugdate',
1966 [('e', 'extended', None, _('try extended date formats'))],
1966 [('e', 'extended', None, _('try extended date formats'))],
1967 _('[-e] DATE [RANGE]'),
1967 _('[-e] DATE [RANGE]'),
1968 norepo=True, optionalrepo=True)
1968 norepo=True, optionalrepo=True)
1969 def debugdate(ui, date, range=None, **opts):
1969 def debugdate(ui, date, range=None, **opts):
1970 """parse and display a date"""
1970 """parse and display a date"""
1971 if opts["extended"]:
1971 if opts["extended"]:
1972 d = util.parsedate(date, util.extendeddateformats)
1972 d = util.parsedate(date, util.extendeddateformats)
1973 else:
1973 else:
1974 d = util.parsedate(date)
1974 d = util.parsedate(date)
1975 ui.write(("internal: %s %s\n") % d)
1975 ui.write(("internal: %s %s\n") % d)
1976 ui.write(("standard: %s\n") % util.datestr(d))
1976 ui.write(("standard: %s\n") % util.datestr(d))
1977 if range:
1977 if range:
1978 m = util.matchdate(range)
1978 m = util.matchdate(range)
1979 ui.write(("match: %s\n") % m(d[0]))
1979 ui.write(("match: %s\n") % m(d[0]))
1980
1980
1981 @command('debugdiscovery',
1981 @command('debugdiscovery',
1982 [('', 'old', None, _('use old-style discovery')),
1982 [('', 'old', None, _('use old-style discovery')),
1983 ('', 'nonheads', None,
1983 ('', 'nonheads', None,
1984 _('use old-style discovery with non-heads included')),
1984 _('use old-style discovery with non-heads included')),
1985 ] + remoteopts,
1985 ] + remoteopts,
1986 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1986 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1987 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1987 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1988 """runs the changeset discovery protocol in isolation"""
1988 """runs the changeset discovery protocol in isolation"""
1989 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1989 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1990 opts.get('branch'))
1990 opts.get('branch'))
1991 remote = hg.peer(repo, opts, remoteurl)
1991 remote = hg.peer(repo, opts, remoteurl)
1992 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1992 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1993
1993
1994 # make sure tests are repeatable
1994 # make sure tests are repeatable
1995 random.seed(12323)
1995 random.seed(12323)
1996
1996
1997 def doit(localheads, remoteheads, remote=remote):
1997 def doit(localheads, remoteheads, remote=remote):
1998 if opts.get('old'):
1998 if opts.get('old'):
1999 if localheads:
1999 if localheads:
2000 raise util.Abort('cannot use localheads with old style '
2000 raise util.Abort('cannot use localheads with old style '
2001 'discovery')
2001 'discovery')
2002 if not util.safehasattr(remote, 'branches'):
2002 if not util.safehasattr(remote, 'branches'):
2003 # enable in-client legacy support
2003 # enable in-client legacy support
2004 remote = localrepo.locallegacypeer(remote.local())
2004 remote = localrepo.locallegacypeer(remote.local())
2005 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2005 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2006 force=True)
2006 force=True)
2007 common = set(common)
2007 common = set(common)
2008 if not opts.get('nonheads'):
2008 if not opts.get('nonheads'):
2009 ui.write(("unpruned common: %s\n") %
2009 ui.write(("unpruned common: %s\n") %
2010 " ".join(sorted(short(n) for n in common)))
2010 " ".join(sorted(short(n) for n in common)))
2011 dag = dagutil.revlogdag(repo.changelog)
2011 dag = dagutil.revlogdag(repo.changelog)
2012 all = dag.ancestorset(dag.internalizeall(common))
2012 all = dag.ancestorset(dag.internalizeall(common))
2013 common = dag.externalizeall(dag.headsetofconnecteds(all))
2013 common = dag.externalizeall(dag.headsetofconnecteds(all))
2014 else:
2014 else:
2015 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2015 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2016 common = set(common)
2016 common = set(common)
2017 rheads = set(hds)
2017 rheads = set(hds)
2018 lheads = set(repo.heads())
2018 lheads = set(repo.heads())
2019 ui.write(("common heads: %s\n") %
2019 ui.write(("common heads: %s\n") %
2020 " ".join(sorted(short(n) for n in common)))
2020 " ".join(sorted(short(n) for n in common)))
2021 if lheads <= common:
2021 if lheads <= common:
2022 ui.write(("local is subset\n"))
2022 ui.write(("local is subset\n"))
2023 elif rheads <= common:
2023 elif rheads <= common:
2024 ui.write(("remote is subset\n"))
2024 ui.write(("remote is subset\n"))
2025
2025
2026 serverlogs = opts.get('serverlog')
2026 serverlogs = opts.get('serverlog')
2027 if serverlogs:
2027 if serverlogs:
2028 for filename in serverlogs:
2028 for filename in serverlogs:
2029 logfile = open(filename, 'r')
2029 logfile = open(filename, 'r')
2030 try:
2030 try:
2031 line = logfile.readline()
2031 line = logfile.readline()
2032 while line:
2032 while line:
2033 parts = line.strip().split(';')
2033 parts = line.strip().split(';')
2034 op = parts[1]
2034 op = parts[1]
2035 if op == 'cg':
2035 if op == 'cg':
2036 pass
2036 pass
2037 elif op == 'cgss':
2037 elif op == 'cgss':
2038 doit(parts[2].split(' '), parts[3].split(' '))
2038 doit(parts[2].split(' '), parts[3].split(' '))
2039 elif op == 'unb':
2039 elif op == 'unb':
2040 doit(parts[3].split(' '), parts[2].split(' '))
2040 doit(parts[3].split(' '), parts[2].split(' '))
2041 line = logfile.readline()
2041 line = logfile.readline()
2042 finally:
2042 finally:
2043 logfile.close()
2043 logfile.close()
2044
2044
2045 else:
2045 else:
2046 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2046 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2047 opts.get('remote_head'))
2047 opts.get('remote_head'))
2048 localrevs = opts.get('local_head')
2048 localrevs = opts.get('local_head')
2049 doit(localrevs, remoterevs)
2049 doit(localrevs, remoterevs)
2050
2050
2051 @command('debugfileset',
2051 @command('debugfileset',
2052 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2052 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2053 _('[-r REV] FILESPEC'))
2053 _('[-r REV] FILESPEC'))
2054 def debugfileset(ui, repo, expr, **opts):
2054 def debugfileset(ui, repo, expr, **opts):
2055 '''parse and apply a fileset specification'''
2055 '''parse and apply a fileset specification'''
2056 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2056 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2057 if ui.verbose:
2057 if ui.verbose:
2058 tree = fileset.parse(expr)[0]
2058 tree = fileset.parse(expr)[0]
2059 ui.note(tree, "\n")
2059 ui.note(tree, "\n")
2060
2060
2061 for f in ctx.getfileset(expr):
2061 for f in ctx.getfileset(expr):
2062 ui.write("%s\n" % f)
2062 ui.write("%s\n" % f)
2063
2063
2064 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2064 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2065 def debugfsinfo(ui, path="."):
2065 def debugfsinfo(ui, path="."):
2066 """show information detected about current filesystem"""
2066 """show information detected about current filesystem"""
2067 util.writefile('.debugfsinfo', '')
2067 util.writefile('.debugfsinfo', '')
2068 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2068 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2069 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2069 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2070 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2070 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2071 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2071 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2072 and 'yes' or 'no'))
2072 and 'yes' or 'no'))
2073 os.unlink('.debugfsinfo')
2073 os.unlink('.debugfsinfo')
2074
2074
2075 @command('debuggetbundle',
2075 @command('debuggetbundle',
2076 [('H', 'head', [], _('id of head node'), _('ID')),
2076 [('H', 'head', [], _('id of head node'), _('ID')),
2077 ('C', 'common', [], _('id of common node'), _('ID')),
2077 ('C', 'common', [], _('id of common node'), _('ID')),
2078 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2078 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2079 _('REPO FILE [-H|-C ID]...'),
2079 _('REPO FILE [-H|-C ID]...'),
2080 norepo=True)
2080 norepo=True)
2081 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2081 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2082 """retrieves a bundle from a repo
2082 """retrieves a bundle from a repo
2083
2083
2084 Every ID must be a full-length hex node id string. Saves the bundle to the
2084 Every ID must be a full-length hex node id string. Saves the bundle to the
2085 given file.
2085 given file.
2086 """
2086 """
2087 repo = hg.peer(ui, opts, repopath)
2087 repo = hg.peer(ui, opts, repopath)
2088 if not repo.capable('getbundle'):
2088 if not repo.capable('getbundle'):
2089 raise util.Abort("getbundle() not supported by target repository")
2089 raise util.Abort("getbundle() not supported by target repository")
2090 args = {}
2090 args = {}
2091 if common:
2091 if common:
2092 args['common'] = [bin(s) for s in common]
2092 args['common'] = [bin(s) for s in common]
2093 if head:
2093 if head:
2094 args['heads'] = [bin(s) for s in head]
2094 args['heads'] = [bin(s) for s in head]
2095 # TODO: get desired bundlecaps from command line.
2095 # TODO: get desired bundlecaps from command line.
2096 args['bundlecaps'] = None
2096 args['bundlecaps'] = None
2097 bundle = repo.getbundle('debug', **args)
2097 bundle = repo.getbundle('debug', **args)
2098
2098
2099 bundletype = opts.get('type', 'bzip2').lower()
2099 bundletype = opts.get('type', 'bzip2').lower()
2100 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2100 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2101 bundletype = btypes.get(bundletype)
2101 bundletype = btypes.get(bundletype)
2102 if bundletype not in changegroup.bundletypes:
2102 if bundletype not in changegroup.bundletypes:
2103 raise util.Abort(_('unknown bundle type specified with --type'))
2103 raise util.Abort(_('unknown bundle type specified with --type'))
2104 changegroup.writebundle(bundle, bundlepath, bundletype)
2104 changegroup.writebundle(bundle, bundlepath, bundletype)
2105
2105
2106 @command('debugignore', [], '')
2106 @command('debugignore', [], '')
2107 def debugignore(ui, repo, *values, **opts):
2107 def debugignore(ui, repo, *values, **opts):
2108 """display the combined ignore pattern"""
2108 """display the combined ignore pattern"""
2109 ignore = repo.dirstate._ignore
2109 ignore = repo.dirstate._ignore
2110 includepat = getattr(ignore, 'includepat', None)
2110 includepat = getattr(ignore, 'includepat', None)
2111 if includepat is not None:
2111 if includepat is not None:
2112 ui.write("%s\n" % includepat)
2112 ui.write("%s\n" % includepat)
2113 else:
2113 else:
2114 raise util.Abort(_("no ignore patterns found"))
2114 raise util.Abort(_("no ignore patterns found"))
2115
2115
2116 @command('debugindex',
2116 @command('debugindex',
2117 [('c', 'changelog', False, _('open changelog')),
2117 [('c', 'changelog', False, _('open changelog')),
2118 ('m', 'manifest', False, _('open manifest')),
2118 ('m', 'manifest', False, _('open manifest')),
2119 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2119 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2120 _('[-f FORMAT] -c|-m|FILE'),
2120 _('[-f FORMAT] -c|-m|FILE'),
2121 optionalrepo=True)
2121 optionalrepo=True)
2122 def debugindex(ui, repo, file_=None, **opts):
2122 def debugindex(ui, repo, file_=None, **opts):
2123 """dump the contents of an index file"""
2123 """dump the contents of an index file"""
2124 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2124 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2125 format = opts.get('format', 0)
2125 format = opts.get('format', 0)
2126 if format not in (0, 1):
2126 if format not in (0, 1):
2127 raise util.Abort(_("unknown format %d") % format)
2127 raise util.Abort(_("unknown format %d") % format)
2128
2128
2129 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2129 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2130 if generaldelta:
2130 if generaldelta:
2131 basehdr = ' delta'
2131 basehdr = ' delta'
2132 else:
2132 else:
2133 basehdr = ' base'
2133 basehdr = ' base'
2134
2134
2135 if format == 0:
2135 if format == 0:
2136 ui.write(" rev offset length " + basehdr + " linkrev"
2136 ui.write(" rev offset length " + basehdr + " linkrev"
2137 " nodeid p1 p2\n")
2137 " nodeid p1 p2\n")
2138 elif format == 1:
2138 elif format == 1:
2139 ui.write(" rev flag offset length"
2139 ui.write(" rev flag offset length"
2140 " size " + basehdr + " link p1 p2"
2140 " size " + basehdr + " link p1 p2"
2141 " nodeid\n")
2141 " nodeid\n")
2142
2142
2143 for i in r:
2143 for i in r:
2144 node = r.node(i)
2144 node = r.node(i)
2145 if generaldelta:
2145 if generaldelta:
2146 base = r.deltaparent(i)
2146 base = r.deltaparent(i)
2147 else:
2147 else:
2148 base = r.chainbase(i)
2148 base = r.chainbase(i)
2149 if format == 0:
2149 if format == 0:
2150 try:
2150 try:
2151 pp = r.parents(node)
2151 pp = r.parents(node)
2152 except Exception:
2152 except Exception:
2153 pp = [nullid, nullid]
2153 pp = [nullid, nullid]
2154 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2154 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2155 i, r.start(i), r.length(i), base, r.linkrev(i),
2155 i, r.start(i), r.length(i), base, r.linkrev(i),
2156 short(node), short(pp[0]), short(pp[1])))
2156 short(node), short(pp[0]), short(pp[1])))
2157 elif format == 1:
2157 elif format == 1:
2158 pr = r.parentrevs(i)
2158 pr = r.parentrevs(i)
2159 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2159 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2160 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2160 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2161 base, r.linkrev(i), pr[0], pr[1], short(node)))
2161 base, r.linkrev(i), pr[0], pr[1], short(node)))
2162
2162
2163 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2163 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2164 def debugindexdot(ui, repo, file_):
2164 def debugindexdot(ui, repo, file_):
2165 """dump an index DAG as a graphviz dot file"""
2165 """dump an index DAG as a graphviz dot file"""
2166 r = None
2166 r = None
2167 if repo:
2167 if repo:
2168 filelog = repo.file(file_)
2168 filelog = repo.file(file_)
2169 if len(filelog):
2169 if len(filelog):
2170 r = filelog
2170 r = filelog
2171 if not r:
2171 if not r:
2172 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2172 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2173 ui.write(("digraph G {\n"))
2173 ui.write(("digraph G {\n"))
2174 for i in r:
2174 for i in r:
2175 node = r.node(i)
2175 node = r.node(i)
2176 pp = r.parents(node)
2176 pp = r.parents(node)
2177 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2177 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2178 if pp[1] != nullid:
2178 if pp[1] != nullid:
2179 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2179 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2180 ui.write("}\n")
2180 ui.write("}\n")
2181
2181
2182 @command('debuginstall', [], '', norepo=True)
2182 @command('debuginstall', [], '', norepo=True)
2183 def debuginstall(ui):
2183 def debuginstall(ui):
2184 '''test Mercurial installation
2184 '''test Mercurial installation
2185
2185
2186 Returns 0 on success.
2186 Returns 0 on success.
2187 '''
2187 '''
2188
2188
2189 def writetemp(contents):
2189 def writetemp(contents):
2190 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2190 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2191 f = os.fdopen(fd, "wb")
2191 f = os.fdopen(fd, "wb")
2192 f.write(contents)
2192 f.write(contents)
2193 f.close()
2193 f.close()
2194 return name
2194 return name
2195
2195
2196 problems = 0
2196 problems = 0
2197
2197
2198 # encoding
2198 # encoding
2199 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2199 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2200 try:
2200 try:
2201 encoding.fromlocal("test")
2201 encoding.fromlocal("test")
2202 except util.Abort, inst:
2202 except util.Abort, inst:
2203 ui.write(" %s\n" % inst)
2203 ui.write(" %s\n" % inst)
2204 ui.write(_(" (check that your locale is properly set)\n"))
2204 ui.write(_(" (check that your locale is properly set)\n"))
2205 problems += 1
2205 problems += 1
2206
2206
2207 # Python
2207 # Python
2208 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2208 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2209 ui.status(_("checking Python version (%s)\n")
2209 ui.status(_("checking Python version (%s)\n")
2210 % ("%s.%s.%s" % sys.version_info[:3]))
2210 % ("%s.%s.%s" % sys.version_info[:3]))
2211 ui.status(_("checking Python lib (%s)...\n")
2211 ui.status(_("checking Python lib (%s)...\n")
2212 % os.path.dirname(os.__file__))
2212 % os.path.dirname(os.__file__))
2213
2213
2214 # compiled modules
2214 # compiled modules
2215 ui.status(_("checking installed modules (%s)...\n")
2215 ui.status(_("checking installed modules (%s)...\n")
2216 % os.path.dirname(__file__))
2216 % os.path.dirname(__file__))
2217 try:
2217 try:
2218 import bdiff, mpatch, base85, osutil
2218 import bdiff, mpatch, base85, osutil
2219 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2219 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2220 except Exception, inst:
2220 except Exception, inst:
2221 ui.write(" %s\n" % inst)
2221 ui.write(" %s\n" % inst)
2222 ui.write(_(" One or more extensions could not be found"))
2222 ui.write(_(" One or more extensions could not be found"))
2223 ui.write(_(" (check that you compiled the extensions)\n"))
2223 ui.write(_(" (check that you compiled the extensions)\n"))
2224 problems += 1
2224 problems += 1
2225
2225
2226 # templates
2226 # templates
2227 import templater
2227 import templater
2228 p = templater.templatepath()
2228 p = templater.templatepath()
2229 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2229 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2230 if p:
2230 if p:
2231 m = templater.templatepath("map-cmdline.default")
2231 m = templater.templatepath("map-cmdline.default")
2232 if m:
2232 if m:
2233 # template found, check if it is working
2233 # template found, check if it is working
2234 try:
2234 try:
2235 templater.templater(m)
2235 templater.templater(m)
2236 except Exception, inst:
2236 except Exception, inst:
2237 ui.write(" %s\n" % inst)
2237 ui.write(" %s\n" % inst)
2238 p = None
2238 p = None
2239 else:
2239 else:
2240 ui.write(_(" template 'default' not found\n"))
2240 ui.write(_(" template 'default' not found\n"))
2241 p = None
2241 p = None
2242 else:
2242 else:
2243 ui.write(_(" no template directories found\n"))
2243 ui.write(_(" no template directories found\n"))
2244 if not p:
2244 if not p:
2245 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2245 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2246 problems += 1
2246 problems += 1
2247
2247
2248 # editor
2248 # editor
2249 ui.status(_("checking commit editor...\n"))
2249 ui.status(_("checking commit editor...\n"))
2250 editor = ui.geteditor()
2250 editor = ui.geteditor()
2251 cmdpath = util.findexe(shlex.split(editor)[0])
2251 cmdpath = util.findexe(shlex.split(editor)[0])
2252 if not cmdpath:
2252 if not cmdpath:
2253 if editor == 'vi':
2253 if editor == 'vi':
2254 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2254 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2255 ui.write(_(" (specify a commit editor in your configuration"
2255 ui.write(_(" (specify a commit editor in your configuration"
2256 " file)\n"))
2256 " file)\n"))
2257 else:
2257 else:
2258 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2258 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2259 ui.write(_(" (specify a commit editor in your configuration"
2259 ui.write(_(" (specify a commit editor in your configuration"
2260 " file)\n"))
2260 " file)\n"))
2261 problems += 1
2261 problems += 1
2262
2262
2263 # check username
2263 # check username
2264 ui.status(_("checking username...\n"))
2264 ui.status(_("checking username...\n"))
2265 try:
2265 try:
2266 ui.username()
2266 ui.username()
2267 except util.Abort, e:
2267 except util.Abort, e:
2268 ui.write(" %s\n" % e)
2268 ui.write(" %s\n" % e)
2269 ui.write(_(" (specify a username in your configuration file)\n"))
2269 ui.write(_(" (specify a username in your configuration file)\n"))
2270 problems += 1
2270 problems += 1
2271
2271
2272 if not problems:
2272 if not problems:
2273 ui.status(_("no problems detected\n"))
2273 ui.status(_("no problems detected\n"))
2274 else:
2274 else:
2275 ui.write(_("%s problems detected,"
2275 ui.write(_("%s problems detected,"
2276 " please check your install!\n") % problems)
2276 " please check your install!\n") % problems)
2277
2277
2278 return problems
2278 return problems
2279
2279
2280 @command('debugknown', [], _('REPO ID...'), norepo=True)
2280 @command('debugknown', [], _('REPO ID...'), norepo=True)
2281 def debugknown(ui, repopath, *ids, **opts):
2281 def debugknown(ui, repopath, *ids, **opts):
2282 """test whether node ids are known to a repo
2282 """test whether node ids are known to a repo
2283
2283
2284 Every ID must be a full-length hex node id string. Returns a list of 0s
2284 Every ID must be a full-length hex node id string. Returns a list of 0s
2285 and 1s indicating unknown/known.
2285 and 1s indicating unknown/known.
2286 """
2286 """
2287 repo = hg.peer(ui, opts, repopath)
2287 repo = hg.peer(ui, opts, repopath)
2288 if not repo.capable('known'):
2288 if not repo.capable('known'):
2289 raise util.Abort("known() not supported by target repository")
2289 raise util.Abort("known() not supported by target repository")
2290 flags = repo.known([bin(s) for s in ids])
2290 flags = repo.known([bin(s) for s in ids])
2291 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2291 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2292
2292
2293 @command('debuglabelcomplete', [], _('LABEL...'))
2293 @command('debuglabelcomplete', [], _('LABEL...'))
2294 def debuglabelcomplete(ui, repo, *args):
2294 def debuglabelcomplete(ui, repo, *args):
2295 '''complete "labels" - tags, open branch names, bookmark names'''
2295 '''complete "labels" - tags, open branch names, bookmark names'''
2296
2296
2297 labels = set()
2297 labels = set()
2298 labels.update(t[0] for t in repo.tagslist())
2298 labels.update(t[0] for t in repo.tagslist())
2299 labels.update(repo._bookmarks.keys())
2299 labels.update(repo._bookmarks.keys())
2300 labels.update(tag for (tag, heads, tip, closed)
2300 labels.update(tag for (tag, heads, tip, closed)
2301 in repo.branchmap().iterbranches() if not closed)
2301 in repo.branchmap().iterbranches() if not closed)
2302 completions = set()
2302 completions = set()
2303 if not args:
2303 if not args:
2304 args = ['']
2304 args = ['']
2305 for a in args:
2305 for a in args:
2306 completions.update(l for l in labels if l.startswith(a))
2306 completions.update(l for l in labels if l.startswith(a))
2307 ui.write('\n'.join(sorted(completions)))
2307 ui.write('\n'.join(sorted(completions)))
2308 ui.write('\n')
2308 ui.write('\n')
2309
2309
2310 @command('debugobsolete',
2310 @command('debugobsolete',
2311 [('', 'flags', 0, _('markers flag')),
2311 [('', 'flags', 0, _('markers flag')),
2312 ] + commitopts2,
2312 ] + commitopts2,
2313 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2313 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2314 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2314 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2315 """create arbitrary obsolete marker
2315 """create arbitrary obsolete marker
2316
2316
2317 With no arguments, displays the list of obsolescence markers."""
2317 With no arguments, displays the list of obsolescence markers."""
2318
2318
2319 def parsenodeid(s):
2319 def parsenodeid(s):
2320 try:
2320 try:
2321 # We do not use revsingle/revrange functions here to accept
2321 # We do not use revsingle/revrange functions here to accept
2322 # arbitrary node identifiers, possibly not present in the
2322 # arbitrary node identifiers, possibly not present in the
2323 # local repository.
2323 # local repository.
2324 n = bin(s)
2324 n = bin(s)
2325 if len(n) != len(nullid):
2325 if len(n) != len(nullid):
2326 raise TypeError()
2326 raise TypeError()
2327 return n
2327 return n
2328 except TypeError:
2328 except TypeError:
2329 raise util.Abort('changeset references must be full hexadecimal '
2329 raise util.Abort('changeset references must be full hexadecimal '
2330 'node identifiers')
2330 'node identifiers')
2331
2331
2332 if precursor is not None:
2332 if precursor is not None:
2333 metadata = {}
2333 metadata = {}
2334 if 'date' in opts:
2335 metadata['date'] = opts['date']
2336 metadata['user'] = opts['user'] or ui.username()
2334 metadata['user'] = opts['user'] or ui.username()
2337 succs = tuple(parsenodeid(succ) for succ in successors)
2335 succs = tuple(parsenodeid(succ) for succ in successors)
2338 l = repo.lock()
2336 l = repo.lock()
2339 try:
2337 try:
2340 tr = repo.transaction('debugobsolete')
2338 tr = repo.transaction('debugobsolete')
2341 try:
2339 try:
2342 try:
2340 try:
2341 date = opts.get('date')
2342 if date:
2343 date = util.parsedate(date)
2344 else:
2345 date = None
2343 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2346 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2344 opts['flags'], metadata=metadata)
2347 opts['flags'], date=date,
2348 metadata=metadata)
2345 tr.close()
2349 tr.close()
2346 except ValueError, exc:
2350 except ValueError, exc:
2347 raise util.Abort(_('bad obsmarker input: %s') % exc)
2351 raise util.Abort(_('bad obsmarker input: %s') % exc)
2348 finally:
2352 finally:
2349 tr.release()
2353 tr.release()
2350 finally:
2354 finally:
2351 l.release()
2355 l.release()
2352 else:
2356 else:
2353 for m in obsolete.allmarkers(repo):
2357 for m in obsolete.allmarkers(repo):
2354 cmdutil.showmarker(ui, m)
2358 cmdutil.showmarker(ui, m)
2355
2359
2356 @command('debugpathcomplete',
2360 @command('debugpathcomplete',
2357 [('f', 'full', None, _('complete an entire path')),
2361 [('f', 'full', None, _('complete an entire path')),
2358 ('n', 'normal', None, _('show only normal files')),
2362 ('n', 'normal', None, _('show only normal files')),
2359 ('a', 'added', None, _('show only added files')),
2363 ('a', 'added', None, _('show only added files')),
2360 ('r', 'removed', None, _('show only removed files'))],
2364 ('r', 'removed', None, _('show only removed files'))],
2361 _('FILESPEC...'))
2365 _('FILESPEC...'))
2362 def debugpathcomplete(ui, repo, *specs, **opts):
2366 def debugpathcomplete(ui, repo, *specs, **opts):
2363 '''complete part or all of a tracked path
2367 '''complete part or all of a tracked path
2364
2368
2365 This command supports shells that offer path name completion. It
2369 This command supports shells that offer path name completion. It
2366 currently completes only files already known to the dirstate.
2370 currently completes only files already known to the dirstate.
2367
2371
2368 Completion extends only to the next path segment unless
2372 Completion extends only to the next path segment unless
2369 --full is specified, in which case entire paths are used.'''
2373 --full is specified, in which case entire paths are used.'''
2370
2374
2371 def complete(path, acceptable):
2375 def complete(path, acceptable):
2372 dirstate = repo.dirstate
2376 dirstate = repo.dirstate
2373 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2377 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2374 rootdir = repo.root + os.sep
2378 rootdir = repo.root + os.sep
2375 if spec != repo.root and not spec.startswith(rootdir):
2379 if spec != repo.root and not spec.startswith(rootdir):
2376 return [], []
2380 return [], []
2377 if os.path.isdir(spec):
2381 if os.path.isdir(spec):
2378 spec += '/'
2382 spec += '/'
2379 spec = spec[len(rootdir):]
2383 spec = spec[len(rootdir):]
2380 fixpaths = os.sep != '/'
2384 fixpaths = os.sep != '/'
2381 if fixpaths:
2385 if fixpaths:
2382 spec = spec.replace(os.sep, '/')
2386 spec = spec.replace(os.sep, '/')
2383 speclen = len(spec)
2387 speclen = len(spec)
2384 fullpaths = opts['full']
2388 fullpaths = opts['full']
2385 files, dirs = set(), set()
2389 files, dirs = set(), set()
2386 adddir, addfile = dirs.add, files.add
2390 adddir, addfile = dirs.add, files.add
2387 for f, st in dirstate.iteritems():
2391 for f, st in dirstate.iteritems():
2388 if f.startswith(spec) and st[0] in acceptable:
2392 if f.startswith(spec) and st[0] in acceptable:
2389 if fixpaths:
2393 if fixpaths:
2390 f = f.replace('/', os.sep)
2394 f = f.replace('/', os.sep)
2391 if fullpaths:
2395 if fullpaths:
2392 addfile(f)
2396 addfile(f)
2393 continue
2397 continue
2394 s = f.find(os.sep, speclen)
2398 s = f.find(os.sep, speclen)
2395 if s >= 0:
2399 if s >= 0:
2396 adddir(f[:s])
2400 adddir(f[:s])
2397 else:
2401 else:
2398 addfile(f)
2402 addfile(f)
2399 return files, dirs
2403 return files, dirs
2400
2404
2401 acceptable = ''
2405 acceptable = ''
2402 if opts['normal']:
2406 if opts['normal']:
2403 acceptable += 'nm'
2407 acceptable += 'nm'
2404 if opts['added']:
2408 if opts['added']:
2405 acceptable += 'a'
2409 acceptable += 'a'
2406 if opts['removed']:
2410 if opts['removed']:
2407 acceptable += 'r'
2411 acceptable += 'r'
2408 cwd = repo.getcwd()
2412 cwd = repo.getcwd()
2409 if not specs:
2413 if not specs:
2410 specs = ['.']
2414 specs = ['.']
2411
2415
2412 files, dirs = set(), set()
2416 files, dirs = set(), set()
2413 for spec in specs:
2417 for spec in specs:
2414 f, d = complete(spec, acceptable or 'nmar')
2418 f, d = complete(spec, acceptable or 'nmar')
2415 files.update(f)
2419 files.update(f)
2416 dirs.update(d)
2420 dirs.update(d)
2417 files.update(dirs)
2421 files.update(dirs)
2418 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2422 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2419 ui.write('\n')
2423 ui.write('\n')
2420
2424
2421 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2425 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2422 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2426 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2423 '''access the pushkey key/value protocol
2427 '''access the pushkey key/value protocol
2424
2428
2425 With two args, list the keys in the given namespace.
2429 With two args, list the keys in the given namespace.
2426
2430
2427 With five args, set a key to new if it currently is set to old.
2431 With five args, set a key to new if it currently is set to old.
2428 Reports success or failure.
2432 Reports success or failure.
2429 '''
2433 '''
2430
2434
2431 target = hg.peer(ui, {}, repopath)
2435 target = hg.peer(ui, {}, repopath)
2432 if keyinfo:
2436 if keyinfo:
2433 key, old, new = keyinfo
2437 key, old, new = keyinfo
2434 r = target.pushkey(namespace, key, old, new)
2438 r = target.pushkey(namespace, key, old, new)
2435 ui.status(str(r) + '\n')
2439 ui.status(str(r) + '\n')
2436 return not r
2440 return not r
2437 else:
2441 else:
2438 for k, v in sorted(target.listkeys(namespace).iteritems()):
2442 for k, v in sorted(target.listkeys(namespace).iteritems()):
2439 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2443 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2440 v.encode('string-escape')))
2444 v.encode('string-escape')))
2441
2445
2442 @command('debugpvec', [], _('A B'))
2446 @command('debugpvec', [], _('A B'))
2443 def debugpvec(ui, repo, a, b=None):
2447 def debugpvec(ui, repo, a, b=None):
2444 ca = scmutil.revsingle(repo, a)
2448 ca = scmutil.revsingle(repo, a)
2445 cb = scmutil.revsingle(repo, b)
2449 cb = scmutil.revsingle(repo, b)
2446 pa = pvec.ctxpvec(ca)
2450 pa = pvec.ctxpvec(ca)
2447 pb = pvec.ctxpvec(cb)
2451 pb = pvec.ctxpvec(cb)
2448 if pa == pb:
2452 if pa == pb:
2449 rel = "="
2453 rel = "="
2450 elif pa > pb:
2454 elif pa > pb:
2451 rel = ">"
2455 rel = ">"
2452 elif pa < pb:
2456 elif pa < pb:
2453 rel = "<"
2457 rel = "<"
2454 elif pa | pb:
2458 elif pa | pb:
2455 rel = "|"
2459 rel = "|"
2456 ui.write(_("a: %s\n") % pa)
2460 ui.write(_("a: %s\n") % pa)
2457 ui.write(_("b: %s\n") % pb)
2461 ui.write(_("b: %s\n") % pb)
2458 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2462 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2459 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2463 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2460 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2464 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2461 pa.distance(pb), rel))
2465 pa.distance(pb), rel))
2462
2466
2463 @command('debugrebuilddirstate|debugrebuildstate',
2467 @command('debugrebuilddirstate|debugrebuildstate',
2464 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2468 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2465 _('[-r REV]'))
2469 _('[-r REV]'))
2466 def debugrebuilddirstate(ui, repo, rev):
2470 def debugrebuilddirstate(ui, repo, rev):
2467 """rebuild the dirstate as it would look like for the given revision
2471 """rebuild the dirstate as it would look like for the given revision
2468
2472
2469 If no revision is specified the first current parent will be used.
2473 If no revision is specified the first current parent will be used.
2470
2474
2471 The dirstate will be set to the files of the given revision.
2475 The dirstate will be set to the files of the given revision.
2472 The actual working directory content or existing dirstate
2476 The actual working directory content or existing dirstate
2473 information such as adds or removes is not considered.
2477 information such as adds or removes is not considered.
2474
2478
2475 One use of this command is to make the next :hg:`status` invocation
2479 One use of this command is to make the next :hg:`status` invocation
2476 check the actual file content.
2480 check the actual file content.
2477 """
2481 """
2478 ctx = scmutil.revsingle(repo, rev)
2482 ctx = scmutil.revsingle(repo, rev)
2479 wlock = repo.wlock()
2483 wlock = repo.wlock()
2480 try:
2484 try:
2481 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2485 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2482 finally:
2486 finally:
2483 wlock.release()
2487 wlock.release()
2484
2488
2485 @command('debugrename',
2489 @command('debugrename',
2486 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2490 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2487 _('[-r REV] FILE'))
2491 _('[-r REV] FILE'))
2488 def debugrename(ui, repo, file1, *pats, **opts):
2492 def debugrename(ui, repo, file1, *pats, **opts):
2489 """dump rename information"""
2493 """dump rename information"""
2490
2494
2491 ctx = scmutil.revsingle(repo, opts.get('rev'))
2495 ctx = scmutil.revsingle(repo, opts.get('rev'))
2492 m = scmutil.match(ctx, (file1,) + pats, opts)
2496 m = scmutil.match(ctx, (file1,) + pats, opts)
2493 for abs in ctx.walk(m):
2497 for abs in ctx.walk(m):
2494 fctx = ctx[abs]
2498 fctx = ctx[abs]
2495 o = fctx.filelog().renamed(fctx.filenode())
2499 o = fctx.filelog().renamed(fctx.filenode())
2496 rel = m.rel(abs)
2500 rel = m.rel(abs)
2497 if o:
2501 if o:
2498 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2502 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2499 else:
2503 else:
2500 ui.write(_("%s not renamed\n") % rel)
2504 ui.write(_("%s not renamed\n") % rel)
2501
2505
2502 @command('debugrevlog',
2506 @command('debugrevlog',
2503 [('c', 'changelog', False, _('open changelog')),
2507 [('c', 'changelog', False, _('open changelog')),
2504 ('m', 'manifest', False, _('open manifest')),
2508 ('m', 'manifest', False, _('open manifest')),
2505 ('d', 'dump', False, _('dump index data'))],
2509 ('d', 'dump', False, _('dump index data'))],
2506 _('-c|-m|FILE'),
2510 _('-c|-m|FILE'),
2507 optionalrepo=True)
2511 optionalrepo=True)
2508 def debugrevlog(ui, repo, file_=None, **opts):
2512 def debugrevlog(ui, repo, file_=None, **opts):
2509 """show data and statistics about a revlog"""
2513 """show data and statistics about a revlog"""
2510 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2514 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2511
2515
2512 if opts.get("dump"):
2516 if opts.get("dump"):
2513 numrevs = len(r)
2517 numrevs = len(r)
2514 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2518 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2515 " rawsize totalsize compression heads\n")
2519 " rawsize totalsize compression heads\n")
2516 ts = 0
2520 ts = 0
2517 heads = set()
2521 heads = set()
2518 for rev in xrange(numrevs):
2522 for rev in xrange(numrevs):
2519 dbase = r.deltaparent(rev)
2523 dbase = r.deltaparent(rev)
2520 if dbase == -1:
2524 if dbase == -1:
2521 dbase = rev
2525 dbase = rev
2522 cbase = r.chainbase(rev)
2526 cbase = r.chainbase(rev)
2523 p1, p2 = r.parentrevs(rev)
2527 p1, p2 = r.parentrevs(rev)
2524 rs = r.rawsize(rev)
2528 rs = r.rawsize(rev)
2525 ts = ts + rs
2529 ts = ts + rs
2526 heads -= set(r.parentrevs(rev))
2530 heads -= set(r.parentrevs(rev))
2527 heads.add(rev)
2531 heads.add(rev)
2528 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2532 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
2529 (rev, p1, p2, r.start(rev), r.end(rev),
2533 (rev, p1, p2, r.start(rev), r.end(rev),
2530 r.start(dbase), r.start(cbase),
2534 r.start(dbase), r.start(cbase),
2531 r.start(p1), r.start(p2),
2535 r.start(p1), r.start(p2),
2532 rs, ts, ts / r.end(rev), len(heads)))
2536 rs, ts, ts / r.end(rev), len(heads)))
2533 return 0
2537 return 0
2534
2538
2535 v = r.version
2539 v = r.version
2536 format = v & 0xFFFF
2540 format = v & 0xFFFF
2537 flags = []
2541 flags = []
2538 gdelta = False
2542 gdelta = False
2539 if v & revlog.REVLOGNGINLINEDATA:
2543 if v & revlog.REVLOGNGINLINEDATA:
2540 flags.append('inline')
2544 flags.append('inline')
2541 if v & revlog.REVLOGGENERALDELTA:
2545 if v & revlog.REVLOGGENERALDELTA:
2542 gdelta = True
2546 gdelta = True
2543 flags.append('generaldelta')
2547 flags.append('generaldelta')
2544 if not flags:
2548 if not flags:
2545 flags = ['(none)']
2549 flags = ['(none)']
2546
2550
2547 nummerges = 0
2551 nummerges = 0
2548 numfull = 0
2552 numfull = 0
2549 numprev = 0
2553 numprev = 0
2550 nump1 = 0
2554 nump1 = 0
2551 nump2 = 0
2555 nump2 = 0
2552 numother = 0
2556 numother = 0
2553 nump1prev = 0
2557 nump1prev = 0
2554 nump2prev = 0
2558 nump2prev = 0
2555 chainlengths = []
2559 chainlengths = []
2556
2560
2557 datasize = [None, 0, 0L]
2561 datasize = [None, 0, 0L]
2558 fullsize = [None, 0, 0L]
2562 fullsize = [None, 0, 0L]
2559 deltasize = [None, 0, 0L]
2563 deltasize = [None, 0, 0L]
2560
2564
2561 def addsize(size, l):
2565 def addsize(size, l):
2562 if l[0] is None or size < l[0]:
2566 if l[0] is None or size < l[0]:
2563 l[0] = size
2567 l[0] = size
2564 if size > l[1]:
2568 if size > l[1]:
2565 l[1] = size
2569 l[1] = size
2566 l[2] += size
2570 l[2] += size
2567
2571
2568 numrevs = len(r)
2572 numrevs = len(r)
2569 for rev in xrange(numrevs):
2573 for rev in xrange(numrevs):
2570 p1, p2 = r.parentrevs(rev)
2574 p1, p2 = r.parentrevs(rev)
2571 delta = r.deltaparent(rev)
2575 delta = r.deltaparent(rev)
2572 if format > 0:
2576 if format > 0:
2573 addsize(r.rawsize(rev), datasize)
2577 addsize(r.rawsize(rev), datasize)
2574 if p2 != nullrev:
2578 if p2 != nullrev:
2575 nummerges += 1
2579 nummerges += 1
2576 size = r.length(rev)
2580 size = r.length(rev)
2577 if delta == nullrev:
2581 if delta == nullrev:
2578 chainlengths.append(0)
2582 chainlengths.append(0)
2579 numfull += 1
2583 numfull += 1
2580 addsize(size, fullsize)
2584 addsize(size, fullsize)
2581 else:
2585 else:
2582 chainlengths.append(chainlengths[delta] + 1)
2586 chainlengths.append(chainlengths[delta] + 1)
2583 addsize(size, deltasize)
2587 addsize(size, deltasize)
2584 if delta == rev - 1:
2588 if delta == rev - 1:
2585 numprev += 1
2589 numprev += 1
2586 if delta == p1:
2590 if delta == p1:
2587 nump1prev += 1
2591 nump1prev += 1
2588 elif delta == p2:
2592 elif delta == p2:
2589 nump2prev += 1
2593 nump2prev += 1
2590 elif delta == p1:
2594 elif delta == p1:
2591 nump1 += 1
2595 nump1 += 1
2592 elif delta == p2:
2596 elif delta == p2:
2593 nump2 += 1
2597 nump2 += 1
2594 elif delta != nullrev:
2598 elif delta != nullrev:
2595 numother += 1
2599 numother += 1
2596
2600
2597 # Adjust size min value for empty cases
2601 # Adjust size min value for empty cases
2598 for size in (datasize, fullsize, deltasize):
2602 for size in (datasize, fullsize, deltasize):
2599 if size[0] is None:
2603 if size[0] is None:
2600 size[0] = 0
2604 size[0] = 0
2601
2605
2602 numdeltas = numrevs - numfull
2606 numdeltas = numrevs - numfull
2603 numoprev = numprev - nump1prev - nump2prev
2607 numoprev = numprev - nump1prev - nump2prev
2604 totalrawsize = datasize[2]
2608 totalrawsize = datasize[2]
2605 datasize[2] /= numrevs
2609 datasize[2] /= numrevs
2606 fulltotal = fullsize[2]
2610 fulltotal = fullsize[2]
2607 fullsize[2] /= numfull
2611 fullsize[2] /= numfull
2608 deltatotal = deltasize[2]
2612 deltatotal = deltasize[2]
2609 if numrevs - numfull > 0:
2613 if numrevs - numfull > 0:
2610 deltasize[2] /= numrevs - numfull
2614 deltasize[2] /= numrevs - numfull
2611 totalsize = fulltotal + deltatotal
2615 totalsize = fulltotal + deltatotal
2612 avgchainlen = sum(chainlengths) / numrevs
2616 avgchainlen = sum(chainlengths) / numrevs
2613 compratio = totalrawsize / totalsize
2617 compratio = totalrawsize / totalsize
2614
2618
2615 basedfmtstr = '%%%dd\n'
2619 basedfmtstr = '%%%dd\n'
2616 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2620 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2617
2621
2618 def dfmtstr(max):
2622 def dfmtstr(max):
2619 return basedfmtstr % len(str(max))
2623 return basedfmtstr % len(str(max))
2620 def pcfmtstr(max, padding=0):
2624 def pcfmtstr(max, padding=0):
2621 return basepcfmtstr % (len(str(max)), ' ' * padding)
2625 return basepcfmtstr % (len(str(max)), ' ' * padding)
2622
2626
2623 def pcfmt(value, total):
2627 def pcfmt(value, total):
2624 return (value, 100 * float(value) / total)
2628 return (value, 100 * float(value) / total)
2625
2629
2626 ui.write(('format : %d\n') % format)
2630 ui.write(('format : %d\n') % format)
2627 ui.write(('flags : %s\n') % ', '.join(flags))
2631 ui.write(('flags : %s\n') % ', '.join(flags))
2628
2632
2629 ui.write('\n')
2633 ui.write('\n')
2630 fmt = pcfmtstr(totalsize)
2634 fmt = pcfmtstr(totalsize)
2631 fmt2 = dfmtstr(totalsize)
2635 fmt2 = dfmtstr(totalsize)
2632 ui.write(('revisions : ') + fmt2 % numrevs)
2636 ui.write(('revisions : ') + fmt2 % numrevs)
2633 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2637 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2634 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2638 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2635 ui.write(('revisions : ') + fmt2 % numrevs)
2639 ui.write(('revisions : ') + fmt2 % numrevs)
2636 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2640 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2637 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2641 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2638 ui.write(('revision size : ') + fmt2 % totalsize)
2642 ui.write(('revision size : ') + fmt2 % totalsize)
2639 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2643 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2640 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2644 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2641
2645
2642 ui.write('\n')
2646 ui.write('\n')
2643 fmt = dfmtstr(max(avgchainlen, compratio))
2647 fmt = dfmtstr(max(avgchainlen, compratio))
2644 ui.write(('avg chain length : ') + fmt % avgchainlen)
2648 ui.write(('avg chain length : ') + fmt % avgchainlen)
2645 ui.write(('compression ratio : ') + fmt % compratio)
2649 ui.write(('compression ratio : ') + fmt % compratio)
2646
2650
2647 if format > 0:
2651 if format > 0:
2648 ui.write('\n')
2652 ui.write('\n')
2649 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2653 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2650 % tuple(datasize))
2654 % tuple(datasize))
2651 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2655 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2652 % tuple(fullsize))
2656 % tuple(fullsize))
2653 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2657 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2654 % tuple(deltasize))
2658 % tuple(deltasize))
2655
2659
2656 if numdeltas > 0:
2660 if numdeltas > 0:
2657 ui.write('\n')
2661 ui.write('\n')
2658 fmt = pcfmtstr(numdeltas)
2662 fmt = pcfmtstr(numdeltas)
2659 fmt2 = pcfmtstr(numdeltas, 4)
2663 fmt2 = pcfmtstr(numdeltas, 4)
2660 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2664 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2661 if numprev > 0:
2665 if numprev > 0:
2662 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2666 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2663 numprev))
2667 numprev))
2664 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2668 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2665 numprev))
2669 numprev))
2666 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2670 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2667 numprev))
2671 numprev))
2668 if gdelta:
2672 if gdelta:
2669 ui.write(('deltas against p1 : ')
2673 ui.write(('deltas against p1 : ')
2670 + fmt % pcfmt(nump1, numdeltas))
2674 + fmt % pcfmt(nump1, numdeltas))
2671 ui.write(('deltas against p2 : ')
2675 ui.write(('deltas against p2 : ')
2672 + fmt % pcfmt(nump2, numdeltas))
2676 + fmt % pcfmt(nump2, numdeltas))
2673 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2677 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2674 numdeltas))
2678 numdeltas))
2675
2679
2676 @command('debugrevspec',
2680 @command('debugrevspec',
2677 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2681 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2678 ('REVSPEC'))
2682 ('REVSPEC'))
2679 def debugrevspec(ui, repo, expr, **opts):
2683 def debugrevspec(ui, repo, expr, **opts):
2680 """parse and apply a revision specification
2684 """parse and apply a revision specification
2681
2685
2682 Use --verbose to print the parsed tree before and after aliases
2686 Use --verbose to print the parsed tree before and after aliases
2683 expansion.
2687 expansion.
2684 """
2688 """
2685 if ui.verbose:
2689 if ui.verbose:
2686 tree = revset.parse(expr)[0]
2690 tree = revset.parse(expr)[0]
2687 ui.note(revset.prettyformat(tree), "\n")
2691 ui.note(revset.prettyformat(tree), "\n")
2688 newtree = revset.findaliases(ui, tree)
2692 newtree = revset.findaliases(ui, tree)
2689 if newtree != tree:
2693 if newtree != tree:
2690 ui.note(revset.prettyformat(newtree), "\n")
2694 ui.note(revset.prettyformat(newtree), "\n")
2691 if opts["optimize"]:
2695 if opts["optimize"]:
2692 weight, optimizedtree = revset.optimize(newtree, True)
2696 weight, optimizedtree = revset.optimize(newtree, True)
2693 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2697 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2694 func = revset.match(ui, expr)
2698 func = revset.match(ui, expr)
2695 for c in func(repo, revset.spanset(repo)):
2699 for c in func(repo, revset.spanset(repo)):
2696 ui.write("%s\n" % c)
2700 ui.write("%s\n" % c)
2697
2701
2698 @command('debugsetparents', [], _('REV1 [REV2]'))
2702 @command('debugsetparents', [], _('REV1 [REV2]'))
2699 def debugsetparents(ui, repo, rev1, rev2=None):
2703 def debugsetparents(ui, repo, rev1, rev2=None):
2700 """manually set the parents of the current working directory
2704 """manually set the parents of the current working directory
2701
2705
2702 This is useful for writing repository conversion tools, but should
2706 This is useful for writing repository conversion tools, but should
2703 be used with care.
2707 be used with care.
2704
2708
2705 Returns 0 on success.
2709 Returns 0 on success.
2706 """
2710 """
2707
2711
2708 r1 = scmutil.revsingle(repo, rev1).node()
2712 r1 = scmutil.revsingle(repo, rev1).node()
2709 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2713 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2710
2714
2711 wlock = repo.wlock()
2715 wlock = repo.wlock()
2712 try:
2716 try:
2713 repo.setparents(r1, r2)
2717 repo.setparents(r1, r2)
2714 finally:
2718 finally:
2715 wlock.release()
2719 wlock.release()
2716
2720
2717 @command('debugdirstate|debugstate',
2721 @command('debugdirstate|debugstate',
2718 [('', 'nodates', None, _('do not display the saved mtime')),
2722 [('', 'nodates', None, _('do not display the saved mtime')),
2719 ('', 'datesort', None, _('sort by saved mtime'))],
2723 ('', 'datesort', None, _('sort by saved mtime'))],
2720 _('[OPTION]...'))
2724 _('[OPTION]...'))
2721 def debugstate(ui, repo, nodates=None, datesort=None):
2725 def debugstate(ui, repo, nodates=None, datesort=None):
2722 """show the contents of the current dirstate"""
2726 """show the contents of the current dirstate"""
2723 timestr = ""
2727 timestr = ""
2724 showdate = not nodates
2728 showdate = not nodates
2725 if datesort:
2729 if datesort:
2726 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2730 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2727 else:
2731 else:
2728 keyfunc = None # sort by filename
2732 keyfunc = None # sort by filename
2729 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2733 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2730 if showdate:
2734 if showdate:
2731 if ent[3] == -1:
2735 if ent[3] == -1:
2732 # Pad or slice to locale representation
2736 # Pad or slice to locale representation
2733 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2737 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2734 time.localtime(0)))
2738 time.localtime(0)))
2735 timestr = 'unset'
2739 timestr = 'unset'
2736 timestr = (timestr[:locale_len] +
2740 timestr = (timestr[:locale_len] +
2737 ' ' * (locale_len - len(timestr)))
2741 ' ' * (locale_len - len(timestr)))
2738 else:
2742 else:
2739 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2743 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2740 time.localtime(ent[3]))
2744 time.localtime(ent[3]))
2741 if ent[1] & 020000:
2745 if ent[1] & 020000:
2742 mode = 'lnk'
2746 mode = 'lnk'
2743 else:
2747 else:
2744 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2748 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2745 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2749 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2746 for f in repo.dirstate.copies():
2750 for f in repo.dirstate.copies():
2747 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2751 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2748
2752
2749 @command('debugsub',
2753 @command('debugsub',
2750 [('r', 'rev', '',
2754 [('r', 'rev', '',
2751 _('revision to check'), _('REV'))],
2755 _('revision to check'), _('REV'))],
2752 _('[-r REV] [REV]'))
2756 _('[-r REV] [REV]'))
2753 def debugsub(ui, repo, rev=None):
2757 def debugsub(ui, repo, rev=None):
2754 ctx = scmutil.revsingle(repo, rev, None)
2758 ctx = scmutil.revsingle(repo, rev, None)
2755 for k, v in sorted(ctx.substate.items()):
2759 for k, v in sorted(ctx.substate.items()):
2756 ui.write(('path %s\n') % k)
2760 ui.write(('path %s\n') % k)
2757 ui.write((' source %s\n') % v[0])
2761 ui.write((' source %s\n') % v[0])
2758 ui.write((' revision %s\n') % v[1])
2762 ui.write((' revision %s\n') % v[1])
2759
2763
2760 @command('debugsuccessorssets',
2764 @command('debugsuccessorssets',
2761 [],
2765 [],
2762 _('[REV]'))
2766 _('[REV]'))
2763 def debugsuccessorssets(ui, repo, *revs):
2767 def debugsuccessorssets(ui, repo, *revs):
2764 """show set of successors for revision
2768 """show set of successors for revision
2765
2769
2766 A successors set of changeset A is a consistent group of revisions that
2770 A successors set of changeset A is a consistent group of revisions that
2767 succeed A. It contains non-obsolete changesets only.
2771 succeed A. It contains non-obsolete changesets only.
2768
2772
2769 In most cases a changeset A has a single successors set containing a single
2773 In most cases a changeset A has a single successors set containing a single
2770 successor (changeset A replaced by A').
2774 successor (changeset A replaced by A').
2771
2775
2772 A changeset that is made obsolete with no successors are called "pruned".
2776 A changeset that is made obsolete with no successors are called "pruned".
2773 Such changesets have no successors sets at all.
2777 Such changesets have no successors sets at all.
2774
2778
2775 A changeset that has been "split" will have a successors set containing
2779 A changeset that has been "split" will have a successors set containing
2776 more than one successor.
2780 more than one successor.
2777
2781
2778 A changeset that has been rewritten in multiple different ways is called
2782 A changeset that has been rewritten in multiple different ways is called
2779 "divergent". Such changesets have multiple successor sets (each of which
2783 "divergent". Such changesets have multiple successor sets (each of which
2780 may also be split, i.e. have multiple successors).
2784 may also be split, i.e. have multiple successors).
2781
2785
2782 Results are displayed as follows::
2786 Results are displayed as follows::
2783
2787
2784 <rev1>
2788 <rev1>
2785 <successors-1A>
2789 <successors-1A>
2786 <rev2>
2790 <rev2>
2787 <successors-2A>
2791 <successors-2A>
2788 <successors-2B1> <successors-2B2> <successors-2B3>
2792 <successors-2B1> <successors-2B2> <successors-2B3>
2789
2793
2790 Here rev2 has two possible (i.e. divergent) successors sets. The first
2794 Here rev2 has two possible (i.e. divergent) successors sets. The first
2791 holds one element, whereas the second holds three (i.e. the changeset has
2795 holds one element, whereas the second holds three (i.e. the changeset has
2792 been split).
2796 been split).
2793 """
2797 """
2794 # passed to successorssets caching computation from one call to another
2798 # passed to successorssets caching computation from one call to another
2795 cache = {}
2799 cache = {}
2796 ctx2str = str
2800 ctx2str = str
2797 node2str = short
2801 node2str = short
2798 if ui.debug():
2802 if ui.debug():
2799 def ctx2str(ctx):
2803 def ctx2str(ctx):
2800 return ctx.hex()
2804 return ctx.hex()
2801 node2str = hex
2805 node2str = hex
2802 for rev in scmutil.revrange(repo, revs):
2806 for rev in scmutil.revrange(repo, revs):
2803 ctx = repo[rev]
2807 ctx = repo[rev]
2804 ui.write('%s\n'% ctx2str(ctx))
2808 ui.write('%s\n'% ctx2str(ctx))
2805 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2809 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2806 if succsset:
2810 if succsset:
2807 ui.write(' ')
2811 ui.write(' ')
2808 ui.write(node2str(succsset[0]))
2812 ui.write(node2str(succsset[0]))
2809 for node in succsset[1:]:
2813 for node in succsset[1:]:
2810 ui.write(' ')
2814 ui.write(' ')
2811 ui.write(node2str(node))
2815 ui.write(node2str(node))
2812 ui.write('\n')
2816 ui.write('\n')
2813
2817
2814 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2818 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2815 def debugwalk(ui, repo, *pats, **opts):
2819 def debugwalk(ui, repo, *pats, **opts):
2816 """show how files match on given patterns"""
2820 """show how files match on given patterns"""
2817 m = scmutil.match(repo[None], pats, opts)
2821 m = scmutil.match(repo[None], pats, opts)
2818 items = list(repo.walk(m))
2822 items = list(repo.walk(m))
2819 if not items:
2823 if not items:
2820 return
2824 return
2821 f = lambda fn: fn
2825 f = lambda fn: fn
2822 if ui.configbool('ui', 'slash') and os.sep != '/':
2826 if ui.configbool('ui', 'slash') and os.sep != '/':
2823 f = lambda fn: util.normpath(fn)
2827 f = lambda fn: util.normpath(fn)
2824 fmt = 'f %%-%ds %%-%ds %%s' % (
2828 fmt = 'f %%-%ds %%-%ds %%s' % (
2825 max([len(abs) for abs in items]),
2829 max([len(abs) for abs in items]),
2826 max([len(m.rel(abs)) for abs in items]))
2830 max([len(m.rel(abs)) for abs in items]))
2827 for abs in items:
2831 for abs in items:
2828 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2832 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2829 ui.write("%s\n" % line.rstrip())
2833 ui.write("%s\n" % line.rstrip())
2830
2834
2831 @command('debugwireargs',
2835 @command('debugwireargs',
2832 [('', 'three', '', 'three'),
2836 [('', 'three', '', 'three'),
2833 ('', 'four', '', 'four'),
2837 ('', 'four', '', 'four'),
2834 ('', 'five', '', 'five'),
2838 ('', 'five', '', 'five'),
2835 ] + remoteopts,
2839 ] + remoteopts,
2836 _('REPO [OPTIONS]... [ONE [TWO]]'),
2840 _('REPO [OPTIONS]... [ONE [TWO]]'),
2837 norepo=True)
2841 norepo=True)
2838 def debugwireargs(ui, repopath, *vals, **opts):
2842 def debugwireargs(ui, repopath, *vals, **opts):
2839 repo = hg.peer(ui, opts, repopath)
2843 repo = hg.peer(ui, opts, repopath)
2840 for opt in remoteopts:
2844 for opt in remoteopts:
2841 del opts[opt[1]]
2845 del opts[opt[1]]
2842 args = {}
2846 args = {}
2843 for k, v in opts.iteritems():
2847 for k, v in opts.iteritems():
2844 if v:
2848 if v:
2845 args[k] = v
2849 args[k] = v
2846 # run twice to check that we don't mess up the stream for the next command
2850 # run twice to check that we don't mess up the stream for the next command
2847 res1 = repo.debugwireargs(*vals, **args)
2851 res1 = repo.debugwireargs(*vals, **args)
2848 res2 = repo.debugwireargs(*vals, **args)
2852 res2 = repo.debugwireargs(*vals, **args)
2849 ui.write("%s\n" % res1)
2853 ui.write("%s\n" % res1)
2850 if res1 != res2:
2854 if res1 != res2:
2851 ui.warn("%s\n" % res2)
2855 ui.warn("%s\n" % res2)
2852
2856
2853 @command('^diff',
2857 @command('^diff',
2854 [('r', 'rev', [], _('revision'), _('REV')),
2858 [('r', 'rev', [], _('revision'), _('REV')),
2855 ('c', 'change', '', _('change made by revision'), _('REV'))
2859 ('c', 'change', '', _('change made by revision'), _('REV'))
2856 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2860 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2857 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2861 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2858 inferrepo=True)
2862 inferrepo=True)
2859 def diff(ui, repo, *pats, **opts):
2863 def diff(ui, repo, *pats, **opts):
2860 """diff repository (or selected files)
2864 """diff repository (or selected files)
2861
2865
2862 Show differences between revisions for the specified files.
2866 Show differences between revisions for the specified files.
2863
2867
2864 Differences between files are shown using the unified diff format.
2868 Differences between files are shown using the unified diff format.
2865
2869
2866 .. note::
2870 .. note::
2867
2871
2868 diff may generate unexpected results for merges, as it will
2872 diff may generate unexpected results for merges, as it will
2869 default to comparing against the working directory's first
2873 default to comparing against the working directory's first
2870 parent changeset if no revisions are specified.
2874 parent changeset if no revisions are specified.
2871
2875
2872 When two revision arguments are given, then changes are shown
2876 When two revision arguments are given, then changes are shown
2873 between those revisions. If only one revision is specified then
2877 between those revisions. If only one revision is specified then
2874 that revision is compared to the working directory, and, when no
2878 that revision is compared to the working directory, and, when no
2875 revisions are specified, the working directory files are compared
2879 revisions are specified, the working directory files are compared
2876 to its parent.
2880 to its parent.
2877
2881
2878 Alternatively you can specify -c/--change with a revision to see
2882 Alternatively you can specify -c/--change with a revision to see
2879 the changes in that changeset relative to its first parent.
2883 the changes in that changeset relative to its first parent.
2880
2884
2881 Without the -a/--text option, diff will avoid generating diffs of
2885 Without the -a/--text option, diff will avoid generating diffs of
2882 files it detects as binary. With -a, diff will generate a diff
2886 files it detects as binary. With -a, diff will generate a diff
2883 anyway, probably with undesirable results.
2887 anyway, probably with undesirable results.
2884
2888
2885 Use the -g/--git option to generate diffs in the git extended diff
2889 Use the -g/--git option to generate diffs in the git extended diff
2886 format. For more information, read :hg:`help diffs`.
2890 format. For more information, read :hg:`help diffs`.
2887
2891
2888 .. container:: verbose
2892 .. container:: verbose
2889
2893
2890 Examples:
2894 Examples:
2891
2895
2892 - compare a file in the current working directory to its parent::
2896 - compare a file in the current working directory to its parent::
2893
2897
2894 hg diff foo.c
2898 hg diff foo.c
2895
2899
2896 - compare two historical versions of a directory, with rename info::
2900 - compare two historical versions of a directory, with rename info::
2897
2901
2898 hg diff --git -r 1.0:1.2 lib/
2902 hg diff --git -r 1.0:1.2 lib/
2899
2903
2900 - get change stats relative to the last change on some date::
2904 - get change stats relative to the last change on some date::
2901
2905
2902 hg diff --stat -r "date('may 2')"
2906 hg diff --stat -r "date('may 2')"
2903
2907
2904 - diff all newly-added files that contain a keyword::
2908 - diff all newly-added files that contain a keyword::
2905
2909
2906 hg diff "set:added() and grep(GNU)"
2910 hg diff "set:added() and grep(GNU)"
2907
2911
2908 - compare a revision and its parents::
2912 - compare a revision and its parents::
2909
2913
2910 hg diff -c 9353 # compare against first parent
2914 hg diff -c 9353 # compare against first parent
2911 hg diff -r 9353^:9353 # same using revset syntax
2915 hg diff -r 9353^:9353 # same using revset syntax
2912 hg diff -r 9353^2:9353 # compare against the second parent
2916 hg diff -r 9353^2:9353 # compare against the second parent
2913
2917
2914 Returns 0 on success.
2918 Returns 0 on success.
2915 """
2919 """
2916
2920
2917 revs = opts.get('rev')
2921 revs = opts.get('rev')
2918 change = opts.get('change')
2922 change = opts.get('change')
2919 stat = opts.get('stat')
2923 stat = opts.get('stat')
2920 reverse = opts.get('reverse')
2924 reverse = opts.get('reverse')
2921
2925
2922 if revs and change:
2926 if revs and change:
2923 msg = _('cannot specify --rev and --change at the same time')
2927 msg = _('cannot specify --rev and --change at the same time')
2924 raise util.Abort(msg)
2928 raise util.Abort(msg)
2925 elif change:
2929 elif change:
2926 node2 = scmutil.revsingle(repo, change, None).node()
2930 node2 = scmutil.revsingle(repo, change, None).node()
2927 node1 = repo[node2].p1().node()
2931 node1 = repo[node2].p1().node()
2928 else:
2932 else:
2929 node1, node2 = scmutil.revpair(repo, revs)
2933 node1, node2 = scmutil.revpair(repo, revs)
2930
2934
2931 if reverse:
2935 if reverse:
2932 node1, node2 = node2, node1
2936 node1, node2 = node2, node1
2933
2937
2934 diffopts = patch.diffopts(ui, opts)
2938 diffopts = patch.diffopts(ui, opts)
2935 m = scmutil.match(repo[node2], pats, opts)
2939 m = scmutil.match(repo[node2], pats, opts)
2936 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2940 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2937 listsubrepos=opts.get('subrepos'))
2941 listsubrepos=opts.get('subrepos'))
2938
2942
2939 @command('^export',
2943 @command('^export',
2940 [('o', 'output', '',
2944 [('o', 'output', '',
2941 _('print output to file with formatted name'), _('FORMAT')),
2945 _('print output to file with formatted name'), _('FORMAT')),
2942 ('', 'switch-parent', None, _('diff against the second parent')),
2946 ('', 'switch-parent', None, _('diff against the second parent')),
2943 ('r', 'rev', [], _('revisions to export'), _('REV')),
2947 ('r', 'rev', [], _('revisions to export'), _('REV')),
2944 ] + diffopts,
2948 ] + diffopts,
2945 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2949 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2946 def export(ui, repo, *changesets, **opts):
2950 def export(ui, repo, *changesets, **opts):
2947 """dump the header and diffs for one or more changesets
2951 """dump the header and diffs for one or more changesets
2948
2952
2949 Print the changeset header and diffs for one or more revisions.
2953 Print the changeset header and diffs for one or more revisions.
2950 If no revision is given, the parent of the working directory is used.
2954 If no revision is given, the parent of the working directory is used.
2951
2955
2952 The information shown in the changeset header is: author, date,
2956 The information shown in the changeset header is: author, date,
2953 branch name (if non-default), changeset hash, parent(s) and commit
2957 branch name (if non-default), changeset hash, parent(s) and commit
2954 comment.
2958 comment.
2955
2959
2956 .. note::
2960 .. note::
2957
2961
2958 export may generate unexpected diff output for merge
2962 export may generate unexpected diff output for merge
2959 changesets, as it will compare the merge changeset against its
2963 changesets, as it will compare the merge changeset against its
2960 first parent only.
2964 first parent only.
2961
2965
2962 Output may be to a file, in which case the name of the file is
2966 Output may be to a file, in which case the name of the file is
2963 given using a format string. The formatting rules are as follows:
2967 given using a format string. The formatting rules are as follows:
2964
2968
2965 :``%%``: literal "%" character
2969 :``%%``: literal "%" character
2966 :``%H``: changeset hash (40 hexadecimal digits)
2970 :``%H``: changeset hash (40 hexadecimal digits)
2967 :``%N``: number of patches being generated
2971 :``%N``: number of patches being generated
2968 :``%R``: changeset revision number
2972 :``%R``: changeset revision number
2969 :``%b``: basename of the exporting repository
2973 :``%b``: basename of the exporting repository
2970 :``%h``: short-form changeset hash (12 hexadecimal digits)
2974 :``%h``: short-form changeset hash (12 hexadecimal digits)
2971 :``%m``: first line of the commit message (only alphanumeric characters)
2975 :``%m``: first line of the commit message (only alphanumeric characters)
2972 :``%n``: zero-padded sequence number, starting at 1
2976 :``%n``: zero-padded sequence number, starting at 1
2973 :``%r``: zero-padded changeset revision number
2977 :``%r``: zero-padded changeset revision number
2974
2978
2975 Without the -a/--text option, export will avoid generating diffs
2979 Without the -a/--text option, export will avoid generating diffs
2976 of files it detects as binary. With -a, export will generate a
2980 of files it detects as binary. With -a, export will generate a
2977 diff anyway, probably with undesirable results.
2981 diff anyway, probably with undesirable results.
2978
2982
2979 Use the -g/--git option to generate diffs in the git extended diff
2983 Use the -g/--git option to generate diffs in the git extended diff
2980 format. See :hg:`help diffs` for more information.
2984 format. See :hg:`help diffs` for more information.
2981
2985
2982 With the --switch-parent option, the diff will be against the
2986 With the --switch-parent option, the diff will be against the
2983 second parent. It can be useful to review a merge.
2987 second parent. It can be useful to review a merge.
2984
2988
2985 .. container:: verbose
2989 .. container:: verbose
2986
2990
2987 Examples:
2991 Examples:
2988
2992
2989 - use export and import to transplant a bugfix to the current
2993 - use export and import to transplant a bugfix to the current
2990 branch::
2994 branch::
2991
2995
2992 hg export -r 9353 | hg import -
2996 hg export -r 9353 | hg import -
2993
2997
2994 - export all the changesets between two revisions to a file with
2998 - export all the changesets between two revisions to a file with
2995 rename information::
2999 rename information::
2996
3000
2997 hg export --git -r 123:150 > changes.txt
3001 hg export --git -r 123:150 > changes.txt
2998
3002
2999 - split outgoing changes into a series of patches with
3003 - split outgoing changes into a series of patches with
3000 descriptive names::
3004 descriptive names::
3001
3005
3002 hg export -r "outgoing()" -o "%n-%m.patch"
3006 hg export -r "outgoing()" -o "%n-%m.patch"
3003
3007
3004 Returns 0 on success.
3008 Returns 0 on success.
3005 """
3009 """
3006 changesets += tuple(opts.get('rev', []))
3010 changesets += tuple(opts.get('rev', []))
3007 if not changesets:
3011 if not changesets:
3008 changesets = ['.']
3012 changesets = ['.']
3009 revs = scmutil.revrange(repo, changesets)
3013 revs = scmutil.revrange(repo, changesets)
3010 if not revs:
3014 if not revs:
3011 raise util.Abort(_("export requires at least one changeset"))
3015 raise util.Abort(_("export requires at least one changeset"))
3012 if len(revs) > 1:
3016 if len(revs) > 1:
3013 ui.note(_('exporting patches:\n'))
3017 ui.note(_('exporting patches:\n'))
3014 else:
3018 else:
3015 ui.note(_('exporting patch:\n'))
3019 ui.note(_('exporting patch:\n'))
3016 cmdutil.export(repo, revs, template=opts.get('output'),
3020 cmdutil.export(repo, revs, template=opts.get('output'),
3017 switch_parent=opts.get('switch_parent'),
3021 switch_parent=opts.get('switch_parent'),
3018 opts=patch.diffopts(ui, opts))
3022 opts=patch.diffopts(ui, opts))
3019
3023
3020 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3024 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3021 def forget(ui, repo, *pats, **opts):
3025 def forget(ui, repo, *pats, **opts):
3022 """forget the specified files on the next commit
3026 """forget the specified files on the next commit
3023
3027
3024 Mark the specified files so they will no longer be tracked
3028 Mark the specified files so they will no longer be tracked
3025 after the next commit.
3029 after the next commit.
3026
3030
3027 This only removes files from the current branch, not from the
3031 This only removes files from the current branch, not from the
3028 entire project history, and it does not delete them from the
3032 entire project history, and it does not delete them from the
3029 working directory.
3033 working directory.
3030
3034
3031 To undo a forget before the next commit, see :hg:`add`.
3035 To undo a forget before the next commit, see :hg:`add`.
3032
3036
3033 .. container:: verbose
3037 .. container:: verbose
3034
3038
3035 Examples:
3039 Examples:
3036
3040
3037 - forget newly-added binary files::
3041 - forget newly-added binary files::
3038
3042
3039 hg forget "set:added() and binary()"
3043 hg forget "set:added() and binary()"
3040
3044
3041 - forget files that would be excluded by .hgignore::
3045 - forget files that would be excluded by .hgignore::
3042
3046
3043 hg forget "set:hgignore()"
3047 hg forget "set:hgignore()"
3044
3048
3045 Returns 0 on success.
3049 Returns 0 on success.
3046 """
3050 """
3047
3051
3048 if not pats:
3052 if not pats:
3049 raise util.Abort(_('no files specified'))
3053 raise util.Abort(_('no files specified'))
3050
3054
3051 m = scmutil.match(repo[None], pats, opts)
3055 m = scmutil.match(repo[None], pats, opts)
3052 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3056 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3053 return rejected and 1 or 0
3057 return rejected and 1 or 0
3054
3058
3055 @command(
3059 @command(
3056 'graft',
3060 'graft',
3057 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3061 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3058 ('c', 'continue', False, _('resume interrupted graft')),
3062 ('c', 'continue', False, _('resume interrupted graft')),
3059 ('e', 'edit', False, _('invoke editor on commit messages')),
3063 ('e', 'edit', False, _('invoke editor on commit messages')),
3060 ('', 'log', None, _('append graft info to log message')),
3064 ('', 'log', None, _('append graft info to log message')),
3061 ('f', 'force', False, _('force graft')),
3065 ('f', 'force', False, _('force graft')),
3062 ('D', 'currentdate', False,
3066 ('D', 'currentdate', False,
3063 _('record the current date as commit date')),
3067 _('record the current date as commit date')),
3064 ('U', 'currentuser', False,
3068 ('U', 'currentuser', False,
3065 _('record the current user as committer'), _('DATE'))]
3069 _('record the current user as committer'), _('DATE'))]
3066 + commitopts2 + mergetoolopts + dryrunopts,
3070 + commitopts2 + mergetoolopts + dryrunopts,
3067 _('[OPTION]... [-r] REV...'))
3071 _('[OPTION]... [-r] REV...'))
3068 def graft(ui, repo, *revs, **opts):
3072 def graft(ui, repo, *revs, **opts):
3069 '''copy changes from other branches onto the current branch
3073 '''copy changes from other branches onto the current branch
3070
3074
3071 This command uses Mercurial's merge logic to copy individual
3075 This command uses Mercurial's merge logic to copy individual
3072 changes from other branches without merging branches in the
3076 changes from other branches without merging branches in the
3073 history graph. This is sometimes known as 'backporting' or
3077 history graph. This is sometimes known as 'backporting' or
3074 'cherry-picking'. By default, graft will copy user, date, and
3078 'cherry-picking'. By default, graft will copy user, date, and
3075 description from the source changesets.
3079 description from the source changesets.
3076
3080
3077 Changesets that are ancestors of the current revision, that have
3081 Changesets that are ancestors of the current revision, that have
3078 already been grafted, or that are merges will be skipped.
3082 already been grafted, or that are merges will be skipped.
3079
3083
3080 If --log is specified, log messages will have a comment appended
3084 If --log is specified, log messages will have a comment appended
3081 of the form::
3085 of the form::
3082
3086
3083 (grafted from CHANGESETHASH)
3087 (grafted from CHANGESETHASH)
3084
3088
3085 If --force is specified, revisions will be grafted even if they
3089 If --force is specified, revisions will be grafted even if they
3086 are already ancestors of or have been grafted to the destination.
3090 are already ancestors of or have been grafted to the destination.
3087 This is useful when the revisions have since been backed out.
3091 This is useful when the revisions have since been backed out.
3088
3092
3089 If a graft merge results in conflicts, the graft process is
3093 If a graft merge results in conflicts, the graft process is
3090 interrupted so that the current merge can be manually resolved.
3094 interrupted so that the current merge can be manually resolved.
3091 Once all conflicts are addressed, the graft process can be
3095 Once all conflicts are addressed, the graft process can be
3092 continued with the -c/--continue option.
3096 continued with the -c/--continue option.
3093
3097
3094 .. note::
3098 .. note::
3095
3099
3096 The -c/--continue option does not reapply earlier options, except
3100 The -c/--continue option does not reapply earlier options, except
3097 for --force.
3101 for --force.
3098
3102
3099 .. container:: verbose
3103 .. container:: verbose
3100
3104
3101 Examples:
3105 Examples:
3102
3106
3103 - copy a single change to the stable branch and edit its description::
3107 - copy a single change to the stable branch and edit its description::
3104
3108
3105 hg update stable
3109 hg update stable
3106 hg graft --edit 9393
3110 hg graft --edit 9393
3107
3111
3108 - graft a range of changesets with one exception, updating dates::
3112 - graft a range of changesets with one exception, updating dates::
3109
3113
3110 hg graft -D "2085::2093 and not 2091"
3114 hg graft -D "2085::2093 and not 2091"
3111
3115
3112 - continue a graft after resolving conflicts::
3116 - continue a graft after resolving conflicts::
3113
3117
3114 hg graft -c
3118 hg graft -c
3115
3119
3116 - show the source of a grafted changeset::
3120 - show the source of a grafted changeset::
3117
3121
3118 hg log --debug -r .
3122 hg log --debug -r .
3119
3123
3120 See :hg:`help revisions` and :hg:`help revsets` for more about
3124 See :hg:`help revisions` and :hg:`help revsets` for more about
3121 specifying revisions.
3125 specifying revisions.
3122
3126
3123 Returns 0 on successful completion.
3127 Returns 0 on successful completion.
3124 '''
3128 '''
3125
3129
3126 revs = list(revs)
3130 revs = list(revs)
3127 revs.extend(opts['rev'])
3131 revs.extend(opts['rev'])
3128
3132
3129 if not opts.get('user') and opts.get('currentuser'):
3133 if not opts.get('user') and opts.get('currentuser'):
3130 opts['user'] = ui.username()
3134 opts['user'] = ui.username()
3131 if not opts.get('date') and opts.get('currentdate'):
3135 if not opts.get('date') and opts.get('currentdate'):
3132 opts['date'] = "%d %d" % util.makedate()
3136 opts['date'] = "%d %d" % util.makedate()
3133
3137
3134 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3138 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3135
3139
3136 cont = False
3140 cont = False
3137 if opts['continue']:
3141 if opts['continue']:
3138 cont = True
3142 cont = True
3139 if revs:
3143 if revs:
3140 raise util.Abort(_("can't specify --continue and revisions"))
3144 raise util.Abort(_("can't specify --continue and revisions"))
3141 # read in unfinished revisions
3145 # read in unfinished revisions
3142 try:
3146 try:
3143 nodes = repo.opener.read('graftstate').splitlines()
3147 nodes = repo.opener.read('graftstate').splitlines()
3144 revs = [repo[node].rev() for node in nodes]
3148 revs = [repo[node].rev() for node in nodes]
3145 except IOError, inst:
3149 except IOError, inst:
3146 if inst.errno != errno.ENOENT:
3150 if inst.errno != errno.ENOENT:
3147 raise
3151 raise
3148 raise util.Abort(_("no graft state found, can't continue"))
3152 raise util.Abort(_("no graft state found, can't continue"))
3149 else:
3153 else:
3150 cmdutil.checkunfinished(repo)
3154 cmdutil.checkunfinished(repo)
3151 cmdutil.bailifchanged(repo)
3155 cmdutil.bailifchanged(repo)
3152 if not revs:
3156 if not revs:
3153 raise util.Abort(_('no revisions specified'))
3157 raise util.Abort(_('no revisions specified'))
3154 revs = scmutil.revrange(repo, revs)
3158 revs = scmutil.revrange(repo, revs)
3155
3159
3156 # check for merges
3160 # check for merges
3157 for rev in repo.revs('%ld and merge()', revs):
3161 for rev in repo.revs('%ld and merge()', revs):
3158 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3162 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3159 revs.remove(rev)
3163 revs.remove(rev)
3160 if not revs:
3164 if not revs:
3161 return -1
3165 return -1
3162
3166
3163 # Don't check in the --continue case, in effect retaining --force across
3167 # Don't check in the --continue case, in effect retaining --force across
3164 # --continues. That's because without --force, any revisions we decided to
3168 # --continues. That's because without --force, any revisions we decided to
3165 # skip would have been filtered out here, so they wouldn't have made their
3169 # skip would have been filtered out here, so they wouldn't have made their
3166 # way to the graftstate. With --force, any revisions we would have otherwise
3170 # way to the graftstate. With --force, any revisions we would have otherwise
3167 # skipped would not have been filtered out, and if they hadn't been applied
3171 # skipped would not have been filtered out, and if they hadn't been applied
3168 # already, they'd have been in the graftstate.
3172 # already, they'd have been in the graftstate.
3169 if not (cont or opts.get('force')):
3173 if not (cont or opts.get('force')):
3170 # check for ancestors of dest branch
3174 # check for ancestors of dest branch
3171 crev = repo['.'].rev()
3175 crev = repo['.'].rev()
3172 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3176 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3173 # Cannot use x.remove(y) on smart set, this has to be a list.
3177 # Cannot use x.remove(y) on smart set, this has to be a list.
3174 # XXX make this lazy in the future
3178 # XXX make this lazy in the future
3175 revs = list(revs)
3179 revs = list(revs)
3176 # don't mutate while iterating, create a copy
3180 # don't mutate while iterating, create a copy
3177 for rev in list(revs):
3181 for rev in list(revs):
3178 if rev in ancestors:
3182 if rev in ancestors:
3179 ui.warn(_('skipping ancestor revision %s\n') % rev)
3183 ui.warn(_('skipping ancestor revision %s\n') % rev)
3180 # XXX remove on list is slow
3184 # XXX remove on list is slow
3181 revs.remove(rev)
3185 revs.remove(rev)
3182 if not revs:
3186 if not revs:
3183 return -1
3187 return -1
3184
3188
3185 # analyze revs for earlier grafts
3189 # analyze revs for earlier grafts
3186 ids = {}
3190 ids = {}
3187 for ctx in repo.set("%ld", revs):
3191 for ctx in repo.set("%ld", revs):
3188 ids[ctx.hex()] = ctx.rev()
3192 ids[ctx.hex()] = ctx.rev()
3189 n = ctx.extra().get('source')
3193 n = ctx.extra().get('source')
3190 if n:
3194 if n:
3191 ids[n] = ctx.rev()
3195 ids[n] = ctx.rev()
3192
3196
3193 # check ancestors for earlier grafts
3197 # check ancestors for earlier grafts
3194 ui.debug('scanning for duplicate grafts\n')
3198 ui.debug('scanning for duplicate grafts\n')
3195
3199
3196 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3200 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3197 ctx = repo[rev]
3201 ctx = repo[rev]
3198 n = ctx.extra().get('source')
3202 n = ctx.extra().get('source')
3199 if n in ids:
3203 if n in ids:
3200 r = repo[n].rev()
3204 r = repo[n].rev()
3201 if r in revs:
3205 if r in revs:
3202 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3206 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3203 % (r, rev))
3207 % (r, rev))
3204 revs.remove(r)
3208 revs.remove(r)
3205 elif ids[n] in revs:
3209 elif ids[n] in revs:
3206 ui.warn(_('skipping already grafted revision %s '
3210 ui.warn(_('skipping already grafted revision %s '
3207 '(%s also has origin %d)\n') % (ids[n], rev, r))
3211 '(%s also has origin %d)\n') % (ids[n], rev, r))
3208 revs.remove(ids[n])
3212 revs.remove(ids[n])
3209 elif ctx.hex() in ids:
3213 elif ctx.hex() in ids:
3210 r = ids[ctx.hex()]
3214 r = ids[ctx.hex()]
3211 ui.warn(_('skipping already grafted revision %s '
3215 ui.warn(_('skipping already grafted revision %s '
3212 '(was grafted from %d)\n') % (r, rev))
3216 '(was grafted from %d)\n') % (r, rev))
3213 revs.remove(r)
3217 revs.remove(r)
3214 if not revs:
3218 if not revs:
3215 return -1
3219 return -1
3216
3220
3217 wlock = repo.wlock()
3221 wlock = repo.wlock()
3218 try:
3222 try:
3219 current = repo['.']
3223 current = repo['.']
3220 for pos, ctx in enumerate(repo.set("%ld", revs)):
3224 for pos, ctx in enumerate(repo.set("%ld", revs)):
3221
3225
3222 ui.status(_('grafting revision %s\n') % ctx.rev())
3226 ui.status(_('grafting revision %s\n') % ctx.rev())
3223 if opts.get('dry_run'):
3227 if opts.get('dry_run'):
3224 continue
3228 continue
3225
3229
3226 source = ctx.extra().get('source')
3230 source = ctx.extra().get('source')
3227 if not source:
3231 if not source:
3228 source = ctx.hex()
3232 source = ctx.hex()
3229 extra = {'source': source}
3233 extra = {'source': source}
3230 user = ctx.user()
3234 user = ctx.user()
3231 if opts.get('user'):
3235 if opts.get('user'):
3232 user = opts['user']
3236 user = opts['user']
3233 date = ctx.date()
3237 date = ctx.date()
3234 if opts.get('date'):
3238 if opts.get('date'):
3235 date = opts['date']
3239 date = opts['date']
3236 message = ctx.description()
3240 message = ctx.description()
3237 if opts.get('log'):
3241 if opts.get('log'):
3238 message += '\n(grafted from %s)' % ctx.hex()
3242 message += '\n(grafted from %s)' % ctx.hex()
3239
3243
3240 # we don't merge the first commit when continuing
3244 # we don't merge the first commit when continuing
3241 if not cont:
3245 if not cont:
3242 # perform the graft merge with p1(rev) as 'ancestor'
3246 # perform the graft merge with p1(rev) as 'ancestor'
3243 try:
3247 try:
3244 # ui.forcemerge is an internal variable, do not document
3248 # ui.forcemerge is an internal variable, do not document
3245 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3249 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3246 'graft')
3250 'graft')
3247 stats = mergemod.update(repo, ctx.node(), True, True, False,
3251 stats = mergemod.update(repo, ctx.node(), True, True, False,
3248 ctx.p1().node(),
3252 ctx.p1().node(),
3249 labels=['local', 'graft'])
3253 labels=['local', 'graft'])
3250 finally:
3254 finally:
3251 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3255 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3252 # report any conflicts
3256 # report any conflicts
3253 if stats and stats[3] > 0:
3257 if stats and stats[3] > 0:
3254 # write out state for --continue
3258 # write out state for --continue
3255 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3259 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3256 repo.opener.write('graftstate', ''.join(nodelines))
3260 repo.opener.write('graftstate', ''.join(nodelines))
3257 raise util.Abort(
3261 raise util.Abort(
3258 _("unresolved conflicts, can't continue"),
3262 _("unresolved conflicts, can't continue"),
3259 hint=_('use hg resolve and hg graft --continue'))
3263 hint=_('use hg resolve and hg graft --continue'))
3260 else:
3264 else:
3261 cont = False
3265 cont = False
3262
3266
3263 # drop the second merge parent
3267 # drop the second merge parent
3264 repo.setparents(current.node(), nullid)
3268 repo.setparents(current.node(), nullid)
3265 repo.dirstate.write()
3269 repo.dirstate.write()
3266 # fix up dirstate for copies and renames
3270 # fix up dirstate for copies and renames
3267 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3271 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3268
3272
3269 # commit
3273 # commit
3270 node = repo.commit(text=message, user=user,
3274 node = repo.commit(text=message, user=user,
3271 date=date, extra=extra, editor=editor)
3275 date=date, extra=extra, editor=editor)
3272 if node is None:
3276 if node is None:
3273 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3277 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3274 else:
3278 else:
3275 current = repo[node]
3279 current = repo[node]
3276 finally:
3280 finally:
3277 wlock.release()
3281 wlock.release()
3278
3282
3279 # remove state when we complete successfully
3283 # remove state when we complete successfully
3280 if not opts.get('dry_run'):
3284 if not opts.get('dry_run'):
3281 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3285 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3282
3286
3283 return 0
3287 return 0
3284
3288
3285 @command('grep',
3289 @command('grep',
3286 [('0', 'print0', None, _('end fields with NUL')),
3290 [('0', 'print0', None, _('end fields with NUL')),
3287 ('', 'all', None, _('print all revisions that match')),
3291 ('', 'all', None, _('print all revisions that match')),
3288 ('a', 'text', None, _('treat all files as text')),
3292 ('a', 'text', None, _('treat all files as text')),
3289 ('f', 'follow', None,
3293 ('f', 'follow', None,
3290 _('follow changeset history,'
3294 _('follow changeset history,'
3291 ' or file history across copies and renames')),
3295 ' or file history across copies and renames')),
3292 ('i', 'ignore-case', None, _('ignore case when matching')),
3296 ('i', 'ignore-case', None, _('ignore case when matching')),
3293 ('l', 'files-with-matches', None,
3297 ('l', 'files-with-matches', None,
3294 _('print only filenames and revisions that match')),
3298 _('print only filenames and revisions that match')),
3295 ('n', 'line-number', None, _('print matching line numbers')),
3299 ('n', 'line-number', None, _('print matching line numbers')),
3296 ('r', 'rev', [],
3300 ('r', 'rev', [],
3297 _('only search files changed within revision range'), _('REV')),
3301 _('only search files changed within revision range'), _('REV')),
3298 ('u', 'user', None, _('list the author (long with -v)')),
3302 ('u', 'user', None, _('list the author (long with -v)')),
3299 ('d', 'date', None, _('list the date (short with -q)')),
3303 ('d', 'date', None, _('list the date (short with -q)')),
3300 ] + walkopts,
3304 ] + walkopts,
3301 _('[OPTION]... PATTERN [FILE]...'),
3305 _('[OPTION]... PATTERN [FILE]...'),
3302 inferrepo=True)
3306 inferrepo=True)
3303 def grep(ui, repo, pattern, *pats, **opts):
3307 def grep(ui, repo, pattern, *pats, **opts):
3304 """search for a pattern in specified files and revisions
3308 """search for a pattern in specified files and revisions
3305
3309
3306 Search revisions of files for a regular expression.
3310 Search revisions of files for a regular expression.
3307
3311
3308 This command behaves differently than Unix grep. It only accepts
3312 This command behaves differently than Unix grep. It only accepts
3309 Python/Perl regexps. It searches repository history, not the
3313 Python/Perl regexps. It searches repository history, not the
3310 working directory. It always prints the revision number in which a
3314 working directory. It always prints the revision number in which a
3311 match appears.
3315 match appears.
3312
3316
3313 By default, grep only prints output for the first revision of a
3317 By default, grep only prints output for the first revision of a
3314 file in which it finds a match. To get it to print every revision
3318 file in which it finds a match. To get it to print every revision
3315 that contains a change in match status ("-" for a match that
3319 that contains a change in match status ("-" for a match that
3316 becomes a non-match, or "+" for a non-match that becomes a match),
3320 becomes a non-match, or "+" for a non-match that becomes a match),
3317 use the --all flag.
3321 use the --all flag.
3318
3322
3319 Returns 0 if a match is found, 1 otherwise.
3323 Returns 0 if a match is found, 1 otherwise.
3320 """
3324 """
3321 reflags = re.M
3325 reflags = re.M
3322 if opts.get('ignore_case'):
3326 if opts.get('ignore_case'):
3323 reflags |= re.I
3327 reflags |= re.I
3324 try:
3328 try:
3325 regexp = util.re.compile(pattern, reflags)
3329 regexp = util.re.compile(pattern, reflags)
3326 except re.error, inst:
3330 except re.error, inst:
3327 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3331 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3328 return 1
3332 return 1
3329 sep, eol = ':', '\n'
3333 sep, eol = ':', '\n'
3330 if opts.get('print0'):
3334 if opts.get('print0'):
3331 sep = eol = '\0'
3335 sep = eol = '\0'
3332
3336
3333 getfile = util.lrucachefunc(repo.file)
3337 getfile = util.lrucachefunc(repo.file)
3334
3338
3335 def matchlines(body):
3339 def matchlines(body):
3336 begin = 0
3340 begin = 0
3337 linenum = 0
3341 linenum = 0
3338 while begin < len(body):
3342 while begin < len(body):
3339 match = regexp.search(body, begin)
3343 match = regexp.search(body, begin)
3340 if not match:
3344 if not match:
3341 break
3345 break
3342 mstart, mend = match.span()
3346 mstart, mend = match.span()
3343 linenum += body.count('\n', begin, mstart) + 1
3347 linenum += body.count('\n', begin, mstart) + 1
3344 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3348 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3345 begin = body.find('\n', mend) + 1 or len(body) + 1
3349 begin = body.find('\n', mend) + 1 or len(body) + 1
3346 lend = begin - 1
3350 lend = begin - 1
3347 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3351 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3348
3352
3349 class linestate(object):
3353 class linestate(object):
3350 def __init__(self, line, linenum, colstart, colend):
3354 def __init__(self, line, linenum, colstart, colend):
3351 self.line = line
3355 self.line = line
3352 self.linenum = linenum
3356 self.linenum = linenum
3353 self.colstart = colstart
3357 self.colstart = colstart
3354 self.colend = colend
3358 self.colend = colend
3355
3359
3356 def __hash__(self):
3360 def __hash__(self):
3357 return hash((self.linenum, self.line))
3361 return hash((self.linenum, self.line))
3358
3362
3359 def __eq__(self, other):
3363 def __eq__(self, other):
3360 return self.line == other.line
3364 return self.line == other.line
3361
3365
3362 def __iter__(self):
3366 def __iter__(self):
3363 yield (self.line[:self.colstart], '')
3367 yield (self.line[:self.colstart], '')
3364 yield (self.line[self.colstart:self.colend], 'grep.match')
3368 yield (self.line[self.colstart:self.colend], 'grep.match')
3365 rest = self.line[self.colend:]
3369 rest = self.line[self.colend:]
3366 while rest != '':
3370 while rest != '':
3367 match = regexp.search(rest)
3371 match = regexp.search(rest)
3368 if not match:
3372 if not match:
3369 yield (rest, '')
3373 yield (rest, '')
3370 break
3374 break
3371 mstart, mend = match.span()
3375 mstart, mend = match.span()
3372 yield (rest[:mstart], '')
3376 yield (rest[:mstart], '')
3373 yield (rest[mstart:mend], 'grep.match')
3377 yield (rest[mstart:mend], 'grep.match')
3374 rest = rest[mend:]
3378 rest = rest[mend:]
3375
3379
3376 matches = {}
3380 matches = {}
3377 copies = {}
3381 copies = {}
3378 def grepbody(fn, rev, body):
3382 def grepbody(fn, rev, body):
3379 matches[rev].setdefault(fn, [])
3383 matches[rev].setdefault(fn, [])
3380 m = matches[rev][fn]
3384 m = matches[rev][fn]
3381 for lnum, cstart, cend, line in matchlines(body):
3385 for lnum, cstart, cend, line in matchlines(body):
3382 s = linestate(line, lnum, cstart, cend)
3386 s = linestate(line, lnum, cstart, cend)
3383 m.append(s)
3387 m.append(s)
3384
3388
3385 def difflinestates(a, b):
3389 def difflinestates(a, b):
3386 sm = difflib.SequenceMatcher(None, a, b)
3390 sm = difflib.SequenceMatcher(None, a, b)
3387 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3391 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3388 if tag == 'insert':
3392 if tag == 'insert':
3389 for i in xrange(blo, bhi):
3393 for i in xrange(blo, bhi):
3390 yield ('+', b[i])
3394 yield ('+', b[i])
3391 elif tag == 'delete':
3395 elif tag == 'delete':
3392 for i in xrange(alo, ahi):
3396 for i in xrange(alo, ahi):
3393 yield ('-', a[i])
3397 yield ('-', a[i])
3394 elif tag == 'replace':
3398 elif tag == 'replace':
3395 for i in xrange(alo, ahi):
3399 for i in xrange(alo, ahi):
3396 yield ('-', a[i])
3400 yield ('-', a[i])
3397 for i in xrange(blo, bhi):
3401 for i in xrange(blo, bhi):
3398 yield ('+', b[i])
3402 yield ('+', b[i])
3399
3403
3400 def display(fn, ctx, pstates, states):
3404 def display(fn, ctx, pstates, states):
3401 rev = ctx.rev()
3405 rev = ctx.rev()
3402 datefunc = ui.quiet and util.shortdate or util.datestr
3406 datefunc = ui.quiet and util.shortdate or util.datestr
3403 found = False
3407 found = False
3404 @util.cachefunc
3408 @util.cachefunc
3405 def binary():
3409 def binary():
3406 flog = getfile(fn)
3410 flog = getfile(fn)
3407 return util.binary(flog.read(ctx.filenode(fn)))
3411 return util.binary(flog.read(ctx.filenode(fn)))
3408
3412
3409 if opts.get('all'):
3413 if opts.get('all'):
3410 iter = difflinestates(pstates, states)
3414 iter = difflinestates(pstates, states)
3411 else:
3415 else:
3412 iter = [('', l) for l in states]
3416 iter = [('', l) for l in states]
3413 for change, l in iter:
3417 for change, l in iter:
3414 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3418 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3415
3419
3416 if opts.get('line_number'):
3420 if opts.get('line_number'):
3417 cols.append((str(l.linenum), 'grep.linenumber'))
3421 cols.append((str(l.linenum), 'grep.linenumber'))
3418 if opts.get('all'):
3422 if opts.get('all'):
3419 cols.append((change, 'grep.change'))
3423 cols.append((change, 'grep.change'))
3420 if opts.get('user'):
3424 if opts.get('user'):
3421 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3425 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3422 if opts.get('date'):
3426 if opts.get('date'):
3423 cols.append((datefunc(ctx.date()), 'grep.date'))
3427 cols.append((datefunc(ctx.date()), 'grep.date'))
3424 for col, label in cols[:-1]:
3428 for col, label in cols[:-1]:
3425 ui.write(col, label=label)
3429 ui.write(col, label=label)
3426 ui.write(sep, label='grep.sep')
3430 ui.write(sep, label='grep.sep')
3427 ui.write(cols[-1][0], label=cols[-1][1])
3431 ui.write(cols[-1][0], label=cols[-1][1])
3428 if not opts.get('files_with_matches'):
3432 if not opts.get('files_with_matches'):
3429 ui.write(sep, label='grep.sep')
3433 ui.write(sep, label='grep.sep')
3430 if not opts.get('text') and binary():
3434 if not opts.get('text') and binary():
3431 ui.write(" Binary file matches")
3435 ui.write(" Binary file matches")
3432 else:
3436 else:
3433 for s, label in l:
3437 for s, label in l:
3434 ui.write(s, label=label)
3438 ui.write(s, label=label)
3435 ui.write(eol)
3439 ui.write(eol)
3436 found = True
3440 found = True
3437 if opts.get('files_with_matches'):
3441 if opts.get('files_with_matches'):
3438 break
3442 break
3439 return found
3443 return found
3440
3444
3441 skip = {}
3445 skip = {}
3442 revfiles = {}
3446 revfiles = {}
3443 matchfn = scmutil.match(repo[None], pats, opts)
3447 matchfn = scmutil.match(repo[None], pats, opts)
3444 found = False
3448 found = False
3445 follow = opts.get('follow')
3449 follow = opts.get('follow')
3446
3450
3447 def prep(ctx, fns):
3451 def prep(ctx, fns):
3448 rev = ctx.rev()
3452 rev = ctx.rev()
3449 pctx = ctx.p1()
3453 pctx = ctx.p1()
3450 parent = pctx.rev()
3454 parent = pctx.rev()
3451 matches.setdefault(rev, {})
3455 matches.setdefault(rev, {})
3452 matches.setdefault(parent, {})
3456 matches.setdefault(parent, {})
3453 files = revfiles.setdefault(rev, [])
3457 files = revfiles.setdefault(rev, [])
3454 for fn in fns:
3458 for fn in fns:
3455 flog = getfile(fn)
3459 flog = getfile(fn)
3456 try:
3460 try:
3457 fnode = ctx.filenode(fn)
3461 fnode = ctx.filenode(fn)
3458 except error.LookupError:
3462 except error.LookupError:
3459 continue
3463 continue
3460
3464
3461 copied = flog.renamed(fnode)
3465 copied = flog.renamed(fnode)
3462 copy = follow and copied and copied[0]
3466 copy = follow and copied and copied[0]
3463 if copy:
3467 if copy:
3464 copies.setdefault(rev, {})[fn] = copy
3468 copies.setdefault(rev, {})[fn] = copy
3465 if fn in skip:
3469 if fn in skip:
3466 if copy:
3470 if copy:
3467 skip[copy] = True
3471 skip[copy] = True
3468 continue
3472 continue
3469 files.append(fn)
3473 files.append(fn)
3470
3474
3471 if fn not in matches[rev]:
3475 if fn not in matches[rev]:
3472 grepbody(fn, rev, flog.read(fnode))
3476 grepbody(fn, rev, flog.read(fnode))
3473
3477
3474 pfn = copy or fn
3478 pfn = copy or fn
3475 if pfn not in matches[parent]:
3479 if pfn not in matches[parent]:
3476 try:
3480 try:
3477 fnode = pctx.filenode(pfn)
3481 fnode = pctx.filenode(pfn)
3478 grepbody(pfn, parent, flog.read(fnode))
3482 grepbody(pfn, parent, flog.read(fnode))
3479 except error.LookupError:
3483 except error.LookupError:
3480 pass
3484 pass
3481
3485
3482 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3486 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3483 rev = ctx.rev()
3487 rev = ctx.rev()
3484 parent = ctx.p1().rev()
3488 parent = ctx.p1().rev()
3485 for fn in sorted(revfiles.get(rev, [])):
3489 for fn in sorted(revfiles.get(rev, [])):
3486 states = matches[rev][fn]
3490 states = matches[rev][fn]
3487 copy = copies.get(rev, {}).get(fn)
3491 copy = copies.get(rev, {}).get(fn)
3488 if fn in skip:
3492 if fn in skip:
3489 if copy:
3493 if copy:
3490 skip[copy] = True
3494 skip[copy] = True
3491 continue
3495 continue
3492 pstates = matches.get(parent, {}).get(copy or fn, [])
3496 pstates = matches.get(parent, {}).get(copy or fn, [])
3493 if pstates or states:
3497 if pstates or states:
3494 r = display(fn, ctx, pstates, states)
3498 r = display(fn, ctx, pstates, states)
3495 found = found or r
3499 found = found or r
3496 if r and not opts.get('all'):
3500 if r and not opts.get('all'):
3497 skip[fn] = True
3501 skip[fn] = True
3498 if copy:
3502 if copy:
3499 skip[copy] = True
3503 skip[copy] = True
3500 del matches[rev]
3504 del matches[rev]
3501 del revfiles[rev]
3505 del revfiles[rev]
3502
3506
3503 return not found
3507 return not found
3504
3508
3505 @command('heads',
3509 @command('heads',
3506 [('r', 'rev', '',
3510 [('r', 'rev', '',
3507 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3511 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3508 ('t', 'topo', False, _('show topological heads only')),
3512 ('t', 'topo', False, _('show topological heads only')),
3509 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3513 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3510 ('c', 'closed', False, _('show normal and closed branch heads')),
3514 ('c', 'closed', False, _('show normal and closed branch heads')),
3511 ] + templateopts,
3515 ] + templateopts,
3512 _('[-ct] [-r STARTREV] [REV]...'))
3516 _('[-ct] [-r STARTREV] [REV]...'))
3513 def heads(ui, repo, *branchrevs, **opts):
3517 def heads(ui, repo, *branchrevs, **opts):
3514 """show branch heads
3518 """show branch heads
3515
3519
3516 With no arguments, show all open branch heads in the repository.
3520 With no arguments, show all open branch heads in the repository.
3517 Branch heads are changesets that have no descendants on the
3521 Branch heads are changesets that have no descendants on the
3518 same branch. They are where development generally takes place and
3522 same branch. They are where development generally takes place and
3519 are the usual targets for update and merge operations.
3523 are the usual targets for update and merge operations.
3520
3524
3521 If one or more REVs are given, only open branch heads on the
3525 If one or more REVs are given, only open branch heads on the
3522 branches associated with the specified changesets are shown. This
3526 branches associated with the specified changesets are shown. This
3523 means that you can use :hg:`heads .` to see the heads on the
3527 means that you can use :hg:`heads .` to see the heads on the
3524 currently checked-out branch.
3528 currently checked-out branch.
3525
3529
3526 If -c/--closed is specified, also show branch heads marked closed
3530 If -c/--closed is specified, also show branch heads marked closed
3527 (see :hg:`commit --close-branch`).
3531 (see :hg:`commit --close-branch`).
3528
3532
3529 If STARTREV is specified, only those heads that are descendants of
3533 If STARTREV is specified, only those heads that are descendants of
3530 STARTREV will be displayed.
3534 STARTREV will be displayed.
3531
3535
3532 If -t/--topo is specified, named branch mechanics will be ignored and only
3536 If -t/--topo is specified, named branch mechanics will be ignored and only
3533 topological heads (changesets with no children) will be shown.
3537 topological heads (changesets with no children) will be shown.
3534
3538
3535 Returns 0 if matching heads are found, 1 if not.
3539 Returns 0 if matching heads are found, 1 if not.
3536 """
3540 """
3537
3541
3538 start = None
3542 start = None
3539 if 'rev' in opts:
3543 if 'rev' in opts:
3540 start = scmutil.revsingle(repo, opts['rev'], None).node()
3544 start = scmutil.revsingle(repo, opts['rev'], None).node()
3541
3545
3542 if opts.get('topo'):
3546 if opts.get('topo'):
3543 heads = [repo[h] for h in repo.heads(start)]
3547 heads = [repo[h] for h in repo.heads(start)]
3544 else:
3548 else:
3545 heads = []
3549 heads = []
3546 for branch in repo.branchmap():
3550 for branch in repo.branchmap():
3547 heads += repo.branchheads(branch, start, opts.get('closed'))
3551 heads += repo.branchheads(branch, start, opts.get('closed'))
3548 heads = [repo[h] for h in heads]
3552 heads = [repo[h] for h in heads]
3549
3553
3550 if branchrevs:
3554 if branchrevs:
3551 branches = set(repo[br].branch() for br in branchrevs)
3555 branches = set(repo[br].branch() for br in branchrevs)
3552 heads = [h for h in heads if h.branch() in branches]
3556 heads = [h for h in heads if h.branch() in branches]
3553
3557
3554 if opts.get('active') and branchrevs:
3558 if opts.get('active') and branchrevs:
3555 dagheads = repo.heads(start)
3559 dagheads = repo.heads(start)
3556 heads = [h for h in heads if h.node() in dagheads]
3560 heads = [h for h in heads if h.node() in dagheads]
3557
3561
3558 if branchrevs:
3562 if branchrevs:
3559 haveheads = set(h.branch() for h in heads)
3563 haveheads = set(h.branch() for h in heads)
3560 if branches - haveheads:
3564 if branches - haveheads:
3561 headless = ', '.join(b for b in branches - haveheads)
3565 headless = ', '.join(b for b in branches - haveheads)
3562 msg = _('no open branch heads found on branches %s')
3566 msg = _('no open branch heads found on branches %s')
3563 if opts.get('rev'):
3567 if opts.get('rev'):
3564 msg += _(' (started at %s)') % opts['rev']
3568 msg += _(' (started at %s)') % opts['rev']
3565 ui.warn((msg + '\n') % headless)
3569 ui.warn((msg + '\n') % headless)
3566
3570
3567 if not heads:
3571 if not heads:
3568 return 1
3572 return 1
3569
3573
3570 heads = sorted(heads, key=lambda x: -x.rev())
3574 heads = sorted(heads, key=lambda x: -x.rev())
3571 displayer = cmdutil.show_changeset(ui, repo, opts)
3575 displayer = cmdutil.show_changeset(ui, repo, opts)
3572 for ctx in heads:
3576 for ctx in heads:
3573 displayer.show(ctx)
3577 displayer.show(ctx)
3574 displayer.close()
3578 displayer.close()
3575
3579
3576 @command('help',
3580 @command('help',
3577 [('e', 'extension', None, _('show only help for extensions')),
3581 [('e', 'extension', None, _('show only help for extensions')),
3578 ('c', 'command', None, _('show only help for commands')),
3582 ('c', 'command', None, _('show only help for commands')),
3579 ('k', 'keyword', '', _('show topics matching keyword')),
3583 ('k', 'keyword', '', _('show topics matching keyword')),
3580 ],
3584 ],
3581 _('[-ec] [TOPIC]'),
3585 _('[-ec] [TOPIC]'),
3582 norepo=True)
3586 norepo=True)
3583 def help_(ui, name=None, **opts):
3587 def help_(ui, name=None, **opts):
3584 """show help for a given topic or a help overview
3588 """show help for a given topic or a help overview
3585
3589
3586 With no arguments, print a list of commands with short help messages.
3590 With no arguments, print a list of commands with short help messages.
3587
3591
3588 Given a topic, extension, or command name, print help for that
3592 Given a topic, extension, or command name, print help for that
3589 topic.
3593 topic.
3590
3594
3591 Returns 0 if successful.
3595 Returns 0 if successful.
3592 """
3596 """
3593
3597
3594 textwidth = min(ui.termwidth(), 80) - 2
3598 textwidth = min(ui.termwidth(), 80) - 2
3595
3599
3596 keep = ui.verbose and ['verbose'] or []
3600 keep = ui.verbose and ['verbose'] or []
3597 text = help.help_(ui, name, **opts)
3601 text = help.help_(ui, name, **opts)
3598
3602
3599 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3603 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3600 if 'verbose' in pruned:
3604 if 'verbose' in pruned:
3601 keep.append('omitted')
3605 keep.append('omitted')
3602 else:
3606 else:
3603 keep.append('notomitted')
3607 keep.append('notomitted')
3604 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3608 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3605 ui.write(formatted)
3609 ui.write(formatted)
3606
3610
3607
3611
3608 @command('identify|id',
3612 @command('identify|id',
3609 [('r', 'rev', '',
3613 [('r', 'rev', '',
3610 _('identify the specified revision'), _('REV')),
3614 _('identify the specified revision'), _('REV')),
3611 ('n', 'num', None, _('show local revision number')),
3615 ('n', 'num', None, _('show local revision number')),
3612 ('i', 'id', None, _('show global revision id')),
3616 ('i', 'id', None, _('show global revision id')),
3613 ('b', 'branch', None, _('show branch')),
3617 ('b', 'branch', None, _('show branch')),
3614 ('t', 'tags', None, _('show tags')),
3618 ('t', 'tags', None, _('show tags')),
3615 ('B', 'bookmarks', None, _('show bookmarks')),
3619 ('B', 'bookmarks', None, _('show bookmarks')),
3616 ] + remoteopts,
3620 ] + remoteopts,
3617 _('[-nibtB] [-r REV] [SOURCE]'),
3621 _('[-nibtB] [-r REV] [SOURCE]'),
3618 optionalrepo=True)
3622 optionalrepo=True)
3619 def identify(ui, repo, source=None, rev=None,
3623 def identify(ui, repo, source=None, rev=None,
3620 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3624 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3621 """identify the working copy or specified revision
3625 """identify the working copy or specified revision
3622
3626
3623 Print a summary identifying the repository state at REV using one or
3627 Print a summary identifying the repository state at REV using one or
3624 two parent hash identifiers, followed by a "+" if the working
3628 two parent hash identifiers, followed by a "+" if the working
3625 directory has uncommitted changes, the branch name (if not default),
3629 directory has uncommitted changes, the branch name (if not default),
3626 a list of tags, and a list of bookmarks.
3630 a list of tags, and a list of bookmarks.
3627
3631
3628 When REV is not given, print a summary of the current state of the
3632 When REV is not given, print a summary of the current state of the
3629 repository.
3633 repository.
3630
3634
3631 Specifying a path to a repository root or Mercurial bundle will
3635 Specifying a path to a repository root or Mercurial bundle will
3632 cause lookup to operate on that repository/bundle.
3636 cause lookup to operate on that repository/bundle.
3633
3637
3634 .. container:: verbose
3638 .. container:: verbose
3635
3639
3636 Examples:
3640 Examples:
3637
3641
3638 - generate a build identifier for the working directory::
3642 - generate a build identifier for the working directory::
3639
3643
3640 hg id --id > build-id.dat
3644 hg id --id > build-id.dat
3641
3645
3642 - find the revision corresponding to a tag::
3646 - find the revision corresponding to a tag::
3643
3647
3644 hg id -n -r 1.3
3648 hg id -n -r 1.3
3645
3649
3646 - check the most recent revision of a remote repository::
3650 - check the most recent revision of a remote repository::
3647
3651
3648 hg id -r tip http://selenic.com/hg/
3652 hg id -r tip http://selenic.com/hg/
3649
3653
3650 Returns 0 if successful.
3654 Returns 0 if successful.
3651 """
3655 """
3652
3656
3653 if not repo and not source:
3657 if not repo and not source:
3654 raise util.Abort(_("there is no Mercurial repository here "
3658 raise util.Abort(_("there is no Mercurial repository here "
3655 "(.hg not found)"))
3659 "(.hg not found)"))
3656
3660
3657 hexfunc = ui.debugflag and hex or short
3661 hexfunc = ui.debugflag and hex or short
3658 default = not (num or id or branch or tags or bookmarks)
3662 default = not (num or id or branch or tags or bookmarks)
3659 output = []
3663 output = []
3660 revs = []
3664 revs = []
3661
3665
3662 if source:
3666 if source:
3663 source, branches = hg.parseurl(ui.expandpath(source))
3667 source, branches = hg.parseurl(ui.expandpath(source))
3664 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3668 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3665 repo = peer.local()
3669 repo = peer.local()
3666 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3670 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3667
3671
3668 if not repo:
3672 if not repo:
3669 if num or branch or tags:
3673 if num or branch or tags:
3670 raise util.Abort(
3674 raise util.Abort(
3671 _("can't query remote revision number, branch, or tags"))
3675 _("can't query remote revision number, branch, or tags"))
3672 if not rev and revs:
3676 if not rev and revs:
3673 rev = revs[0]
3677 rev = revs[0]
3674 if not rev:
3678 if not rev:
3675 rev = "tip"
3679 rev = "tip"
3676
3680
3677 remoterev = peer.lookup(rev)
3681 remoterev = peer.lookup(rev)
3678 if default or id:
3682 if default or id:
3679 output = [hexfunc(remoterev)]
3683 output = [hexfunc(remoterev)]
3680
3684
3681 def getbms():
3685 def getbms():
3682 bms = []
3686 bms = []
3683
3687
3684 if 'bookmarks' in peer.listkeys('namespaces'):
3688 if 'bookmarks' in peer.listkeys('namespaces'):
3685 hexremoterev = hex(remoterev)
3689 hexremoterev = hex(remoterev)
3686 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3690 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3687 if bmr == hexremoterev]
3691 if bmr == hexremoterev]
3688
3692
3689 return sorted(bms)
3693 return sorted(bms)
3690
3694
3691 if bookmarks:
3695 if bookmarks:
3692 output.extend(getbms())
3696 output.extend(getbms())
3693 elif default and not ui.quiet:
3697 elif default and not ui.quiet:
3694 # multiple bookmarks for a single parent separated by '/'
3698 # multiple bookmarks for a single parent separated by '/'
3695 bm = '/'.join(getbms())
3699 bm = '/'.join(getbms())
3696 if bm:
3700 if bm:
3697 output.append(bm)
3701 output.append(bm)
3698 else:
3702 else:
3699 if not rev:
3703 if not rev:
3700 ctx = repo[None]
3704 ctx = repo[None]
3701 parents = ctx.parents()
3705 parents = ctx.parents()
3702 changed = ""
3706 changed = ""
3703 if default or id or num:
3707 if default or id or num:
3704 if (util.any(repo.status())
3708 if (util.any(repo.status())
3705 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3709 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3706 changed = '+'
3710 changed = '+'
3707 if default or id:
3711 if default or id:
3708 output = ["%s%s" %
3712 output = ["%s%s" %
3709 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3713 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3710 if num:
3714 if num:
3711 output.append("%s%s" %
3715 output.append("%s%s" %
3712 ('+'.join([str(p.rev()) for p in parents]), changed))
3716 ('+'.join([str(p.rev()) for p in parents]), changed))
3713 else:
3717 else:
3714 ctx = scmutil.revsingle(repo, rev)
3718 ctx = scmutil.revsingle(repo, rev)
3715 if default or id:
3719 if default or id:
3716 output = [hexfunc(ctx.node())]
3720 output = [hexfunc(ctx.node())]
3717 if num:
3721 if num:
3718 output.append(str(ctx.rev()))
3722 output.append(str(ctx.rev()))
3719
3723
3720 if default and not ui.quiet:
3724 if default and not ui.quiet:
3721 b = ctx.branch()
3725 b = ctx.branch()
3722 if b != 'default':
3726 if b != 'default':
3723 output.append("(%s)" % b)
3727 output.append("(%s)" % b)
3724
3728
3725 # multiple tags for a single parent separated by '/'
3729 # multiple tags for a single parent separated by '/'
3726 t = '/'.join(ctx.tags())
3730 t = '/'.join(ctx.tags())
3727 if t:
3731 if t:
3728 output.append(t)
3732 output.append(t)
3729
3733
3730 # multiple bookmarks for a single parent separated by '/'
3734 # multiple bookmarks for a single parent separated by '/'
3731 bm = '/'.join(ctx.bookmarks())
3735 bm = '/'.join(ctx.bookmarks())
3732 if bm:
3736 if bm:
3733 output.append(bm)
3737 output.append(bm)
3734 else:
3738 else:
3735 if branch:
3739 if branch:
3736 output.append(ctx.branch())
3740 output.append(ctx.branch())
3737
3741
3738 if tags:
3742 if tags:
3739 output.extend(ctx.tags())
3743 output.extend(ctx.tags())
3740
3744
3741 if bookmarks:
3745 if bookmarks:
3742 output.extend(ctx.bookmarks())
3746 output.extend(ctx.bookmarks())
3743
3747
3744 ui.write("%s\n" % ' '.join(output))
3748 ui.write("%s\n" % ' '.join(output))
3745
3749
3746 @command('import|patch',
3750 @command('import|patch',
3747 [('p', 'strip', 1,
3751 [('p', 'strip', 1,
3748 _('directory strip option for patch. This has the same '
3752 _('directory strip option for patch. This has the same '
3749 'meaning as the corresponding patch option'), _('NUM')),
3753 'meaning as the corresponding patch option'), _('NUM')),
3750 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3754 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3751 ('e', 'edit', False, _('invoke editor on commit messages')),
3755 ('e', 'edit', False, _('invoke editor on commit messages')),
3752 ('f', 'force', None,
3756 ('f', 'force', None,
3753 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3757 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3754 ('', 'no-commit', None,
3758 ('', 'no-commit', None,
3755 _("don't commit, just update the working directory")),
3759 _("don't commit, just update the working directory")),
3756 ('', 'bypass', None,
3760 ('', 'bypass', None,
3757 _("apply patch without touching the working directory")),
3761 _("apply patch without touching the working directory")),
3758 ('', 'partial', None,
3762 ('', 'partial', None,
3759 _('commit even if some hunks fail')),
3763 _('commit even if some hunks fail')),
3760 ('', 'exact', None,
3764 ('', 'exact', None,
3761 _('apply patch to the nodes from which it was generated')),
3765 _('apply patch to the nodes from which it was generated')),
3762 ('', 'import-branch', None,
3766 ('', 'import-branch', None,
3763 _('use any branch information in patch (implied by --exact)'))] +
3767 _('use any branch information in patch (implied by --exact)'))] +
3764 commitopts + commitopts2 + similarityopts,
3768 commitopts + commitopts2 + similarityopts,
3765 _('[OPTION]... PATCH...'))
3769 _('[OPTION]... PATCH...'))
3766 def import_(ui, repo, patch1=None, *patches, **opts):
3770 def import_(ui, repo, patch1=None, *patches, **opts):
3767 """import an ordered set of patches
3771 """import an ordered set of patches
3768
3772
3769 Import a list of patches and commit them individually (unless
3773 Import a list of patches and commit them individually (unless
3770 --no-commit is specified).
3774 --no-commit is specified).
3771
3775
3772 Because import first applies changes to the working directory,
3776 Because import first applies changes to the working directory,
3773 import will abort if there are outstanding changes.
3777 import will abort if there are outstanding changes.
3774
3778
3775 You can import a patch straight from a mail message. Even patches
3779 You can import a patch straight from a mail message. Even patches
3776 as attachments work (to use the body part, it must have type
3780 as attachments work (to use the body part, it must have type
3777 text/plain or text/x-patch). From and Subject headers of email
3781 text/plain or text/x-patch). From and Subject headers of email
3778 message are used as default committer and commit message. All
3782 message are used as default committer and commit message. All
3779 text/plain body parts before first diff are added to commit
3783 text/plain body parts before first diff are added to commit
3780 message.
3784 message.
3781
3785
3782 If the imported patch was generated by :hg:`export`, user and
3786 If the imported patch was generated by :hg:`export`, user and
3783 description from patch override values from message headers and
3787 description from patch override values from message headers and
3784 body. Values given on command line with -m/--message and -u/--user
3788 body. Values given on command line with -m/--message and -u/--user
3785 override these.
3789 override these.
3786
3790
3787 If --exact is specified, import will set the working directory to
3791 If --exact is specified, import will set the working directory to
3788 the parent of each patch before applying it, and will abort if the
3792 the parent of each patch before applying it, and will abort if the
3789 resulting changeset has a different ID than the one recorded in
3793 resulting changeset has a different ID than the one recorded in
3790 the patch. This may happen due to character set problems or other
3794 the patch. This may happen due to character set problems or other
3791 deficiencies in the text patch format.
3795 deficiencies in the text patch format.
3792
3796
3793 Use --bypass to apply and commit patches directly to the
3797 Use --bypass to apply and commit patches directly to the
3794 repository, not touching the working directory. Without --exact,
3798 repository, not touching the working directory. Without --exact,
3795 patches will be applied on top of the working directory parent
3799 patches will be applied on top of the working directory parent
3796 revision.
3800 revision.
3797
3801
3798 With -s/--similarity, hg will attempt to discover renames and
3802 With -s/--similarity, hg will attempt to discover renames and
3799 copies in the patch in the same way as :hg:`addremove`.
3803 copies in the patch in the same way as :hg:`addremove`.
3800
3804
3801 Use --partial to ensure a changeset will be created from the patch
3805 Use --partial to ensure a changeset will be created from the patch
3802 even if some hunks fail to apply. Hunks that fail to apply will be
3806 even if some hunks fail to apply. Hunks that fail to apply will be
3803 written to a <target-file>.rej file. Conflicts can then be resolved
3807 written to a <target-file>.rej file. Conflicts can then be resolved
3804 by hand before :hg:`commit --amend` is run to update the created
3808 by hand before :hg:`commit --amend` is run to update the created
3805 changeset. This flag exists to let people import patches that
3809 changeset. This flag exists to let people import patches that
3806 partially apply without losing the associated metadata (author,
3810 partially apply without losing the associated metadata (author,
3807 date, description, ...). Note that when none of the hunk applies
3811 date, description, ...). Note that when none of the hunk applies
3808 cleanly, :hg:`import --partial` will create an empty changeset,
3812 cleanly, :hg:`import --partial` will create an empty changeset,
3809 importing only the patch metadata.
3813 importing only the patch metadata.
3810
3814
3811 To read a patch from standard input, use "-" as the patch name. If
3815 To read a patch from standard input, use "-" as the patch name. If
3812 a URL is specified, the patch will be downloaded from it.
3816 a URL is specified, the patch will be downloaded from it.
3813 See :hg:`help dates` for a list of formats valid for -d/--date.
3817 See :hg:`help dates` for a list of formats valid for -d/--date.
3814
3818
3815 .. container:: verbose
3819 .. container:: verbose
3816
3820
3817 Examples:
3821 Examples:
3818
3822
3819 - import a traditional patch from a website and detect renames::
3823 - import a traditional patch from a website and detect renames::
3820
3824
3821 hg import -s 80 http://example.com/bugfix.patch
3825 hg import -s 80 http://example.com/bugfix.patch
3822
3826
3823 - import a changeset from an hgweb server::
3827 - import a changeset from an hgweb server::
3824
3828
3825 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3829 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3826
3830
3827 - import all the patches in an Unix-style mbox::
3831 - import all the patches in an Unix-style mbox::
3828
3832
3829 hg import incoming-patches.mbox
3833 hg import incoming-patches.mbox
3830
3834
3831 - attempt to exactly restore an exported changeset (not always
3835 - attempt to exactly restore an exported changeset (not always
3832 possible)::
3836 possible)::
3833
3837
3834 hg import --exact proposed-fix.patch
3838 hg import --exact proposed-fix.patch
3835
3839
3836 Returns 0 on success, 1 on partial success (see --partial).
3840 Returns 0 on success, 1 on partial success (see --partial).
3837 """
3841 """
3838
3842
3839 if not patch1:
3843 if not patch1:
3840 raise util.Abort(_('need at least one patch to import'))
3844 raise util.Abort(_('need at least one patch to import'))
3841
3845
3842 patches = (patch1,) + patches
3846 patches = (patch1,) + patches
3843
3847
3844 date = opts.get('date')
3848 date = opts.get('date')
3845 if date:
3849 if date:
3846 opts['date'] = util.parsedate(date)
3850 opts['date'] = util.parsedate(date)
3847
3851
3848 update = not opts.get('bypass')
3852 update = not opts.get('bypass')
3849 if not update and opts.get('no_commit'):
3853 if not update and opts.get('no_commit'):
3850 raise util.Abort(_('cannot use --no-commit with --bypass'))
3854 raise util.Abort(_('cannot use --no-commit with --bypass'))
3851 try:
3855 try:
3852 sim = float(opts.get('similarity') or 0)
3856 sim = float(opts.get('similarity') or 0)
3853 except ValueError:
3857 except ValueError:
3854 raise util.Abort(_('similarity must be a number'))
3858 raise util.Abort(_('similarity must be a number'))
3855 if sim < 0 or sim > 100:
3859 if sim < 0 or sim > 100:
3856 raise util.Abort(_('similarity must be between 0 and 100'))
3860 raise util.Abort(_('similarity must be between 0 and 100'))
3857 if sim and not update:
3861 if sim and not update:
3858 raise util.Abort(_('cannot use --similarity with --bypass'))
3862 raise util.Abort(_('cannot use --similarity with --bypass'))
3859
3863
3860 if update:
3864 if update:
3861 cmdutil.checkunfinished(repo)
3865 cmdutil.checkunfinished(repo)
3862 if (opts.get('exact') or not opts.get('force')) and update:
3866 if (opts.get('exact') or not opts.get('force')) and update:
3863 cmdutil.bailifchanged(repo)
3867 cmdutil.bailifchanged(repo)
3864
3868
3865 base = opts["base"]
3869 base = opts["base"]
3866 wlock = lock = tr = None
3870 wlock = lock = tr = None
3867 msgs = []
3871 msgs = []
3868 ret = 0
3872 ret = 0
3869
3873
3870
3874
3871 try:
3875 try:
3872 try:
3876 try:
3873 wlock = repo.wlock()
3877 wlock = repo.wlock()
3874 if not opts.get('no_commit'):
3878 if not opts.get('no_commit'):
3875 lock = repo.lock()
3879 lock = repo.lock()
3876 tr = repo.transaction('import')
3880 tr = repo.transaction('import')
3877 parents = repo.parents()
3881 parents = repo.parents()
3878 for patchurl in patches:
3882 for patchurl in patches:
3879 if patchurl == '-':
3883 if patchurl == '-':
3880 ui.status(_('applying patch from stdin\n'))
3884 ui.status(_('applying patch from stdin\n'))
3881 patchfile = ui.fin
3885 patchfile = ui.fin
3882 patchurl = 'stdin' # for error message
3886 patchurl = 'stdin' # for error message
3883 else:
3887 else:
3884 patchurl = os.path.join(base, patchurl)
3888 patchurl = os.path.join(base, patchurl)
3885 ui.status(_('applying %s\n') % patchurl)
3889 ui.status(_('applying %s\n') % patchurl)
3886 patchfile = hg.openpath(ui, patchurl)
3890 patchfile = hg.openpath(ui, patchurl)
3887
3891
3888 haspatch = False
3892 haspatch = False
3889 for hunk in patch.split(patchfile):
3893 for hunk in patch.split(patchfile):
3890 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3894 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3891 parents, opts,
3895 parents, opts,
3892 msgs, hg.clean)
3896 msgs, hg.clean)
3893 if msg:
3897 if msg:
3894 haspatch = True
3898 haspatch = True
3895 ui.note(msg + '\n')
3899 ui.note(msg + '\n')
3896 if update or opts.get('exact'):
3900 if update or opts.get('exact'):
3897 parents = repo.parents()
3901 parents = repo.parents()
3898 else:
3902 else:
3899 parents = [repo[node]]
3903 parents = [repo[node]]
3900 if rej:
3904 if rej:
3901 ui.write_err(_("patch applied partially\n"))
3905 ui.write_err(_("patch applied partially\n"))
3902 ui.write_err(_("(fix the .rej files and run "
3906 ui.write_err(_("(fix the .rej files and run "
3903 "`hg commit --amend`)\n"))
3907 "`hg commit --amend`)\n"))
3904 ret = 1
3908 ret = 1
3905 break
3909 break
3906
3910
3907 if not haspatch:
3911 if not haspatch:
3908 raise util.Abort(_('%s: no diffs found') % patchurl)
3912 raise util.Abort(_('%s: no diffs found') % patchurl)
3909
3913
3910 if tr:
3914 if tr:
3911 tr.close()
3915 tr.close()
3912 if msgs:
3916 if msgs:
3913 repo.savecommitmessage('\n* * *\n'.join(msgs))
3917 repo.savecommitmessage('\n* * *\n'.join(msgs))
3914 return ret
3918 return ret
3915 except: # re-raises
3919 except: # re-raises
3916 # wlock.release() indirectly calls dirstate.write(): since
3920 # wlock.release() indirectly calls dirstate.write(): since
3917 # we're crashing, we do not want to change the working dir
3921 # we're crashing, we do not want to change the working dir
3918 # parent after all, so make sure it writes nothing
3922 # parent after all, so make sure it writes nothing
3919 repo.dirstate.invalidate()
3923 repo.dirstate.invalidate()
3920 raise
3924 raise
3921 finally:
3925 finally:
3922 if tr:
3926 if tr:
3923 tr.release()
3927 tr.release()
3924 release(lock, wlock)
3928 release(lock, wlock)
3925
3929
3926 @command('incoming|in',
3930 @command('incoming|in',
3927 [('f', 'force', None,
3931 [('f', 'force', None,
3928 _('run even if remote repository is unrelated')),
3932 _('run even if remote repository is unrelated')),
3929 ('n', 'newest-first', None, _('show newest record first')),
3933 ('n', 'newest-first', None, _('show newest record first')),
3930 ('', 'bundle', '',
3934 ('', 'bundle', '',
3931 _('file to store the bundles into'), _('FILE')),
3935 _('file to store the bundles into'), _('FILE')),
3932 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3936 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3933 ('B', 'bookmarks', False, _("compare bookmarks")),
3937 ('B', 'bookmarks', False, _("compare bookmarks")),
3934 ('b', 'branch', [],
3938 ('b', 'branch', [],
3935 _('a specific branch you would like to pull'), _('BRANCH')),
3939 _('a specific branch you would like to pull'), _('BRANCH')),
3936 ] + logopts + remoteopts + subrepoopts,
3940 ] + logopts + remoteopts + subrepoopts,
3937 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3941 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3938 def incoming(ui, repo, source="default", **opts):
3942 def incoming(ui, repo, source="default", **opts):
3939 """show new changesets found in source
3943 """show new changesets found in source
3940
3944
3941 Show new changesets found in the specified path/URL or the default
3945 Show new changesets found in the specified path/URL or the default
3942 pull location. These are the changesets that would have been pulled
3946 pull location. These are the changesets that would have been pulled
3943 if a pull at the time you issued this command.
3947 if a pull at the time you issued this command.
3944
3948
3945 For remote repository, using --bundle avoids downloading the
3949 For remote repository, using --bundle avoids downloading the
3946 changesets twice if the incoming is followed by a pull.
3950 changesets twice if the incoming is followed by a pull.
3947
3951
3948 See pull for valid source format details.
3952 See pull for valid source format details.
3949
3953
3950 .. container:: verbose
3954 .. container:: verbose
3951
3955
3952 Examples:
3956 Examples:
3953
3957
3954 - show incoming changes with patches and full description::
3958 - show incoming changes with patches and full description::
3955
3959
3956 hg incoming -vp
3960 hg incoming -vp
3957
3961
3958 - show incoming changes excluding merges, store a bundle::
3962 - show incoming changes excluding merges, store a bundle::
3959
3963
3960 hg in -vpM --bundle incoming.hg
3964 hg in -vpM --bundle incoming.hg
3961 hg pull incoming.hg
3965 hg pull incoming.hg
3962
3966
3963 - briefly list changes inside a bundle::
3967 - briefly list changes inside a bundle::
3964
3968
3965 hg in changes.hg -T "{desc|firstline}\\n"
3969 hg in changes.hg -T "{desc|firstline}\\n"
3966
3970
3967 Returns 0 if there are incoming changes, 1 otherwise.
3971 Returns 0 if there are incoming changes, 1 otherwise.
3968 """
3972 """
3969 if opts.get('graph'):
3973 if opts.get('graph'):
3970 cmdutil.checkunsupportedgraphflags([], opts)
3974 cmdutil.checkunsupportedgraphflags([], opts)
3971 def display(other, chlist, displayer):
3975 def display(other, chlist, displayer):
3972 revdag = cmdutil.graphrevs(other, chlist, opts)
3976 revdag = cmdutil.graphrevs(other, chlist, opts)
3973 showparents = [ctx.node() for ctx in repo[None].parents()]
3977 showparents = [ctx.node() for ctx in repo[None].parents()]
3974 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3978 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3975 graphmod.asciiedges)
3979 graphmod.asciiedges)
3976
3980
3977 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3981 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3978 return 0
3982 return 0
3979
3983
3980 if opts.get('bundle') and opts.get('subrepos'):
3984 if opts.get('bundle') and opts.get('subrepos'):
3981 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3985 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3982
3986
3983 if opts.get('bookmarks'):
3987 if opts.get('bookmarks'):
3984 source, branches = hg.parseurl(ui.expandpath(source),
3988 source, branches = hg.parseurl(ui.expandpath(source),
3985 opts.get('branch'))
3989 opts.get('branch'))
3986 other = hg.peer(repo, opts, source)
3990 other = hg.peer(repo, opts, source)
3987 if 'bookmarks' not in other.listkeys('namespaces'):
3991 if 'bookmarks' not in other.listkeys('namespaces'):
3988 ui.warn(_("remote doesn't support bookmarks\n"))
3992 ui.warn(_("remote doesn't support bookmarks\n"))
3989 return 0
3993 return 0
3990 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3994 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3991 return bookmarks.diff(ui, repo, other)
3995 return bookmarks.diff(ui, repo, other)
3992
3996
3993 repo._subtoppath = ui.expandpath(source)
3997 repo._subtoppath = ui.expandpath(source)
3994 try:
3998 try:
3995 return hg.incoming(ui, repo, source, opts)
3999 return hg.incoming(ui, repo, source, opts)
3996 finally:
4000 finally:
3997 del repo._subtoppath
4001 del repo._subtoppath
3998
4002
3999
4003
4000 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4004 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4001 norepo=True)
4005 norepo=True)
4002 def init(ui, dest=".", **opts):
4006 def init(ui, dest=".", **opts):
4003 """create a new repository in the given directory
4007 """create a new repository in the given directory
4004
4008
4005 Initialize a new repository in the given directory. If the given
4009 Initialize a new repository in the given directory. If the given
4006 directory does not exist, it will be created.
4010 directory does not exist, it will be created.
4007
4011
4008 If no directory is given, the current directory is used.
4012 If no directory is given, the current directory is used.
4009
4013
4010 It is possible to specify an ``ssh://`` URL as the destination.
4014 It is possible to specify an ``ssh://`` URL as the destination.
4011 See :hg:`help urls` for more information.
4015 See :hg:`help urls` for more information.
4012
4016
4013 Returns 0 on success.
4017 Returns 0 on success.
4014 """
4018 """
4015 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4019 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4016
4020
4017 @command('locate',
4021 @command('locate',
4018 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4022 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4019 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4023 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4020 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4024 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4021 ] + walkopts,
4025 ] + walkopts,
4022 _('[OPTION]... [PATTERN]...'))
4026 _('[OPTION]... [PATTERN]...'))
4023 def locate(ui, repo, *pats, **opts):
4027 def locate(ui, repo, *pats, **opts):
4024 """locate files matching specific patterns
4028 """locate files matching specific patterns
4025
4029
4026 Print files under Mercurial control in the working directory whose
4030 Print files under Mercurial control in the working directory whose
4027 names match the given patterns.
4031 names match the given patterns.
4028
4032
4029 By default, this command searches all directories in the working
4033 By default, this command searches all directories in the working
4030 directory. To search just the current directory and its
4034 directory. To search just the current directory and its
4031 subdirectories, use "--include .".
4035 subdirectories, use "--include .".
4032
4036
4033 If no patterns are given to match, this command prints the names
4037 If no patterns are given to match, this command prints the names
4034 of all files under Mercurial control in the working directory.
4038 of all files under Mercurial control in the working directory.
4035
4039
4036 If you want to feed the output of this command into the "xargs"
4040 If you want to feed the output of this command into the "xargs"
4037 command, use the -0 option to both this command and "xargs". This
4041 command, use the -0 option to both this command and "xargs". This
4038 will avoid the problem of "xargs" treating single filenames that
4042 will avoid the problem of "xargs" treating single filenames that
4039 contain whitespace as multiple filenames.
4043 contain whitespace as multiple filenames.
4040
4044
4041 Returns 0 if a match is found, 1 otherwise.
4045 Returns 0 if a match is found, 1 otherwise.
4042 """
4046 """
4043 end = opts.get('print0') and '\0' or '\n'
4047 end = opts.get('print0') and '\0' or '\n'
4044 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4048 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4045
4049
4046 ret = 1
4050 ret = 1
4047 ctx = repo[rev]
4051 ctx = repo[rev]
4048 m = scmutil.match(ctx, pats, opts, default='relglob')
4052 m = scmutil.match(ctx, pats, opts, default='relglob')
4049 m.bad = lambda x, y: False
4053 m.bad = lambda x, y: False
4050
4054
4051 for abs in ctx.matches(m):
4055 for abs in ctx.matches(m):
4052 if opts.get('fullpath'):
4056 if opts.get('fullpath'):
4053 ui.write(repo.wjoin(abs), end)
4057 ui.write(repo.wjoin(abs), end)
4054 else:
4058 else:
4055 ui.write(((pats and m.rel(abs)) or abs), end)
4059 ui.write(((pats and m.rel(abs)) or abs), end)
4056 ret = 0
4060 ret = 0
4057
4061
4058 return ret
4062 return ret
4059
4063
4060 @command('^log|history',
4064 @command('^log|history',
4061 [('f', 'follow', None,
4065 [('f', 'follow', None,
4062 _('follow changeset history, or file history across copies and renames')),
4066 _('follow changeset history, or file history across copies and renames')),
4063 ('', 'follow-first', None,
4067 ('', 'follow-first', None,
4064 _('only follow the first parent of merge changesets (DEPRECATED)')),
4068 _('only follow the first parent of merge changesets (DEPRECATED)')),
4065 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4069 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4066 ('C', 'copies', None, _('show copied files')),
4070 ('C', 'copies', None, _('show copied files')),
4067 ('k', 'keyword', [],
4071 ('k', 'keyword', [],
4068 _('do case-insensitive search for a given text'), _('TEXT')),
4072 _('do case-insensitive search for a given text'), _('TEXT')),
4069 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4073 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4070 ('', 'removed', None, _('include revisions where files were removed')),
4074 ('', 'removed', None, _('include revisions where files were removed')),
4071 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4075 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4072 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4076 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4073 ('', 'only-branch', [],
4077 ('', 'only-branch', [],
4074 _('show only changesets within the given named branch (DEPRECATED)'),
4078 _('show only changesets within the given named branch (DEPRECATED)'),
4075 _('BRANCH')),
4079 _('BRANCH')),
4076 ('b', 'branch', [],
4080 ('b', 'branch', [],
4077 _('show changesets within the given named branch'), _('BRANCH')),
4081 _('show changesets within the given named branch'), _('BRANCH')),
4078 ('P', 'prune', [],
4082 ('P', 'prune', [],
4079 _('do not display revision or any of its ancestors'), _('REV')),
4083 _('do not display revision or any of its ancestors'), _('REV')),
4080 ] + logopts + walkopts,
4084 ] + logopts + walkopts,
4081 _('[OPTION]... [FILE]'),
4085 _('[OPTION]... [FILE]'),
4082 inferrepo=True)
4086 inferrepo=True)
4083 def log(ui, repo, *pats, **opts):
4087 def log(ui, repo, *pats, **opts):
4084 """show revision history of entire repository or files
4088 """show revision history of entire repository or files
4085
4089
4086 Print the revision history of the specified files or the entire
4090 Print the revision history of the specified files or the entire
4087 project.
4091 project.
4088
4092
4089 If no revision range is specified, the default is ``tip:0`` unless
4093 If no revision range is specified, the default is ``tip:0`` unless
4090 --follow is set, in which case the working directory parent is
4094 --follow is set, in which case the working directory parent is
4091 used as the starting revision.
4095 used as the starting revision.
4092
4096
4093 File history is shown without following rename or copy history of
4097 File history is shown without following rename or copy history of
4094 files. Use -f/--follow with a filename to follow history across
4098 files. Use -f/--follow with a filename to follow history across
4095 renames and copies. --follow without a filename will only show
4099 renames and copies. --follow without a filename will only show
4096 ancestors or descendants of the starting revision.
4100 ancestors or descendants of the starting revision.
4097
4101
4098 By default this command prints revision number and changeset id,
4102 By default this command prints revision number and changeset id,
4099 tags, non-trivial parents, user, date and time, and a summary for
4103 tags, non-trivial parents, user, date and time, and a summary for
4100 each commit. When the -v/--verbose switch is used, the list of
4104 each commit. When the -v/--verbose switch is used, the list of
4101 changed files and full commit message are shown.
4105 changed files and full commit message are shown.
4102
4106
4103 With --graph the revisions are shown as an ASCII art DAG with the most
4107 With --graph the revisions are shown as an ASCII art DAG with the most
4104 recent changeset at the top.
4108 recent changeset at the top.
4105 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4109 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4106 and '+' represents a fork where the changeset from the lines below is a
4110 and '+' represents a fork where the changeset from the lines below is a
4107 parent of the 'o' merge on the same line.
4111 parent of the 'o' merge on the same line.
4108
4112
4109 .. note::
4113 .. note::
4110
4114
4111 log -p/--patch may generate unexpected diff output for merge
4115 log -p/--patch may generate unexpected diff output for merge
4112 changesets, as it will only compare the merge changeset against
4116 changesets, as it will only compare the merge changeset against
4113 its first parent. Also, only files different from BOTH parents
4117 its first parent. Also, only files different from BOTH parents
4114 will appear in files:.
4118 will appear in files:.
4115
4119
4116 .. note::
4120 .. note::
4117
4121
4118 for performance reasons, log FILE may omit duplicate changes
4122 for performance reasons, log FILE may omit duplicate changes
4119 made on branches and will not show deletions. To see all
4123 made on branches and will not show deletions. To see all
4120 changes including duplicates and deletions, use the --removed
4124 changes including duplicates and deletions, use the --removed
4121 switch.
4125 switch.
4122
4126
4123 .. container:: verbose
4127 .. container:: verbose
4124
4128
4125 Some examples:
4129 Some examples:
4126
4130
4127 - changesets with full descriptions and file lists::
4131 - changesets with full descriptions and file lists::
4128
4132
4129 hg log -v
4133 hg log -v
4130
4134
4131 - changesets ancestral to the working directory::
4135 - changesets ancestral to the working directory::
4132
4136
4133 hg log -f
4137 hg log -f
4134
4138
4135 - last 10 commits on the current branch::
4139 - last 10 commits on the current branch::
4136
4140
4137 hg log -l 10 -b .
4141 hg log -l 10 -b .
4138
4142
4139 - changesets showing all modifications of a file, including removals::
4143 - changesets showing all modifications of a file, including removals::
4140
4144
4141 hg log --removed file.c
4145 hg log --removed file.c
4142
4146
4143 - all changesets that touch a directory, with diffs, excluding merges::
4147 - all changesets that touch a directory, with diffs, excluding merges::
4144
4148
4145 hg log -Mp lib/
4149 hg log -Mp lib/
4146
4150
4147 - all revision numbers that match a keyword::
4151 - all revision numbers that match a keyword::
4148
4152
4149 hg log -k bug --template "{rev}\\n"
4153 hg log -k bug --template "{rev}\\n"
4150
4154
4151 - list available log templates::
4155 - list available log templates::
4152
4156
4153 hg log -T list
4157 hg log -T list
4154
4158
4155 - check if a given changeset is included is a tagged release::
4159 - check if a given changeset is included is a tagged release::
4156
4160
4157 hg log -r "a21ccf and ancestor(1.9)"
4161 hg log -r "a21ccf and ancestor(1.9)"
4158
4162
4159 - find all changesets by some user in a date range::
4163 - find all changesets by some user in a date range::
4160
4164
4161 hg log -k alice -d "may 2008 to jul 2008"
4165 hg log -k alice -d "may 2008 to jul 2008"
4162
4166
4163 - summary of all changesets after the last tag::
4167 - summary of all changesets after the last tag::
4164
4168
4165 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4169 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4166
4170
4167 See :hg:`help dates` for a list of formats valid for -d/--date.
4171 See :hg:`help dates` for a list of formats valid for -d/--date.
4168
4172
4169 See :hg:`help revisions` and :hg:`help revsets` for more about
4173 See :hg:`help revisions` and :hg:`help revsets` for more about
4170 specifying revisions.
4174 specifying revisions.
4171
4175
4172 See :hg:`help templates` for more about pre-packaged styles and
4176 See :hg:`help templates` for more about pre-packaged styles and
4173 specifying custom templates.
4177 specifying custom templates.
4174
4178
4175 Returns 0 on success.
4179 Returns 0 on success.
4176 """
4180 """
4177 if opts.get('graph'):
4181 if opts.get('graph'):
4178 return cmdutil.graphlog(ui, repo, *pats, **opts)
4182 return cmdutil.graphlog(ui, repo, *pats, **opts)
4179
4183
4180 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4184 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4181 limit = cmdutil.loglimit(opts)
4185 limit = cmdutil.loglimit(opts)
4182 count = 0
4186 count = 0
4183
4187
4184 getrenamed = None
4188 getrenamed = None
4185 if opts.get('copies'):
4189 if opts.get('copies'):
4186 endrev = None
4190 endrev = None
4187 if opts.get('rev'):
4191 if opts.get('rev'):
4188 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4192 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4189 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4193 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4190
4194
4191 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4195 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4192 for rev in revs:
4196 for rev in revs:
4193 if count == limit:
4197 if count == limit:
4194 break
4198 break
4195 ctx = repo[rev]
4199 ctx = repo[rev]
4196 copies = None
4200 copies = None
4197 if getrenamed is not None and rev:
4201 if getrenamed is not None and rev:
4198 copies = []
4202 copies = []
4199 for fn in ctx.files():
4203 for fn in ctx.files():
4200 rename = getrenamed(fn, rev)
4204 rename = getrenamed(fn, rev)
4201 if rename:
4205 if rename:
4202 copies.append((fn, rename[0]))
4206 copies.append((fn, rename[0]))
4203 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4207 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4204 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4208 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4205 if displayer.flush(rev):
4209 if displayer.flush(rev):
4206 count += 1
4210 count += 1
4207
4211
4208 displayer.close()
4212 displayer.close()
4209
4213
4210 @command('manifest',
4214 @command('manifest',
4211 [('r', 'rev', '', _('revision to display'), _('REV')),
4215 [('r', 'rev', '', _('revision to display'), _('REV')),
4212 ('', 'all', False, _("list files from all revisions"))],
4216 ('', 'all', False, _("list files from all revisions"))],
4213 _('[-r REV]'))
4217 _('[-r REV]'))
4214 def manifest(ui, repo, node=None, rev=None, **opts):
4218 def manifest(ui, repo, node=None, rev=None, **opts):
4215 """output the current or given revision of the project manifest
4219 """output the current or given revision of the project manifest
4216
4220
4217 Print a list of version controlled files for the given revision.
4221 Print a list of version controlled files for the given revision.
4218 If no revision is given, the first parent of the working directory
4222 If no revision is given, the first parent of the working directory
4219 is used, or the null revision if no revision is checked out.
4223 is used, or the null revision if no revision is checked out.
4220
4224
4221 With -v, print file permissions, symlink and executable bits.
4225 With -v, print file permissions, symlink and executable bits.
4222 With --debug, print file revision hashes.
4226 With --debug, print file revision hashes.
4223
4227
4224 If option --all is specified, the list of all files from all revisions
4228 If option --all is specified, the list of all files from all revisions
4225 is printed. This includes deleted and renamed files.
4229 is printed. This includes deleted and renamed files.
4226
4230
4227 Returns 0 on success.
4231 Returns 0 on success.
4228 """
4232 """
4229
4233
4230 fm = ui.formatter('manifest', opts)
4234 fm = ui.formatter('manifest', opts)
4231
4235
4232 if opts.get('all'):
4236 if opts.get('all'):
4233 if rev or node:
4237 if rev or node:
4234 raise util.Abort(_("can't specify a revision with --all"))
4238 raise util.Abort(_("can't specify a revision with --all"))
4235
4239
4236 res = []
4240 res = []
4237 prefix = "data/"
4241 prefix = "data/"
4238 suffix = ".i"
4242 suffix = ".i"
4239 plen = len(prefix)
4243 plen = len(prefix)
4240 slen = len(suffix)
4244 slen = len(suffix)
4241 lock = repo.lock()
4245 lock = repo.lock()
4242 try:
4246 try:
4243 for fn, b, size in repo.store.datafiles():
4247 for fn, b, size in repo.store.datafiles():
4244 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4248 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4245 res.append(fn[plen:-slen])
4249 res.append(fn[plen:-slen])
4246 finally:
4250 finally:
4247 lock.release()
4251 lock.release()
4248 for f in res:
4252 for f in res:
4249 fm.startitem()
4253 fm.startitem()
4250 fm.write("path", '%s\n', f)
4254 fm.write("path", '%s\n', f)
4251 fm.end()
4255 fm.end()
4252 return
4256 return
4253
4257
4254 if rev and node:
4258 if rev and node:
4255 raise util.Abort(_("please specify just one revision"))
4259 raise util.Abort(_("please specify just one revision"))
4256
4260
4257 if not node:
4261 if not node:
4258 node = rev
4262 node = rev
4259
4263
4260 char = {'l': '@', 'x': '*', '': ''}
4264 char = {'l': '@', 'x': '*', '': ''}
4261 mode = {'l': '644', 'x': '755', '': '644'}
4265 mode = {'l': '644', 'x': '755', '': '644'}
4262 ctx = scmutil.revsingle(repo, node)
4266 ctx = scmutil.revsingle(repo, node)
4263 mf = ctx.manifest()
4267 mf = ctx.manifest()
4264 for f in ctx:
4268 for f in ctx:
4265 fm.startitem()
4269 fm.startitem()
4266 fl = ctx[f].flags()
4270 fl = ctx[f].flags()
4267 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4271 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4268 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4272 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4269 fm.write('path', '%s\n', f)
4273 fm.write('path', '%s\n', f)
4270 fm.end()
4274 fm.end()
4271
4275
4272 @command('^merge',
4276 @command('^merge',
4273 [('f', 'force', None,
4277 [('f', 'force', None,
4274 _('force a merge including outstanding changes (DEPRECATED)')),
4278 _('force a merge including outstanding changes (DEPRECATED)')),
4275 ('r', 'rev', '', _('revision to merge'), _('REV')),
4279 ('r', 'rev', '', _('revision to merge'), _('REV')),
4276 ('P', 'preview', None,
4280 ('P', 'preview', None,
4277 _('review revisions to merge (no merge is performed)'))
4281 _('review revisions to merge (no merge is performed)'))
4278 ] + mergetoolopts,
4282 ] + mergetoolopts,
4279 _('[-P] [-f] [[-r] REV]'))
4283 _('[-P] [-f] [[-r] REV]'))
4280 def merge(ui, repo, node=None, **opts):
4284 def merge(ui, repo, node=None, **opts):
4281 """merge working directory with another revision
4285 """merge working directory with another revision
4282
4286
4283 The current working directory is updated with all changes made in
4287 The current working directory is updated with all changes made in
4284 the requested revision since the last common predecessor revision.
4288 the requested revision since the last common predecessor revision.
4285
4289
4286 Files that changed between either parent are marked as changed for
4290 Files that changed between either parent are marked as changed for
4287 the next commit and a commit must be performed before any further
4291 the next commit and a commit must be performed before any further
4288 updates to the repository are allowed. The next commit will have
4292 updates to the repository are allowed. The next commit will have
4289 two parents.
4293 two parents.
4290
4294
4291 ``--tool`` can be used to specify the merge tool used for file
4295 ``--tool`` can be used to specify the merge tool used for file
4292 merges. It overrides the HGMERGE environment variable and your
4296 merges. It overrides the HGMERGE environment variable and your
4293 configuration files. See :hg:`help merge-tools` for options.
4297 configuration files. See :hg:`help merge-tools` for options.
4294
4298
4295 If no revision is specified, the working directory's parent is a
4299 If no revision is specified, the working directory's parent is a
4296 head revision, and the current branch contains exactly one other
4300 head revision, and the current branch contains exactly one other
4297 head, the other head is merged with by default. Otherwise, an
4301 head, the other head is merged with by default. Otherwise, an
4298 explicit revision with which to merge with must be provided.
4302 explicit revision with which to merge with must be provided.
4299
4303
4300 :hg:`resolve` must be used to resolve unresolved files.
4304 :hg:`resolve` must be used to resolve unresolved files.
4301
4305
4302 To undo an uncommitted merge, use :hg:`update --clean .` which
4306 To undo an uncommitted merge, use :hg:`update --clean .` which
4303 will check out a clean copy of the original merge parent, losing
4307 will check out a clean copy of the original merge parent, losing
4304 all changes.
4308 all changes.
4305
4309
4306 Returns 0 on success, 1 if there are unresolved files.
4310 Returns 0 on success, 1 if there are unresolved files.
4307 """
4311 """
4308
4312
4309 if opts.get('rev') and node:
4313 if opts.get('rev') and node:
4310 raise util.Abort(_("please specify just one revision"))
4314 raise util.Abort(_("please specify just one revision"))
4311 if not node:
4315 if not node:
4312 node = opts.get('rev')
4316 node = opts.get('rev')
4313
4317
4314 if node:
4318 if node:
4315 node = scmutil.revsingle(repo, node).node()
4319 node = scmutil.revsingle(repo, node).node()
4316
4320
4317 if not node and repo._bookmarkcurrent:
4321 if not node and repo._bookmarkcurrent:
4318 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4322 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4319 curhead = repo[repo._bookmarkcurrent].node()
4323 curhead = repo[repo._bookmarkcurrent].node()
4320 if len(bmheads) == 2:
4324 if len(bmheads) == 2:
4321 if curhead == bmheads[0]:
4325 if curhead == bmheads[0]:
4322 node = bmheads[1]
4326 node = bmheads[1]
4323 else:
4327 else:
4324 node = bmheads[0]
4328 node = bmheads[0]
4325 elif len(bmheads) > 2:
4329 elif len(bmheads) > 2:
4326 raise util.Abort(_("multiple matching bookmarks to merge - "
4330 raise util.Abort(_("multiple matching bookmarks to merge - "
4327 "please merge with an explicit rev or bookmark"),
4331 "please merge with an explicit rev or bookmark"),
4328 hint=_("run 'hg heads' to see all heads"))
4332 hint=_("run 'hg heads' to see all heads"))
4329 elif len(bmheads) <= 1:
4333 elif len(bmheads) <= 1:
4330 raise util.Abort(_("no matching bookmark to merge - "
4334 raise util.Abort(_("no matching bookmark to merge - "
4331 "please merge with an explicit rev or bookmark"),
4335 "please merge with an explicit rev or bookmark"),
4332 hint=_("run 'hg heads' to see all heads"))
4336 hint=_("run 'hg heads' to see all heads"))
4333
4337
4334 if not node and not repo._bookmarkcurrent:
4338 if not node and not repo._bookmarkcurrent:
4335 branch = repo[None].branch()
4339 branch = repo[None].branch()
4336 bheads = repo.branchheads(branch)
4340 bheads = repo.branchheads(branch)
4337 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4341 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4338
4342
4339 if len(nbhs) > 2:
4343 if len(nbhs) > 2:
4340 raise util.Abort(_("branch '%s' has %d heads - "
4344 raise util.Abort(_("branch '%s' has %d heads - "
4341 "please merge with an explicit rev")
4345 "please merge with an explicit rev")
4342 % (branch, len(bheads)),
4346 % (branch, len(bheads)),
4343 hint=_("run 'hg heads .' to see heads"))
4347 hint=_("run 'hg heads .' to see heads"))
4344
4348
4345 parent = repo.dirstate.p1()
4349 parent = repo.dirstate.p1()
4346 if len(nbhs) <= 1:
4350 if len(nbhs) <= 1:
4347 if len(bheads) > 1:
4351 if len(bheads) > 1:
4348 raise util.Abort(_("heads are bookmarked - "
4352 raise util.Abort(_("heads are bookmarked - "
4349 "please merge with an explicit rev"),
4353 "please merge with an explicit rev"),
4350 hint=_("run 'hg heads' to see all heads"))
4354 hint=_("run 'hg heads' to see all heads"))
4351 if len(repo.heads()) > 1:
4355 if len(repo.heads()) > 1:
4352 raise util.Abort(_("branch '%s' has one head - "
4356 raise util.Abort(_("branch '%s' has one head - "
4353 "please merge with an explicit rev")
4357 "please merge with an explicit rev")
4354 % branch,
4358 % branch,
4355 hint=_("run 'hg heads' to see all heads"))
4359 hint=_("run 'hg heads' to see all heads"))
4356 msg, hint = _('nothing to merge'), None
4360 msg, hint = _('nothing to merge'), None
4357 if parent != repo.lookup(branch):
4361 if parent != repo.lookup(branch):
4358 hint = _("use 'hg update' instead")
4362 hint = _("use 'hg update' instead")
4359 raise util.Abort(msg, hint=hint)
4363 raise util.Abort(msg, hint=hint)
4360
4364
4361 if parent not in bheads:
4365 if parent not in bheads:
4362 raise util.Abort(_('working directory not at a head revision'),
4366 raise util.Abort(_('working directory not at a head revision'),
4363 hint=_("use 'hg update' or merge with an "
4367 hint=_("use 'hg update' or merge with an "
4364 "explicit revision"))
4368 "explicit revision"))
4365 if parent == nbhs[0]:
4369 if parent == nbhs[0]:
4366 node = nbhs[-1]
4370 node = nbhs[-1]
4367 else:
4371 else:
4368 node = nbhs[0]
4372 node = nbhs[0]
4369
4373
4370 if opts.get('preview'):
4374 if opts.get('preview'):
4371 # find nodes that are ancestors of p2 but not of p1
4375 # find nodes that are ancestors of p2 but not of p1
4372 p1 = repo.lookup('.')
4376 p1 = repo.lookup('.')
4373 p2 = repo.lookup(node)
4377 p2 = repo.lookup(node)
4374 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4378 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4375
4379
4376 displayer = cmdutil.show_changeset(ui, repo, opts)
4380 displayer = cmdutil.show_changeset(ui, repo, opts)
4377 for node in nodes:
4381 for node in nodes:
4378 displayer.show(repo[node])
4382 displayer.show(repo[node])
4379 displayer.close()
4383 displayer.close()
4380 return 0
4384 return 0
4381
4385
4382 try:
4386 try:
4383 # ui.forcemerge is an internal variable, do not document
4387 # ui.forcemerge is an internal variable, do not document
4384 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4388 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4385 return hg.merge(repo, node, force=opts.get('force'))
4389 return hg.merge(repo, node, force=opts.get('force'))
4386 finally:
4390 finally:
4387 ui.setconfig('ui', 'forcemerge', '', 'merge')
4391 ui.setconfig('ui', 'forcemerge', '', 'merge')
4388
4392
4389 @command('outgoing|out',
4393 @command('outgoing|out',
4390 [('f', 'force', None, _('run even when the destination is unrelated')),
4394 [('f', 'force', None, _('run even when the destination is unrelated')),
4391 ('r', 'rev', [],
4395 ('r', 'rev', [],
4392 _('a changeset intended to be included in the destination'), _('REV')),
4396 _('a changeset intended to be included in the destination'), _('REV')),
4393 ('n', 'newest-first', None, _('show newest record first')),
4397 ('n', 'newest-first', None, _('show newest record first')),
4394 ('B', 'bookmarks', False, _('compare bookmarks')),
4398 ('B', 'bookmarks', False, _('compare bookmarks')),
4395 ('b', 'branch', [], _('a specific branch you would like to push'),
4399 ('b', 'branch', [], _('a specific branch you would like to push'),
4396 _('BRANCH')),
4400 _('BRANCH')),
4397 ] + logopts + remoteopts + subrepoopts,
4401 ] + logopts + remoteopts + subrepoopts,
4398 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4402 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4399 def outgoing(ui, repo, dest=None, **opts):
4403 def outgoing(ui, repo, dest=None, **opts):
4400 """show changesets not found in the destination
4404 """show changesets not found in the destination
4401
4405
4402 Show changesets not found in the specified destination repository
4406 Show changesets not found in the specified destination repository
4403 or the default push location. These are the changesets that would
4407 or the default push location. These are the changesets that would
4404 be pushed if a push was requested.
4408 be pushed if a push was requested.
4405
4409
4406 See pull for details of valid destination formats.
4410 See pull for details of valid destination formats.
4407
4411
4408 Returns 0 if there are outgoing changes, 1 otherwise.
4412 Returns 0 if there are outgoing changes, 1 otherwise.
4409 """
4413 """
4410 if opts.get('graph'):
4414 if opts.get('graph'):
4411 cmdutil.checkunsupportedgraphflags([], opts)
4415 cmdutil.checkunsupportedgraphflags([], opts)
4412 o, other = hg._outgoing(ui, repo, dest, opts)
4416 o, other = hg._outgoing(ui, repo, dest, opts)
4413 if not o:
4417 if not o:
4414 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4418 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4415 return
4419 return
4416
4420
4417 revdag = cmdutil.graphrevs(repo, o, opts)
4421 revdag = cmdutil.graphrevs(repo, o, opts)
4418 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4422 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4419 showparents = [ctx.node() for ctx in repo[None].parents()]
4423 showparents = [ctx.node() for ctx in repo[None].parents()]
4420 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4424 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4421 graphmod.asciiedges)
4425 graphmod.asciiedges)
4422 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4426 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4423 return 0
4427 return 0
4424
4428
4425 if opts.get('bookmarks'):
4429 if opts.get('bookmarks'):
4426 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4430 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4427 dest, branches = hg.parseurl(dest, opts.get('branch'))
4431 dest, branches = hg.parseurl(dest, opts.get('branch'))
4428 other = hg.peer(repo, opts, dest)
4432 other = hg.peer(repo, opts, dest)
4429 if 'bookmarks' not in other.listkeys('namespaces'):
4433 if 'bookmarks' not in other.listkeys('namespaces'):
4430 ui.warn(_("remote doesn't support bookmarks\n"))
4434 ui.warn(_("remote doesn't support bookmarks\n"))
4431 return 0
4435 return 0
4432 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4436 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4433 return bookmarks.diff(ui, other, repo)
4437 return bookmarks.diff(ui, other, repo)
4434
4438
4435 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4439 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4436 try:
4440 try:
4437 return hg.outgoing(ui, repo, dest, opts)
4441 return hg.outgoing(ui, repo, dest, opts)
4438 finally:
4442 finally:
4439 del repo._subtoppath
4443 del repo._subtoppath
4440
4444
4441 @command('parents',
4445 @command('parents',
4442 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4446 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4443 ] + templateopts,
4447 ] + templateopts,
4444 _('[-r REV] [FILE]'),
4448 _('[-r REV] [FILE]'),
4445 inferrepo=True)
4449 inferrepo=True)
4446 def parents(ui, repo, file_=None, **opts):
4450 def parents(ui, repo, file_=None, **opts):
4447 """show the parents of the working directory or revision
4451 """show the parents of the working directory or revision
4448
4452
4449 Print the working directory's parent revisions. If a revision is
4453 Print the working directory's parent revisions. If a revision is
4450 given via -r/--rev, the parent of that revision will be printed.
4454 given via -r/--rev, the parent of that revision will be printed.
4451 If a file argument is given, the revision in which the file was
4455 If a file argument is given, the revision in which the file was
4452 last changed (before the working directory revision or the
4456 last changed (before the working directory revision or the
4453 argument to --rev if given) is printed.
4457 argument to --rev if given) is printed.
4454
4458
4455 Returns 0 on success.
4459 Returns 0 on success.
4456 """
4460 """
4457
4461
4458 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4462 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4459
4463
4460 if file_:
4464 if file_:
4461 m = scmutil.match(ctx, (file_,), opts)
4465 m = scmutil.match(ctx, (file_,), opts)
4462 if m.anypats() or len(m.files()) != 1:
4466 if m.anypats() or len(m.files()) != 1:
4463 raise util.Abort(_('can only specify an explicit filename'))
4467 raise util.Abort(_('can only specify an explicit filename'))
4464 file_ = m.files()[0]
4468 file_ = m.files()[0]
4465 filenodes = []
4469 filenodes = []
4466 for cp in ctx.parents():
4470 for cp in ctx.parents():
4467 if not cp:
4471 if not cp:
4468 continue
4472 continue
4469 try:
4473 try:
4470 filenodes.append(cp.filenode(file_))
4474 filenodes.append(cp.filenode(file_))
4471 except error.LookupError:
4475 except error.LookupError:
4472 pass
4476 pass
4473 if not filenodes:
4477 if not filenodes:
4474 raise util.Abort(_("'%s' not found in manifest!") % file_)
4478 raise util.Abort(_("'%s' not found in manifest!") % file_)
4475 p = []
4479 p = []
4476 for fn in filenodes:
4480 for fn in filenodes:
4477 fctx = repo.filectx(file_, fileid=fn)
4481 fctx = repo.filectx(file_, fileid=fn)
4478 p.append(fctx.node())
4482 p.append(fctx.node())
4479 else:
4483 else:
4480 p = [cp.node() for cp in ctx.parents()]
4484 p = [cp.node() for cp in ctx.parents()]
4481
4485
4482 displayer = cmdutil.show_changeset(ui, repo, opts)
4486 displayer = cmdutil.show_changeset(ui, repo, opts)
4483 for n in p:
4487 for n in p:
4484 if n != nullid:
4488 if n != nullid:
4485 displayer.show(repo[n])
4489 displayer.show(repo[n])
4486 displayer.close()
4490 displayer.close()
4487
4491
4488 @command('paths', [], _('[NAME]'), optionalrepo=True)
4492 @command('paths', [], _('[NAME]'), optionalrepo=True)
4489 def paths(ui, repo, search=None):
4493 def paths(ui, repo, search=None):
4490 """show aliases for remote repositories
4494 """show aliases for remote repositories
4491
4495
4492 Show definition of symbolic path name NAME. If no name is given,
4496 Show definition of symbolic path name NAME. If no name is given,
4493 show definition of all available names.
4497 show definition of all available names.
4494
4498
4495 Option -q/--quiet suppresses all output when searching for NAME
4499 Option -q/--quiet suppresses all output when searching for NAME
4496 and shows only the path names when listing all definitions.
4500 and shows only the path names when listing all definitions.
4497
4501
4498 Path names are defined in the [paths] section of your
4502 Path names are defined in the [paths] section of your
4499 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4503 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4500 repository, ``.hg/hgrc`` is used, too.
4504 repository, ``.hg/hgrc`` is used, too.
4501
4505
4502 The path names ``default`` and ``default-push`` have a special
4506 The path names ``default`` and ``default-push`` have a special
4503 meaning. When performing a push or pull operation, they are used
4507 meaning. When performing a push or pull operation, they are used
4504 as fallbacks if no location is specified on the command-line.
4508 as fallbacks if no location is specified on the command-line.
4505 When ``default-push`` is set, it will be used for push and
4509 When ``default-push`` is set, it will be used for push and
4506 ``default`` will be used for pull; otherwise ``default`` is used
4510 ``default`` will be used for pull; otherwise ``default`` is used
4507 as the fallback for both. When cloning a repository, the clone
4511 as the fallback for both. When cloning a repository, the clone
4508 source is written as ``default`` in ``.hg/hgrc``. Note that
4512 source is written as ``default`` in ``.hg/hgrc``. Note that
4509 ``default`` and ``default-push`` apply to all inbound (e.g.
4513 ``default`` and ``default-push`` apply to all inbound (e.g.
4510 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4514 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4511 :hg:`bundle`) operations.
4515 :hg:`bundle`) operations.
4512
4516
4513 See :hg:`help urls` for more information.
4517 See :hg:`help urls` for more information.
4514
4518
4515 Returns 0 on success.
4519 Returns 0 on success.
4516 """
4520 """
4517 if search:
4521 if search:
4518 for name, path in ui.configitems("paths"):
4522 for name, path in ui.configitems("paths"):
4519 if name == search:
4523 if name == search:
4520 ui.status("%s\n" % util.hidepassword(path))
4524 ui.status("%s\n" % util.hidepassword(path))
4521 return
4525 return
4522 if not ui.quiet:
4526 if not ui.quiet:
4523 ui.warn(_("not found!\n"))
4527 ui.warn(_("not found!\n"))
4524 return 1
4528 return 1
4525 else:
4529 else:
4526 for name, path in ui.configitems("paths"):
4530 for name, path in ui.configitems("paths"):
4527 if ui.quiet:
4531 if ui.quiet:
4528 ui.write("%s\n" % name)
4532 ui.write("%s\n" % name)
4529 else:
4533 else:
4530 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4534 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4531
4535
4532 @command('phase',
4536 @command('phase',
4533 [('p', 'public', False, _('set changeset phase to public')),
4537 [('p', 'public', False, _('set changeset phase to public')),
4534 ('d', 'draft', False, _('set changeset phase to draft')),
4538 ('d', 'draft', False, _('set changeset phase to draft')),
4535 ('s', 'secret', False, _('set changeset phase to secret')),
4539 ('s', 'secret', False, _('set changeset phase to secret')),
4536 ('f', 'force', False, _('allow to move boundary backward')),
4540 ('f', 'force', False, _('allow to move boundary backward')),
4537 ('r', 'rev', [], _('target revision'), _('REV')),
4541 ('r', 'rev', [], _('target revision'), _('REV')),
4538 ],
4542 ],
4539 _('[-p|-d|-s] [-f] [-r] REV...'))
4543 _('[-p|-d|-s] [-f] [-r] REV...'))
4540 def phase(ui, repo, *revs, **opts):
4544 def phase(ui, repo, *revs, **opts):
4541 """set or show the current phase name
4545 """set or show the current phase name
4542
4546
4543 With no argument, show the phase name of specified revisions.
4547 With no argument, show the phase name of specified revisions.
4544
4548
4545 With one of -p/--public, -d/--draft or -s/--secret, change the
4549 With one of -p/--public, -d/--draft or -s/--secret, change the
4546 phase value of the specified revisions.
4550 phase value of the specified revisions.
4547
4551
4548 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4552 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4549 lower phase to an higher phase. Phases are ordered as follows::
4553 lower phase to an higher phase. Phases are ordered as follows::
4550
4554
4551 public < draft < secret
4555 public < draft < secret
4552
4556
4553 Returns 0 on success, 1 if no phases were changed or some could not
4557 Returns 0 on success, 1 if no phases were changed or some could not
4554 be changed.
4558 be changed.
4555 """
4559 """
4556 # search for a unique phase argument
4560 # search for a unique phase argument
4557 targetphase = None
4561 targetphase = None
4558 for idx, name in enumerate(phases.phasenames):
4562 for idx, name in enumerate(phases.phasenames):
4559 if opts[name]:
4563 if opts[name]:
4560 if targetphase is not None:
4564 if targetphase is not None:
4561 raise util.Abort(_('only one phase can be specified'))
4565 raise util.Abort(_('only one phase can be specified'))
4562 targetphase = idx
4566 targetphase = idx
4563
4567
4564 # look for specified revision
4568 # look for specified revision
4565 revs = list(revs)
4569 revs = list(revs)
4566 revs.extend(opts['rev'])
4570 revs.extend(opts['rev'])
4567 if not revs:
4571 if not revs:
4568 raise util.Abort(_('no revisions specified'))
4572 raise util.Abort(_('no revisions specified'))
4569
4573
4570 revs = scmutil.revrange(repo, revs)
4574 revs = scmutil.revrange(repo, revs)
4571
4575
4572 lock = None
4576 lock = None
4573 ret = 0
4577 ret = 0
4574 if targetphase is None:
4578 if targetphase is None:
4575 # display
4579 # display
4576 for r in revs:
4580 for r in revs:
4577 ctx = repo[r]
4581 ctx = repo[r]
4578 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4582 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4579 else:
4583 else:
4580 tr = None
4584 tr = None
4581 lock = repo.lock()
4585 lock = repo.lock()
4582 try:
4586 try:
4583 tr = repo.transaction("phase")
4587 tr = repo.transaction("phase")
4584 # set phase
4588 # set phase
4585 if not revs:
4589 if not revs:
4586 raise util.Abort(_('empty revision set'))
4590 raise util.Abort(_('empty revision set'))
4587 nodes = [repo[r].node() for r in revs]
4591 nodes = [repo[r].node() for r in revs]
4588 olddata = repo._phasecache.getphaserevs(repo)[:]
4592 olddata = repo._phasecache.getphaserevs(repo)[:]
4589 phases.advanceboundary(repo, tr, targetphase, nodes)
4593 phases.advanceboundary(repo, tr, targetphase, nodes)
4590 if opts['force']:
4594 if opts['force']:
4591 phases.retractboundary(repo, tr, targetphase, nodes)
4595 phases.retractboundary(repo, tr, targetphase, nodes)
4592 tr.close()
4596 tr.close()
4593 finally:
4597 finally:
4594 if tr is not None:
4598 if tr is not None:
4595 tr.release()
4599 tr.release()
4596 lock.release()
4600 lock.release()
4597 # moving revision from public to draft may hide them
4601 # moving revision from public to draft may hide them
4598 # We have to check result on an unfiltered repository
4602 # We have to check result on an unfiltered repository
4599 unfi = repo.unfiltered()
4603 unfi = repo.unfiltered()
4600 newdata = repo._phasecache.getphaserevs(unfi)
4604 newdata = repo._phasecache.getphaserevs(unfi)
4601 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4605 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4602 cl = unfi.changelog
4606 cl = unfi.changelog
4603 rejected = [n for n in nodes
4607 rejected = [n for n in nodes
4604 if newdata[cl.rev(n)] < targetphase]
4608 if newdata[cl.rev(n)] < targetphase]
4605 if rejected:
4609 if rejected:
4606 ui.warn(_('cannot move %i changesets to a higher '
4610 ui.warn(_('cannot move %i changesets to a higher '
4607 'phase, use --force\n') % len(rejected))
4611 'phase, use --force\n') % len(rejected))
4608 ret = 1
4612 ret = 1
4609 if changes:
4613 if changes:
4610 msg = _('phase changed for %i changesets\n') % changes
4614 msg = _('phase changed for %i changesets\n') % changes
4611 if ret:
4615 if ret:
4612 ui.status(msg)
4616 ui.status(msg)
4613 else:
4617 else:
4614 ui.note(msg)
4618 ui.note(msg)
4615 else:
4619 else:
4616 ui.warn(_('no phases changed\n'))
4620 ui.warn(_('no phases changed\n'))
4617 ret = 1
4621 ret = 1
4618 return ret
4622 return ret
4619
4623
4620 def postincoming(ui, repo, modheads, optupdate, checkout):
4624 def postincoming(ui, repo, modheads, optupdate, checkout):
4621 if modheads == 0:
4625 if modheads == 0:
4622 return
4626 return
4623 if optupdate:
4627 if optupdate:
4624 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4628 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4625 try:
4629 try:
4626 ret = hg.update(repo, checkout)
4630 ret = hg.update(repo, checkout)
4627 except util.Abort, inst:
4631 except util.Abort, inst:
4628 ui.warn(_("not updating: %s\n") % str(inst))
4632 ui.warn(_("not updating: %s\n") % str(inst))
4629 if inst.hint:
4633 if inst.hint:
4630 ui.warn(_("(%s)\n") % inst.hint)
4634 ui.warn(_("(%s)\n") % inst.hint)
4631 return 0
4635 return 0
4632 if not ret and not checkout:
4636 if not ret and not checkout:
4633 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4637 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4634 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4638 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4635 return ret
4639 return ret
4636 if modheads > 1:
4640 if modheads > 1:
4637 currentbranchheads = len(repo.branchheads())
4641 currentbranchheads = len(repo.branchheads())
4638 if currentbranchheads == modheads:
4642 if currentbranchheads == modheads:
4639 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4643 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4640 elif currentbranchheads > 1:
4644 elif currentbranchheads > 1:
4641 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4645 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4642 "merge)\n"))
4646 "merge)\n"))
4643 else:
4647 else:
4644 ui.status(_("(run 'hg heads' to see heads)\n"))
4648 ui.status(_("(run 'hg heads' to see heads)\n"))
4645 else:
4649 else:
4646 ui.status(_("(run 'hg update' to get a working copy)\n"))
4650 ui.status(_("(run 'hg update' to get a working copy)\n"))
4647
4651
4648 @command('^pull',
4652 @command('^pull',
4649 [('u', 'update', None,
4653 [('u', 'update', None,
4650 _('update to new branch head if changesets were pulled')),
4654 _('update to new branch head if changesets were pulled')),
4651 ('f', 'force', None, _('run even when remote repository is unrelated')),
4655 ('f', 'force', None, _('run even when remote repository is unrelated')),
4652 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4656 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4653 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4657 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4654 ('b', 'branch', [], _('a specific branch you would like to pull'),
4658 ('b', 'branch', [], _('a specific branch you would like to pull'),
4655 _('BRANCH')),
4659 _('BRANCH')),
4656 ] + remoteopts,
4660 ] + remoteopts,
4657 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4661 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4658 def pull(ui, repo, source="default", **opts):
4662 def pull(ui, repo, source="default", **opts):
4659 """pull changes from the specified source
4663 """pull changes from the specified source
4660
4664
4661 Pull changes from a remote repository to a local one.
4665 Pull changes from a remote repository to a local one.
4662
4666
4663 This finds all changes from the repository at the specified path
4667 This finds all changes from the repository at the specified path
4664 or URL and adds them to a local repository (the current one unless
4668 or URL and adds them to a local repository (the current one unless
4665 -R is specified). By default, this does not update the copy of the
4669 -R is specified). By default, this does not update the copy of the
4666 project in the working directory.
4670 project in the working directory.
4667
4671
4668 Use :hg:`incoming` if you want to see what would have been added
4672 Use :hg:`incoming` if you want to see what would have been added
4669 by a pull at the time you issued this command. If you then decide
4673 by a pull at the time you issued this command. If you then decide
4670 to add those changes to the repository, you should use :hg:`pull
4674 to add those changes to the repository, you should use :hg:`pull
4671 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4675 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4672
4676
4673 If SOURCE is omitted, the 'default' path will be used.
4677 If SOURCE is omitted, the 'default' path will be used.
4674 See :hg:`help urls` for more information.
4678 See :hg:`help urls` for more information.
4675
4679
4676 Returns 0 on success, 1 if an update had unresolved files.
4680 Returns 0 on success, 1 if an update had unresolved files.
4677 """
4681 """
4678 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4682 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4679 other = hg.peer(repo, opts, source)
4683 other = hg.peer(repo, opts, source)
4680 try:
4684 try:
4681 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4685 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4682 revs, checkout = hg.addbranchrevs(repo, other, branches,
4686 revs, checkout = hg.addbranchrevs(repo, other, branches,
4683 opts.get('rev'))
4687 opts.get('rev'))
4684
4688
4685 remotebookmarks = other.listkeys('bookmarks')
4689 remotebookmarks = other.listkeys('bookmarks')
4686
4690
4687 if opts.get('bookmark'):
4691 if opts.get('bookmark'):
4688 if not revs:
4692 if not revs:
4689 revs = []
4693 revs = []
4690 for b in opts['bookmark']:
4694 for b in opts['bookmark']:
4691 if b not in remotebookmarks:
4695 if b not in remotebookmarks:
4692 raise util.Abort(_('remote bookmark %s not found!') % b)
4696 raise util.Abort(_('remote bookmark %s not found!') % b)
4693 revs.append(remotebookmarks[b])
4697 revs.append(remotebookmarks[b])
4694
4698
4695 if revs:
4699 if revs:
4696 try:
4700 try:
4697 revs = [other.lookup(rev) for rev in revs]
4701 revs = [other.lookup(rev) for rev in revs]
4698 except error.CapabilityError:
4702 except error.CapabilityError:
4699 err = _("other repository doesn't support revision lookup, "
4703 err = _("other repository doesn't support revision lookup, "
4700 "so a rev cannot be specified.")
4704 "so a rev cannot be specified.")
4701 raise util.Abort(err)
4705 raise util.Abort(err)
4702
4706
4703 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4707 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4704 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4708 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4705 if checkout:
4709 if checkout:
4706 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4710 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4707 repo._subtoppath = source
4711 repo._subtoppath = source
4708 try:
4712 try:
4709 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4713 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4710
4714
4711 finally:
4715 finally:
4712 del repo._subtoppath
4716 del repo._subtoppath
4713
4717
4714 # update specified bookmarks
4718 # update specified bookmarks
4715 if opts.get('bookmark'):
4719 if opts.get('bookmark'):
4716 marks = repo._bookmarks
4720 marks = repo._bookmarks
4717 for b in opts['bookmark']:
4721 for b in opts['bookmark']:
4718 # explicit pull overrides local bookmark if any
4722 # explicit pull overrides local bookmark if any
4719 ui.status(_("importing bookmark %s\n") % b)
4723 ui.status(_("importing bookmark %s\n") % b)
4720 marks[b] = repo[remotebookmarks[b]].node()
4724 marks[b] = repo[remotebookmarks[b]].node()
4721 marks.write()
4725 marks.write()
4722 finally:
4726 finally:
4723 other.close()
4727 other.close()
4724 return ret
4728 return ret
4725
4729
4726 @command('^push',
4730 @command('^push',
4727 [('f', 'force', None, _('force push')),
4731 [('f', 'force', None, _('force push')),
4728 ('r', 'rev', [],
4732 ('r', 'rev', [],
4729 _('a changeset intended to be included in the destination'),
4733 _('a changeset intended to be included in the destination'),
4730 _('REV')),
4734 _('REV')),
4731 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4735 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4732 ('b', 'branch', [],
4736 ('b', 'branch', [],
4733 _('a specific branch you would like to push'), _('BRANCH')),
4737 _('a specific branch you would like to push'), _('BRANCH')),
4734 ('', 'new-branch', False, _('allow pushing a new branch')),
4738 ('', 'new-branch', False, _('allow pushing a new branch')),
4735 ] + remoteopts,
4739 ] + remoteopts,
4736 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4740 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4737 def push(ui, repo, dest=None, **opts):
4741 def push(ui, repo, dest=None, **opts):
4738 """push changes to the specified destination
4742 """push changes to the specified destination
4739
4743
4740 Push changesets from the local repository to the specified
4744 Push changesets from the local repository to the specified
4741 destination.
4745 destination.
4742
4746
4743 This operation is symmetrical to pull: it is identical to a pull
4747 This operation is symmetrical to pull: it is identical to a pull
4744 in the destination repository from the current one.
4748 in the destination repository from the current one.
4745
4749
4746 By default, push will not allow creation of new heads at the
4750 By default, push will not allow creation of new heads at the
4747 destination, since multiple heads would make it unclear which head
4751 destination, since multiple heads would make it unclear which head
4748 to use. In this situation, it is recommended to pull and merge
4752 to use. In this situation, it is recommended to pull and merge
4749 before pushing.
4753 before pushing.
4750
4754
4751 Use --new-branch if you want to allow push to create a new named
4755 Use --new-branch if you want to allow push to create a new named
4752 branch that is not present at the destination. This allows you to
4756 branch that is not present at the destination. This allows you to
4753 only create a new branch without forcing other changes.
4757 only create a new branch without forcing other changes.
4754
4758
4755 .. note::
4759 .. note::
4756
4760
4757 Extra care should be taken with the -f/--force option,
4761 Extra care should be taken with the -f/--force option,
4758 which will push all new heads on all branches, an action which will
4762 which will push all new heads on all branches, an action which will
4759 almost always cause confusion for collaborators.
4763 almost always cause confusion for collaborators.
4760
4764
4761 If -r/--rev is used, the specified revision and all its ancestors
4765 If -r/--rev is used, the specified revision and all its ancestors
4762 will be pushed to the remote repository.
4766 will be pushed to the remote repository.
4763
4767
4764 If -B/--bookmark is used, the specified bookmarked revision, its
4768 If -B/--bookmark is used, the specified bookmarked revision, its
4765 ancestors, and the bookmark will be pushed to the remote
4769 ancestors, and the bookmark will be pushed to the remote
4766 repository.
4770 repository.
4767
4771
4768 Please see :hg:`help urls` for important details about ``ssh://``
4772 Please see :hg:`help urls` for important details about ``ssh://``
4769 URLs. If DESTINATION is omitted, a default path will be used.
4773 URLs. If DESTINATION is omitted, a default path will be used.
4770
4774
4771 Returns 0 if push was successful, 1 if nothing to push.
4775 Returns 0 if push was successful, 1 if nothing to push.
4772 """
4776 """
4773
4777
4774 if opts.get('bookmark'):
4778 if opts.get('bookmark'):
4775 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4779 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4776 for b in opts['bookmark']:
4780 for b in opts['bookmark']:
4777 # translate -B options to -r so changesets get pushed
4781 # translate -B options to -r so changesets get pushed
4778 if b in repo._bookmarks:
4782 if b in repo._bookmarks:
4779 opts.setdefault('rev', []).append(b)
4783 opts.setdefault('rev', []).append(b)
4780 else:
4784 else:
4781 # if we try to push a deleted bookmark, translate it to null
4785 # if we try to push a deleted bookmark, translate it to null
4782 # this lets simultaneous -r, -b options continue working
4786 # this lets simultaneous -r, -b options continue working
4783 opts.setdefault('rev', []).append("null")
4787 opts.setdefault('rev', []).append("null")
4784
4788
4785 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4789 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4786 dest, branches = hg.parseurl(dest, opts.get('branch'))
4790 dest, branches = hg.parseurl(dest, opts.get('branch'))
4787 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4791 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4788 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4792 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4789 try:
4793 try:
4790 other = hg.peer(repo, opts, dest)
4794 other = hg.peer(repo, opts, dest)
4791 except error.RepoError:
4795 except error.RepoError:
4792 if dest == "default-push":
4796 if dest == "default-push":
4793 raise util.Abort(_("default repository not configured!"),
4797 raise util.Abort(_("default repository not configured!"),
4794 hint=_('see the "path" section in "hg help config"'))
4798 hint=_('see the "path" section in "hg help config"'))
4795 else:
4799 else:
4796 raise
4800 raise
4797
4801
4798 if revs:
4802 if revs:
4799 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4803 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4800
4804
4801 repo._subtoppath = dest
4805 repo._subtoppath = dest
4802 try:
4806 try:
4803 # push subrepos depth-first for coherent ordering
4807 # push subrepos depth-first for coherent ordering
4804 c = repo['']
4808 c = repo['']
4805 subs = c.substate # only repos that are committed
4809 subs = c.substate # only repos that are committed
4806 for s in sorted(subs):
4810 for s in sorted(subs):
4807 result = c.sub(s).push(opts)
4811 result = c.sub(s).push(opts)
4808 if result == 0:
4812 if result == 0:
4809 return not result
4813 return not result
4810 finally:
4814 finally:
4811 del repo._subtoppath
4815 del repo._subtoppath
4812 result = repo.push(other, opts.get('force'), revs=revs,
4816 result = repo.push(other, opts.get('force'), revs=revs,
4813 newbranch=opts.get('new_branch'))
4817 newbranch=opts.get('new_branch'))
4814
4818
4815 result = not result
4819 result = not result
4816
4820
4817 if opts.get('bookmark'):
4821 if opts.get('bookmark'):
4818 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4822 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4819 if bresult == 2:
4823 if bresult == 2:
4820 return 2
4824 return 2
4821 if not result and bresult:
4825 if not result and bresult:
4822 result = 2
4826 result = 2
4823
4827
4824 return result
4828 return result
4825
4829
4826 @command('recover', [])
4830 @command('recover', [])
4827 def recover(ui, repo):
4831 def recover(ui, repo):
4828 """roll back an interrupted transaction
4832 """roll back an interrupted transaction
4829
4833
4830 Recover from an interrupted commit or pull.
4834 Recover from an interrupted commit or pull.
4831
4835
4832 This command tries to fix the repository status after an
4836 This command tries to fix the repository status after an
4833 interrupted operation. It should only be necessary when Mercurial
4837 interrupted operation. It should only be necessary when Mercurial
4834 suggests it.
4838 suggests it.
4835
4839
4836 Returns 0 if successful, 1 if nothing to recover or verify fails.
4840 Returns 0 if successful, 1 if nothing to recover or verify fails.
4837 """
4841 """
4838 if repo.recover():
4842 if repo.recover():
4839 return hg.verify(repo)
4843 return hg.verify(repo)
4840 return 1
4844 return 1
4841
4845
4842 @command('^remove|rm',
4846 @command('^remove|rm',
4843 [('A', 'after', None, _('record delete for missing files')),
4847 [('A', 'after', None, _('record delete for missing files')),
4844 ('f', 'force', None,
4848 ('f', 'force', None,
4845 _('remove (and delete) file even if added or modified')),
4849 _('remove (and delete) file even if added or modified')),
4846 ] + walkopts,
4850 ] + walkopts,
4847 _('[OPTION]... FILE...'),
4851 _('[OPTION]... FILE...'),
4848 inferrepo=True)
4852 inferrepo=True)
4849 def remove(ui, repo, *pats, **opts):
4853 def remove(ui, repo, *pats, **opts):
4850 """remove the specified files on the next commit
4854 """remove the specified files on the next commit
4851
4855
4852 Schedule the indicated files for removal from the current branch.
4856 Schedule the indicated files for removal from the current branch.
4853
4857
4854 This command schedules the files to be removed at the next commit.
4858 This command schedules the files to be removed at the next commit.
4855 To undo a remove before that, see :hg:`revert`. To undo added
4859 To undo a remove before that, see :hg:`revert`. To undo added
4856 files, see :hg:`forget`.
4860 files, see :hg:`forget`.
4857
4861
4858 .. container:: verbose
4862 .. container:: verbose
4859
4863
4860 -A/--after can be used to remove only files that have already
4864 -A/--after can be used to remove only files that have already
4861 been deleted, -f/--force can be used to force deletion, and -Af
4865 been deleted, -f/--force can be used to force deletion, and -Af
4862 can be used to remove files from the next revision without
4866 can be used to remove files from the next revision without
4863 deleting them from the working directory.
4867 deleting them from the working directory.
4864
4868
4865 The following table details the behavior of remove for different
4869 The following table details the behavior of remove for different
4866 file states (columns) and option combinations (rows). The file
4870 file states (columns) and option combinations (rows). The file
4867 states are Added [A], Clean [C], Modified [M] and Missing [!]
4871 states are Added [A], Clean [C], Modified [M] and Missing [!]
4868 (as reported by :hg:`status`). The actions are Warn, Remove
4872 (as reported by :hg:`status`). The actions are Warn, Remove
4869 (from branch) and Delete (from disk):
4873 (from branch) and Delete (from disk):
4870
4874
4871 ========= == == == ==
4875 ========= == == == ==
4872 opt/state A C M !
4876 opt/state A C M !
4873 ========= == == == ==
4877 ========= == == == ==
4874 none W RD W R
4878 none W RD W R
4875 -f R RD RD R
4879 -f R RD RD R
4876 -A W W W R
4880 -A W W W R
4877 -Af R R R R
4881 -Af R R R R
4878 ========= == == == ==
4882 ========= == == == ==
4879
4883
4880 Note that remove never deletes files in Added [A] state from the
4884 Note that remove never deletes files in Added [A] state from the
4881 working directory, not even if option --force is specified.
4885 working directory, not even if option --force is specified.
4882
4886
4883 Returns 0 on success, 1 if any warnings encountered.
4887 Returns 0 on success, 1 if any warnings encountered.
4884 """
4888 """
4885
4889
4886 ret = 0
4890 ret = 0
4887 after, force = opts.get('after'), opts.get('force')
4891 after, force = opts.get('after'), opts.get('force')
4888 if not pats and not after:
4892 if not pats and not after:
4889 raise util.Abort(_('no files specified'))
4893 raise util.Abort(_('no files specified'))
4890
4894
4891 m = scmutil.match(repo[None], pats, opts)
4895 m = scmutil.match(repo[None], pats, opts)
4892 s = repo.status(match=m, clean=True)
4896 s = repo.status(match=m, clean=True)
4893 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4897 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4894
4898
4895 # warn about failure to delete explicit files/dirs
4899 # warn about failure to delete explicit files/dirs
4896 wctx = repo[None]
4900 wctx = repo[None]
4897 for f in m.files():
4901 for f in m.files():
4898 if f in repo.dirstate or f in wctx.dirs():
4902 if f in repo.dirstate or f in wctx.dirs():
4899 continue
4903 continue
4900 if os.path.exists(m.rel(f)):
4904 if os.path.exists(m.rel(f)):
4901 if os.path.isdir(m.rel(f)):
4905 if os.path.isdir(m.rel(f)):
4902 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4906 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4903 else:
4907 else:
4904 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4908 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4905 # missing files will generate a warning elsewhere
4909 # missing files will generate a warning elsewhere
4906 ret = 1
4910 ret = 1
4907
4911
4908 if force:
4912 if force:
4909 list = modified + deleted + clean + added
4913 list = modified + deleted + clean + added
4910 elif after:
4914 elif after:
4911 list = deleted
4915 list = deleted
4912 for f in modified + added + clean:
4916 for f in modified + added + clean:
4913 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4917 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4914 ret = 1
4918 ret = 1
4915 else:
4919 else:
4916 list = deleted + clean
4920 list = deleted + clean
4917 for f in modified:
4921 for f in modified:
4918 ui.warn(_('not removing %s: file is modified (use -f'
4922 ui.warn(_('not removing %s: file is modified (use -f'
4919 ' to force removal)\n') % m.rel(f))
4923 ' to force removal)\n') % m.rel(f))
4920 ret = 1
4924 ret = 1
4921 for f in added:
4925 for f in added:
4922 ui.warn(_('not removing %s: file has been marked for add'
4926 ui.warn(_('not removing %s: file has been marked for add'
4923 ' (use forget to undo)\n') % m.rel(f))
4927 ' (use forget to undo)\n') % m.rel(f))
4924 ret = 1
4928 ret = 1
4925
4929
4926 for f in sorted(list):
4930 for f in sorted(list):
4927 if ui.verbose or not m.exact(f):
4931 if ui.verbose or not m.exact(f):
4928 ui.status(_('removing %s\n') % m.rel(f))
4932 ui.status(_('removing %s\n') % m.rel(f))
4929
4933
4930 wlock = repo.wlock()
4934 wlock = repo.wlock()
4931 try:
4935 try:
4932 if not after:
4936 if not after:
4933 for f in list:
4937 for f in list:
4934 if f in added:
4938 if f in added:
4935 continue # we never unlink added files on remove
4939 continue # we never unlink added files on remove
4936 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4940 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4937 repo[None].forget(list)
4941 repo[None].forget(list)
4938 finally:
4942 finally:
4939 wlock.release()
4943 wlock.release()
4940
4944
4941 return ret
4945 return ret
4942
4946
4943 @command('rename|move|mv',
4947 @command('rename|move|mv',
4944 [('A', 'after', None, _('record a rename that has already occurred')),
4948 [('A', 'after', None, _('record a rename that has already occurred')),
4945 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4949 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4946 ] + walkopts + dryrunopts,
4950 ] + walkopts + dryrunopts,
4947 _('[OPTION]... SOURCE... DEST'))
4951 _('[OPTION]... SOURCE... DEST'))
4948 def rename(ui, repo, *pats, **opts):
4952 def rename(ui, repo, *pats, **opts):
4949 """rename files; equivalent of copy + remove
4953 """rename files; equivalent of copy + remove
4950
4954
4951 Mark dest as copies of sources; mark sources for deletion. If dest
4955 Mark dest as copies of sources; mark sources for deletion. If dest
4952 is a directory, copies are put in that directory. If dest is a
4956 is a directory, copies are put in that directory. If dest is a
4953 file, there can only be one source.
4957 file, there can only be one source.
4954
4958
4955 By default, this command copies the contents of files as they
4959 By default, this command copies the contents of files as they
4956 exist in the working directory. If invoked with -A/--after, the
4960 exist in the working directory. If invoked with -A/--after, the
4957 operation is recorded, but no copying is performed.
4961 operation is recorded, but no copying is performed.
4958
4962
4959 This command takes effect at the next commit. To undo a rename
4963 This command takes effect at the next commit. To undo a rename
4960 before that, see :hg:`revert`.
4964 before that, see :hg:`revert`.
4961
4965
4962 Returns 0 on success, 1 if errors are encountered.
4966 Returns 0 on success, 1 if errors are encountered.
4963 """
4967 """
4964 wlock = repo.wlock(False)
4968 wlock = repo.wlock(False)
4965 try:
4969 try:
4966 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4970 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4967 finally:
4971 finally:
4968 wlock.release()
4972 wlock.release()
4969
4973
4970 @command('resolve',
4974 @command('resolve',
4971 [('a', 'all', None, _('select all unresolved files')),
4975 [('a', 'all', None, _('select all unresolved files')),
4972 ('l', 'list', None, _('list state of files needing merge')),
4976 ('l', 'list', None, _('list state of files needing merge')),
4973 ('m', 'mark', None, _('mark files as resolved')),
4977 ('m', 'mark', None, _('mark files as resolved')),
4974 ('u', 'unmark', None, _('mark files as unresolved')),
4978 ('u', 'unmark', None, _('mark files as unresolved')),
4975 ('n', 'no-status', None, _('hide status prefix'))]
4979 ('n', 'no-status', None, _('hide status prefix'))]
4976 + mergetoolopts + walkopts,
4980 + mergetoolopts + walkopts,
4977 _('[OPTION]... [FILE]...'),
4981 _('[OPTION]... [FILE]...'),
4978 inferrepo=True)
4982 inferrepo=True)
4979 def resolve(ui, repo, *pats, **opts):
4983 def resolve(ui, repo, *pats, **opts):
4980 """redo merges or set/view the merge status of files
4984 """redo merges or set/view the merge status of files
4981
4985
4982 Merges with unresolved conflicts are often the result of
4986 Merges with unresolved conflicts are often the result of
4983 non-interactive merging using the ``internal:merge`` configuration
4987 non-interactive merging using the ``internal:merge`` configuration
4984 setting, or a command-line merge tool like ``diff3``. The resolve
4988 setting, or a command-line merge tool like ``diff3``. The resolve
4985 command is used to manage the files involved in a merge, after
4989 command is used to manage the files involved in a merge, after
4986 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4990 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4987 working directory must have two parents). See :hg:`help
4991 working directory must have two parents). See :hg:`help
4988 merge-tools` for information on configuring merge tools.
4992 merge-tools` for information on configuring merge tools.
4989
4993
4990 The resolve command can be used in the following ways:
4994 The resolve command can be used in the following ways:
4991
4995
4992 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4996 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4993 files, discarding any previous merge attempts. Re-merging is not
4997 files, discarding any previous merge attempts. Re-merging is not
4994 performed for files already marked as resolved. Use ``--all/-a``
4998 performed for files already marked as resolved. Use ``--all/-a``
4995 to select all unresolved files. ``--tool`` can be used to specify
4999 to select all unresolved files. ``--tool`` can be used to specify
4996 the merge tool used for the given files. It overrides the HGMERGE
5000 the merge tool used for the given files. It overrides the HGMERGE
4997 environment variable and your configuration files. Previous file
5001 environment variable and your configuration files. Previous file
4998 contents are saved with a ``.orig`` suffix.
5002 contents are saved with a ``.orig`` suffix.
4999
5003
5000 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5004 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5001 (e.g. after having manually fixed-up the files). The default is
5005 (e.g. after having manually fixed-up the files). The default is
5002 to mark all unresolved files.
5006 to mark all unresolved files.
5003
5007
5004 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5008 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5005 default is to mark all resolved files.
5009 default is to mark all resolved files.
5006
5010
5007 - :hg:`resolve -l`: list files which had or still have conflicts.
5011 - :hg:`resolve -l`: list files which had or still have conflicts.
5008 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5012 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5009
5013
5010 Note that Mercurial will not let you commit files with unresolved
5014 Note that Mercurial will not let you commit files with unresolved
5011 merge conflicts. You must use :hg:`resolve -m ...` before you can
5015 merge conflicts. You must use :hg:`resolve -m ...` before you can
5012 commit after a conflicting merge.
5016 commit after a conflicting merge.
5013
5017
5014 Returns 0 on success, 1 if any files fail a resolve attempt.
5018 Returns 0 on success, 1 if any files fail a resolve attempt.
5015 """
5019 """
5016
5020
5017 all, mark, unmark, show, nostatus = \
5021 all, mark, unmark, show, nostatus = \
5018 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5022 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5019
5023
5020 if (show and (mark or unmark)) or (mark and unmark):
5024 if (show and (mark or unmark)) or (mark and unmark):
5021 raise util.Abort(_("too many options specified"))
5025 raise util.Abort(_("too many options specified"))
5022 if pats and all:
5026 if pats and all:
5023 raise util.Abort(_("can't specify --all and patterns"))
5027 raise util.Abort(_("can't specify --all and patterns"))
5024 if not (all or pats or show or mark or unmark):
5028 if not (all or pats or show or mark or unmark):
5025 raise util.Abort(_('no files or directories specified'),
5029 raise util.Abort(_('no files or directories specified'),
5026 hint=('use --all to remerge all files'))
5030 hint=('use --all to remerge all files'))
5027
5031
5028 wlock = repo.wlock()
5032 wlock = repo.wlock()
5029 try:
5033 try:
5030 ms = mergemod.mergestate(repo)
5034 ms = mergemod.mergestate(repo)
5031
5035
5032 if not ms.active() and not show:
5036 if not ms.active() and not show:
5033 raise util.Abort(
5037 raise util.Abort(
5034 _('resolve command not applicable when not merging'))
5038 _('resolve command not applicable when not merging'))
5035
5039
5036 m = scmutil.match(repo[None], pats, opts)
5040 m = scmutil.match(repo[None], pats, opts)
5037 ret = 0
5041 ret = 0
5038 didwork = False
5042 didwork = False
5039
5043
5040 for f in ms:
5044 for f in ms:
5041 if not m(f):
5045 if not m(f):
5042 continue
5046 continue
5043
5047
5044 didwork = True
5048 didwork = True
5045
5049
5046 if show:
5050 if show:
5047 if nostatus:
5051 if nostatus:
5048 ui.write("%s\n" % f)
5052 ui.write("%s\n" % f)
5049 else:
5053 else:
5050 ui.write("%s %s\n" % (ms[f].upper(), f),
5054 ui.write("%s %s\n" % (ms[f].upper(), f),
5051 label='resolve.' +
5055 label='resolve.' +
5052 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5056 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5053 elif mark:
5057 elif mark:
5054 ms.mark(f, "r")
5058 ms.mark(f, "r")
5055 elif unmark:
5059 elif unmark:
5056 ms.mark(f, "u")
5060 ms.mark(f, "u")
5057 else:
5061 else:
5058 wctx = repo[None]
5062 wctx = repo[None]
5059
5063
5060 # backup pre-resolve (merge uses .orig for its own purposes)
5064 # backup pre-resolve (merge uses .orig for its own purposes)
5061 a = repo.wjoin(f)
5065 a = repo.wjoin(f)
5062 util.copyfile(a, a + ".resolve")
5066 util.copyfile(a, a + ".resolve")
5063
5067
5064 try:
5068 try:
5065 # resolve file
5069 # resolve file
5066 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5070 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5067 'resolve')
5071 'resolve')
5068 if ms.resolve(f, wctx):
5072 if ms.resolve(f, wctx):
5069 ret = 1
5073 ret = 1
5070 finally:
5074 finally:
5071 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5075 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5072 ms.commit()
5076 ms.commit()
5073
5077
5074 # replace filemerge's .orig file with our resolve file
5078 # replace filemerge's .orig file with our resolve file
5075 util.rename(a + ".resolve", a + ".orig")
5079 util.rename(a + ".resolve", a + ".orig")
5076
5080
5077 ms.commit()
5081 ms.commit()
5078
5082
5079 if not didwork and pats:
5083 if not didwork and pats:
5080 ui.warn(_("arguments do not match paths that need resolving\n"))
5084 ui.warn(_("arguments do not match paths that need resolving\n"))
5081
5085
5082 finally:
5086 finally:
5083 wlock.release()
5087 wlock.release()
5084
5088
5085 # Nudge users into finishing an unfinished operation. We don't print
5089 # Nudge users into finishing an unfinished operation. We don't print
5086 # this with the list/show operation because we want list/show to remain
5090 # this with the list/show operation because we want list/show to remain
5087 # machine readable.
5091 # machine readable.
5088 if not list(ms.unresolved()) and not show:
5092 if not list(ms.unresolved()) and not show:
5089 ui.status(_('(no more unresolved files)\n'))
5093 ui.status(_('(no more unresolved files)\n'))
5090
5094
5091 return ret
5095 return ret
5092
5096
5093 @command('revert',
5097 @command('revert',
5094 [('a', 'all', None, _('revert all changes when no arguments given')),
5098 [('a', 'all', None, _('revert all changes when no arguments given')),
5095 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5099 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5096 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5100 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5097 ('C', 'no-backup', None, _('do not save backup copies of files')),
5101 ('C', 'no-backup', None, _('do not save backup copies of files')),
5098 ] + walkopts + dryrunopts,
5102 ] + walkopts + dryrunopts,
5099 _('[OPTION]... [-r REV] [NAME]...'))
5103 _('[OPTION]... [-r REV] [NAME]...'))
5100 def revert(ui, repo, *pats, **opts):
5104 def revert(ui, repo, *pats, **opts):
5101 """restore files to their checkout state
5105 """restore files to their checkout state
5102
5106
5103 .. note::
5107 .. note::
5104
5108
5105 To check out earlier revisions, you should use :hg:`update REV`.
5109 To check out earlier revisions, you should use :hg:`update REV`.
5106 To cancel an uncommitted merge (and lose your changes),
5110 To cancel an uncommitted merge (and lose your changes),
5107 use :hg:`update --clean .`.
5111 use :hg:`update --clean .`.
5108
5112
5109 With no revision specified, revert the specified files or directories
5113 With no revision specified, revert the specified files or directories
5110 to the contents they had in the parent of the working directory.
5114 to the contents they had in the parent of the working directory.
5111 This restores the contents of files to an unmodified
5115 This restores the contents of files to an unmodified
5112 state and unschedules adds, removes, copies, and renames. If the
5116 state and unschedules adds, removes, copies, and renames. If the
5113 working directory has two parents, you must explicitly specify a
5117 working directory has two parents, you must explicitly specify a
5114 revision.
5118 revision.
5115
5119
5116 Using the -r/--rev or -d/--date options, revert the given files or
5120 Using the -r/--rev or -d/--date options, revert the given files or
5117 directories to their states as of a specific revision. Because
5121 directories to their states as of a specific revision. Because
5118 revert does not change the working directory parents, this will
5122 revert does not change the working directory parents, this will
5119 cause these files to appear modified. This can be helpful to "back
5123 cause these files to appear modified. This can be helpful to "back
5120 out" some or all of an earlier change. See :hg:`backout` for a
5124 out" some or all of an earlier change. See :hg:`backout` for a
5121 related method.
5125 related method.
5122
5126
5123 Modified files are saved with a .orig suffix before reverting.
5127 Modified files are saved with a .orig suffix before reverting.
5124 To disable these backups, use --no-backup.
5128 To disable these backups, use --no-backup.
5125
5129
5126 See :hg:`help dates` for a list of formats valid for -d/--date.
5130 See :hg:`help dates` for a list of formats valid for -d/--date.
5127
5131
5128 Returns 0 on success.
5132 Returns 0 on success.
5129 """
5133 """
5130
5134
5131 if opts.get("date"):
5135 if opts.get("date"):
5132 if opts.get("rev"):
5136 if opts.get("rev"):
5133 raise util.Abort(_("you can't specify a revision and a date"))
5137 raise util.Abort(_("you can't specify a revision and a date"))
5134 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5138 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5135
5139
5136 parent, p2 = repo.dirstate.parents()
5140 parent, p2 = repo.dirstate.parents()
5137 if not opts.get('rev') and p2 != nullid:
5141 if not opts.get('rev') and p2 != nullid:
5138 # revert after merge is a trap for new users (issue2915)
5142 # revert after merge is a trap for new users (issue2915)
5139 raise util.Abort(_('uncommitted merge with no revision specified'),
5143 raise util.Abort(_('uncommitted merge with no revision specified'),
5140 hint=_('use "hg update" or see "hg help revert"'))
5144 hint=_('use "hg update" or see "hg help revert"'))
5141
5145
5142 ctx = scmutil.revsingle(repo, opts.get('rev'))
5146 ctx = scmutil.revsingle(repo, opts.get('rev'))
5143
5147
5144 if not pats and not opts.get('all'):
5148 if not pats and not opts.get('all'):
5145 msg = _("no files or directories specified")
5149 msg = _("no files or directories specified")
5146 if p2 != nullid:
5150 if p2 != nullid:
5147 hint = _("uncommitted merge, use --all to discard all changes,"
5151 hint = _("uncommitted merge, use --all to discard all changes,"
5148 " or 'hg update -C .' to abort the merge")
5152 " or 'hg update -C .' to abort the merge")
5149 raise util.Abort(msg, hint=hint)
5153 raise util.Abort(msg, hint=hint)
5150 dirty = util.any(repo.status())
5154 dirty = util.any(repo.status())
5151 node = ctx.node()
5155 node = ctx.node()
5152 if node != parent:
5156 if node != parent:
5153 if dirty:
5157 if dirty:
5154 hint = _("uncommitted changes, use --all to discard all"
5158 hint = _("uncommitted changes, use --all to discard all"
5155 " changes, or 'hg update %s' to update") % ctx.rev()
5159 " changes, or 'hg update %s' to update") % ctx.rev()
5156 else:
5160 else:
5157 hint = _("use --all to revert all files,"
5161 hint = _("use --all to revert all files,"
5158 " or 'hg update %s' to update") % ctx.rev()
5162 " or 'hg update %s' to update") % ctx.rev()
5159 elif dirty:
5163 elif dirty:
5160 hint = _("uncommitted changes, use --all to discard all changes")
5164 hint = _("uncommitted changes, use --all to discard all changes")
5161 else:
5165 else:
5162 hint = _("use --all to revert all files")
5166 hint = _("use --all to revert all files")
5163 raise util.Abort(msg, hint=hint)
5167 raise util.Abort(msg, hint=hint)
5164
5168
5165 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5169 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5166
5170
5167 @command('rollback', dryrunopts +
5171 @command('rollback', dryrunopts +
5168 [('f', 'force', False, _('ignore safety measures'))])
5172 [('f', 'force', False, _('ignore safety measures'))])
5169 def rollback(ui, repo, **opts):
5173 def rollback(ui, repo, **opts):
5170 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5174 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5171
5175
5172 Please use :hg:`commit --amend` instead of rollback to correct
5176 Please use :hg:`commit --amend` instead of rollback to correct
5173 mistakes in the last commit.
5177 mistakes in the last commit.
5174
5178
5175 This command should be used with care. There is only one level of
5179 This command should be used with care. There is only one level of
5176 rollback, and there is no way to undo a rollback. It will also
5180 rollback, and there is no way to undo a rollback. It will also
5177 restore the dirstate at the time of the last transaction, losing
5181 restore the dirstate at the time of the last transaction, losing
5178 any dirstate changes since that time. This command does not alter
5182 any dirstate changes since that time. This command does not alter
5179 the working directory.
5183 the working directory.
5180
5184
5181 Transactions are used to encapsulate the effects of all commands
5185 Transactions are used to encapsulate the effects of all commands
5182 that create new changesets or propagate existing changesets into a
5186 that create new changesets or propagate existing changesets into a
5183 repository.
5187 repository.
5184
5188
5185 .. container:: verbose
5189 .. container:: verbose
5186
5190
5187 For example, the following commands are transactional, and their
5191 For example, the following commands are transactional, and their
5188 effects can be rolled back:
5192 effects can be rolled back:
5189
5193
5190 - commit
5194 - commit
5191 - import
5195 - import
5192 - pull
5196 - pull
5193 - push (with this repository as the destination)
5197 - push (with this repository as the destination)
5194 - unbundle
5198 - unbundle
5195
5199
5196 To avoid permanent data loss, rollback will refuse to rollback a
5200 To avoid permanent data loss, rollback will refuse to rollback a
5197 commit transaction if it isn't checked out. Use --force to
5201 commit transaction if it isn't checked out. Use --force to
5198 override this protection.
5202 override this protection.
5199
5203
5200 This command is not intended for use on public repositories. Once
5204 This command is not intended for use on public repositories. Once
5201 changes are visible for pull by other users, rolling a transaction
5205 changes are visible for pull by other users, rolling a transaction
5202 back locally is ineffective (someone else may already have pulled
5206 back locally is ineffective (someone else may already have pulled
5203 the changes). Furthermore, a race is possible with readers of the
5207 the changes). Furthermore, a race is possible with readers of the
5204 repository; for example an in-progress pull from the repository
5208 repository; for example an in-progress pull from the repository
5205 may fail if a rollback is performed.
5209 may fail if a rollback is performed.
5206
5210
5207 Returns 0 on success, 1 if no rollback data is available.
5211 Returns 0 on success, 1 if no rollback data is available.
5208 """
5212 """
5209 return repo.rollback(dryrun=opts.get('dry_run'),
5213 return repo.rollback(dryrun=opts.get('dry_run'),
5210 force=opts.get('force'))
5214 force=opts.get('force'))
5211
5215
5212 @command('root', [])
5216 @command('root', [])
5213 def root(ui, repo):
5217 def root(ui, repo):
5214 """print the root (top) of the current working directory
5218 """print the root (top) of the current working directory
5215
5219
5216 Print the root directory of the current repository.
5220 Print the root directory of the current repository.
5217
5221
5218 Returns 0 on success.
5222 Returns 0 on success.
5219 """
5223 """
5220 ui.write(repo.root + "\n")
5224 ui.write(repo.root + "\n")
5221
5225
5222 @command('^serve',
5226 @command('^serve',
5223 [('A', 'accesslog', '', _('name of access log file to write to'),
5227 [('A', 'accesslog', '', _('name of access log file to write to'),
5224 _('FILE')),
5228 _('FILE')),
5225 ('d', 'daemon', None, _('run server in background')),
5229 ('d', 'daemon', None, _('run server in background')),
5226 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5230 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5227 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5231 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5228 # use string type, then we can check if something was passed
5232 # use string type, then we can check if something was passed
5229 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5233 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5230 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5234 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5231 _('ADDR')),
5235 _('ADDR')),
5232 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5236 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5233 _('PREFIX')),
5237 _('PREFIX')),
5234 ('n', 'name', '',
5238 ('n', 'name', '',
5235 _('name to show in web pages (default: working directory)'), _('NAME')),
5239 _('name to show in web pages (default: working directory)'), _('NAME')),
5236 ('', 'web-conf', '',
5240 ('', 'web-conf', '',
5237 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5241 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5238 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5242 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5239 _('FILE')),
5243 _('FILE')),
5240 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5244 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5241 ('', 'stdio', None, _('for remote clients')),
5245 ('', 'stdio', None, _('for remote clients')),
5242 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5246 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5243 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5247 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5244 ('', 'style', '', _('template style to use'), _('STYLE')),
5248 ('', 'style', '', _('template style to use'), _('STYLE')),
5245 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5249 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5246 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5250 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5247 _('[OPTION]...'),
5251 _('[OPTION]...'),
5248 optionalrepo=True)
5252 optionalrepo=True)
5249 def serve(ui, repo, **opts):
5253 def serve(ui, repo, **opts):
5250 """start stand-alone webserver
5254 """start stand-alone webserver
5251
5255
5252 Start a local HTTP repository browser and pull server. You can use
5256 Start a local HTTP repository browser and pull server. You can use
5253 this for ad-hoc sharing and browsing of repositories. It is
5257 this for ad-hoc sharing and browsing of repositories. It is
5254 recommended to use a real web server to serve a repository for
5258 recommended to use a real web server to serve a repository for
5255 longer periods of time.
5259 longer periods of time.
5256
5260
5257 Please note that the server does not implement access control.
5261 Please note that the server does not implement access control.
5258 This means that, by default, anybody can read from the server and
5262 This means that, by default, anybody can read from the server and
5259 nobody can write to it by default. Set the ``web.allow_push``
5263 nobody can write to it by default. Set the ``web.allow_push``
5260 option to ``*`` to allow everybody to push to the server. You
5264 option to ``*`` to allow everybody to push to the server. You
5261 should use a real web server if you need to authenticate users.
5265 should use a real web server if you need to authenticate users.
5262
5266
5263 By default, the server logs accesses to stdout and errors to
5267 By default, the server logs accesses to stdout and errors to
5264 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5268 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5265 files.
5269 files.
5266
5270
5267 To have the server choose a free port number to listen on, specify
5271 To have the server choose a free port number to listen on, specify
5268 a port number of 0; in this case, the server will print the port
5272 a port number of 0; in this case, the server will print the port
5269 number it uses.
5273 number it uses.
5270
5274
5271 Returns 0 on success.
5275 Returns 0 on success.
5272 """
5276 """
5273
5277
5274 if opts["stdio"] and opts["cmdserver"]:
5278 if opts["stdio"] and opts["cmdserver"]:
5275 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5279 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5276
5280
5277 if opts["stdio"]:
5281 if opts["stdio"]:
5278 if repo is None:
5282 if repo is None:
5279 raise error.RepoError(_("there is no Mercurial repository here"
5283 raise error.RepoError(_("there is no Mercurial repository here"
5280 " (.hg not found)"))
5284 " (.hg not found)"))
5281 s = sshserver.sshserver(ui, repo)
5285 s = sshserver.sshserver(ui, repo)
5282 s.serve_forever()
5286 s.serve_forever()
5283
5287
5284 if opts["cmdserver"]:
5288 if opts["cmdserver"]:
5285 s = commandserver.server(ui, repo, opts["cmdserver"])
5289 s = commandserver.server(ui, repo, opts["cmdserver"])
5286 return s.serve()
5290 return s.serve()
5287
5291
5288 # this way we can check if something was given in the command-line
5292 # this way we can check if something was given in the command-line
5289 if opts.get('port'):
5293 if opts.get('port'):
5290 opts['port'] = util.getport(opts.get('port'))
5294 opts['port'] = util.getport(opts.get('port'))
5291
5295
5292 baseui = repo and repo.baseui or ui
5296 baseui = repo and repo.baseui or ui
5293 optlist = ("name templates style address port prefix ipv6"
5297 optlist = ("name templates style address port prefix ipv6"
5294 " accesslog errorlog certificate encoding")
5298 " accesslog errorlog certificate encoding")
5295 for o in optlist.split():
5299 for o in optlist.split():
5296 val = opts.get(o, '')
5300 val = opts.get(o, '')
5297 if val in (None, ''): # should check against default options instead
5301 if val in (None, ''): # should check against default options instead
5298 continue
5302 continue
5299 baseui.setconfig("web", o, val, 'serve')
5303 baseui.setconfig("web", o, val, 'serve')
5300 if repo and repo.ui != baseui:
5304 if repo and repo.ui != baseui:
5301 repo.ui.setconfig("web", o, val, 'serve')
5305 repo.ui.setconfig("web", o, val, 'serve')
5302
5306
5303 o = opts.get('web_conf') or opts.get('webdir_conf')
5307 o = opts.get('web_conf') or opts.get('webdir_conf')
5304 if not o:
5308 if not o:
5305 if not repo:
5309 if not repo:
5306 raise error.RepoError(_("there is no Mercurial repository"
5310 raise error.RepoError(_("there is no Mercurial repository"
5307 " here (.hg not found)"))
5311 " here (.hg not found)"))
5308 o = repo
5312 o = repo
5309
5313
5310 app = hgweb.hgweb(o, baseui=baseui)
5314 app = hgweb.hgweb(o, baseui=baseui)
5311 service = httpservice(ui, app, opts)
5315 service = httpservice(ui, app, opts)
5312 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5316 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5313
5317
5314 class httpservice(object):
5318 class httpservice(object):
5315 def __init__(self, ui, app, opts):
5319 def __init__(self, ui, app, opts):
5316 self.ui = ui
5320 self.ui = ui
5317 self.app = app
5321 self.app = app
5318 self.opts = opts
5322 self.opts = opts
5319
5323
5320 def init(self):
5324 def init(self):
5321 util.setsignalhandler()
5325 util.setsignalhandler()
5322 self.httpd = hgweb_server.create_server(self.ui, self.app)
5326 self.httpd = hgweb_server.create_server(self.ui, self.app)
5323
5327
5324 if self.opts['port'] and not self.ui.verbose:
5328 if self.opts['port'] and not self.ui.verbose:
5325 return
5329 return
5326
5330
5327 if self.httpd.prefix:
5331 if self.httpd.prefix:
5328 prefix = self.httpd.prefix.strip('/') + '/'
5332 prefix = self.httpd.prefix.strip('/') + '/'
5329 else:
5333 else:
5330 prefix = ''
5334 prefix = ''
5331
5335
5332 port = ':%d' % self.httpd.port
5336 port = ':%d' % self.httpd.port
5333 if port == ':80':
5337 if port == ':80':
5334 port = ''
5338 port = ''
5335
5339
5336 bindaddr = self.httpd.addr
5340 bindaddr = self.httpd.addr
5337 if bindaddr == '0.0.0.0':
5341 if bindaddr == '0.0.0.0':
5338 bindaddr = '*'
5342 bindaddr = '*'
5339 elif ':' in bindaddr: # IPv6
5343 elif ':' in bindaddr: # IPv6
5340 bindaddr = '[%s]' % bindaddr
5344 bindaddr = '[%s]' % bindaddr
5341
5345
5342 fqaddr = self.httpd.fqaddr
5346 fqaddr = self.httpd.fqaddr
5343 if ':' in fqaddr:
5347 if ':' in fqaddr:
5344 fqaddr = '[%s]' % fqaddr
5348 fqaddr = '[%s]' % fqaddr
5345 if self.opts['port']:
5349 if self.opts['port']:
5346 write = self.ui.status
5350 write = self.ui.status
5347 else:
5351 else:
5348 write = self.ui.write
5352 write = self.ui.write
5349 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5353 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5350 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5354 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5351 self.ui.flush() # avoid buffering of status message
5355 self.ui.flush() # avoid buffering of status message
5352
5356
5353 def run(self):
5357 def run(self):
5354 self.httpd.serve_forever()
5358 self.httpd.serve_forever()
5355
5359
5356
5360
5357 @command('^status|st',
5361 @command('^status|st',
5358 [('A', 'all', None, _('show status of all files')),
5362 [('A', 'all', None, _('show status of all files')),
5359 ('m', 'modified', None, _('show only modified files')),
5363 ('m', 'modified', None, _('show only modified files')),
5360 ('a', 'added', None, _('show only added files')),
5364 ('a', 'added', None, _('show only added files')),
5361 ('r', 'removed', None, _('show only removed files')),
5365 ('r', 'removed', None, _('show only removed files')),
5362 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5366 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5363 ('c', 'clean', None, _('show only files without changes')),
5367 ('c', 'clean', None, _('show only files without changes')),
5364 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5368 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5365 ('i', 'ignored', None, _('show only ignored files')),
5369 ('i', 'ignored', None, _('show only ignored files')),
5366 ('n', 'no-status', None, _('hide status prefix')),
5370 ('n', 'no-status', None, _('hide status prefix')),
5367 ('C', 'copies', None, _('show source of copied files')),
5371 ('C', 'copies', None, _('show source of copied files')),
5368 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5372 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5369 ('', 'rev', [], _('show difference from revision'), _('REV')),
5373 ('', 'rev', [], _('show difference from revision'), _('REV')),
5370 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5374 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5371 ] + walkopts + subrepoopts,
5375 ] + walkopts + subrepoopts,
5372 _('[OPTION]... [FILE]...'),
5376 _('[OPTION]... [FILE]...'),
5373 inferrepo=True)
5377 inferrepo=True)
5374 def status(ui, repo, *pats, **opts):
5378 def status(ui, repo, *pats, **opts):
5375 """show changed files in the working directory
5379 """show changed files in the working directory
5376
5380
5377 Show status of files in the repository. If names are given, only
5381 Show status of files in the repository. If names are given, only
5378 files that match are shown. Files that are clean or ignored or
5382 files that match are shown. Files that are clean or ignored or
5379 the source of a copy/move operation, are not listed unless
5383 the source of a copy/move operation, are not listed unless
5380 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5384 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5381 Unless options described with "show only ..." are given, the
5385 Unless options described with "show only ..." are given, the
5382 options -mardu are used.
5386 options -mardu are used.
5383
5387
5384 Option -q/--quiet hides untracked (unknown and ignored) files
5388 Option -q/--quiet hides untracked (unknown and ignored) files
5385 unless explicitly requested with -u/--unknown or -i/--ignored.
5389 unless explicitly requested with -u/--unknown or -i/--ignored.
5386
5390
5387 .. note::
5391 .. note::
5388
5392
5389 status may appear to disagree with diff if permissions have
5393 status may appear to disagree with diff if permissions have
5390 changed or a merge has occurred. The standard diff format does
5394 changed or a merge has occurred. The standard diff format does
5391 not report permission changes and diff only reports changes
5395 not report permission changes and diff only reports changes
5392 relative to one merge parent.
5396 relative to one merge parent.
5393
5397
5394 If one revision is given, it is used as the base revision.
5398 If one revision is given, it is used as the base revision.
5395 If two revisions are given, the differences between them are
5399 If two revisions are given, the differences between them are
5396 shown. The --change option can also be used as a shortcut to list
5400 shown. The --change option can also be used as a shortcut to list
5397 the changed files of a revision from its first parent.
5401 the changed files of a revision from its first parent.
5398
5402
5399 The codes used to show the status of files are::
5403 The codes used to show the status of files are::
5400
5404
5401 M = modified
5405 M = modified
5402 A = added
5406 A = added
5403 R = removed
5407 R = removed
5404 C = clean
5408 C = clean
5405 ! = missing (deleted by non-hg command, but still tracked)
5409 ! = missing (deleted by non-hg command, but still tracked)
5406 ? = not tracked
5410 ? = not tracked
5407 I = ignored
5411 I = ignored
5408 = origin of the previous file (with --copies)
5412 = origin of the previous file (with --copies)
5409
5413
5410 .. container:: verbose
5414 .. container:: verbose
5411
5415
5412 Examples:
5416 Examples:
5413
5417
5414 - show changes in the working directory relative to a
5418 - show changes in the working directory relative to a
5415 changeset::
5419 changeset::
5416
5420
5417 hg status --rev 9353
5421 hg status --rev 9353
5418
5422
5419 - show all changes including copies in an existing changeset::
5423 - show all changes including copies in an existing changeset::
5420
5424
5421 hg status --copies --change 9353
5425 hg status --copies --change 9353
5422
5426
5423 - get a NUL separated list of added files, suitable for xargs::
5427 - get a NUL separated list of added files, suitable for xargs::
5424
5428
5425 hg status -an0
5429 hg status -an0
5426
5430
5427 Returns 0 on success.
5431 Returns 0 on success.
5428 """
5432 """
5429
5433
5430 revs = opts.get('rev')
5434 revs = opts.get('rev')
5431 change = opts.get('change')
5435 change = opts.get('change')
5432
5436
5433 if revs and change:
5437 if revs and change:
5434 msg = _('cannot specify --rev and --change at the same time')
5438 msg = _('cannot specify --rev and --change at the same time')
5435 raise util.Abort(msg)
5439 raise util.Abort(msg)
5436 elif change:
5440 elif change:
5437 node2 = scmutil.revsingle(repo, change, None).node()
5441 node2 = scmutil.revsingle(repo, change, None).node()
5438 node1 = repo[node2].p1().node()
5442 node1 = repo[node2].p1().node()
5439 else:
5443 else:
5440 node1, node2 = scmutil.revpair(repo, revs)
5444 node1, node2 = scmutil.revpair(repo, revs)
5441
5445
5442 cwd = (pats and repo.getcwd()) or ''
5446 cwd = (pats and repo.getcwd()) or ''
5443 end = opts.get('print0') and '\0' or '\n'
5447 end = opts.get('print0') and '\0' or '\n'
5444 copy = {}
5448 copy = {}
5445 states = 'modified added removed deleted unknown ignored clean'.split()
5449 states = 'modified added removed deleted unknown ignored clean'.split()
5446 show = [k for k in states if opts.get(k)]
5450 show = [k for k in states if opts.get(k)]
5447 if opts.get('all'):
5451 if opts.get('all'):
5448 show += ui.quiet and (states[:4] + ['clean']) or states
5452 show += ui.quiet and (states[:4] + ['clean']) or states
5449 if not show:
5453 if not show:
5450 show = ui.quiet and states[:4] or states[:5]
5454 show = ui.quiet and states[:4] or states[:5]
5451
5455
5452 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5456 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5453 'ignored' in show, 'clean' in show, 'unknown' in show,
5457 'ignored' in show, 'clean' in show, 'unknown' in show,
5454 opts.get('subrepos'))
5458 opts.get('subrepos'))
5455 changestates = zip(states, 'MAR!?IC', stat)
5459 changestates = zip(states, 'MAR!?IC', stat)
5456
5460
5457 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5461 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5458 copy = copies.pathcopies(repo[node1], repo[node2])
5462 copy = copies.pathcopies(repo[node1], repo[node2])
5459
5463
5460 fm = ui.formatter('status', opts)
5464 fm = ui.formatter('status', opts)
5461 fmt = '%s' + end
5465 fmt = '%s' + end
5462 showchar = not opts.get('no_status')
5466 showchar = not opts.get('no_status')
5463
5467
5464 for state, char, files in changestates:
5468 for state, char, files in changestates:
5465 if state in show:
5469 if state in show:
5466 label = 'status.' + state
5470 label = 'status.' + state
5467 for f in files:
5471 for f in files:
5468 fm.startitem()
5472 fm.startitem()
5469 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5473 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5470 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5474 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5471 if f in copy:
5475 if f in copy:
5472 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5476 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5473 label='status.copied')
5477 label='status.copied')
5474 fm.end()
5478 fm.end()
5475
5479
5476 @command('^summary|sum',
5480 @command('^summary|sum',
5477 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5481 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5478 def summary(ui, repo, **opts):
5482 def summary(ui, repo, **opts):
5479 """summarize working directory state
5483 """summarize working directory state
5480
5484
5481 This generates a brief summary of the working directory state,
5485 This generates a brief summary of the working directory state,
5482 including parents, branch, commit status, and available updates.
5486 including parents, branch, commit status, and available updates.
5483
5487
5484 With the --remote option, this will check the default paths for
5488 With the --remote option, this will check the default paths for
5485 incoming and outgoing changes. This can be time-consuming.
5489 incoming and outgoing changes. This can be time-consuming.
5486
5490
5487 Returns 0 on success.
5491 Returns 0 on success.
5488 """
5492 """
5489
5493
5490 ctx = repo[None]
5494 ctx = repo[None]
5491 parents = ctx.parents()
5495 parents = ctx.parents()
5492 pnode = parents[0].node()
5496 pnode = parents[0].node()
5493 marks = []
5497 marks = []
5494
5498
5495 for p in parents:
5499 for p in parents:
5496 # label with log.changeset (instead of log.parent) since this
5500 # label with log.changeset (instead of log.parent) since this
5497 # shows a working directory parent *changeset*:
5501 # shows a working directory parent *changeset*:
5498 # i18n: column positioning for "hg summary"
5502 # i18n: column positioning for "hg summary"
5499 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5503 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5500 label='log.changeset changeset.%s' % p.phasestr())
5504 label='log.changeset changeset.%s' % p.phasestr())
5501 ui.write(' '.join(p.tags()), label='log.tag')
5505 ui.write(' '.join(p.tags()), label='log.tag')
5502 if p.bookmarks():
5506 if p.bookmarks():
5503 marks.extend(p.bookmarks())
5507 marks.extend(p.bookmarks())
5504 if p.rev() == -1:
5508 if p.rev() == -1:
5505 if not len(repo):
5509 if not len(repo):
5506 ui.write(_(' (empty repository)'))
5510 ui.write(_(' (empty repository)'))
5507 else:
5511 else:
5508 ui.write(_(' (no revision checked out)'))
5512 ui.write(_(' (no revision checked out)'))
5509 ui.write('\n')
5513 ui.write('\n')
5510 if p.description():
5514 if p.description():
5511 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5515 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5512 label='log.summary')
5516 label='log.summary')
5513
5517
5514 branch = ctx.branch()
5518 branch = ctx.branch()
5515 bheads = repo.branchheads(branch)
5519 bheads = repo.branchheads(branch)
5516 # i18n: column positioning for "hg summary"
5520 # i18n: column positioning for "hg summary"
5517 m = _('branch: %s\n') % branch
5521 m = _('branch: %s\n') % branch
5518 if branch != 'default':
5522 if branch != 'default':
5519 ui.write(m, label='log.branch')
5523 ui.write(m, label='log.branch')
5520 else:
5524 else:
5521 ui.status(m, label='log.branch')
5525 ui.status(m, label='log.branch')
5522
5526
5523 if marks:
5527 if marks:
5524 current = repo._bookmarkcurrent
5528 current = repo._bookmarkcurrent
5525 # i18n: column positioning for "hg summary"
5529 # i18n: column positioning for "hg summary"
5526 ui.write(_('bookmarks:'), label='log.bookmark')
5530 ui.write(_('bookmarks:'), label='log.bookmark')
5527 if current is not None:
5531 if current is not None:
5528 if current in marks:
5532 if current in marks:
5529 ui.write(' *' + current, label='bookmarks.current')
5533 ui.write(' *' + current, label='bookmarks.current')
5530 marks.remove(current)
5534 marks.remove(current)
5531 else:
5535 else:
5532 ui.write(' [%s]' % current, label='bookmarks.current')
5536 ui.write(' [%s]' % current, label='bookmarks.current')
5533 for m in marks:
5537 for m in marks:
5534 ui.write(' ' + m, label='log.bookmark')
5538 ui.write(' ' + m, label='log.bookmark')
5535 ui.write('\n', label='log.bookmark')
5539 ui.write('\n', label='log.bookmark')
5536
5540
5537 st = list(repo.status(unknown=True))[:6]
5541 st = list(repo.status(unknown=True))[:6]
5538
5542
5539 c = repo.dirstate.copies()
5543 c = repo.dirstate.copies()
5540 copied, renamed = [], []
5544 copied, renamed = [], []
5541 for d, s in c.iteritems():
5545 for d, s in c.iteritems():
5542 if s in st[2]:
5546 if s in st[2]:
5543 st[2].remove(s)
5547 st[2].remove(s)
5544 renamed.append(d)
5548 renamed.append(d)
5545 else:
5549 else:
5546 copied.append(d)
5550 copied.append(d)
5547 if d in st[1]:
5551 if d in st[1]:
5548 st[1].remove(d)
5552 st[1].remove(d)
5549 st.insert(3, renamed)
5553 st.insert(3, renamed)
5550 st.insert(4, copied)
5554 st.insert(4, copied)
5551
5555
5552 ms = mergemod.mergestate(repo)
5556 ms = mergemod.mergestate(repo)
5553 st.append([f for f in ms if ms[f] == 'u'])
5557 st.append([f for f in ms if ms[f] == 'u'])
5554
5558
5555 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5559 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5556 st.append(subs)
5560 st.append(subs)
5557
5561
5558 labels = [ui.label(_('%d modified'), 'status.modified'),
5562 labels = [ui.label(_('%d modified'), 'status.modified'),
5559 ui.label(_('%d added'), 'status.added'),
5563 ui.label(_('%d added'), 'status.added'),
5560 ui.label(_('%d removed'), 'status.removed'),
5564 ui.label(_('%d removed'), 'status.removed'),
5561 ui.label(_('%d renamed'), 'status.copied'),
5565 ui.label(_('%d renamed'), 'status.copied'),
5562 ui.label(_('%d copied'), 'status.copied'),
5566 ui.label(_('%d copied'), 'status.copied'),
5563 ui.label(_('%d deleted'), 'status.deleted'),
5567 ui.label(_('%d deleted'), 'status.deleted'),
5564 ui.label(_('%d unknown'), 'status.unknown'),
5568 ui.label(_('%d unknown'), 'status.unknown'),
5565 ui.label(_('%d ignored'), 'status.ignored'),
5569 ui.label(_('%d ignored'), 'status.ignored'),
5566 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5570 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5567 ui.label(_('%d subrepos'), 'status.modified')]
5571 ui.label(_('%d subrepos'), 'status.modified')]
5568 t = []
5572 t = []
5569 for s, l in zip(st, labels):
5573 for s, l in zip(st, labels):
5570 if s:
5574 if s:
5571 t.append(l % len(s))
5575 t.append(l % len(s))
5572
5576
5573 t = ', '.join(t)
5577 t = ', '.join(t)
5574 cleanworkdir = False
5578 cleanworkdir = False
5575
5579
5576 if repo.vfs.exists('updatestate'):
5580 if repo.vfs.exists('updatestate'):
5577 t += _(' (interrupted update)')
5581 t += _(' (interrupted update)')
5578 elif len(parents) > 1:
5582 elif len(parents) > 1:
5579 t += _(' (merge)')
5583 t += _(' (merge)')
5580 elif branch != parents[0].branch():
5584 elif branch != parents[0].branch():
5581 t += _(' (new branch)')
5585 t += _(' (new branch)')
5582 elif (parents[0].closesbranch() and
5586 elif (parents[0].closesbranch() and
5583 pnode in repo.branchheads(branch, closed=True)):
5587 pnode in repo.branchheads(branch, closed=True)):
5584 t += _(' (head closed)')
5588 t += _(' (head closed)')
5585 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5589 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5586 t += _(' (clean)')
5590 t += _(' (clean)')
5587 cleanworkdir = True
5591 cleanworkdir = True
5588 elif pnode not in bheads:
5592 elif pnode not in bheads:
5589 t += _(' (new branch head)')
5593 t += _(' (new branch head)')
5590
5594
5591 if cleanworkdir:
5595 if cleanworkdir:
5592 # i18n: column positioning for "hg summary"
5596 # i18n: column positioning for "hg summary"
5593 ui.status(_('commit: %s\n') % t.strip())
5597 ui.status(_('commit: %s\n') % t.strip())
5594 else:
5598 else:
5595 # i18n: column positioning for "hg summary"
5599 # i18n: column positioning for "hg summary"
5596 ui.write(_('commit: %s\n') % t.strip())
5600 ui.write(_('commit: %s\n') % t.strip())
5597
5601
5598 # all ancestors of branch heads - all ancestors of parent = new csets
5602 # all ancestors of branch heads - all ancestors of parent = new csets
5599 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5603 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5600 bheads))
5604 bheads))
5601
5605
5602 if new == 0:
5606 if new == 0:
5603 # i18n: column positioning for "hg summary"
5607 # i18n: column positioning for "hg summary"
5604 ui.status(_('update: (current)\n'))
5608 ui.status(_('update: (current)\n'))
5605 elif pnode not in bheads:
5609 elif pnode not in bheads:
5606 # i18n: column positioning for "hg summary"
5610 # i18n: column positioning for "hg summary"
5607 ui.write(_('update: %d new changesets (update)\n') % new)
5611 ui.write(_('update: %d new changesets (update)\n') % new)
5608 else:
5612 else:
5609 # i18n: column positioning for "hg summary"
5613 # i18n: column positioning for "hg summary"
5610 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5614 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5611 (new, len(bheads)))
5615 (new, len(bheads)))
5612
5616
5613 cmdutil.summaryhooks(ui, repo)
5617 cmdutil.summaryhooks(ui, repo)
5614
5618
5615 if opts.get('remote'):
5619 if opts.get('remote'):
5616 needsincoming, needsoutgoing = True, True
5620 needsincoming, needsoutgoing = True, True
5617 else:
5621 else:
5618 needsincoming, needsoutgoing = False, False
5622 needsincoming, needsoutgoing = False, False
5619 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5623 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5620 if i:
5624 if i:
5621 needsincoming = True
5625 needsincoming = True
5622 if o:
5626 if o:
5623 needsoutgoing = True
5627 needsoutgoing = True
5624 if not needsincoming and not needsoutgoing:
5628 if not needsincoming and not needsoutgoing:
5625 return
5629 return
5626
5630
5627 def getincoming():
5631 def getincoming():
5628 source, branches = hg.parseurl(ui.expandpath('default'))
5632 source, branches = hg.parseurl(ui.expandpath('default'))
5629 sbranch = branches[0]
5633 sbranch = branches[0]
5630 try:
5634 try:
5631 other = hg.peer(repo, {}, source)
5635 other = hg.peer(repo, {}, source)
5632 except error.RepoError:
5636 except error.RepoError:
5633 if opts.get('remote'):
5637 if opts.get('remote'):
5634 raise
5638 raise
5635 return source, sbranch, None, None, None
5639 return source, sbranch, None, None, None
5636 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5640 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5637 if revs:
5641 if revs:
5638 revs = [other.lookup(rev) for rev in revs]
5642 revs = [other.lookup(rev) for rev in revs]
5639 ui.debug('comparing with %s\n' % util.hidepassword(source))
5643 ui.debug('comparing with %s\n' % util.hidepassword(source))
5640 repo.ui.pushbuffer()
5644 repo.ui.pushbuffer()
5641 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5645 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5642 repo.ui.popbuffer()
5646 repo.ui.popbuffer()
5643 return source, sbranch, other, commoninc, commoninc[1]
5647 return source, sbranch, other, commoninc, commoninc[1]
5644
5648
5645 if needsincoming:
5649 if needsincoming:
5646 source, sbranch, sother, commoninc, incoming = getincoming()
5650 source, sbranch, sother, commoninc, incoming = getincoming()
5647 else:
5651 else:
5648 source = sbranch = sother = commoninc = incoming = None
5652 source = sbranch = sother = commoninc = incoming = None
5649
5653
5650 def getoutgoing():
5654 def getoutgoing():
5651 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5655 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5652 dbranch = branches[0]
5656 dbranch = branches[0]
5653 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5657 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5654 if source != dest:
5658 if source != dest:
5655 try:
5659 try:
5656 dother = hg.peer(repo, {}, dest)
5660 dother = hg.peer(repo, {}, dest)
5657 except error.RepoError:
5661 except error.RepoError:
5658 if opts.get('remote'):
5662 if opts.get('remote'):
5659 raise
5663 raise
5660 return dest, dbranch, None, None
5664 return dest, dbranch, None, None
5661 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5665 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5662 elif sother is None:
5666 elif sother is None:
5663 # there is no explicit destination peer, but source one is invalid
5667 # there is no explicit destination peer, but source one is invalid
5664 return dest, dbranch, None, None
5668 return dest, dbranch, None, None
5665 else:
5669 else:
5666 dother = sother
5670 dother = sother
5667 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5671 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5668 common = None
5672 common = None
5669 else:
5673 else:
5670 common = commoninc
5674 common = commoninc
5671 if revs:
5675 if revs:
5672 revs = [repo.lookup(rev) for rev in revs]
5676 revs = [repo.lookup(rev) for rev in revs]
5673 repo.ui.pushbuffer()
5677 repo.ui.pushbuffer()
5674 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5678 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5675 commoninc=common)
5679 commoninc=common)
5676 repo.ui.popbuffer()
5680 repo.ui.popbuffer()
5677 return dest, dbranch, dother, outgoing
5681 return dest, dbranch, dother, outgoing
5678
5682
5679 if needsoutgoing:
5683 if needsoutgoing:
5680 dest, dbranch, dother, outgoing = getoutgoing()
5684 dest, dbranch, dother, outgoing = getoutgoing()
5681 else:
5685 else:
5682 dest = dbranch = dother = outgoing = None
5686 dest = dbranch = dother = outgoing = None
5683
5687
5684 if opts.get('remote'):
5688 if opts.get('remote'):
5685 t = []
5689 t = []
5686 if incoming:
5690 if incoming:
5687 t.append(_('1 or more incoming'))
5691 t.append(_('1 or more incoming'))
5688 o = outgoing.missing
5692 o = outgoing.missing
5689 if o:
5693 if o:
5690 t.append(_('%d outgoing') % len(o))
5694 t.append(_('%d outgoing') % len(o))
5691 other = dother or sother
5695 other = dother or sother
5692 if 'bookmarks' in other.listkeys('namespaces'):
5696 if 'bookmarks' in other.listkeys('namespaces'):
5693 lmarks = repo.listkeys('bookmarks')
5697 lmarks = repo.listkeys('bookmarks')
5694 rmarks = other.listkeys('bookmarks')
5698 rmarks = other.listkeys('bookmarks')
5695 diff = set(rmarks) - set(lmarks)
5699 diff = set(rmarks) - set(lmarks)
5696 if len(diff) > 0:
5700 if len(diff) > 0:
5697 t.append(_('%d incoming bookmarks') % len(diff))
5701 t.append(_('%d incoming bookmarks') % len(diff))
5698 diff = set(lmarks) - set(rmarks)
5702 diff = set(lmarks) - set(rmarks)
5699 if len(diff) > 0:
5703 if len(diff) > 0:
5700 t.append(_('%d outgoing bookmarks') % len(diff))
5704 t.append(_('%d outgoing bookmarks') % len(diff))
5701
5705
5702 if t:
5706 if t:
5703 # i18n: column positioning for "hg summary"
5707 # i18n: column positioning for "hg summary"
5704 ui.write(_('remote: %s\n') % (', '.join(t)))
5708 ui.write(_('remote: %s\n') % (', '.join(t)))
5705 else:
5709 else:
5706 # i18n: column positioning for "hg summary"
5710 # i18n: column positioning for "hg summary"
5707 ui.status(_('remote: (synced)\n'))
5711 ui.status(_('remote: (synced)\n'))
5708
5712
5709 cmdutil.summaryremotehooks(ui, repo, opts,
5713 cmdutil.summaryremotehooks(ui, repo, opts,
5710 ((source, sbranch, sother, commoninc),
5714 ((source, sbranch, sother, commoninc),
5711 (dest, dbranch, dother, outgoing)))
5715 (dest, dbranch, dother, outgoing)))
5712
5716
5713 @command('tag',
5717 @command('tag',
5714 [('f', 'force', None, _('force tag')),
5718 [('f', 'force', None, _('force tag')),
5715 ('l', 'local', None, _('make the tag local')),
5719 ('l', 'local', None, _('make the tag local')),
5716 ('r', 'rev', '', _('revision to tag'), _('REV')),
5720 ('r', 'rev', '', _('revision to tag'), _('REV')),
5717 ('', 'remove', None, _('remove a tag')),
5721 ('', 'remove', None, _('remove a tag')),
5718 # -l/--local is already there, commitopts cannot be used
5722 # -l/--local is already there, commitopts cannot be used
5719 ('e', 'edit', None, _('invoke editor on commit messages')),
5723 ('e', 'edit', None, _('invoke editor on commit messages')),
5720 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5724 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5721 ] + commitopts2,
5725 ] + commitopts2,
5722 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5726 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5723 def tag(ui, repo, name1, *names, **opts):
5727 def tag(ui, repo, name1, *names, **opts):
5724 """add one or more tags for the current or given revision
5728 """add one or more tags for the current or given revision
5725
5729
5726 Name a particular revision using <name>.
5730 Name a particular revision using <name>.
5727
5731
5728 Tags are used to name particular revisions of the repository and are
5732 Tags are used to name particular revisions of the repository and are
5729 very useful to compare different revisions, to go back to significant
5733 very useful to compare different revisions, to go back to significant
5730 earlier versions or to mark branch points as releases, etc. Changing
5734 earlier versions or to mark branch points as releases, etc. Changing
5731 an existing tag is normally disallowed; use -f/--force to override.
5735 an existing tag is normally disallowed; use -f/--force to override.
5732
5736
5733 If no revision is given, the parent of the working directory is
5737 If no revision is given, the parent of the working directory is
5734 used.
5738 used.
5735
5739
5736 To facilitate version control, distribution, and merging of tags,
5740 To facilitate version control, distribution, and merging of tags,
5737 they are stored as a file named ".hgtags" which is managed similarly
5741 they are stored as a file named ".hgtags" which is managed similarly
5738 to other project files and can be hand-edited if necessary. This
5742 to other project files and can be hand-edited if necessary. This
5739 also means that tagging creates a new commit. The file
5743 also means that tagging creates a new commit. The file
5740 ".hg/localtags" is used for local tags (not shared among
5744 ".hg/localtags" is used for local tags (not shared among
5741 repositories).
5745 repositories).
5742
5746
5743 Tag commits are usually made at the head of a branch. If the parent
5747 Tag commits are usually made at the head of a branch. If the parent
5744 of the working directory is not a branch head, :hg:`tag` aborts; use
5748 of the working directory is not a branch head, :hg:`tag` aborts; use
5745 -f/--force to force the tag commit to be based on a non-head
5749 -f/--force to force the tag commit to be based on a non-head
5746 changeset.
5750 changeset.
5747
5751
5748 See :hg:`help dates` for a list of formats valid for -d/--date.
5752 See :hg:`help dates` for a list of formats valid for -d/--date.
5749
5753
5750 Since tag names have priority over branch names during revision
5754 Since tag names have priority over branch names during revision
5751 lookup, using an existing branch name as a tag name is discouraged.
5755 lookup, using an existing branch name as a tag name is discouraged.
5752
5756
5753 Returns 0 on success.
5757 Returns 0 on success.
5754 """
5758 """
5755 wlock = lock = None
5759 wlock = lock = None
5756 try:
5760 try:
5757 wlock = repo.wlock()
5761 wlock = repo.wlock()
5758 lock = repo.lock()
5762 lock = repo.lock()
5759 rev_ = "."
5763 rev_ = "."
5760 names = [t.strip() for t in (name1,) + names]
5764 names = [t.strip() for t in (name1,) + names]
5761 if len(names) != len(set(names)):
5765 if len(names) != len(set(names)):
5762 raise util.Abort(_('tag names must be unique'))
5766 raise util.Abort(_('tag names must be unique'))
5763 for n in names:
5767 for n in names:
5764 scmutil.checknewlabel(repo, n, 'tag')
5768 scmutil.checknewlabel(repo, n, 'tag')
5765 if not n:
5769 if not n:
5766 raise util.Abort(_('tag names cannot consist entirely of '
5770 raise util.Abort(_('tag names cannot consist entirely of '
5767 'whitespace'))
5771 'whitespace'))
5768 if opts.get('rev') and opts.get('remove'):
5772 if opts.get('rev') and opts.get('remove'):
5769 raise util.Abort(_("--rev and --remove are incompatible"))
5773 raise util.Abort(_("--rev and --remove are incompatible"))
5770 if opts.get('rev'):
5774 if opts.get('rev'):
5771 rev_ = opts['rev']
5775 rev_ = opts['rev']
5772 message = opts.get('message')
5776 message = opts.get('message')
5773 if opts.get('remove'):
5777 if opts.get('remove'):
5774 expectedtype = opts.get('local') and 'local' or 'global'
5778 expectedtype = opts.get('local') and 'local' or 'global'
5775 for n in names:
5779 for n in names:
5776 if not repo.tagtype(n):
5780 if not repo.tagtype(n):
5777 raise util.Abort(_("tag '%s' does not exist") % n)
5781 raise util.Abort(_("tag '%s' does not exist") % n)
5778 if repo.tagtype(n) != expectedtype:
5782 if repo.tagtype(n) != expectedtype:
5779 if expectedtype == 'global':
5783 if expectedtype == 'global':
5780 raise util.Abort(_("tag '%s' is not a global tag") % n)
5784 raise util.Abort(_("tag '%s' is not a global tag") % n)
5781 else:
5785 else:
5782 raise util.Abort(_("tag '%s' is not a local tag") % n)
5786 raise util.Abort(_("tag '%s' is not a local tag") % n)
5783 rev_ = nullid
5787 rev_ = nullid
5784 if not message:
5788 if not message:
5785 # we don't translate commit messages
5789 # we don't translate commit messages
5786 message = 'Removed tag %s' % ', '.join(names)
5790 message = 'Removed tag %s' % ', '.join(names)
5787 elif not opts.get('force'):
5791 elif not opts.get('force'):
5788 for n in names:
5792 for n in names:
5789 if n in repo.tags():
5793 if n in repo.tags():
5790 raise util.Abort(_("tag '%s' already exists "
5794 raise util.Abort(_("tag '%s' already exists "
5791 "(use -f to force)") % n)
5795 "(use -f to force)") % n)
5792 if not opts.get('local'):
5796 if not opts.get('local'):
5793 p1, p2 = repo.dirstate.parents()
5797 p1, p2 = repo.dirstate.parents()
5794 if p2 != nullid:
5798 if p2 != nullid:
5795 raise util.Abort(_('uncommitted merge'))
5799 raise util.Abort(_('uncommitted merge'))
5796 bheads = repo.branchheads()
5800 bheads = repo.branchheads()
5797 if not opts.get('force') and bheads and p1 not in bheads:
5801 if not opts.get('force') and bheads and p1 not in bheads:
5798 raise util.Abort(_('not at a branch head (use -f to force)'))
5802 raise util.Abort(_('not at a branch head (use -f to force)'))
5799 r = scmutil.revsingle(repo, rev_).node()
5803 r = scmutil.revsingle(repo, rev_).node()
5800
5804
5801 if not message:
5805 if not message:
5802 # we don't translate commit messages
5806 # we don't translate commit messages
5803 message = ('Added tag %s for changeset %s' %
5807 message = ('Added tag %s for changeset %s' %
5804 (', '.join(names), short(r)))
5808 (', '.join(names), short(r)))
5805
5809
5806 date = opts.get('date')
5810 date = opts.get('date')
5807 if date:
5811 if date:
5808 date = util.parsedate(date)
5812 date = util.parsedate(date)
5809
5813
5810 if opts.get('remove'):
5814 if opts.get('remove'):
5811 editform = 'tag.remove'
5815 editform = 'tag.remove'
5812 else:
5816 else:
5813 editform = 'tag.add'
5817 editform = 'tag.add'
5814 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5818 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5815
5819
5816 # don't allow tagging the null rev
5820 # don't allow tagging the null rev
5817 if (not opts.get('remove') and
5821 if (not opts.get('remove') and
5818 scmutil.revsingle(repo, rev_).rev() == nullrev):
5822 scmutil.revsingle(repo, rev_).rev() == nullrev):
5819 raise util.Abort(_("cannot tag null revision"))
5823 raise util.Abort(_("cannot tag null revision"))
5820
5824
5821 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5825 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5822 editor=editor)
5826 editor=editor)
5823 finally:
5827 finally:
5824 release(lock, wlock)
5828 release(lock, wlock)
5825
5829
5826 @command('tags', [], '')
5830 @command('tags', [], '')
5827 def tags(ui, repo, **opts):
5831 def tags(ui, repo, **opts):
5828 """list repository tags
5832 """list repository tags
5829
5833
5830 This lists both regular and local tags. When the -v/--verbose
5834 This lists both regular and local tags. When the -v/--verbose
5831 switch is used, a third column "local" is printed for local tags.
5835 switch is used, a third column "local" is printed for local tags.
5832
5836
5833 Returns 0 on success.
5837 Returns 0 on success.
5834 """
5838 """
5835
5839
5836 fm = ui.formatter('tags', opts)
5840 fm = ui.formatter('tags', opts)
5837 hexfunc = ui.debugflag and hex or short
5841 hexfunc = ui.debugflag and hex or short
5838 tagtype = ""
5842 tagtype = ""
5839
5843
5840 for t, n in reversed(repo.tagslist()):
5844 for t, n in reversed(repo.tagslist()):
5841 hn = hexfunc(n)
5845 hn = hexfunc(n)
5842 label = 'tags.normal'
5846 label = 'tags.normal'
5843 tagtype = ''
5847 tagtype = ''
5844 if repo.tagtype(t) == 'local':
5848 if repo.tagtype(t) == 'local':
5845 label = 'tags.local'
5849 label = 'tags.local'
5846 tagtype = 'local'
5850 tagtype = 'local'
5847
5851
5848 fm.startitem()
5852 fm.startitem()
5849 fm.write('tag', '%s', t, label=label)
5853 fm.write('tag', '%s', t, label=label)
5850 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5854 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5851 fm.condwrite(not ui.quiet, 'rev id', fmt,
5855 fm.condwrite(not ui.quiet, 'rev id', fmt,
5852 repo.changelog.rev(n), hn, label=label)
5856 repo.changelog.rev(n), hn, label=label)
5853 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5857 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5854 tagtype, label=label)
5858 tagtype, label=label)
5855 fm.plain('\n')
5859 fm.plain('\n')
5856 fm.end()
5860 fm.end()
5857
5861
5858 @command('tip',
5862 @command('tip',
5859 [('p', 'patch', None, _('show patch')),
5863 [('p', 'patch', None, _('show patch')),
5860 ('g', 'git', None, _('use git extended diff format')),
5864 ('g', 'git', None, _('use git extended diff format')),
5861 ] + templateopts,
5865 ] + templateopts,
5862 _('[-p] [-g]'))
5866 _('[-p] [-g]'))
5863 def tip(ui, repo, **opts):
5867 def tip(ui, repo, **opts):
5864 """show the tip revision (DEPRECATED)
5868 """show the tip revision (DEPRECATED)
5865
5869
5866 The tip revision (usually just called the tip) is the changeset
5870 The tip revision (usually just called the tip) is the changeset
5867 most recently added to the repository (and therefore the most
5871 most recently added to the repository (and therefore the most
5868 recently changed head).
5872 recently changed head).
5869
5873
5870 If you have just made a commit, that commit will be the tip. If
5874 If you have just made a commit, that commit will be the tip. If
5871 you have just pulled changes from another repository, the tip of
5875 you have just pulled changes from another repository, the tip of
5872 that repository becomes the current tip. The "tip" tag is special
5876 that repository becomes the current tip. The "tip" tag is special
5873 and cannot be renamed or assigned to a different changeset.
5877 and cannot be renamed or assigned to a different changeset.
5874
5878
5875 This command is deprecated, please use :hg:`heads` instead.
5879 This command is deprecated, please use :hg:`heads` instead.
5876
5880
5877 Returns 0 on success.
5881 Returns 0 on success.
5878 """
5882 """
5879 displayer = cmdutil.show_changeset(ui, repo, opts)
5883 displayer = cmdutil.show_changeset(ui, repo, opts)
5880 displayer.show(repo['tip'])
5884 displayer.show(repo['tip'])
5881 displayer.close()
5885 displayer.close()
5882
5886
5883 @command('unbundle',
5887 @command('unbundle',
5884 [('u', 'update', None,
5888 [('u', 'update', None,
5885 _('update to new branch head if changesets were unbundled'))],
5889 _('update to new branch head if changesets were unbundled'))],
5886 _('[-u] FILE...'))
5890 _('[-u] FILE...'))
5887 def unbundle(ui, repo, fname1, *fnames, **opts):
5891 def unbundle(ui, repo, fname1, *fnames, **opts):
5888 """apply one or more changegroup files
5892 """apply one or more changegroup files
5889
5893
5890 Apply one or more compressed changegroup files generated by the
5894 Apply one or more compressed changegroup files generated by the
5891 bundle command.
5895 bundle command.
5892
5896
5893 Returns 0 on success, 1 if an update has unresolved files.
5897 Returns 0 on success, 1 if an update has unresolved files.
5894 """
5898 """
5895 fnames = (fname1,) + fnames
5899 fnames = (fname1,) + fnames
5896
5900
5897 lock = repo.lock()
5901 lock = repo.lock()
5898 try:
5902 try:
5899 for fname in fnames:
5903 for fname in fnames:
5900 f = hg.openpath(ui, fname)
5904 f = hg.openpath(ui, fname)
5901 gen = exchange.readbundle(ui, f, fname)
5905 gen = exchange.readbundle(ui, f, fname)
5902 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5906 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
5903 'bundle:' + fname)
5907 'bundle:' + fname)
5904 finally:
5908 finally:
5905 lock.release()
5909 lock.release()
5906
5910
5907 return postincoming(ui, repo, modheads, opts.get('update'), None)
5911 return postincoming(ui, repo, modheads, opts.get('update'), None)
5908
5912
5909 @command('^update|up|checkout|co',
5913 @command('^update|up|checkout|co',
5910 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5914 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5911 ('c', 'check', None,
5915 ('c', 'check', None,
5912 _('update across branches if no uncommitted changes')),
5916 _('update across branches if no uncommitted changes')),
5913 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5917 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5914 ('r', 'rev', '', _('revision'), _('REV'))
5918 ('r', 'rev', '', _('revision'), _('REV'))
5915 ] + mergetoolopts,
5919 ] + mergetoolopts,
5916 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5920 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5917 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5921 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5918 tool=None):
5922 tool=None):
5919 """update working directory (or switch revisions)
5923 """update working directory (or switch revisions)
5920
5924
5921 Update the repository's working directory to the specified
5925 Update the repository's working directory to the specified
5922 changeset. If no changeset is specified, update to the tip of the
5926 changeset. If no changeset is specified, update to the tip of the
5923 current named branch and move the current bookmark (see :hg:`help
5927 current named branch and move the current bookmark (see :hg:`help
5924 bookmarks`).
5928 bookmarks`).
5925
5929
5926 Update sets the working directory's parent revision to the specified
5930 Update sets the working directory's parent revision to the specified
5927 changeset (see :hg:`help parents`).
5931 changeset (see :hg:`help parents`).
5928
5932
5929 If the changeset is not a descendant or ancestor of the working
5933 If the changeset is not a descendant or ancestor of the working
5930 directory's parent, the update is aborted. With the -c/--check
5934 directory's parent, the update is aborted. With the -c/--check
5931 option, the working directory is checked for uncommitted changes; if
5935 option, the working directory is checked for uncommitted changes; if
5932 none are found, the working directory is updated to the specified
5936 none are found, the working directory is updated to the specified
5933 changeset.
5937 changeset.
5934
5938
5935 .. container:: verbose
5939 .. container:: verbose
5936
5940
5937 The following rules apply when the working directory contains
5941 The following rules apply when the working directory contains
5938 uncommitted changes:
5942 uncommitted changes:
5939
5943
5940 1. If neither -c/--check nor -C/--clean is specified, and if
5944 1. If neither -c/--check nor -C/--clean is specified, and if
5941 the requested changeset is an ancestor or descendant of
5945 the requested changeset is an ancestor or descendant of
5942 the working directory's parent, the uncommitted changes
5946 the working directory's parent, the uncommitted changes
5943 are merged into the requested changeset and the merged
5947 are merged into the requested changeset and the merged
5944 result is left uncommitted. If the requested changeset is
5948 result is left uncommitted. If the requested changeset is
5945 not an ancestor or descendant (that is, it is on another
5949 not an ancestor or descendant (that is, it is on another
5946 branch), the update is aborted and the uncommitted changes
5950 branch), the update is aborted and the uncommitted changes
5947 are preserved.
5951 are preserved.
5948
5952
5949 2. With the -c/--check option, the update is aborted and the
5953 2. With the -c/--check option, the update is aborted and the
5950 uncommitted changes are preserved.
5954 uncommitted changes are preserved.
5951
5955
5952 3. With the -C/--clean option, uncommitted changes are discarded and
5956 3. With the -C/--clean option, uncommitted changes are discarded and
5953 the working directory is updated to the requested changeset.
5957 the working directory is updated to the requested changeset.
5954
5958
5955 To cancel an uncommitted merge (and lose your changes), use
5959 To cancel an uncommitted merge (and lose your changes), use
5956 :hg:`update --clean .`.
5960 :hg:`update --clean .`.
5957
5961
5958 Use null as the changeset to remove the working directory (like
5962 Use null as the changeset to remove the working directory (like
5959 :hg:`clone -U`).
5963 :hg:`clone -U`).
5960
5964
5961 If you want to revert just one file to an older revision, use
5965 If you want to revert just one file to an older revision, use
5962 :hg:`revert [-r REV] NAME`.
5966 :hg:`revert [-r REV] NAME`.
5963
5967
5964 See :hg:`help dates` for a list of formats valid for -d/--date.
5968 See :hg:`help dates` for a list of formats valid for -d/--date.
5965
5969
5966 Returns 0 on success, 1 if there are unresolved files.
5970 Returns 0 on success, 1 if there are unresolved files.
5967 """
5971 """
5968 if rev and node:
5972 if rev and node:
5969 raise util.Abort(_("please specify just one revision"))
5973 raise util.Abort(_("please specify just one revision"))
5970
5974
5971 if rev is None or rev == '':
5975 if rev is None or rev == '':
5972 rev = node
5976 rev = node
5973
5977
5974 cmdutil.clearunfinished(repo)
5978 cmdutil.clearunfinished(repo)
5975
5979
5976 # with no argument, we also move the current bookmark, if any
5980 # with no argument, we also move the current bookmark, if any
5977 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5981 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5978
5982
5979 # if we defined a bookmark, we have to remember the original bookmark name
5983 # if we defined a bookmark, we have to remember the original bookmark name
5980 brev = rev
5984 brev = rev
5981 rev = scmutil.revsingle(repo, rev, rev).rev()
5985 rev = scmutil.revsingle(repo, rev, rev).rev()
5982
5986
5983 if check and clean:
5987 if check and clean:
5984 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5988 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5985
5989
5986 if date:
5990 if date:
5987 if rev is not None:
5991 if rev is not None:
5988 raise util.Abort(_("you can't specify a revision and a date"))
5992 raise util.Abort(_("you can't specify a revision and a date"))
5989 rev = cmdutil.finddate(ui, repo, date)
5993 rev = cmdutil.finddate(ui, repo, date)
5990
5994
5991 if check:
5995 if check:
5992 c = repo[None]
5996 c = repo[None]
5993 if c.dirty(merge=False, branch=False, missing=True):
5997 if c.dirty(merge=False, branch=False, missing=True):
5994 raise util.Abort(_("uncommitted changes"))
5998 raise util.Abort(_("uncommitted changes"))
5995 if rev is None:
5999 if rev is None:
5996 rev = repo[repo[None].branch()].rev()
6000 rev = repo[repo[None].branch()].rev()
5997 mergemod._checkunknown(repo, repo[None], repo[rev])
6001 mergemod._checkunknown(repo, repo[None], repo[rev])
5998
6002
5999 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6003 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6000
6004
6001 if clean:
6005 if clean:
6002 ret = hg.clean(repo, rev)
6006 ret = hg.clean(repo, rev)
6003 else:
6007 else:
6004 ret = hg.update(repo, rev)
6008 ret = hg.update(repo, rev)
6005
6009
6006 if not ret and movemarkfrom:
6010 if not ret and movemarkfrom:
6007 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6011 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6008 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6012 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6009 elif brev in repo._bookmarks:
6013 elif brev in repo._bookmarks:
6010 bookmarks.setcurrent(repo, brev)
6014 bookmarks.setcurrent(repo, brev)
6011 ui.status(_("(activating bookmark %s)\n") % brev)
6015 ui.status(_("(activating bookmark %s)\n") % brev)
6012 elif brev:
6016 elif brev:
6013 if repo._bookmarkcurrent:
6017 if repo._bookmarkcurrent:
6014 ui.status(_("(leaving bookmark %s)\n") %
6018 ui.status(_("(leaving bookmark %s)\n") %
6015 repo._bookmarkcurrent)
6019 repo._bookmarkcurrent)
6016 bookmarks.unsetcurrent(repo)
6020 bookmarks.unsetcurrent(repo)
6017
6021
6018 return ret
6022 return ret
6019
6023
6020 @command('verify', [])
6024 @command('verify', [])
6021 def verify(ui, repo):
6025 def verify(ui, repo):
6022 """verify the integrity of the repository
6026 """verify the integrity of the repository
6023
6027
6024 Verify the integrity of the current repository.
6028 Verify the integrity of the current repository.
6025
6029
6026 This will perform an extensive check of the repository's
6030 This will perform an extensive check of the repository's
6027 integrity, validating the hashes and checksums of each entry in
6031 integrity, validating the hashes and checksums of each entry in
6028 the changelog, manifest, and tracked files, as well as the
6032 the changelog, manifest, and tracked files, as well as the
6029 integrity of their crosslinks and indices.
6033 integrity of their crosslinks and indices.
6030
6034
6031 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6035 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6032 for more information about recovery from corruption of the
6036 for more information about recovery from corruption of the
6033 repository.
6037 repository.
6034
6038
6035 Returns 0 on success, 1 if errors are encountered.
6039 Returns 0 on success, 1 if errors are encountered.
6036 """
6040 """
6037 return hg.verify(repo)
6041 return hg.verify(repo)
6038
6042
6039 @command('version', [], norepo=True)
6043 @command('version', [], norepo=True)
6040 def version_(ui):
6044 def version_(ui):
6041 """output version and copyright information"""
6045 """output version and copyright information"""
6042 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6046 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6043 % util.version())
6047 % util.version())
6044 ui.status(_(
6048 ui.status(_(
6045 "(see http://mercurial.selenic.com for more information)\n"
6049 "(see http://mercurial.selenic.com for more information)\n"
6046 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6050 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6047 "This is free software; see the source for copying conditions. "
6051 "This is free software; see the source for copying conditions. "
6048 "There is NO\nwarranty; "
6052 "There is NO\nwarranty; "
6049 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6053 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6050 ))
6054 ))
6051
6055
6052 ui.note(_("\nEnabled extensions:\n\n"))
6056 ui.note(_("\nEnabled extensions:\n\n"))
6053 if ui.verbose:
6057 if ui.verbose:
6054 # format names and versions into columns
6058 # format names and versions into columns
6055 names = []
6059 names = []
6056 vers = []
6060 vers = []
6057 for name, module in extensions.extensions():
6061 for name, module in extensions.extensions():
6058 names.append(name)
6062 names.append(name)
6059 vers.append(extensions.moduleversion(module))
6063 vers.append(extensions.moduleversion(module))
6060 if names:
6064 if names:
6061 maxnamelen = max(len(n) for n in names)
6065 maxnamelen = max(len(n) for n in names)
6062 for i, name in enumerate(names):
6066 for i, name in enumerate(names):
6063 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6067 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now