##// END OF EJS Templates
annotate: remove redundant check for empty list of annotation data...
Yuya Nishihara -
r22452:75e166b8 default
parent child Browse files
Show More
@@ -1,6206 +1,6205 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 # hidden for now
104 # hidden for now
105 formatteropts = [
105 formatteropts = [
106 ('T', 'template', '',
106 ('T', 'template', '',
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 ]
108 ]
109
109
110 templateopts = [
110 templateopts = [
111 ('', 'style', '',
111 ('', 'style', '',
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 ('T', 'template', '',
113 ('T', 'template', '',
114 _('display with template'), _('TEMPLATE')),
114 _('display with template'), _('TEMPLATE')),
115 ]
115 ]
116
116
117 logopts = [
117 logopts = [
118 ('p', 'patch', None, _('show patch')),
118 ('p', 'patch', None, _('show patch')),
119 ('g', 'git', None, _('use git extended diff format')),
119 ('g', 'git', None, _('use git extended diff format')),
120 ('l', 'limit', '',
120 ('l', 'limit', '',
121 _('limit number of changes displayed'), _('NUM')),
121 _('limit number of changes displayed'), _('NUM')),
122 ('M', 'no-merges', None, _('do not show merges')),
122 ('M', 'no-merges', None, _('do not show merges')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('G', 'graph', None, _("show the revision DAG")),
124 ('G', 'graph', None, _("show the revision DAG")),
125 ] + templateopts
125 ] + templateopts
126
126
127 diffopts = [
127 diffopts = [
128 ('a', 'text', None, _('treat all files as text')),
128 ('a', 'text', None, _('treat all files as text')),
129 ('g', 'git', None, _('use git extended diff format')),
129 ('g', 'git', None, _('use git extended diff format')),
130 ('', 'nodates', None, _('omit dates from diff headers'))
130 ('', 'nodates', None, _('omit dates from diff headers'))
131 ]
131 ]
132
132
133 diffwsopts = [
133 diffwsopts = [
134 ('w', 'ignore-all-space', None,
134 ('w', 'ignore-all-space', None,
135 _('ignore white space when comparing lines')),
135 _('ignore white space when comparing lines')),
136 ('b', 'ignore-space-change', None,
136 ('b', 'ignore-space-change', None,
137 _('ignore changes in the amount of white space')),
137 _('ignore changes in the amount of white space')),
138 ('B', 'ignore-blank-lines', None,
138 ('B', 'ignore-blank-lines', None,
139 _('ignore changes whose lines are all blank')),
139 _('ignore changes whose lines are all blank')),
140 ]
140 ]
141
141
142 diffopts2 = [
142 diffopts2 = [
143 ('p', 'show-function', None, _('show which function each change is in')),
143 ('p', 'show-function', None, _('show which function each change is in')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
145 ] + diffwsopts + [
145 ] + diffwsopts + [
146 ('U', 'unified', '',
146 ('U', 'unified', '',
147 _('number of lines of context to show'), _('NUM')),
147 _('number of lines of context to show'), _('NUM')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
149 ]
149 ]
150
150
151 mergetoolopts = [
151 mergetoolopts = [
152 ('t', 'tool', '', _('specify merge tool')),
152 ('t', 'tool', '', _('specify merge tool')),
153 ]
153 ]
154
154
155 similarityopts = [
155 similarityopts = [
156 ('s', 'similarity', '',
156 ('s', 'similarity', '',
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
158 ]
158 ]
159
159
160 subrepoopts = [
160 subrepoopts = [
161 ('S', 'subrepos', None,
161 ('S', 'subrepos', None,
162 _('recurse into subrepositories'))
162 _('recurse into subrepositories'))
163 ]
163 ]
164
164
165 # Commands start here, listed alphabetically
165 # Commands start here, listed alphabetically
166
166
167 @command('^add',
167 @command('^add',
168 walkopts + subrepoopts + dryrunopts,
168 walkopts + subrepoopts + dryrunopts,
169 _('[OPTION]... [FILE]...'),
169 _('[OPTION]... [FILE]...'),
170 inferrepo=True)
170 inferrepo=True)
171 def add(ui, repo, *pats, **opts):
171 def add(ui, repo, *pats, **opts):
172 """add the specified files on the next commit
172 """add the specified files on the next commit
173
173
174 Schedule files to be version controlled and added to the
174 Schedule files to be version controlled and added to the
175 repository.
175 repository.
176
176
177 The files will be added to the repository at the next commit. To
177 The files will be added to the repository at the next commit. To
178 undo an add before that, see :hg:`forget`.
178 undo an add before that, see :hg:`forget`.
179
179
180 If no names are given, add all files to the repository.
180 If no names are given, add all files to the repository.
181
181
182 .. container:: verbose
182 .. container:: verbose
183
183
184 An example showing how new (unknown) files are added
184 An example showing how new (unknown) files are added
185 automatically by :hg:`add`::
185 automatically by :hg:`add`::
186
186
187 $ ls
187 $ ls
188 foo.c
188 foo.c
189 $ hg status
189 $ hg status
190 ? foo.c
190 ? foo.c
191 $ hg add
191 $ hg add
192 adding foo.c
192 adding foo.c
193 $ hg status
193 $ hg status
194 A foo.c
194 A foo.c
195
195
196 Returns 0 if all files are successfully added.
196 Returns 0 if all files are successfully added.
197 """
197 """
198
198
199 m = scmutil.match(repo[None], pats, opts)
199 m = scmutil.match(repo[None], pats, opts)
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
201 opts.get('subrepos'), prefix="", explicitonly=False)
201 opts.get('subrepos'), prefix="", explicitonly=False)
202 return rejected and 1 or 0
202 return rejected and 1 or 0
203
203
204 @command('addremove',
204 @command('addremove',
205 similarityopts + walkopts + dryrunopts,
205 similarityopts + walkopts + dryrunopts,
206 _('[OPTION]... [FILE]...'),
206 _('[OPTION]... [FILE]...'),
207 inferrepo=True)
207 inferrepo=True)
208 def addremove(ui, repo, *pats, **opts):
208 def addremove(ui, repo, *pats, **opts):
209 """add all new files, delete all missing files
209 """add all new files, delete all missing files
210
210
211 Add all new files and remove all missing files from the
211 Add all new files and remove all missing files from the
212 repository.
212 repository.
213
213
214 New files are ignored if they match any of the patterns in
214 New files are ignored if they match any of the patterns in
215 ``.hgignore``. As with add, these changes take effect at the next
215 ``.hgignore``. As with add, these changes take effect at the next
216 commit.
216 commit.
217
217
218 Use the -s/--similarity option to detect renamed files. This
218 Use the -s/--similarity option to detect renamed files. This
219 option takes a percentage between 0 (disabled) and 100 (files must
219 option takes a percentage between 0 (disabled) and 100 (files must
220 be identical) as its parameter. With a parameter greater than 0,
220 be identical) as its parameter. With a parameter greater than 0,
221 this compares every removed file with every added file and records
221 this compares every removed file with every added file and records
222 those similar enough as renames. Detecting renamed files this way
222 those similar enough as renames. Detecting renamed files this way
223 can be expensive. After using this option, :hg:`status -C` can be
223 can be expensive. After using this option, :hg:`status -C` can be
224 used to check which files were identified as moved or renamed. If
224 used to check which files were identified as moved or renamed. If
225 not specified, -s/--similarity defaults to 100 and only renames of
225 not specified, -s/--similarity defaults to 100 and only renames of
226 identical files are detected.
226 identical files are detected.
227
227
228 Returns 0 if all files are successfully added.
228 Returns 0 if all files are successfully added.
229 """
229 """
230 try:
230 try:
231 sim = float(opts.get('similarity') or 100)
231 sim = float(opts.get('similarity') or 100)
232 except ValueError:
232 except ValueError:
233 raise util.Abort(_('similarity must be a number'))
233 raise util.Abort(_('similarity must be a number'))
234 if sim < 0 or sim > 100:
234 if sim < 0 or sim > 100:
235 raise util.Abort(_('similarity must be between 0 and 100'))
235 raise util.Abort(_('similarity must be between 0 and 100'))
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
237
237
238 @command('^annotate|blame',
238 @command('^annotate|blame',
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
240 ('', 'follow', None,
240 ('', 'follow', None,
241 _('follow copies/renames and list the filename (DEPRECATED)')),
241 _('follow copies/renames and list the filename (DEPRECATED)')),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
243 ('a', 'text', None, _('treat all files as text')),
243 ('a', 'text', None, _('treat all files as text')),
244 ('u', 'user', None, _('list the author (long with -v)')),
244 ('u', 'user', None, _('list the author (long with -v)')),
245 ('f', 'file', None, _('list the filename')),
245 ('f', 'file', None, _('list the filename')),
246 ('d', 'date', None, _('list the date (short with -q)')),
246 ('d', 'date', None, _('list the date (short with -q)')),
247 ('n', 'number', None, _('list the revision number (default)')),
247 ('n', 'number', None, _('list the revision number (default)')),
248 ('c', 'changeset', None, _('list the changeset')),
248 ('c', 'changeset', None, _('list the changeset')),
249 ('l', 'line-number', None, _('show line number at the first appearance'))
249 ('l', 'line-number', None, _('show line number at the first appearance'))
250 ] + diffwsopts + walkopts,
250 ] + diffwsopts + walkopts,
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
252 inferrepo=True)
252 inferrepo=True)
253 def annotate(ui, repo, *pats, **opts):
253 def annotate(ui, repo, *pats, **opts):
254 """show changeset information by line for each file
254 """show changeset information by line for each file
255
255
256 List changes in files, showing the revision id responsible for
256 List changes in files, showing the revision id responsible for
257 each line
257 each line
258
258
259 This command is useful for discovering when a change was made and
259 This command is useful for discovering when a change was made and
260 by whom.
260 by whom.
261
261
262 Without the -a/--text option, annotate will avoid processing files
262 Without the -a/--text option, annotate will avoid processing files
263 it detects as binary. With -a, annotate will annotate the file
263 it detects as binary. With -a, annotate will annotate the file
264 anyway, although the results will probably be neither useful
264 anyway, although the results will probably be neither useful
265 nor desirable.
265 nor desirable.
266
266
267 Returns 0 on success.
267 Returns 0 on success.
268 """
268 """
269 if not pats:
269 if not pats:
270 raise util.Abort(_('at least one filename or pattern is required'))
270 raise util.Abort(_('at least one filename or pattern is required'))
271
271
272 if opts.get('follow'):
272 if opts.get('follow'):
273 # --follow is deprecated and now just an alias for -f/--file
273 # --follow is deprecated and now just an alias for -f/--file
274 # to mimic the behavior of Mercurial before version 1.5
274 # to mimic the behavior of Mercurial before version 1.5
275 opts['file'] = True
275 opts['file'] = True
276
276
277 datefunc = ui.quiet and util.shortdate or util.datestr
277 datefunc = ui.quiet and util.shortdate or util.datestr
278 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
278 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
279 hexfn = ui.debugflag and hex or short
279 hexfn = ui.debugflag and hex or short
280
280
281 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
281 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
282 ('number', ' ', lambda x: str(x[0].rev())),
282 ('number', ' ', lambda x: str(x[0].rev())),
283 ('changeset', ' ', lambda x: hexfn(x[0].node())),
283 ('changeset', ' ', lambda x: hexfn(x[0].node())),
284 ('date', ' ', getdate),
284 ('date', ' ', getdate),
285 ('file', ' ', lambda x: x[0].path()),
285 ('file', ' ', lambda x: x[0].path()),
286 ('line_number', ':', lambda x: str(x[1])),
286 ('line_number', ':', lambda x: str(x[1])),
287 ]
287 ]
288
288
289 if (not opts.get('user') and not opts.get('changeset')
289 if (not opts.get('user') and not opts.get('changeset')
290 and not opts.get('date') and not opts.get('file')):
290 and not opts.get('date') and not opts.get('file')):
291 opts['number'] = True
291 opts['number'] = True
292
292
293 linenumber = opts.get('line_number') is not None
293 linenumber = opts.get('line_number') is not None
294 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
294 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
295 raise util.Abort(_('at least one of -n/-c is required for -l'))
295 raise util.Abort(_('at least one of -n/-c is required for -l'))
296
296
297 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
297 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
298 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
298 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
299
299
300 def bad(x, y):
300 def bad(x, y):
301 raise util.Abort("%s: %s" % (x, y))
301 raise util.Abort("%s: %s" % (x, y))
302
302
303 ctx = scmutil.revsingle(repo, opts.get('rev'))
303 ctx = scmutil.revsingle(repo, opts.get('rev'))
304 m = scmutil.match(ctx, pats, opts)
304 m = scmutil.match(ctx, pats, opts)
305 m.bad = bad
305 m.bad = bad
306 follow = not opts.get('no_follow')
306 follow = not opts.get('no_follow')
307 diffopts = patch.diffopts(ui, opts, section='annotate')
307 diffopts = patch.diffopts(ui, opts, section='annotate')
308 for abs in ctx.walk(m):
308 for abs in ctx.walk(m):
309 fctx = ctx[abs]
309 fctx = ctx[abs]
310 if not opts.get('text') and util.binary(fctx.data()):
310 if not opts.get('text') and util.binary(fctx.data()):
311 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
311 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
312 continue
312 continue
313
313
314 lines = fctx.annotate(follow=follow, linenumber=linenumber,
314 lines = fctx.annotate(follow=follow, linenumber=linenumber,
315 diffopts=diffopts)
315 diffopts=diffopts)
316 pieces = []
316 pieces = []
317
317
318 for f, sep in funcmap:
318 for f, sep in funcmap:
319 l = [f(n) for n, dummy in lines]
319 l = [f(n) for n, dummy in lines]
320 if l:
320 if l:
321 sized = [(x, encoding.colwidth(x)) for x in l]
321 sized = [(x, encoding.colwidth(x)) for x in l]
322 ml = max([w for x, w in sized])
322 ml = max([w for x, w in sized])
323 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
323 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
324 for x, w in sized])
324 for x, w in sized])
325
325
326 if pieces:
326 for p, l in zip(zip(*pieces), lines):
327 for p, l in zip(zip(*pieces), lines):
327 ui.write("%s: %s" % ("".join(p), l[1]))
328 ui.write("%s: %s" % ("".join(p), l[1]))
328
329
329 if lines and not lines[-1][1].endswith('\n'):
330 if lines and not lines[-1][1].endswith('\n'):
330 ui.write('\n')
331 ui.write('\n')
332
331
333 @command('archive',
332 @command('archive',
334 [('', 'no-decode', None, _('do not pass files through decoders')),
333 [('', 'no-decode', None, _('do not pass files through decoders')),
335 ('p', 'prefix', '', _('directory prefix for files in archive'),
334 ('p', 'prefix', '', _('directory prefix for files in archive'),
336 _('PREFIX')),
335 _('PREFIX')),
337 ('r', 'rev', '', _('revision to distribute'), _('REV')),
336 ('r', 'rev', '', _('revision to distribute'), _('REV')),
338 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
337 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
339 ] + subrepoopts + walkopts,
338 ] + subrepoopts + walkopts,
340 _('[OPTION]... DEST'))
339 _('[OPTION]... DEST'))
341 def archive(ui, repo, dest, **opts):
340 def archive(ui, repo, dest, **opts):
342 '''create an unversioned archive of a repository revision
341 '''create an unversioned archive of a repository revision
343
342
344 By default, the revision used is the parent of the working
343 By default, the revision used is the parent of the working
345 directory; use -r/--rev to specify a different revision.
344 directory; use -r/--rev to specify a different revision.
346
345
347 The archive type is automatically detected based on file
346 The archive type is automatically detected based on file
348 extension (or override using -t/--type).
347 extension (or override using -t/--type).
349
348
350 .. container:: verbose
349 .. container:: verbose
351
350
352 Examples:
351 Examples:
353
352
354 - create a zip file containing the 1.0 release::
353 - create a zip file containing the 1.0 release::
355
354
356 hg archive -r 1.0 project-1.0.zip
355 hg archive -r 1.0 project-1.0.zip
357
356
358 - create a tarball excluding .hg files::
357 - create a tarball excluding .hg files::
359
358
360 hg archive project.tar.gz -X ".hg*"
359 hg archive project.tar.gz -X ".hg*"
361
360
362 Valid types are:
361 Valid types are:
363
362
364 :``files``: a directory full of files (default)
363 :``files``: a directory full of files (default)
365 :``tar``: tar archive, uncompressed
364 :``tar``: tar archive, uncompressed
366 :``tbz2``: tar archive, compressed using bzip2
365 :``tbz2``: tar archive, compressed using bzip2
367 :``tgz``: tar archive, compressed using gzip
366 :``tgz``: tar archive, compressed using gzip
368 :``uzip``: zip archive, uncompressed
367 :``uzip``: zip archive, uncompressed
369 :``zip``: zip archive, compressed using deflate
368 :``zip``: zip archive, compressed using deflate
370
369
371 The exact name of the destination archive or directory is given
370 The exact name of the destination archive or directory is given
372 using a format string; see :hg:`help export` for details.
371 using a format string; see :hg:`help export` for details.
373
372
374 Each member added to an archive file has a directory prefix
373 Each member added to an archive file has a directory prefix
375 prepended. Use -p/--prefix to specify a format string for the
374 prepended. Use -p/--prefix to specify a format string for the
376 prefix. The default is the basename of the archive, with suffixes
375 prefix. The default is the basename of the archive, with suffixes
377 removed.
376 removed.
378
377
379 Returns 0 on success.
378 Returns 0 on success.
380 '''
379 '''
381
380
382 ctx = scmutil.revsingle(repo, opts.get('rev'))
381 ctx = scmutil.revsingle(repo, opts.get('rev'))
383 if not ctx:
382 if not ctx:
384 raise util.Abort(_('no working directory: please specify a revision'))
383 raise util.Abort(_('no working directory: please specify a revision'))
385 node = ctx.node()
384 node = ctx.node()
386 dest = cmdutil.makefilename(repo, dest, node)
385 dest = cmdutil.makefilename(repo, dest, node)
387 if os.path.realpath(dest) == repo.root:
386 if os.path.realpath(dest) == repo.root:
388 raise util.Abort(_('repository root cannot be destination'))
387 raise util.Abort(_('repository root cannot be destination'))
389
388
390 kind = opts.get('type') or archival.guesskind(dest) or 'files'
389 kind = opts.get('type') or archival.guesskind(dest) or 'files'
391 prefix = opts.get('prefix')
390 prefix = opts.get('prefix')
392
391
393 if dest == '-':
392 if dest == '-':
394 if kind == 'files':
393 if kind == 'files':
395 raise util.Abort(_('cannot archive plain files to stdout'))
394 raise util.Abort(_('cannot archive plain files to stdout'))
396 dest = cmdutil.makefileobj(repo, dest)
395 dest = cmdutil.makefileobj(repo, dest)
397 if not prefix:
396 if not prefix:
398 prefix = os.path.basename(repo.root) + '-%h'
397 prefix = os.path.basename(repo.root) + '-%h'
399
398
400 prefix = cmdutil.makefilename(repo, prefix, node)
399 prefix = cmdutil.makefilename(repo, prefix, node)
401 matchfn = scmutil.match(ctx, [], opts)
400 matchfn = scmutil.match(ctx, [], opts)
402 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
401 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
403 matchfn, prefix, subrepos=opts.get('subrepos'))
402 matchfn, prefix, subrepos=opts.get('subrepos'))
404
403
405 @command('backout',
404 @command('backout',
406 [('', 'merge', None, _('merge with old dirstate parent after backout')),
405 [('', 'merge', None, _('merge with old dirstate parent after backout')),
407 ('', 'parent', '',
406 ('', 'parent', '',
408 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
407 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
409 ('r', 'rev', '', _('revision to backout'), _('REV')),
408 ('r', 'rev', '', _('revision to backout'), _('REV')),
410 ('e', 'edit', False, _('invoke editor on commit messages')),
409 ('e', 'edit', False, _('invoke editor on commit messages')),
411 ] + mergetoolopts + walkopts + commitopts + commitopts2,
410 ] + mergetoolopts + walkopts + commitopts + commitopts2,
412 _('[OPTION]... [-r] REV'))
411 _('[OPTION]... [-r] REV'))
413 def backout(ui, repo, node=None, rev=None, **opts):
412 def backout(ui, repo, node=None, rev=None, **opts):
414 '''reverse effect of earlier changeset
413 '''reverse effect of earlier changeset
415
414
416 Prepare a new changeset with the effect of REV undone in the
415 Prepare a new changeset with the effect of REV undone in the
417 current working directory.
416 current working directory.
418
417
419 If REV is the parent of the working directory, then this new changeset
418 If REV is the parent of the working directory, then this new changeset
420 is committed automatically. Otherwise, hg needs to merge the
419 is committed automatically. Otherwise, hg needs to merge the
421 changes and the merged result is left uncommitted.
420 changes and the merged result is left uncommitted.
422
421
423 .. note::
422 .. note::
424
423
425 backout cannot be used to fix either an unwanted or
424 backout cannot be used to fix either an unwanted or
426 incorrect merge.
425 incorrect merge.
427
426
428 .. container:: verbose
427 .. container:: verbose
429
428
430 By default, the pending changeset will have one parent,
429 By default, the pending changeset will have one parent,
431 maintaining a linear history. With --merge, the pending
430 maintaining a linear history. With --merge, the pending
432 changeset will instead have two parents: the old parent of the
431 changeset will instead have two parents: the old parent of the
433 working directory and a new child of REV that simply undoes REV.
432 working directory and a new child of REV that simply undoes REV.
434
433
435 Before version 1.7, the behavior without --merge was equivalent
434 Before version 1.7, the behavior without --merge was equivalent
436 to specifying --merge followed by :hg:`update --clean .` to
435 to specifying --merge followed by :hg:`update --clean .` to
437 cancel the merge and leave the child of REV as a head to be
436 cancel the merge and leave the child of REV as a head to be
438 merged separately.
437 merged separately.
439
438
440 See :hg:`help dates` for a list of formats valid for -d/--date.
439 See :hg:`help dates` for a list of formats valid for -d/--date.
441
440
442 Returns 0 on success, 1 if nothing to backout or there are unresolved
441 Returns 0 on success, 1 if nothing to backout or there are unresolved
443 files.
442 files.
444 '''
443 '''
445 if rev and node:
444 if rev and node:
446 raise util.Abort(_("please specify just one revision"))
445 raise util.Abort(_("please specify just one revision"))
447
446
448 if not rev:
447 if not rev:
449 rev = node
448 rev = node
450
449
451 if not rev:
450 if not rev:
452 raise util.Abort(_("please specify a revision to backout"))
451 raise util.Abort(_("please specify a revision to backout"))
453
452
454 date = opts.get('date')
453 date = opts.get('date')
455 if date:
454 if date:
456 opts['date'] = util.parsedate(date)
455 opts['date'] = util.parsedate(date)
457
456
458 cmdutil.checkunfinished(repo)
457 cmdutil.checkunfinished(repo)
459 cmdutil.bailifchanged(repo)
458 cmdutil.bailifchanged(repo)
460 node = scmutil.revsingle(repo, rev).node()
459 node = scmutil.revsingle(repo, rev).node()
461
460
462 op1, op2 = repo.dirstate.parents()
461 op1, op2 = repo.dirstate.parents()
463 if not repo.changelog.isancestor(node, op1):
462 if not repo.changelog.isancestor(node, op1):
464 raise util.Abort(_('cannot backout change that is not an ancestor'))
463 raise util.Abort(_('cannot backout change that is not an ancestor'))
465
464
466 p1, p2 = repo.changelog.parents(node)
465 p1, p2 = repo.changelog.parents(node)
467 if p1 == nullid:
466 if p1 == nullid:
468 raise util.Abort(_('cannot backout a change with no parents'))
467 raise util.Abort(_('cannot backout a change with no parents'))
469 if p2 != nullid:
468 if p2 != nullid:
470 if not opts.get('parent'):
469 if not opts.get('parent'):
471 raise util.Abort(_('cannot backout a merge changeset'))
470 raise util.Abort(_('cannot backout a merge changeset'))
472 p = repo.lookup(opts['parent'])
471 p = repo.lookup(opts['parent'])
473 if p not in (p1, p2):
472 if p not in (p1, p2):
474 raise util.Abort(_('%s is not a parent of %s') %
473 raise util.Abort(_('%s is not a parent of %s') %
475 (short(p), short(node)))
474 (short(p), short(node)))
476 parent = p
475 parent = p
477 else:
476 else:
478 if opts.get('parent'):
477 if opts.get('parent'):
479 raise util.Abort(_('cannot use --parent on non-merge changeset'))
478 raise util.Abort(_('cannot use --parent on non-merge changeset'))
480 parent = p1
479 parent = p1
481
480
482 # the backout should appear on the same branch
481 # the backout should appear on the same branch
483 wlock = repo.wlock()
482 wlock = repo.wlock()
484 try:
483 try:
485 branch = repo.dirstate.branch()
484 branch = repo.dirstate.branch()
486 bheads = repo.branchheads(branch)
485 bheads = repo.branchheads(branch)
487 rctx = scmutil.revsingle(repo, hex(parent))
486 rctx = scmutil.revsingle(repo, hex(parent))
488 if not opts.get('merge') and op1 != node:
487 if not opts.get('merge') and op1 != node:
489 try:
488 try:
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
491 'backout')
490 'backout')
492 repo.dirstate.beginparentchange()
491 repo.dirstate.beginparentchange()
493 stats = mergemod.update(repo, parent, True, True, False,
492 stats = mergemod.update(repo, parent, True, True, False,
494 node, False)
493 node, False)
495 repo.setparents(op1, op2)
494 repo.setparents(op1, op2)
496 repo.dirstate.endparentchange()
495 repo.dirstate.endparentchange()
497 hg._showstats(repo, stats)
496 hg._showstats(repo, stats)
498 if stats[3]:
497 if stats[3]:
499 repo.ui.status(_("use 'hg resolve' to retry unresolved "
498 repo.ui.status(_("use 'hg resolve' to retry unresolved "
500 "file merges\n"))
499 "file merges\n"))
501 else:
500 else:
502 msg = _("changeset %s backed out, "
501 msg = _("changeset %s backed out, "
503 "don't forget to commit.\n")
502 "don't forget to commit.\n")
504 ui.status(msg % short(node))
503 ui.status(msg % short(node))
505 return stats[3] > 0
504 return stats[3] > 0
506 finally:
505 finally:
507 ui.setconfig('ui', 'forcemerge', '', '')
506 ui.setconfig('ui', 'forcemerge', '', '')
508 else:
507 else:
509 hg.clean(repo, node, show_stats=False)
508 hg.clean(repo, node, show_stats=False)
510 repo.dirstate.setbranch(branch)
509 repo.dirstate.setbranch(branch)
511 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
510 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
512
511
513
512
514 def commitfunc(ui, repo, message, match, opts):
513 def commitfunc(ui, repo, message, match, opts):
515 editform = 'backout'
514 editform = 'backout'
516 e = cmdutil.getcommiteditor(editform=editform, **opts)
515 e = cmdutil.getcommiteditor(editform=editform, **opts)
517 if not message:
516 if not message:
518 # we don't translate commit messages
517 # we don't translate commit messages
519 message = "Backed out changeset %s" % short(node)
518 message = "Backed out changeset %s" % short(node)
520 e = cmdutil.getcommiteditor(edit=True, editform=editform)
519 e = cmdutil.getcommiteditor(edit=True, editform=editform)
521 return repo.commit(message, opts.get('user'), opts.get('date'),
520 return repo.commit(message, opts.get('user'), opts.get('date'),
522 match, editor=e)
521 match, editor=e)
523 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
522 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
524 if not newnode:
523 if not newnode:
525 ui.status(_("nothing changed\n"))
524 ui.status(_("nothing changed\n"))
526 return 1
525 return 1
527 cmdutil.commitstatus(repo, newnode, branch, bheads)
526 cmdutil.commitstatus(repo, newnode, branch, bheads)
528
527
529 def nice(node):
528 def nice(node):
530 return '%d:%s' % (repo.changelog.rev(node), short(node))
529 return '%d:%s' % (repo.changelog.rev(node), short(node))
531 ui.status(_('changeset %s backs out changeset %s\n') %
530 ui.status(_('changeset %s backs out changeset %s\n') %
532 (nice(repo.changelog.tip()), nice(node)))
531 (nice(repo.changelog.tip()), nice(node)))
533 if opts.get('merge') and op1 != node:
532 if opts.get('merge') and op1 != node:
534 hg.clean(repo, op1, show_stats=False)
533 hg.clean(repo, op1, show_stats=False)
535 ui.status(_('merging with changeset %s\n')
534 ui.status(_('merging with changeset %s\n')
536 % nice(repo.changelog.tip()))
535 % nice(repo.changelog.tip()))
537 try:
536 try:
538 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
537 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
539 'backout')
538 'backout')
540 return hg.merge(repo, hex(repo.changelog.tip()))
539 return hg.merge(repo, hex(repo.changelog.tip()))
541 finally:
540 finally:
542 ui.setconfig('ui', 'forcemerge', '', '')
541 ui.setconfig('ui', 'forcemerge', '', '')
543 finally:
542 finally:
544 wlock.release()
543 wlock.release()
545 return 0
544 return 0
546
545
547 @command('bisect',
546 @command('bisect',
548 [('r', 'reset', False, _('reset bisect state')),
547 [('r', 'reset', False, _('reset bisect state')),
549 ('g', 'good', False, _('mark changeset good')),
548 ('g', 'good', False, _('mark changeset good')),
550 ('b', 'bad', False, _('mark changeset bad')),
549 ('b', 'bad', False, _('mark changeset bad')),
551 ('s', 'skip', False, _('skip testing changeset')),
550 ('s', 'skip', False, _('skip testing changeset')),
552 ('e', 'extend', False, _('extend the bisect range')),
551 ('e', 'extend', False, _('extend the bisect range')),
553 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
552 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
554 ('U', 'noupdate', False, _('do not update to target'))],
553 ('U', 'noupdate', False, _('do not update to target'))],
555 _("[-gbsr] [-U] [-c CMD] [REV]"))
554 _("[-gbsr] [-U] [-c CMD] [REV]"))
556 def bisect(ui, repo, rev=None, extra=None, command=None,
555 def bisect(ui, repo, rev=None, extra=None, command=None,
557 reset=None, good=None, bad=None, skip=None, extend=None,
556 reset=None, good=None, bad=None, skip=None, extend=None,
558 noupdate=None):
557 noupdate=None):
559 """subdivision search of changesets
558 """subdivision search of changesets
560
559
561 This command helps to find changesets which introduce problems. To
560 This command helps to find changesets which introduce problems. To
562 use, mark the earliest changeset you know exhibits the problem as
561 use, mark the earliest changeset you know exhibits the problem as
563 bad, then mark the latest changeset which is free from the problem
562 bad, then mark the latest changeset which is free from the problem
564 as good. Bisect will update your working directory to a revision
563 as good. Bisect will update your working directory to a revision
565 for testing (unless the -U/--noupdate option is specified). Once
564 for testing (unless the -U/--noupdate option is specified). Once
566 you have performed tests, mark the working directory as good or
565 you have performed tests, mark the working directory as good or
567 bad, and bisect will either update to another candidate changeset
566 bad, and bisect will either update to another candidate changeset
568 or announce that it has found the bad revision.
567 or announce that it has found the bad revision.
569
568
570 As a shortcut, you can also use the revision argument to mark a
569 As a shortcut, you can also use the revision argument to mark a
571 revision as good or bad without checking it out first.
570 revision as good or bad without checking it out first.
572
571
573 If you supply a command, it will be used for automatic bisection.
572 If you supply a command, it will be used for automatic bisection.
574 The environment variable HG_NODE will contain the ID of the
573 The environment variable HG_NODE will contain the ID of the
575 changeset being tested. The exit status of the command will be
574 changeset being tested. The exit status of the command will be
576 used to mark revisions as good or bad: status 0 means good, 125
575 used to mark revisions as good or bad: status 0 means good, 125
577 means to skip the revision, 127 (command not found) will abort the
576 means to skip the revision, 127 (command not found) will abort the
578 bisection, and any other non-zero exit status means the revision
577 bisection, and any other non-zero exit status means the revision
579 is bad.
578 is bad.
580
579
581 .. container:: verbose
580 .. container:: verbose
582
581
583 Some examples:
582 Some examples:
584
583
585 - start a bisection with known bad revision 34, and good revision 12::
584 - start a bisection with known bad revision 34, and good revision 12::
586
585
587 hg bisect --bad 34
586 hg bisect --bad 34
588 hg bisect --good 12
587 hg bisect --good 12
589
588
590 - advance the current bisection by marking current revision as good or
589 - advance the current bisection by marking current revision as good or
591 bad::
590 bad::
592
591
593 hg bisect --good
592 hg bisect --good
594 hg bisect --bad
593 hg bisect --bad
595
594
596 - mark the current revision, or a known revision, to be skipped (e.g. if
595 - mark the current revision, or a known revision, to be skipped (e.g. if
597 that revision is not usable because of another issue)::
596 that revision is not usable because of another issue)::
598
597
599 hg bisect --skip
598 hg bisect --skip
600 hg bisect --skip 23
599 hg bisect --skip 23
601
600
602 - skip all revisions that do not touch directories ``foo`` or ``bar``::
601 - skip all revisions that do not touch directories ``foo`` or ``bar``::
603
602
604 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
603 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
605
604
606 - forget the current bisection::
605 - forget the current bisection::
607
606
608 hg bisect --reset
607 hg bisect --reset
609
608
610 - use 'make && make tests' to automatically find the first broken
609 - use 'make && make tests' to automatically find the first broken
611 revision::
610 revision::
612
611
613 hg bisect --reset
612 hg bisect --reset
614 hg bisect --bad 34
613 hg bisect --bad 34
615 hg bisect --good 12
614 hg bisect --good 12
616 hg bisect --command "make && make tests"
615 hg bisect --command "make && make tests"
617
616
618 - see all changesets whose states are already known in the current
617 - see all changesets whose states are already known in the current
619 bisection::
618 bisection::
620
619
621 hg log -r "bisect(pruned)"
620 hg log -r "bisect(pruned)"
622
621
623 - see the changeset currently being bisected (especially useful
622 - see the changeset currently being bisected (especially useful
624 if running with -U/--noupdate)::
623 if running with -U/--noupdate)::
625
624
626 hg log -r "bisect(current)"
625 hg log -r "bisect(current)"
627
626
628 - see all changesets that took part in the current bisection::
627 - see all changesets that took part in the current bisection::
629
628
630 hg log -r "bisect(range)"
629 hg log -r "bisect(range)"
631
630
632 - you can even get a nice graph::
631 - you can even get a nice graph::
633
632
634 hg log --graph -r "bisect(range)"
633 hg log --graph -r "bisect(range)"
635
634
636 See :hg:`help revsets` for more about the `bisect()` keyword.
635 See :hg:`help revsets` for more about the `bisect()` keyword.
637
636
638 Returns 0 on success.
637 Returns 0 on success.
639 """
638 """
640 def extendbisectrange(nodes, good):
639 def extendbisectrange(nodes, good):
641 # bisect is incomplete when it ends on a merge node and
640 # bisect is incomplete when it ends on a merge node and
642 # one of the parent was not checked.
641 # one of the parent was not checked.
643 parents = repo[nodes[0]].parents()
642 parents = repo[nodes[0]].parents()
644 if len(parents) > 1:
643 if len(parents) > 1:
645 side = good and state['bad'] or state['good']
644 side = good and state['bad'] or state['good']
646 num = len(set(i.node() for i in parents) & set(side))
645 num = len(set(i.node() for i in parents) & set(side))
647 if num == 1:
646 if num == 1:
648 return parents[0].ancestor(parents[1])
647 return parents[0].ancestor(parents[1])
649 return None
648 return None
650
649
651 def print_result(nodes, good):
650 def print_result(nodes, good):
652 displayer = cmdutil.show_changeset(ui, repo, {})
651 displayer = cmdutil.show_changeset(ui, repo, {})
653 if len(nodes) == 1:
652 if len(nodes) == 1:
654 # narrowed it down to a single revision
653 # narrowed it down to a single revision
655 if good:
654 if good:
656 ui.write(_("The first good revision is:\n"))
655 ui.write(_("The first good revision is:\n"))
657 else:
656 else:
658 ui.write(_("The first bad revision is:\n"))
657 ui.write(_("The first bad revision is:\n"))
659 displayer.show(repo[nodes[0]])
658 displayer.show(repo[nodes[0]])
660 extendnode = extendbisectrange(nodes, good)
659 extendnode = extendbisectrange(nodes, good)
661 if extendnode is not None:
660 if extendnode is not None:
662 ui.write(_('Not all ancestors of this changeset have been'
661 ui.write(_('Not all ancestors of this changeset have been'
663 ' checked.\nUse bisect --extend to continue the '
662 ' checked.\nUse bisect --extend to continue the '
664 'bisection from\nthe common ancestor, %s.\n')
663 'bisection from\nthe common ancestor, %s.\n')
665 % extendnode)
664 % extendnode)
666 else:
665 else:
667 # multiple possible revisions
666 # multiple possible revisions
668 if good:
667 if good:
669 ui.write(_("Due to skipped revisions, the first "
668 ui.write(_("Due to skipped revisions, the first "
670 "good revision could be any of:\n"))
669 "good revision could be any of:\n"))
671 else:
670 else:
672 ui.write(_("Due to skipped revisions, the first "
671 ui.write(_("Due to skipped revisions, the first "
673 "bad revision could be any of:\n"))
672 "bad revision could be any of:\n"))
674 for n in nodes:
673 for n in nodes:
675 displayer.show(repo[n])
674 displayer.show(repo[n])
676 displayer.close()
675 displayer.close()
677
676
678 def check_state(state, interactive=True):
677 def check_state(state, interactive=True):
679 if not state['good'] or not state['bad']:
678 if not state['good'] or not state['bad']:
680 if (good or bad or skip or reset) and interactive:
679 if (good or bad or skip or reset) and interactive:
681 return
680 return
682 if not state['good']:
681 if not state['good']:
683 raise util.Abort(_('cannot bisect (no known good revisions)'))
682 raise util.Abort(_('cannot bisect (no known good revisions)'))
684 else:
683 else:
685 raise util.Abort(_('cannot bisect (no known bad revisions)'))
684 raise util.Abort(_('cannot bisect (no known bad revisions)'))
686 return True
685 return True
687
686
688 # backward compatibility
687 # backward compatibility
689 if rev in "good bad reset init".split():
688 if rev in "good bad reset init".split():
690 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
689 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
691 cmd, rev, extra = rev, extra, None
690 cmd, rev, extra = rev, extra, None
692 if cmd == "good":
691 if cmd == "good":
693 good = True
692 good = True
694 elif cmd == "bad":
693 elif cmd == "bad":
695 bad = True
694 bad = True
696 else:
695 else:
697 reset = True
696 reset = True
698 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
697 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
699 raise util.Abort(_('incompatible arguments'))
698 raise util.Abort(_('incompatible arguments'))
700
699
701 cmdutil.checkunfinished(repo)
700 cmdutil.checkunfinished(repo)
702
701
703 if reset:
702 if reset:
704 p = repo.join("bisect.state")
703 p = repo.join("bisect.state")
705 if os.path.exists(p):
704 if os.path.exists(p):
706 os.unlink(p)
705 os.unlink(p)
707 return
706 return
708
707
709 state = hbisect.load_state(repo)
708 state = hbisect.load_state(repo)
710
709
711 if command:
710 if command:
712 changesets = 1
711 changesets = 1
713 if noupdate:
712 if noupdate:
714 try:
713 try:
715 node = state['current'][0]
714 node = state['current'][0]
716 except LookupError:
715 except LookupError:
717 raise util.Abort(_('current bisect revision is unknown - '
716 raise util.Abort(_('current bisect revision is unknown - '
718 'start a new bisect to fix'))
717 'start a new bisect to fix'))
719 else:
718 else:
720 node, p2 = repo.dirstate.parents()
719 node, p2 = repo.dirstate.parents()
721 if p2 != nullid:
720 if p2 != nullid:
722 raise util.Abort(_('current bisect revision is a merge'))
721 raise util.Abort(_('current bisect revision is a merge'))
723 try:
722 try:
724 while changesets:
723 while changesets:
725 # update state
724 # update state
726 state['current'] = [node]
725 state['current'] = [node]
727 hbisect.save_state(repo, state)
726 hbisect.save_state(repo, state)
728 status = util.system(command,
727 status = util.system(command,
729 environ={'HG_NODE': hex(node)},
728 environ={'HG_NODE': hex(node)},
730 out=ui.fout)
729 out=ui.fout)
731 if status == 125:
730 if status == 125:
732 transition = "skip"
731 transition = "skip"
733 elif status == 0:
732 elif status == 0:
734 transition = "good"
733 transition = "good"
735 # status < 0 means process was killed
734 # status < 0 means process was killed
736 elif status == 127:
735 elif status == 127:
737 raise util.Abort(_("failed to execute %s") % command)
736 raise util.Abort(_("failed to execute %s") % command)
738 elif status < 0:
737 elif status < 0:
739 raise util.Abort(_("%s killed") % command)
738 raise util.Abort(_("%s killed") % command)
740 else:
739 else:
741 transition = "bad"
740 transition = "bad"
742 ctx = scmutil.revsingle(repo, rev, node)
741 ctx = scmutil.revsingle(repo, rev, node)
743 rev = None # clear for future iterations
742 rev = None # clear for future iterations
744 state[transition].append(ctx.node())
743 state[transition].append(ctx.node())
745 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
744 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
746 check_state(state, interactive=False)
745 check_state(state, interactive=False)
747 # bisect
746 # bisect
748 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
747 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
749 # update to next check
748 # update to next check
750 node = nodes[0]
749 node = nodes[0]
751 if not noupdate:
750 if not noupdate:
752 cmdutil.bailifchanged(repo)
751 cmdutil.bailifchanged(repo)
753 hg.clean(repo, node, show_stats=False)
752 hg.clean(repo, node, show_stats=False)
754 finally:
753 finally:
755 state['current'] = [node]
754 state['current'] = [node]
756 hbisect.save_state(repo, state)
755 hbisect.save_state(repo, state)
757 print_result(nodes, bgood)
756 print_result(nodes, bgood)
758 return
757 return
759
758
760 # update state
759 # update state
761
760
762 if rev:
761 if rev:
763 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
762 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
764 else:
763 else:
765 nodes = [repo.lookup('.')]
764 nodes = [repo.lookup('.')]
766
765
767 if good or bad or skip:
766 if good or bad or skip:
768 if good:
767 if good:
769 state['good'] += nodes
768 state['good'] += nodes
770 elif bad:
769 elif bad:
771 state['bad'] += nodes
770 state['bad'] += nodes
772 elif skip:
771 elif skip:
773 state['skip'] += nodes
772 state['skip'] += nodes
774 hbisect.save_state(repo, state)
773 hbisect.save_state(repo, state)
775
774
776 if not check_state(state):
775 if not check_state(state):
777 return
776 return
778
777
779 # actually bisect
778 # actually bisect
780 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
779 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
781 if extend:
780 if extend:
782 if not changesets:
781 if not changesets:
783 extendnode = extendbisectrange(nodes, good)
782 extendnode = extendbisectrange(nodes, good)
784 if extendnode is not None:
783 if extendnode is not None:
785 ui.write(_("Extending search to changeset %d:%s\n")
784 ui.write(_("Extending search to changeset %d:%s\n")
786 % (extendnode.rev(), extendnode))
785 % (extendnode.rev(), extendnode))
787 state['current'] = [extendnode.node()]
786 state['current'] = [extendnode.node()]
788 hbisect.save_state(repo, state)
787 hbisect.save_state(repo, state)
789 if noupdate:
788 if noupdate:
790 return
789 return
791 cmdutil.bailifchanged(repo)
790 cmdutil.bailifchanged(repo)
792 return hg.clean(repo, extendnode.node())
791 return hg.clean(repo, extendnode.node())
793 raise util.Abort(_("nothing to extend"))
792 raise util.Abort(_("nothing to extend"))
794
793
795 if changesets == 0:
794 if changesets == 0:
796 print_result(nodes, good)
795 print_result(nodes, good)
797 else:
796 else:
798 assert len(nodes) == 1 # only a single node can be tested next
797 assert len(nodes) == 1 # only a single node can be tested next
799 node = nodes[0]
798 node = nodes[0]
800 # compute the approximate number of remaining tests
799 # compute the approximate number of remaining tests
801 tests, size = 0, 2
800 tests, size = 0, 2
802 while size <= changesets:
801 while size <= changesets:
803 tests, size = tests + 1, size * 2
802 tests, size = tests + 1, size * 2
804 rev = repo.changelog.rev(node)
803 rev = repo.changelog.rev(node)
805 ui.write(_("Testing changeset %d:%s "
804 ui.write(_("Testing changeset %d:%s "
806 "(%d changesets remaining, ~%d tests)\n")
805 "(%d changesets remaining, ~%d tests)\n")
807 % (rev, short(node), changesets, tests))
806 % (rev, short(node), changesets, tests))
808 state['current'] = [node]
807 state['current'] = [node]
809 hbisect.save_state(repo, state)
808 hbisect.save_state(repo, state)
810 if not noupdate:
809 if not noupdate:
811 cmdutil.bailifchanged(repo)
810 cmdutil.bailifchanged(repo)
812 return hg.clean(repo, node)
811 return hg.clean(repo, node)
813
812
814 @command('bookmarks|bookmark',
813 @command('bookmarks|bookmark',
815 [('f', 'force', False, _('force')),
814 [('f', 'force', False, _('force')),
816 ('r', 'rev', '', _('revision'), _('REV')),
815 ('r', 'rev', '', _('revision'), _('REV')),
817 ('d', 'delete', False, _('delete a given bookmark')),
816 ('d', 'delete', False, _('delete a given bookmark')),
818 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
817 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
819 ('i', 'inactive', False, _('mark a bookmark inactive'))],
818 ('i', 'inactive', False, _('mark a bookmark inactive'))],
820 _('hg bookmarks [OPTIONS]... [NAME]...'))
819 _('hg bookmarks [OPTIONS]... [NAME]...'))
821 def bookmark(ui, repo, *names, **opts):
820 def bookmark(ui, repo, *names, **opts):
822 '''create a new bookmark or list existing bookmarks
821 '''create a new bookmark or list existing bookmarks
823
822
824 Bookmarks are labels on changesets to help track lines of development.
823 Bookmarks are labels on changesets to help track lines of development.
825 Bookmarks are unversioned and can be moved, renamed and deleted.
824 Bookmarks are unversioned and can be moved, renamed and deleted.
826 Deleting or moving a bookmark has no effect on the associated changesets.
825 Deleting or moving a bookmark has no effect on the associated changesets.
827
826
828 Creating or updating to a bookmark causes it to be marked as 'active'.
827 Creating or updating to a bookmark causes it to be marked as 'active'.
829 The active bookmark is indicated with a '*'.
828 The active bookmark is indicated with a '*'.
830 When a commit is made, the active bookmark will advance to the new commit.
829 When a commit is made, the active bookmark will advance to the new commit.
831 A plain :hg:`update` will also advance an active bookmark, if possible.
830 A plain :hg:`update` will also advance an active bookmark, if possible.
832 Updating away from a bookmark will cause it to be deactivated.
831 Updating away from a bookmark will cause it to be deactivated.
833
832
834 Bookmarks can be pushed and pulled between repositories (see
833 Bookmarks can be pushed and pulled between repositories (see
835 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
834 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
836 diverged, a new 'divergent bookmark' of the form 'name@path' will
835 diverged, a new 'divergent bookmark' of the form 'name@path' will
837 be created. Using :hg:'merge' will resolve the divergence.
836 be created. Using :hg:'merge' will resolve the divergence.
838
837
839 A bookmark named '@' has the special property that :hg:`clone` will
838 A bookmark named '@' has the special property that :hg:`clone` will
840 check it out by default if it exists.
839 check it out by default if it exists.
841
840
842 .. container:: verbose
841 .. container:: verbose
843
842
844 Examples:
843 Examples:
845
844
846 - create an active bookmark for a new line of development::
845 - create an active bookmark for a new line of development::
847
846
848 hg book new-feature
847 hg book new-feature
849
848
850 - create an inactive bookmark as a place marker::
849 - create an inactive bookmark as a place marker::
851
850
852 hg book -i reviewed
851 hg book -i reviewed
853
852
854 - create an inactive bookmark on another changeset::
853 - create an inactive bookmark on another changeset::
855
854
856 hg book -r .^ tested
855 hg book -r .^ tested
857
856
858 - move the '@' bookmark from another branch::
857 - move the '@' bookmark from another branch::
859
858
860 hg book -f @
859 hg book -f @
861 '''
860 '''
862 force = opts.get('force')
861 force = opts.get('force')
863 rev = opts.get('rev')
862 rev = opts.get('rev')
864 delete = opts.get('delete')
863 delete = opts.get('delete')
865 rename = opts.get('rename')
864 rename = opts.get('rename')
866 inactive = opts.get('inactive')
865 inactive = opts.get('inactive')
867
866
868 def checkformat(mark):
867 def checkformat(mark):
869 mark = mark.strip()
868 mark = mark.strip()
870 if not mark:
869 if not mark:
871 raise util.Abort(_("bookmark names cannot consist entirely of "
870 raise util.Abort(_("bookmark names cannot consist entirely of "
872 "whitespace"))
871 "whitespace"))
873 scmutil.checknewlabel(repo, mark, 'bookmark')
872 scmutil.checknewlabel(repo, mark, 'bookmark')
874 return mark
873 return mark
875
874
876 def checkconflict(repo, mark, cur, force=False, target=None):
875 def checkconflict(repo, mark, cur, force=False, target=None):
877 if mark in marks and not force:
876 if mark in marks and not force:
878 if target:
877 if target:
879 if marks[mark] == target and target == cur:
878 if marks[mark] == target and target == cur:
880 # re-activating a bookmark
879 # re-activating a bookmark
881 return
880 return
882 anc = repo.changelog.ancestors([repo[target].rev()])
881 anc = repo.changelog.ancestors([repo[target].rev()])
883 bmctx = repo[marks[mark]]
882 bmctx = repo[marks[mark]]
884 divs = [repo[b].node() for b in marks
883 divs = [repo[b].node() for b in marks
885 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
884 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
886
885
887 # allow resolving a single divergent bookmark even if moving
886 # allow resolving a single divergent bookmark even if moving
888 # the bookmark across branches when a revision is specified
887 # the bookmark across branches when a revision is specified
889 # that contains a divergent bookmark
888 # that contains a divergent bookmark
890 if bmctx.rev() not in anc and target in divs:
889 if bmctx.rev() not in anc and target in divs:
891 bookmarks.deletedivergent(repo, [target], mark)
890 bookmarks.deletedivergent(repo, [target], mark)
892 return
891 return
893
892
894 deletefrom = [b for b in divs
893 deletefrom = [b for b in divs
895 if repo[b].rev() in anc or b == target]
894 if repo[b].rev() in anc or b == target]
896 bookmarks.deletedivergent(repo, deletefrom, mark)
895 bookmarks.deletedivergent(repo, deletefrom, mark)
897 if bookmarks.validdest(repo, bmctx, repo[target]):
896 if bookmarks.validdest(repo, bmctx, repo[target]):
898 ui.status(_("moving bookmark '%s' forward from %s\n") %
897 ui.status(_("moving bookmark '%s' forward from %s\n") %
899 (mark, short(bmctx.node())))
898 (mark, short(bmctx.node())))
900 return
899 return
901 raise util.Abort(_("bookmark '%s' already exists "
900 raise util.Abort(_("bookmark '%s' already exists "
902 "(use -f to force)") % mark)
901 "(use -f to force)") % mark)
903 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
902 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
904 and not force):
903 and not force):
905 raise util.Abort(
904 raise util.Abort(
906 _("a bookmark cannot have the name of an existing branch"))
905 _("a bookmark cannot have the name of an existing branch"))
907
906
908 if delete and rename:
907 if delete and rename:
909 raise util.Abort(_("--delete and --rename are incompatible"))
908 raise util.Abort(_("--delete and --rename are incompatible"))
910 if delete and rev:
909 if delete and rev:
911 raise util.Abort(_("--rev is incompatible with --delete"))
910 raise util.Abort(_("--rev is incompatible with --delete"))
912 if rename and rev:
911 if rename and rev:
913 raise util.Abort(_("--rev is incompatible with --rename"))
912 raise util.Abort(_("--rev is incompatible with --rename"))
914 if not names and (delete or rev):
913 if not names and (delete or rev):
915 raise util.Abort(_("bookmark name required"))
914 raise util.Abort(_("bookmark name required"))
916
915
917 if delete or rename or names or inactive:
916 if delete or rename or names or inactive:
918 wlock = repo.wlock()
917 wlock = repo.wlock()
919 try:
918 try:
920 cur = repo.changectx('.').node()
919 cur = repo.changectx('.').node()
921 marks = repo._bookmarks
920 marks = repo._bookmarks
922 if delete:
921 if delete:
923 for mark in names:
922 for mark in names:
924 if mark not in marks:
923 if mark not in marks:
925 raise util.Abort(_("bookmark '%s' does not exist") %
924 raise util.Abort(_("bookmark '%s' does not exist") %
926 mark)
925 mark)
927 if mark == repo._bookmarkcurrent:
926 if mark == repo._bookmarkcurrent:
928 bookmarks.unsetcurrent(repo)
927 bookmarks.unsetcurrent(repo)
929 del marks[mark]
928 del marks[mark]
930 marks.write()
929 marks.write()
931
930
932 elif rename:
931 elif rename:
933 if not names:
932 if not names:
934 raise util.Abort(_("new bookmark name required"))
933 raise util.Abort(_("new bookmark name required"))
935 elif len(names) > 1:
934 elif len(names) > 1:
936 raise util.Abort(_("only one new bookmark name allowed"))
935 raise util.Abort(_("only one new bookmark name allowed"))
937 mark = checkformat(names[0])
936 mark = checkformat(names[0])
938 if rename not in marks:
937 if rename not in marks:
939 raise util.Abort(_("bookmark '%s' does not exist") % rename)
938 raise util.Abort(_("bookmark '%s' does not exist") % rename)
940 checkconflict(repo, mark, cur, force)
939 checkconflict(repo, mark, cur, force)
941 marks[mark] = marks[rename]
940 marks[mark] = marks[rename]
942 if repo._bookmarkcurrent == rename and not inactive:
941 if repo._bookmarkcurrent == rename and not inactive:
943 bookmarks.setcurrent(repo, mark)
942 bookmarks.setcurrent(repo, mark)
944 del marks[rename]
943 del marks[rename]
945 marks.write()
944 marks.write()
946
945
947 elif names:
946 elif names:
948 newact = None
947 newact = None
949 for mark in names:
948 for mark in names:
950 mark = checkformat(mark)
949 mark = checkformat(mark)
951 if newact is None:
950 if newact is None:
952 newact = mark
951 newact = mark
953 if inactive and mark == repo._bookmarkcurrent:
952 if inactive and mark == repo._bookmarkcurrent:
954 bookmarks.unsetcurrent(repo)
953 bookmarks.unsetcurrent(repo)
955 return
954 return
956 tgt = cur
955 tgt = cur
957 if rev:
956 if rev:
958 tgt = scmutil.revsingle(repo, rev).node()
957 tgt = scmutil.revsingle(repo, rev).node()
959 checkconflict(repo, mark, cur, force, tgt)
958 checkconflict(repo, mark, cur, force, tgt)
960 marks[mark] = tgt
959 marks[mark] = tgt
961 if not inactive and cur == marks[newact] and not rev:
960 if not inactive and cur == marks[newact] and not rev:
962 bookmarks.setcurrent(repo, newact)
961 bookmarks.setcurrent(repo, newact)
963 elif cur != tgt and newact == repo._bookmarkcurrent:
962 elif cur != tgt and newact == repo._bookmarkcurrent:
964 bookmarks.unsetcurrent(repo)
963 bookmarks.unsetcurrent(repo)
965 marks.write()
964 marks.write()
966
965
967 elif inactive:
966 elif inactive:
968 if len(marks) == 0:
967 if len(marks) == 0:
969 ui.status(_("no bookmarks set\n"))
968 ui.status(_("no bookmarks set\n"))
970 elif not repo._bookmarkcurrent:
969 elif not repo._bookmarkcurrent:
971 ui.status(_("no active bookmark\n"))
970 ui.status(_("no active bookmark\n"))
972 else:
971 else:
973 bookmarks.unsetcurrent(repo)
972 bookmarks.unsetcurrent(repo)
974 finally:
973 finally:
975 wlock.release()
974 wlock.release()
976 else: # show bookmarks
975 else: # show bookmarks
977 hexfn = ui.debugflag and hex or short
976 hexfn = ui.debugflag and hex or short
978 marks = repo._bookmarks
977 marks = repo._bookmarks
979 if len(marks) == 0:
978 if len(marks) == 0:
980 ui.status(_("no bookmarks set\n"))
979 ui.status(_("no bookmarks set\n"))
981 else:
980 else:
982 for bmark, n in sorted(marks.iteritems()):
981 for bmark, n in sorted(marks.iteritems()):
983 current = repo._bookmarkcurrent
982 current = repo._bookmarkcurrent
984 if bmark == current:
983 if bmark == current:
985 prefix, label = '*', 'bookmarks.current'
984 prefix, label = '*', 'bookmarks.current'
986 else:
985 else:
987 prefix, label = ' ', ''
986 prefix, label = ' ', ''
988
987
989 if ui.quiet:
988 if ui.quiet:
990 ui.write("%s\n" % bmark, label=label)
989 ui.write("%s\n" % bmark, label=label)
991 else:
990 else:
992 pad = " " * (25 - encoding.colwidth(bmark))
991 pad = " " * (25 - encoding.colwidth(bmark))
993 ui.write(" %s %s%s %d:%s\n" % (
992 ui.write(" %s %s%s %d:%s\n" % (
994 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
993 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
995 label=label)
994 label=label)
996
995
997 @command('branch',
996 @command('branch',
998 [('f', 'force', None,
997 [('f', 'force', None,
999 _('set branch name even if it shadows an existing branch')),
998 _('set branch name even if it shadows an existing branch')),
1000 ('C', 'clean', None, _('reset branch name to parent branch name'))],
999 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1001 _('[-fC] [NAME]'))
1000 _('[-fC] [NAME]'))
1002 def branch(ui, repo, label=None, **opts):
1001 def branch(ui, repo, label=None, **opts):
1003 """set or show the current branch name
1002 """set or show the current branch name
1004
1003
1005 .. note::
1004 .. note::
1006
1005
1007 Branch names are permanent and global. Use :hg:`bookmark` to create a
1006 Branch names are permanent and global. Use :hg:`bookmark` to create a
1008 light-weight bookmark instead. See :hg:`help glossary` for more
1007 light-weight bookmark instead. See :hg:`help glossary` for more
1009 information about named branches and bookmarks.
1008 information about named branches and bookmarks.
1010
1009
1011 With no argument, show the current branch name. With one argument,
1010 With no argument, show the current branch name. With one argument,
1012 set the working directory branch name (the branch will not exist
1011 set the working directory branch name (the branch will not exist
1013 in the repository until the next commit). Standard practice
1012 in the repository until the next commit). Standard practice
1014 recommends that primary development take place on the 'default'
1013 recommends that primary development take place on the 'default'
1015 branch.
1014 branch.
1016
1015
1017 Unless -f/--force is specified, branch will not let you set a
1016 Unless -f/--force is specified, branch will not let you set a
1018 branch name that already exists, even if it's inactive.
1017 branch name that already exists, even if it's inactive.
1019
1018
1020 Use -C/--clean to reset the working directory branch to that of
1019 Use -C/--clean to reset the working directory branch to that of
1021 the parent of the working directory, negating a previous branch
1020 the parent of the working directory, negating a previous branch
1022 change.
1021 change.
1023
1022
1024 Use the command :hg:`update` to switch to an existing branch. Use
1023 Use the command :hg:`update` to switch to an existing branch. Use
1025 :hg:`commit --close-branch` to mark this branch as closed.
1024 :hg:`commit --close-branch` to mark this branch as closed.
1026
1025
1027 Returns 0 on success.
1026 Returns 0 on success.
1028 """
1027 """
1029 if label:
1028 if label:
1030 label = label.strip()
1029 label = label.strip()
1031
1030
1032 if not opts.get('clean') and not label:
1031 if not opts.get('clean') and not label:
1033 ui.write("%s\n" % repo.dirstate.branch())
1032 ui.write("%s\n" % repo.dirstate.branch())
1034 return
1033 return
1035
1034
1036 wlock = repo.wlock()
1035 wlock = repo.wlock()
1037 try:
1036 try:
1038 if opts.get('clean'):
1037 if opts.get('clean'):
1039 label = repo[None].p1().branch()
1038 label = repo[None].p1().branch()
1040 repo.dirstate.setbranch(label)
1039 repo.dirstate.setbranch(label)
1041 ui.status(_('reset working directory to branch %s\n') % label)
1040 ui.status(_('reset working directory to branch %s\n') % label)
1042 elif label:
1041 elif label:
1043 if not opts.get('force') and label in repo.branchmap():
1042 if not opts.get('force') and label in repo.branchmap():
1044 if label not in [p.branch() for p in repo.parents()]:
1043 if label not in [p.branch() for p in repo.parents()]:
1045 raise util.Abort(_('a branch of the same name already'
1044 raise util.Abort(_('a branch of the same name already'
1046 ' exists'),
1045 ' exists'),
1047 # i18n: "it" refers to an existing branch
1046 # i18n: "it" refers to an existing branch
1048 hint=_("use 'hg update' to switch to it"))
1047 hint=_("use 'hg update' to switch to it"))
1049 scmutil.checknewlabel(repo, label, 'branch')
1048 scmutil.checknewlabel(repo, label, 'branch')
1050 repo.dirstate.setbranch(label)
1049 repo.dirstate.setbranch(label)
1051 ui.status(_('marked working directory as branch %s\n') % label)
1050 ui.status(_('marked working directory as branch %s\n') % label)
1052 ui.status(_('(branches are permanent and global, '
1051 ui.status(_('(branches are permanent and global, '
1053 'did you want a bookmark?)\n'))
1052 'did you want a bookmark?)\n'))
1054 finally:
1053 finally:
1055 wlock.release()
1054 wlock.release()
1056
1055
1057 @command('branches',
1056 @command('branches',
1058 [('a', 'active', False, _('show only branches that have unmerged heads')),
1057 [('a', 'active', False, _('show only branches that have unmerged heads')),
1059 ('c', 'closed', False, _('show normal and closed branches'))],
1058 ('c', 'closed', False, _('show normal and closed branches'))],
1060 _('[-ac]'))
1059 _('[-ac]'))
1061 def branches(ui, repo, active=False, closed=False):
1060 def branches(ui, repo, active=False, closed=False):
1062 """list repository named branches
1061 """list repository named branches
1063
1062
1064 List the repository's named branches, indicating which ones are
1063 List the repository's named branches, indicating which ones are
1065 inactive. If -c/--closed is specified, also list branches which have
1064 inactive. If -c/--closed is specified, also list branches which have
1066 been marked closed (see :hg:`commit --close-branch`).
1065 been marked closed (see :hg:`commit --close-branch`).
1067
1066
1068 If -a/--active is specified, only show active branches. A branch
1067 If -a/--active is specified, only show active branches. A branch
1069 is considered active if it contains repository heads.
1068 is considered active if it contains repository heads.
1070
1069
1071 Use the command :hg:`update` to switch to an existing branch.
1070 Use the command :hg:`update` to switch to an existing branch.
1072
1071
1073 Returns 0.
1072 Returns 0.
1074 """
1073 """
1075
1074
1076 hexfunc = ui.debugflag and hex or short
1075 hexfunc = ui.debugflag and hex or short
1077
1076
1078 allheads = set(repo.heads())
1077 allheads = set(repo.heads())
1079 branches = []
1078 branches = []
1080 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1079 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1081 isactive = not isclosed and bool(set(heads) & allheads)
1080 isactive = not isclosed and bool(set(heads) & allheads)
1082 branches.append((tag, repo[tip], isactive, not isclosed))
1081 branches.append((tag, repo[tip], isactive, not isclosed))
1083 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1082 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1084 reverse=True)
1083 reverse=True)
1085
1084
1086 for tag, ctx, isactive, isopen in branches:
1085 for tag, ctx, isactive, isopen in branches:
1087 if (not active) or isactive:
1086 if (not active) or isactive:
1088 if isactive:
1087 if isactive:
1089 label = 'branches.active'
1088 label = 'branches.active'
1090 notice = ''
1089 notice = ''
1091 elif not isopen:
1090 elif not isopen:
1092 if not closed:
1091 if not closed:
1093 continue
1092 continue
1094 label = 'branches.closed'
1093 label = 'branches.closed'
1095 notice = _(' (closed)')
1094 notice = _(' (closed)')
1096 else:
1095 else:
1097 label = 'branches.inactive'
1096 label = 'branches.inactive'
1098 notice = _(' (inactive)')
1097 notice = _(' (inactive)')
1099 if tag == repo.dirstate.branch():
1098 if tag == repo.dirstate.branch():
1100 label = 'branches.current'
1099 label = 'branches.current'
1101 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1100 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1102 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1101 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1103 'log.changeset changeset.%s' % ctx.phasestr())
1102 'log.changeset changeset.%s' % ctx.phasestr())
1104 labeledtag = ui.label(tag, label)
1103 labeledtag = ui.label(tag, label)
1105 if ui.quiet:
1104 if ui.quiet:
1106 ui.write("%s\n" % labeledtag)
1105 ui.write("%s\n" % labeledtag)
1107 else:
1106 else:
1108 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1107 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1109
1108
1110 @command('bundle',
1109 @command('bundle',
1111 [('f', 'force', None, _('run even when the destination is unrelated')),
1110 [('f', 'force', None, _('run even when the destination is unrelated')),
1112 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1111 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1113 _('REV')),
1112 _('REV')),
1114 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1113 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1115 _('BRANCH')),
1114 _('BRANCH')),
1116 ('', 'base', [],
1115 ('', 'base', [],
1117 _('a base changeset assumed to be available at the destination'),
1116 _('a base changeset assumed to be available at the destination'),
1118 _('REV')),
1117 _('REV')),
1119 ('a', 'all', None, _('bundle all changesets in the repository')),
1118 ('a', 'all', None, _('bundle all changesets in the repository')),
1120 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1119 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1121 ] + remoteopts,
1120 ] + remoteopts,
1122 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1121 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1123 def bundle(ui, repo, fname, dest=None, **opts):
1122 def bundle(ui, repo, fname, dest=None, **opts):
1124 """create a changegroup file
1123 """create a changegroup file
1125
1124
1126 Generate a compressed changegroup file collecting changesets not
1125 Generate a compressed changegroup file collecting changesets not
1127 known to be in another repository.
1126 known to be in another repository.
1128
1127
1129 If you omit the destination repository, then hg assumes the
1128 If you omit the destination repository, then hg assumes the
1130 destination will have all the nodes you specify with --base
1129 destination will have all the nodes you specify with --base
1131 parameters. To create a bundle containing all changesets, use
1130 parameters. To create a bundle containing all changesets, use
1132 -a/--all (or --base null).
1131 -a/--all (or --base null).
1133
1132
1134 You can change compression method with the -t/--type option.
1133 You can change compression method with the -t/--type option.
1135 The available compression methods are: none, bzip2, and
1134 The available compression methods are: none, bzip2, and
1136 gzip (by default, bundles are compressed using bzip2).
1135 gzip (by default, bundles are compressed using bzip2).
1137
1136
1138 The bundle file can then be transferred using conventional means
1137 The bundle file can then be transferred using conventional means
1139 and applied to another repository with the unbundle or pull
1138 and applied to another repository with the unbundle or pull
1140 command. This is useful when direct push and pull are not
1139 command. This is useful when direct push and pull are not
1141 available or when exporting an entire repository is undesirable.
1140 available or when exporting an entire repository is undesirable.
1142
1141
1143 Applying bundles preserves all changeset contents including
1142 Applying bundles preserves all changeset contents including
1144 permissions, copy/rename information, and revision history.
1143 permissions, copy/rename information, and revision history.
1145
1144
1146 Returns 0 on success, 1 if no changes found.
1145 Returns 0 on success, 1 if no changes found.
1147 """
1146 """
1148 revs = None
1147 revs = None
1149 if 'rev' in opts:
1148 if 'rev' in opts:
1150 revs = scmutil.revrange(repo, opts['rev'])
1149 revs = scmutil.revrange(repo, opts['rev'])
1151
1150
1152 bundletype = opts.get('type', 'bzip2').lower()
1151 bundletype = opts.get('type', 'bzip2').lower()
1153 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1152 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1154 bundletype = btypes.get(bundletype)
1153 bundletype = btypes.get(bundletype)
1155 if bundletype not in changegroup.bundletypes:
1154 if bundletype not in changegroup.bundletypes:
1156 raise util.Abort(_('unknown bundle type specified with --type'))
1155 raise util.Abort(_('unknown bundle type specified with --type'))
1157
1156
1158 if opts.get('all'):
1157 if opts.get('all'):
1159 base = ['null']
1158 base = ['null']
1160 else:
1159 else:
1161 base = scmutil.revrange(repo, opts.get('base'))
1160 base = scmutil.revrange(repo, opts.get('base'))
1162 # TODO: get desired bundlecaps from command line.
1161 # TODO: get desired bundlecaps from command line.
1163 bundlecaps = None
1162 bundlecaps = None
1164 if base:
1163 if base:
1165 if dest:
1164 if dest:
1166 raise util.Abort(_("--base is incompatible with specifying "
1165 raise util.Abort(_("--base is incompatible with specifying "
1167 "a destination"))
1166 "a destination"))
1168 common = [repo.lookup(rev) for rev in base]
1167 common = [repo.lookup(rev) for rev in base]
1169 heads = revs and map(repo.lookup, revs) or revs
1168 heads = revs and map(repo.lookup, revs) or revs
1170 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1169 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1171 common=common, bundlecaps=bundlecaps)
1170 common=common, bundlecaps=bundlecaps)
1172 outgoing = None
1171 outgoing = None
1173 else:
1172 else:
1174 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1173 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1175 dest, branches = hg.parseurl(dest, opts.get('branch'))
1174 dest, branches = hg.parseurl(dest, opts.get('branch'))
1176 other = hg.peer(repo, opts, dest)
1175 other = hg.peer(repo, opts, dest)
1177 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1176 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1178 heads = revs and map(repo.lookup, revs) or revs
1177 heads = revs and map(repo.lookup, revs) or revs
1179 outgoing = discovery.findcommonoutgoing(repo, other,
1178 outgoing = discovery.findcommonoutgoing(repo, other,
1180 onlyheads=heads,
1179 onlyheads=heads,
1181 force=opts.get('force'),
1180 force=opts.get('force'),
1182 portable=True)
1181 portable=True)
1183 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1182 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1184 bundlecaps)
1183 bundlecaps)
1185 if not cg:
1184 if not cg:
1186 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1185 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1187 return 1
1186 return 1
1188
1187
1189 changegroup.writebundle(cg, fname, bundletype)
1188 changegroup.writebundle(cg, fname, bundletype)
1190
1189
1191 @command('cat',
1190 @command('cat',
1192 [('o', 'output', '',
1191 [('o', 'output', '',
1193 _('print output to file with formatted name'), _('FORMAT')),
1192 _('print output to file with formatted name'), _('FORMAT')),
1194 ('r', 'rev', '', _('print the given revision'), _('REV')),
1193 ('r', 'rev', '', _('print the given revision'), _('REV')),
1195 ('', 'decode', None, _('apply any matching decode filter')),
1194 ('', 'decode', None, _('apply any matching decode filter')),
1196 ] + walkopts,
1195 ] + walkopts,
1197 _('[OPTION]... FILE...'),
1196 _('[OPTION]... FILE...'),
1198 inferrepo=True)
1197 inferrepo=True)
1199 def cat(ui, repo, file1, *pats, **opts):
1198 def cat(ui, repo, file1, *pats, **opts):
1200 """output the current or given revision of files
1199 """output the current or given revision of files
1201
1200
1202 Print the specified files as they were at the given revision. If
1201 Print the specified files as they were at the given revision. If
1203 no revision is given, the parent of the working directory is used.
1202 no revision is given, the parent of the working directory is used.
1204
1203
1205 Output may be to a file, in which case the name of the file is
1204 Output may be to a file, in which case the name of the file is
1206 given using a format string. The formatting rules as follows:
1205 given using a format string. The formatting rules as follows:
1207
1206
1208 :``%%``: literal "%" character
1207 :``%%``: literal "%" character
1209 :``%s``: basename of file being printed
1208 :``%s``: basename of file being printed
1210 :``%d``: dirname of file being printed, or '.' if in repository root
1209 :``%d``: dirname of file being printed, or '.' if in repository root
1211 :``%p``: root-relative path name of file being printed
1210 :``%p``: root-relative path name of file being printed
1212 :``%H``: changeset hash (40 hexadecimal digits)
1211 :``%H``: changeset hash (40 hexadecimal digits)
1213 :``%R``: changeset revision number
1212 :``%R``: changeset revision number
1214 :``%h``: short-form changeset hash (12 hexadecimal digits)
1213 :``%h``: short-form changeset hash (12 hexadecimal digits)
1215 :``%r``: zero-padded changeset revision number
1214 :``%r``: zero-padded changeset revision number
1216 :``%b``: basename of the exporting repository
1215 :``%b``: basename of the exporting repository
1217
1216
1218 Returns 0 on success.
1217 Returns 0 on success.
1219 """
1218 """
1220 ctx = scmutil.revsingle(repo, opts.get('rev'))
1219 ctx = scmutil.revsingle(repo, opts.get('rev'))
1221 m = scmutil.match(ctx, (file1,) + pats, opts)
1220 m = scmutil.match(ctx, (file1,) + pats, opts)
1222
1221
1223 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1222 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1224
1223
1225 @command('^clone',
1224 @command('^clone',
1226 [('U', 'noupdate', None,
1225 [('U', 'noupdate', None,
1227 _('the clone will include an empty working copy (only a repository)')),
1226 _('the clone will include an empty working copy (only a repository)')),
1228 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1227 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1229 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1228 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1230 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1229 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1231 ('', 'pull', None, _('use pull protocol to copy metadata')),
1230 ('', 'pull', None, _('use pull protocol to copy metadata')),
1232 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1231 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1233 ] + remoteopts,
1232 ] + remoteopts,
1234 _('[OPTION]... SOURCE [DEST]'),
1233 _('[OPTION]... SOURCE [DEST]'),
1235 norepo=True)
1234 norepo=True)
1236 def clone(ui, source, dest=None, **opts):
1235 def clone(ui, source, dest=None, **opts):
1237 """make a copy of an existing repository
1236 """make a copy of an existing repository
1238
1237
1239 Create a copy of an existing repository in a new directory.
1238 Create a copy of an existing repository in a new directory.
1240
1239
1241 If no destination directory name is specified, it defaults to the
1240 If no destination directory name is specified, it defaults to the
1242 basename of the source.
1241 basename of the source.
1243
1242
1244 The location of the source is added to the new repository's
1243 The location of the source is added to the new repository's
1245 ``.hg/hgrc`` file, as the default to be used for future pulls.
1244 ``.hg/hgrc`` file, as the default to be used for future pulls.
1246
1245
1247 Only local paths and ``ssh://`` URLs are supported as
1246 Only local paths and ``ssh://`` URLs are supported as
1248 destinations. For ``ssh://`` destinations, no working directory or
1247 destinations. For ``ssh://`` destinations, no working directory or
1249 ``.hg/hgrc`` will be created on the remote side.
1248 ``.hg/hgrc`` will be created on the remote side.
1250
1249
1251 To pull only a subset of changesets, specify one or more revisions
1250 To pull only a subset of changesets, specify one or more revisions
1252 identifiers with -r/--rev or branches with -b/--branch. The
1251 identifiers with -r/--rev or branches with -b/--branch. The
1253 resulting clone will contain only the specified changesets and
1252 resulting clone will contain only the specified changesets and
1254 their ancestors. These options (or 'clone src#rev dest') imply
1253 their ancestors. These options (or 'clone src#rev dest') imply
1255 --pull, even for local source repositories. Note that specifying a
1254 --pull, even for local source repositories. Note that specifying a
1256 tag will include the tagged changeset but not the changeset
1255 tag will include the tagged changeset but not the changeset
1257 containing the tag.
1256 containing the tag.
1258
1257
1259 If the source repository has a bookmark called '@' set, that
1258 If the source repository has a bookmark called '@' set, that
1260 revision will be checked out in the new repository by default.
1259 revision will be checked out in the new repository by default.
1261
1260
1262 To check out a particular version, use -u/--update, or
1261 To check out a particular version, use -u/--update, or
1263 -U/--noupdate to create a clone with no working directory.
1262 -U/--noupdate to create a clone with no working directory.
1264
1263
1265 .. container:: verbose
1264 .. container:: verbose
1266
1265
1267 For efficiency, hardlinks are used for cloning whenever the
1266 For efficiency, hardlinks are used for cloning whenever the
1268 source and destination are on the same filesystem (note this
1267 source and destination are on the same filesystem (note this
1269 applies only to the repository data, not to the working
1268 applies only to the repository data, not to the working
1270 directory). Some filesystems, such as AFS, implement hardlinking
1269 directory). Some filesystems, such as AFS, implement hardlinking
1271 incorrectly, but do not report errors. In these cases, use the
1270 incorrectly, but do not report errors. In these cases, use the
1272 --pull option to avoid hardlinking.
1271 --pull option to avoid hardlinking.
1273
1272
1274 In some cases, you can clone repositories and the working
1273 In some cases, you can clone repositories and the working
1275 directory using full hardlinks with ::
1274 directory using full hardlinks with ::
1276
1275
1277 $ cp -al REPO REPOCLONE
1276 $ cp -al REPO REPOCLONE
1278
1277
1279 This is the fastest way to clone, but it is not always safe. The
1278 This is the fastest way to clone, but it is not always safe. The
1280 operation is not atomic (making sure REPO is not modified during
1279 operation is not atomic (making sure REPO is not modified during
1281 the operation is up to you) and you have to make sure your
1280 the operation is up to you) and you have to make sure your
1282 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1281 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1283 so). Also, this is not compatible with certain extensions that
1282 so). Also, this is not compatible with certain extensions that
1284 place their metadata under the .hg directory, such as mq.
1283 place their metadata under the .hg directory, such as mq.
1285
1284
1286 Mercurial will update the working directory to the first applicable
1285 Mercurial will update the working directory to the first applicable
1287 revision from this list:
1286 revision from this list:
1288
1287
1289 a) null if -U or the source repository has no changesets
1288 a) null if -U or the source repository has no changesets
1290 b) if -u . and the source repository is local, the first parent of
1289 b) if -u . and the source repository is local, the first parent of
1291 the source repository's working directory
1290 the source repository's working directory
1292 c) the changeset specified with -u (if a branch name, this means the
1291 c) the changeset specified with -u (if a branch name, this means the
1293 latest head of that branch)
1292 latest head of that branch)
1294 d) the changeset specified with -r
1293 d) the changeset specified with -r
1295 e) the tipmost head specified with -b
1294 e) the tipmost head specified with -b
1296 f) the tipmost head specified with the url#branch source syntax
1295 f) the tipmost head specified with the url#branch source syntax
1297 g) the revision marked with the '@' bookmark, if present
1296 g) the revision marked with the '@' bookmark, if present
1298 h) the tipmost head of the default branch
1297 h) the tipmost head of the default branch
1299 i) tip
1298 i) tip
1300
1299
1301 Examples:
1300 Examples:
1302
1301
1303 - clone a remote repository to a new directory named hg/::
1302 - clone a remote repository to a new directory named hg/::
1304
1303
1305 hg clone http://selenic.com/hg
1304 hg clone http://selenic.com/hg
1306
1305
1307 - create a lightweight local clone::
1306 - create a lightweight local clone::
1308
1307
1309 hg clone project/ project-feature/
1308 hg clone project/ project-feature/
1310
1309
1311 - clone from an absolute path on an ssh server (note double-slash)::
1310 - clone from an absolute path on an ssh server (note double-slash)::
1312
1311
1313 hg clone ssh://user@server//home/projects/alpha/
1312 hg clone ssh://user@server//home/projects/alpha/
1314
1313
1315 - do a high-speed clone over a LAN while checking out a
1314 - do a high-speed clone over a LAN while checking out a
1316 specified version::
1315 specified version::
1317
1316
1318 hg clone --uncompressed http://server/repo -u 1.5
1317 hg clone --uncompressed http://server/repo -u 1.5
1319
1318
1320 - create a repository without changesets after a particular revision::
1319 - create a repository without changesets after a particular revision::
1321
1320
1322 hg clone -r 04e544 experimental/ good/
1321 hg clone -r 04e544 experimental/ good/
1323
1322
1324 - clone (and track) a particular named branch::
1323 - clone (and track) a particular named branch::
1325
1324
1326 hg clone http://selenic.com/hg#stable
1325 hg clone http://selenic.com/hg#stable
1327
1326
1328 See :hg:`help urls` for details on specifying URLs.
1327 See :hg:`help urls` for details on specifying URLs.
1329
1328
1330 Returns 0 on success.
1329 Returns 0 on success.
1331 """
1330 """
1332 if opts.get('noupdate') and opts.get('updaterev'):
1331 if opts.get('noupdate') and opts.get('updaterev'):
1333 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1332 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1334
1333
1335 r = hg.clone(ui, opts, source, dest,
1334 r = hg.clone(ui, opts, source, dest,
1336 pull=opts.get('pull'),
1335 pull=opts.get('pull'),
1337 stream=opts.get('uncompressed'),
1336 stream=opts.get('uncompressed'),
1338 rev=opts.get('rev'),
1337 rev=opts.get('rev'),
1339 update=opts.get('updaterev') or not opts.get('noupdate'),
1338 update=opts.get('updaterev') or not opts.get('noupdate'),
1340 branch=opts.get('branch'))
1339 branch=opts.get('branch'))
1341
1340
1342 return r is None
1341 return r is None
1343
1342
1344 @command('^commit|ci',
1343 @command('^commit|ci',
1345 [('A', 'addremove', None,
1344 [('A', 'addremove', None,
1346 _('mark new/missing files as added/removed before committing')),
1345 _('mark new/missing files as added/removed before committing')),
1347 ('', 'close-branch', None,
1346 ('', 'close-branch', None,
1348 _('mark a branch as closed, hiding it from the branch list')),
1347 _('mark a branch as closed, hiding it from the branch list')),
1349 ('', 'amend', None, _('amend the parent of the working dir')),
1348 ('', 'amend', None, _('amend the parent of the working dir')),
1350 ('s', 'secret', None, _('use the secret phase for committing')),
1349 ('s', 'secret', None, _('use the secret phase for committing')),
1351 ('e', 'edit', None, _('invoke editor on commit messages')),
1350 ('e', 'edit', None, _('invoke editor on commit messages')),
1352 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1351 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1353 _('[OPTION]... [FILE]...'),
1352 _('[OPTION]... [FILE]...'),
1354 inferrepo=True)
1353 inferrepo=True)
1355 def commit(ui, repo, *pats, **opts):
1354 def commit(ui, repo, *pats, **opts):
1356 """commit the specified files or all outstanding changes
1355 """commit the specified files or all outstanding changes
1357
1356
1358 Commit changes to the given files into the repository. Unlike a
1357 Commit changes to the given files into the repository. Unlike a
1359 centralized SCM, this operation is a local operation. See
1358 centralized SCM, this operation is a local operation. See
1360 :hg:`push` for a way to actively distribute your changes.
1359 :hg:`push` for a way to actively distribute your changes.
1361
1360
1362 If a list of files is omitted, all changes reported by :hg:`status`
1361 If a list of files is omitted, all changes reported by :hg:`status`
1363 will be committed.
1362 will be committed.
1364
1363
1365 If you are committing the result of a merge, do not provide any
1364 If you are committing the result of a merge, do not provide any
1366 filenames or -I/-X filters.
1365 filenames or -I/-X filters.
1367
1366
1368 If no commit message is specified, Mercurial starts your
1367 If no commit message is specified, Mercurial starts your
1369 configured editor where you can enter a message. In case your
1368 configured editor where you can enter a message. In case your
1370 commit fails, you will find a backup of your message in
1369 commit fails, you will find a backup of your message in
1371 ``.hg/last-message.txt``.
1370 ``.hg/last-message.txt``.
1372
1371
1373 The --amend flag can be used to amend the parent of the
1372 The --amend flag can be used to amend the parent of the
1374 working directory with a new commit that contains the changes
1373 working directory with a new commit that contains the changes
1375 in the parent in addition to those currently reported by :hg:`status`,
1374 in the parent in addition to those currently reported by :hg:`status`,
1376 if there are any. The old commit is stored in a backup bundle in
1375 if there are any. The old commit is stored in a backup bundle in
1377 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1376 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1378 on how to restore it).
1377 on how to restore it).
1379
1378
1380 Message, user and date are taken from the amended commit unless
1379 Message, user and date are taken from the amended commit unless
1381 specified. When a message isn't specified on the command line,
1380 specified. When a message isn't specified on the command line,
1382 the editor will open with the message of the amended commit.
1381 the editor will open with the message of the amended commit.
1383
1382
1384 It is not possible to amend public changesets (see :hg:`help phases`)
1383 It is not possible to amend public changesets (see :hg:`help phases`)
1385 or changesets that have children.
1384 or changesets that have children.
1386
1385
1387 See :hg:`help dates` for a list of formats valid for -d/--date.
1386 See :hg:`help dates` for a list of formats valid for -d/--date.
1388
1387
1389 Returns 0 on success, 1 if nothing changed.
1388 Returns 0 on success, 1 if nothing changed.
1390 """
1389 """
1391 if opts.get('subrepos'):
1390 if opts.get('subrepos'):
1392 if opts.get('amend'):
1391 if opts.get('amend'):
1393 raise util.Abort(_('cannot amend with --subrepos'))
1392 raise util.Abort(_('cannot amend with --subrepos'))
1394 # Let --subrepos on the command line override config setting.
1393 # Let --subrepos on the command line override config setting.
1395 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1394 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1396
1395
1397 cmdutil.checkunfinished(repo, commit=True)
1396 cmdutil.checkunfinished(repo, commit=True)
1398
1397
1399 branch = repo[None].branch()
1398 branch = repo[None].branch()
1400 bheads = repo.branchheads(branch)
1399 bheads = repo.branchheads(branch)
1401
1400
1402 extra = {}
1401 extra = {}
1403 if opts.get('close_branch'):
1402 if opts.get('close_branch'):
1404 extra['close'] = 1
1403 extra['close'] = 1
1405
1404
1406 if not bheads:
1405 if not bheads:
1407 raise util.Abort(_('can only close branch heads'))
1406 raise util.Abort(_('can only close branch heads'))
1408 elif opts.get('amend'):
1407 elif opts.get('amend'):
1409 if repo.parents()[0].p1().branch() != branch and \
1408 if repo.parents()[0].p1().branch() != branch and \
1410 repo.parents()[0].p2().branch() != branch:
1409 repo.parents()[0].p2().branch() != branch:
1411 raise util.Abort(_('can only close branch heads'))
1410 raise util.Abort(_('can only close branch heads'))
1412
1411
1413 if opts.get('amend'):
1412 if opts.get('amend'):
1414 if ui.configbool('ui', 'commitsubrepos'):
1413 if ui.configbool('ui', 'commitsubrepos'):
1415 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1414 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1416
1415
1417 old = repo['.']
1416 old = repo['.']
1418 if not old.mutable():
1417 if not old.mutable():
1419 raise util.Abort(_('cannot amend public changesets'))
1418 raise util.Abort(_('cannot amend public changesets'))
1420 if len(repo[None].parents()) > 1:
1419 if len(repo[None].parents()) > 1:
1421 raise util.Abort(_('cannot amend while merging'))
1420 raise util.Abort(_('cannot amend while merging'))
1422 if (not obsolete._enabled) and old.children():
1421 if (not obsolete._enabled) and old.children():
1423 raise util.Abort(_('cannot amend changeset with children'))
1422 raise util.Abort(_('cannot amend changeset with children'))
1424
1423
1425 # commitfunc is used only for temporary amend commit by cmdutil.amend
1424 # commitfunc is used only for temporary amend commit by cmdutil.amend
1426 def commitfunc(ui, repo, message, match, opts):
1425 def commitfunc(ui, repo, message, match, opts):
1427 return repo.commit(message,
1426 return repo.commit(message,
1428 opts.get('user') or old.user(),
1427 opts.get('user') or old.user(),
1429 opts.get('date') or old.date(),
1428 opts.get('date') or old.date(),
1430 match,
1429 match,
1431 extra=extra)
1430 extra=extra)
1432
1431
1433 current = repo._bookmarkcurrent
1432 current = repo._bookmarkcurrent
1434 marks = old.bookmarks()
1433 marks = old.bookmarks()
1435 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1434 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1436 if node == old.node():
1435 if node == old.node():
1437 ui.status(_("nothing changed\n"))
1436 ui.status(_("nothing changed\n"))
1438 return 1
1437 return 1
1439 elif marks:
1438 elif marks:
1440 ui.debug('moving bookmarks %r from %s to %s\n' %
1439 ui.debug('moving bookmarks %r from %s to %s\n' %
1441 (marks, old.hex(), hex(node)))
1440 (marks, old.hex(), hex(node)))
1442 newmarks = repo._bookmarks
1441 newmarks = repo._bookmarks
1443 for bm in marks:
1442 for bm in marks:
1444 newmarks[bm] = node
1443 newmarks[bm] = node
1445 if bm == current:
1444 if bm == current:
1446 bookmarks.setcurrent(repo, bm)
1445 bookmarks.setcurrent(repo, bm)
1447 newmarks.write()
1446 newmarks.write()
1448 else:
1447 else:
1449 def commitfunc(ui, repo, message, match, opts):
1448 def commitfunc(ui, repo, message, match, opts):
1450 backup = ui.backupconfig('phases', 'new-commit')
1449 backup = ui.backupconfig('phases', 'new-commit')
1451 baseui = repo.baseui
1450 baseui = repo.baseui
1452 basebackup = baseui.backupconfig('phases', 'new-commit')
1451 basebackup = baseui.backupconfig('phases', 'new-commit')
1453 try:
1452 try:
1454 if opts.get('secret'):
1453 if opts.get('secret'):
1455 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1454 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1456 # Propagate to subrepos
1455 # Propagate to subrepos
1457 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1456 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1458
1457
1459 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1458 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1460 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1459 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1461 return repo.commit(message, opts.get('user'), opts.get('date'),
1460 return repo.commit(message, opts.get('user'), opts.get('date'),
1462 match,
1461 match,
1463 editor=editor,
1462 editor=editor,
1464 extra=extra)
1463 extra=extra)
1465 finally:
1464 finally:
1466 ui.restoreconfig(backup)
1465 ui.restoreconfig(backup)
1467 repo.baseui.restoreconfig(basebackup)
1466 repo.baseui.restoreconfig(basebackup)
1468
1467
1469
1468
1470 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1469 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1471
1470
1472 if not node:
1471 if not node:
1473 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1472 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1474 if stat[3]:
1473 if stat[3]:
1475 ui.status(_("nothing changed (%d missing files, see "
1474 ui.status(_("nothing changed (%d missing files, see "
1476 "'hg status')\n") % len(stat[3]))
1475 "'hg status')\n") % len(stat[3]))
1477 else:
1476 else:
1478 ui.status(_("nothing changed\n"))
1477 ui.status(_("nothing changed\n"))
1479 return 1
1478 return 1
1480
1479
1481 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1480 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1482
1481
1483 @command('config|showconfig|debugconfig',
1482 @command('config|showconfig|debugconfig',
1484 [('u', 'untrusted', None, _('show untrusted configuration options')),
1483 [('u', 'untrusted', None, _('show untrusted configuration options')),
1485 ('e', 'edit', None, _('edit user config')),
1484 ('e', 'edit', None, _('edit user config')),
1486 ('l', 'local', None, _('edit repository config')),
1485 ('l', 'local', None, _('edit repository config')),
1487 ('g', 'global', None, _('edit global config'))],
1486 ('g', 'global', None, _('edit global config'))],
1488 _('[-u] [NAME]...'),
1487 _('[-u] [NAME]...'),
1489 optionalrepo=True)
1488 optionalrepo=True)
1490 def config(ui, repo, *values, **opts):
1489 def config(ui, repo, *values, **opts):
1491 """show combined config settings from all hgrc files
1490 """show combined config settings from all hgrc files
1492
1491
1493 With no arguments, print names and values of all config items.
1492 With no arguments, print names and values of all config items.
1494
1493
1495 With one argument of the form section.name, print just the value
1494 With one argument of the form section.name, print just the value
1496 of that config item.
1495 of that config item.
1497
1496
1498 With multiple arguments, print names and values of all config
1497 With multiple arguments, print names and values of all config
1499 items with matching section names.
1498 items with matching section names.
1500
1499
1501 With --edit, start an editor on the user-level config file. With
1500 With --edit, start an editor on the user-level config file. With
1502 --global, edit the system-wide config file. With --local, edit the
1501 --global, edit the system-wide config file. With --local, edit the
1503 repository-level config file.
1502 repository-level config file.
1504
1503
1505 With --debug, the source (filename and line number) is printed
1504 With --debug, the source (filename and line number) is printed
1506 for each config item.
1505 for each config item.
1507
1506
1508 See :hg:`help config` for more information about config files.
1507 See :hg:`help config` for more information about config files.
1509
1508
1510 Returns 0 on success, 1 if NAME does not exist.
1509 Returns 0 on success, 1 if NAME does not exist.
1511
1510
1512 """
1511 """
1513
1512
1514 if opts.get('edit') or opts.get('local') or opts.get('global'):
1513 if opts.get('edit') or opts.get('local') or opts.get('global'):
1515 if opts.get('local') and opts.get('global'):
1514 if opts.get('local') and opts.get('global'):
1516 raise util.Abort(_("can't use --local and --global together"))
1515 raise util.Abort(_("can't use --local and --global together"))
1517
1516
1518 if opts.get('local'):
1517 if opts.get('local'):
1519 if not repo:
1518 if not repo:
1520 raise util.Abort(_("can't use --local outside a repository"))
1519 raise util.Abort(_("can't use --local outside a repository"))
1521 paths = [repo.join('hgrc')]
1520 paths = [repo.join('hgrc')]
1522 elif opts.get('global'):
1521 elif opts.get('global'):
1523 paths = scmutil.systemrcpath()
1522 paths = scmutil.systemrcpath()
1524 else:
1523 else:
1525 paths = scmutil.userrcpath()
1524 paths = scmutil.userrcpath()
1526
1525
1527 for f in paths:
1526 for f in paths:
1528 if os.path.exists(f):
1527 if os.path.exists(f):
1529 break
1528 break
1530 else:
1529 else:
1531 from ui import samplehgrcs
1530 from ui import samplehgrcs
1532
1531
1533 if opts.get('global'):
1532 if opts.get('global'):
1534 samplehgrc = samplehgrcs['global']
1533 samplehgrc = samplehgrcs['global']
1535 elif opts.get('local'):
1534 elif opts.get('local'):
1536 samplehgrc = samplehgrcs['local']
1535 samplehgrc = samplehgrcs['local']
1537 else:
1536 else:
1538 samplehgrc = samplehgrcs['user']
1537 samplehgrc = samplehgrcs['user']
1539
1538
1540 f = paths[0]
1539 f = paths[0]
1541 fp = open(f, "w")
1540 fp = open(f, "w")
1542 fp.write(samplehgrc)
1541 fp.write(samplehgrc)
1543 fp.close()
1542 fp.close()
1544
1543
1545 editor = ui.geteditor()
1544 editor = ui.geteditor()
1546 util.system("%s \"%s\"" % (editor, f),
1545 util.system("%s \"%s\"" % (editor, f),
1547 onerr=util.Abort, errprefix=_("edit failed"),
1546 onerr=util.Abort, errprefix=_("edit failed"),
1548 out=ui.fout)
1547 out=ui.fout)
1549 return
1548 return
1550
1549
1551 for f in scmutil.rcpath():
1550 for f in scmutil.rcpath():
1552 ui.debug('read config from: %s\n' % f)
1551 ui.debug('read config from: %s\n' % f)
1553 untrusted = bool(opts.get('untrusted'))
1552 untrusted = bool(opts.get('untrusted'))
1554 if values:
1553 if values:
1555 sections = [v for v in values if '.' not in v]
1554 sections = [v for v in values if '.' not in v]
1556 items = [v for v in values if '.' in v]
1555 items = [v for v in values if '.' in v]
1557 if len(items) > 1 or items and sections:
1556 if len(items) > 1 or items and sections:
1558 raise util.Abort(_('only one config item permitted'))
1557 raise util.Abort(_('only one config item permitted'))
1559 matched = False
1558 matched = False
1560 for section, name, value in ui.walkconfig(untrusted=untrusted):
1559 for section, name, value in ui.walkconfig(untrusted=untrusted):
1561 value = str(value).replace('\n', '\\n')
1560 value = str(value).replace('\n', '\\n')
1562 sectname = section + '.' + name
1561 sectname = section + '.' + name
1563 if values:
1562 if values:
1564 for v in values:
1563 for v in values:
1565 if v == section:
1564 if v == section:
1566 ui.debug('%s: ' %
1565 ui.debug('%s: ' %
1567 ui.configsource(section, name, untrusted))
1566 ui.configsource(section, name, untrusted))
1568 ui.write('%s=%s\n' % (sectname, value))
1567 ui.write('%s=%s\n' % (sectname, value))
1569 matched = True
1568 matched = True
1570 elif v == sectname:
1569 elif v == sectname:
1571 ui.debug('%s: ' %
1570 ui.debug('%s: ' %
1572 ui.configsource(section, name, untrusted))
1571 ui.configsource(section, name, untrusted))
1573 ui.write(value, '\n')
1572 ui.write(value, '\n')
1574 matched = True
1573 matched = True
1575 else:
1574 else:
1576 ui.debug('%s: ' %
1575 ui.debug('%s: ' %
1577 ui.configsource(section, name, untrusted))
1576 ui.configsource(section, name, untrusted))
1578 ui.write('%s=%s\n' % (sectname, value))
1577 ui.write('%s=%s\n' % (sectname, value))
1579 matched = True
1578 matched = True
1580 if matched:
1579 if matched:
1581 return 0
1580 return 0
1582 return 1
1581 return 1
1583
1582
1584 @command('copy|cp',
1583 @command('copy|cp',
1585 [('A', 'after', None, _('record a copy that has already occurred')),
1584 [('A', 'after', None, _('record a copy that has already occurred')),
1586 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1585 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1587 ] + walkopts + dryrunopts,
1586 ] + walkopts + dryrunopts,
1588 _('[OPTION]... [SOURCE]... DEST'))
1587 _('[OPTION]... [SOURCE]... DEST'))
1589 def copy(ui, repo, *pats, **opts):
1588 def copy(ui, repo, *pats, **opts):
1590 """mark files as copied for the next commit
1589 """mark files as copied for the next commit
1591
1590
1592 Mark dest as having copies of source files. If dest is a
1591 Mark dest as having copies of source files. If dest is a
1593 directory, copies are put in that directory. If dest is a file,
1592 directory, copies are put in that directory. If dest is a file,
1594 the source must be a single file.
1593 the source must be a single file.
1595
1594
1596 By default, this command copies the contents of files as they
1595 By default, this command copies the contents of files as they
1597 exist in the working directory. If invoked with -A/--after, the
1596 exist in the working directory. If invoked with -A/--after, the
1598 operation is recorded, but no copying is performed.
1597 operation is recorded, but no copying is performed.
1599
1598
1600 This command takes effect with the next commit. To undo a copy
1599 This command takes effect with the next commit. To undo a copy
1601 before that, see :hg:`revert`.
1600 before that, see :hg:`revert`.
1602
1601
1603 Returns 0 on success, 1 if errors are encountered.
1602 Returns 0 on success, 1 if errors are encountered.
1604 """
1603 """
1605 wlock = repo.wlock(False)
1604 wlock = repo.wlock(False)
1606 try:
1605 try:
1607 return cmdutil.copy(ui, repo, pats, opts)
1606 return cmdutil.copy(ui, repo, pats, opts)
1608 finally:
1607 finally:
1609 wlock.release()
1608 wlock.release()
1610
1609
1611 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1610 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1612 def debugancestor(ui, repo, *args):
1611 def debugancestor(ui, repo, *args):
1613 """find the ancestor revision of two revisions in a given index"""
1612 """find the ancestor revision of two revisions in a given index"""
1614 if len(args) == 3:
1613 if len(args) == 3:
1615 index, rev1, rev2 = args
1614 index, rev1, rev2 = args
1616 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1615 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1617 lookup = r.lookup
1616 lookup = r.lookup
1618 elif len(args) == 2:
1617 elif len(args) == 2:
1619 if not repo:
1618 if not repo:
1620 raise util.Abort(_("there is no Mercurial repository here "
1619 raise util.Abort(_("there is no Mercurial repository here "
1621 "(.hg not found)"))
1620 "(.hg not found)"))
1622 rev1, rev2 = args
1621 rev1, rev2 = args
1623 r = repo.changelog
1622 r = repo.changelog
1624 lookup = repo.lookup
1623 lookup = repo.lookup
1625 else:
1624 else:
1626 raise util.Abort(_('either two or three arguments required'))
1625 raise util.Abort(_('either two or three arguments required'))
1627 a = r.ancestor(lookup(rev1), lookup(rev2))
1626 a = r.ancestor(lookup(rev1), lookup(rev2))
1628 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1627 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1629
1628
1630 @command('debugbuilddag',
1629 @command('debugbuilddag',
1631 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1630 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1632 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1631 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1633 ('n', 'new-file', None, _('add new file at each rev'))],
1632 ('n', 'new-file', None, _('add new file at each rev'))],
1634 _('[OPTION]... [TEXT]'))
1633 _('[OPTION]... [TEXT]'))
1635 def debugbuilddag(ui, repo, text=None,
1634 def debugbuilddag(ui, repo, text=None,
1636 mergeable_file=False,
1635 mergeable_file=False,
1637 overwritten_file=False,
1636 overwritten_file=False,
1638 new_file=False):
1637 new_file=False):
1639 """builds a repo with a given DAG from scratch in the current empty repo
1638 """builds a repo with a given DAG from scratch in the current empty repo
1640
1639
1641 The description of the DAG is read from stdin if not given on the
1640 The description of the DAG is read from stdin if not given on the
1642 command line.
1641 command line.
1643
1642
1644 Elements:
1643 Elements:
1645
1644
1646 - "+n" is a linear run of n nodes based on the current default parent
1645 - "+n" is a linear run of n nodes based on the current default parent
1647 - "." is a single node based on the current default parent
1646 - "." is a single node based on the current default parent
1648 - "$" resets the default parent to null (implied at the start);
1647 - "$" resets the default parent to null (implied at the start);
1649 otherwise the default parent is always the last node created
1648 otherwise the default parent is always the last node created
1650 - "<p" sets the default parent to the backref p
1649 - "<p" sets the default parent to the backref p
1651 - "*p" is a fork at parent p, which is a backref
1650 - "*p" is a fork at parent p, which is a backref
1652 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1651 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1653 - "/p2" is a merge of the preceding node and p2
1652 - "/p2" is a merge of the preceding node and p2
1654 - ":tag" defines a local tag for the preceding node
1653 - ":tag" defines a local tag for the preceding node
1655 - "@branch" sets the named branch for subsequent nodes
1654 - "@branch" sets the named branch for subsequent nodes
1656 - "#...\\n" is a comment up to the end of the line
1655 - "#...\\n" is a comment up to the end of the line
1657
1656
1658 Whitespace between the above elements is ignored.
1657 Whitespace between the above elements is ignored.
1659
1658
1660 A backref is either
1659 A backref is either
1661
1660
1662 - a number n, which references the node curr-n, where curr is the current
1661 - a number n, which references the node curr-n, where curr is the current
1663 node, or
1662 node, or
1664 - the name of a local tag you placed earlier using ":tag", or
1663 - the name of a local tag you placed earlier using ":tag", or
1665 - empty to denote the default parent.
1664 - empty to denote the default parent.
1666
1665
1667 All string valued-elements are either strictly alphanumeric, or must
1666 All string valued-elements are either strictly alphanumeric, or must
1668 be enclosed in double quotes ("..."), with "\\" as escape character.
1667 be enclosed in double quotes ("..."), with "\\" as escape character.
1669 """
1668 """
1670
1669
1671 if text is None:
1670 if text is None:
1672 ui.status(_("reading DAG from stdin\n"))
1671 ui.status(_("reading DAG from stdin\n"))
1673 text = ui.fin.read()
1672 text = ui.fin.read()
1674
1673
1675 cl = repo.changelog
1674 cl = repo.changelog
1676 if len(cl) > 0:
1675 if len(cl) > 0:
1677 raise util.Abort(_('repository is not empty'))
1676 raise util.Abort(_('repository is not empty'))
1678
1677
1679 # determine number of revs in DAG
1678 # determine number of revs in DAG
1680 total = 0
1679 total = 0
1681 for type, data in dagparser.parsedag(text):
1680 for type, data in dagparser.parsedag(text):
1682 if type == 'n':
1681 if type == 'n':
1683 total += 1
1682 total += 1
1684
1683
1685 if mergeable_file:
1684 if mergeable_file:
1686 linesperrev = 2
1685 linesperrev = 2
1687 # make a file with k lines per rev
1686 # make a file with k lines per rev
1688 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1687 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1689 initialmergedlines.append("")
1688 initialmergedlines.append("")
1690
1689
1691 tags = []
1690 tags = []
1692
1691
1693 lock = tr = None
1692 lock = tr = None
1694 try:
1693 try:
1695 lock = repo.lock()
1694 lock = repo.lock()
1696 tr = repo.transaction("builddag")
1695 tr = repo.transaction("builddag")
1697
1696
1698 at = -1
1697 at = -1
1699 atbranch = 'default'
1698 atbranch = 'default'
1700 nodeids = []
1699 nodeids = []
1701 id = 0
1700 id = 0
1702 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1701 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1703 for type, data in dagparser.parsedag(text):
1702 for type, data in dagparser.parsedag(text):
1704 if type == 'n':
1703 if type == 'n':
1705 ui.note(('node %s\n' % str(data)))
1704 ui.note(('node %s\n' % str(data)))
1706 id, ps = data
1705 id, ps = data
1707
1706
1708 files = []
1707 files = []
1709 fctxs = {}
1708 fctxs = {}
1710
1709
1711 p2 = None
1710 p2 = None
1712 if mergeable_file:
1711 if mergeable_file:
1713 fn = "mf"
1712 fn = "mf"
1714 p1 = repo[ps[0]]
1713 p1 = repo[ps[0]]
1715 if len(ps) > 1:
1714 if len(ps) > 1:
1716 p2 = repo[ps[1]]
1715 p2 = repo[ps[1]]
1717 pa = p1.ancestor(p2)
1716 pa = p1.ancestor(p2)
1718 base, local, other = [x[fn].data() for x in (pa, p1,
1717 base, local, other = [x[fn].data() for x in (pa, p1,
1719 p2)]
1718 p2)]
1720 m3 = simplemerge.Merge3Text(base, local, other)
1719 m3 = simplemerge.Merge3Text(base, local, other)
1721 ml = [l.strip() for l in m3.merge_lines()]
1720 ml = [l.strip() for l in m3.merge_lines()]
1722 ml.append("")
1721 ml.append("")
1723 elif at > 0:
1722 elif at > 0:
1724 ml = p1[fn].data().split("\n")
1723 ml = p1[fn].data().split("\n")
1725 else:
1724 else:
1726 ml = initialmergedlines
1725 ml = initialmergedlines
1727 ml[id * linesperrev] += " r%i" % id
1726 ml[id * linesperrev] += " r%i" % id
1728 mergedtext = "\n".join(ml)
1727 mergedtext = "\n".join(ml)
1729 files.append(fn)
1728 files.append(fn)
1730 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1729 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1731
1730
1732 if overwritten_file:
1731 if overwritten_file:
1733 fn = "of"
1732 fn = "of"
1734 files.append(fn)
1733 files.append(fn)
1735 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1734 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1736
1735
1737 if new_file:
1736 if new_file:
1738 fn = "nf%i" % id
1737 fn = "nf%i" % id
1739 files.append(fn)
1738 files.append(fn)
1740 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1739 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1741 if len(ps) > 1:
1740 if len(ps) > 1:
1742 if not p2:
1741 if not p2:
1743 p2 = repo[ps[1]]
1742 p2 = repo[ps[1]]
1744 for fn in p2:
1743 for fn in p2:
1745 if fn.startswith("nf"):
1744 if fn.startswith("nf"):
1746 files.append(fn)
1745 files.append(fn)
1747 fctxs[fn] = p2[fn]
1746 fctxs[fn] = p2[fn]
1748
1747
1749 def fctxfn(repo, cx, path):
1748 def fctxfn(repo, cx, path):
1750 return fctxs.get(path)
1749 return fctxs.get(path)
1751
1750
1752 if len(ps) == 0 or ps[0] < 0:
1751 if len(ps) == 0 or ps[0] < 0:
1753 pars = [None, None]
1752 pars = [None, None]
1754 elif len(ps) == 1:
1753 elif len(ps) == 1:
1755 pars = [nodeids[ps[0]], None]
1754 pars = [nodeids[ps[0]], None]
1756 else:
1755 else:
1757 pars = [nodeids[p] for p in ps]
1756 pars = [nodeids[p] for p in ps]
1758 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1757 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1759 date=(id, 0),
1758 date=(id, 0),
1760 user="debugbuilddag",
1759 user="debugbuilddag",
1761 extra={'branch': atbranch})
1760 extra={'branch': atbranch})
1762 nodeid = repo.commitctx(cx)
1761 nodeid = repo.commitctx(cx)
1763 nodeids.append(nodeid)
1762 nodeids.append(nodeid)
1764 at = id
1763 at = id
1765 elif type == 'l':
1764 elif type == 'l':
1766 id, name = data
1765 id, name = data
1767 ui.note(('tag %s\n' % name))
1766 ui.note(('tag %s\n' % name))
1768 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1767 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1769 elif type == 'a':
1768 elif type == 'a':
1770 ui.note(('branch %s\n' % data))
1769 ui.note(('branch %s\n' % data))
1771 atbranch = data
1770 atbranch = data
1772 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1771 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1773 tr.close()
1772 tr.close()
1774
1773
1775 if tags:
1774 if tags:
1776 repo.opener.write("localtags", "".join(tags))
1775 repo.opener.write("localtags", "".join(tags))
1777 finally:
1776 finally:
1778 ui.progress(_('building'), None)
1777 ui.progress(_('building'), None)
1779 release(tr, lock)
1778 release(tr, lock)
1780
1779
1781 @command('debugbundle',
1780 @command('debugbundle',
1782 [('a', 'all', None, _('show all details'))],
1781 [('a', 'all', None, _('show all details'))],
1783 _('FILE'),
1782 _('FILE'),
1784 norepo=True)
1783 norepo=True)
1785 def debugbundle(ui, bundlepath, all=None, **opts):
1784 def debugbundle(ui, bundlepath, all=None, **opts):
1786 """lists the contents of a bundle"""
1785 """lists the contents of a bundle"""
1787 f = hg.openpath(ui, bundlepath)
1786 f = hg.openpath(ui, bundlepath)
1788 try:
1787 try:
1789 gen = exchange.readbundle(ui, f, bundlepath)
1788 gen = exchange.readbundle(ui, f, bundlepath)
1790 if all:
1789 if all:
1791 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1790 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1792
1791
1793 def showchunks(named):
1792 def showchunks(named):
1794 ui.write("\n%s\n" % named)
1793 ui.write("\n%s\n" % named)
1795 chain = None
1794 chain = None
1796 while True:
1795 while True:
1797 chunkdata = gen.deltachunk(chain)
1796 chunkdata = gen.deltachunk(chain)
1798 if not chunkdata:
1797 if not chunkdata:
1799 break
1798 break
1800 node = chunkdata['node']
1799 node = chunkdata['node']
1801 p1 = chunkdata['p1']
1800 p1 = chunkdata['p1']
1802 p2 = chunkdata['p2']
1801 p2 = chunkdata['p2']
1803 cs = chunkdata['cs']
1802 cs = chunkdata['cs']
1804 deltabase = chunkdata['deltabase']
1803 deltabase = chunkdata['deltabase']
1805 delta = chunkdata['delta']
1804 delta = chunkdata['delta']
1806 ui.write("%s %s %s %s %s %s\n" %
1805 ui.write("%s %s %s %s %s %s\n" %
1807 (hex(node), hex(p1), hex(p2),
1806 (hex(node), hex(p1), hex(p2),
1808 hex(cs), hex(deltabase), len(delta)))
1807 hex(cs), hex(deltabase), len(delta)))
1809 chain = node
1808 chain = node
1810
1809
1811 chunkdata = gen.changelogheader()
1810 chunkdata = gen.changelogheader()
1812 showchunks("changelog")
1811 showchunks("changelog")
1813 chunkdata = gen.manifestheader()
1812 chunkdata = gen.manifestheader()
1814 showchunks("manifest")
1813 showchunks("manifest")
1815 while True:
1814 while True:
1816 chunkdata = gen.filelogheader()
1815 chunkdata = gen.filelogheader()
1817 if not chunkdata:
1816 if not chunkdata:
1818 break
1817 break
1819 fname = chunkdata['filename']
1818 fname = chunkdata['filename']
1820 showchunks(fname)
1819 showchunks(fname)
1821 else:
1820 else:
1822 chunkdata = gen.changelogheader()
1821 chunkdata = gen.changelogheader()
1823 chain = None
1822 chain = None
1824 while True:
1823 while True:
1825 chunkdata = gen.deltachunk(chain)
1824 chunkdata = gen.deltachunk(chain)
1826 if not chunkdata:
1825 if not chunkdata:
1827 break
1826 break
1828 node = chunkdata['node']
1827 node = chunkdata['node']
1829 ui.write("%s\n" % hex(node))
1828 ui.write("%s\n" % hex(node))
1830 chain = node
1829 chain = node
1831 finally:
1830 finally:
1832 f.close()
1831 f.close()
1833
1832
1834 @command('debugcheckstate', [], '')
1833 @command('debugcheckstate', [], '')
1835 def debugcheckstate(ui, repo):
1834 def debugcheckstate(ui, repo):
1836 """validate the correctness of the current dirstate"""
1835 """validate the correctness of the current dirstate"""
1837 parent1, parent2 = repo.dirstate.parents()
1836 parent1, parent2 = repo.dirstate.parents()
1838 m1 = repo[parent1].manifest()
1837 m1 = repo[parent1].manifest()
1839 m2 = repo[parent2].manifest()
1838 m2 = repo[parent2].manifest()
1840 errors = 0
1839 errors = 0
1841 for f in repo.dirstate:
1840 for f in repo.dirstate:
1842 state = repo.dirstate[f]
1841 state = repo.dirstate[f]
1843 if state in "nr" and f not in m1:
1842 if state in "nr" and f not in m1:
1844 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1843 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1845 errors += 1
1844 errors += 1
1846 if state in "a" and f in m1:
1845 if state in "a" and f in m1:
1847 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1846 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1848 errors += 1
1847 errors += 1
1849 if state in "m" and f not in m1 and f not in m2:
1848 if state in "m" and f not in m1 and f not in m2:
1850 ui.warn(_("%s in state %s, but not in either manifest\n") %
1849 ui.warn(_("%s in state %s, but not in either manifest\n") %
1851 (f, state))
1850 (f, state))
1852 errors += 1
1851 errors += 1
1853 for f in m1:
1852 for f in m1:
1854 state = repo.dirstate[f]
1853 state = repo.dirstate[f]
1855 if state not in "nrm":
1854 if state not in "nrm":
1856 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1855 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1857 errors += 1
1856 errors += 1
1858 if errors:
1857 if errors:
1859 error = _(".hg/dirstate inconsistent with current parent's manifest")
1858 error = _(".hg/dirstate inconsistent with current parent's manifest")
1860 raise util.Abort(error)
1859 raise util.Abort(error)
1861
1860
1862 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1861 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1863 def debugcommands(ui, cmd='', *args):
1862 def debugcommands(ui, cmd='', *args):
1864 """list all available commands and options"""
1863 """list all available commands and options"""
1865 for cmd, vals in sorted(table.iteritems()):
1864 for cmd, vals in sorted(table.iteritems()):
1866 cmd = cmd.split('|')[0].strip('^')
1865 cmd = cmd.split('|')[0].strip('^')
1867 opts = ', '.join([i[1] for i in vals[1]])
1866 opts = ', '.join([i[1] for i in vals[1]])
1868 ui.write('%s: %s\n' % (cmd, opts))
1867 ui.write('%s: %s\n' % (cmd, opts))
1869
1868
1870 @command('debugcomplete',
1869 @command('debugcomplete',
1871 [('o', 'options', None, _('show the command options'))],
1870 [('o', 'options', None, _('show the command options'))],
1872 _('[-o] CMD'),
1871 _('[-o] CMD'),
1873 norepo=True)
1872 norepo=True)
1874 def debugcomplete(ui, cmd='', **opts):
1873 def debugcomplete(ui, cmd='', **opts):
1875 """returns the completion list associated with the given command"""
1874 """returns the completion list associated with the given command"""
1876
1875
1877 if opts.get('options'):
1876 if opts.get('options'):
1878 options = []
1877 options = []
1879 otables = [globalopts]
1878 otables = [globalopts]
1880 if cmd:
1879 if cmd:
1881 aliases, entry = cmdutil.findcmd(cmd, table, False)
1880 aliases, entry = cmdutil.findcmd(cmd, table, False)
1882 otables.append(entry[1])
1881 otables.append(entry[1])
1883 for t in otables:
1882 for t in otables:
1884 for o in t:
1883 for o in t:
1885 if "(DEPRECATED)" in o[3]:
1884 if "(DEPRECATED)" in o[3]:
1886 continue
1885 continue
1887 if o[0]:
1886 if o[0]:
1888 options.append('-%s' % o[0])
1887 options.append('-%s' % o[0])
1889 options.append('--%s' % o[1])
1888 options.append('--%s' % o[1])
1890 ui.write("%s\n" % "\n".join(options))
1889 ui.write("%s\n" % "\n".join(options))
1891 return
1890 return
1892
1891
1893 cmdlist = cmdutil.findpossible(cmd, table)
1892 cmdlist = cmdutil.findpossible(cmd, table)
1894 if ui.verbose:
1893 if ui.verbose:
1895 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1894 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1896 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1895 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1897
1896
1898 @command('debugdag',
1897 @command('debugdag',
1899 [('t', 'tags', None, _('use tags as labels')),
1898 [('t', 'tags', None, _('use tags as labels')),
1900 ('b', 'branches', None, _('annotate with branch names')),
1899 ('b', 'branches', None, _('annotate with branch names')),
1901 ('', 'dots', None, _('use dots for runs')),
1900 ('', 'dots', None, _('use dots for runs')),
1902 ('s', 'spaces', None, _('separate elements by spaces'))],
1901 ('s', 'spaces', None, _('separate elements by spaces'))],
1903 _('[OPTION]... [FILE [REV]...]'),
1902 _('[OPTION]... [FILE [REV]...]'),
1904 optionalrepo=True)
1903 optionalrepo=True)
1905 def debugdag(ui, repo, file_=None, *revs, **opts):
1904 def debugdag(ui, repo, file_=None, *revs, **opts):
1906 """format the changelog or an index DAG as a concise textual description
1905 """format the changelog or an index DAG as a concise textual description
1907
1906
1908 If you pass a revlog index, the revlog's DAG is emitted. If you list
1907 If you pass a revlog index, the revlog's DAG is emitted. If you list
1909 revision numbers, they get labeled in the output as rN.
1908 revision numbers, they get labeled in the output as rN.
1910
1909
1911 Otherwise, the changelog DAG of the current repo is emitted.
1910 Otherwise, the changelog DAG of the current repo is emitted.
1912 """
1911 """
1913 spaces = opts.get('spaces')
1912 spaces = opts.get('spaces')
1914 dots = opts.get('dots')
1913 dots = opts.get('dots')
1915 if file_:
1914 if file_:
1916 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1915 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1917 revs = set((int(r) for r in revs))
1916 revs = set((int(r) for r in revs))
1918 def events():
1917 def events():
1919 for r in rlog:
1918 for r in rlog:
1920 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1919 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1921 if p != -1))
1920 if p != -1))
1922 if r in revs:
1921 if r in revs:
1923 yield 'l', (r, "r%i" % r)
1922 yield 'l', (r, "r%i" % r)
1924 elif repo:
1923 elif repo:
1925 cl = repo.changelog
1924 cl = repo.changelog
1926 tags = opts.get('tags')
1925 tags = opts.get('tags')
1927 branches = opts.get('branches')
1926 branches = opts.get('branches')
1928 if tags:
1927 if tags:
1929 labels = {}
1928 labels = {}
1930 for l, n in repo.tags().items():
1929 for l, n in repo.tags().items():
1931 labels.setdefault(cl.rev(n), []).append(l)
1930 labels.setdefault(cl.rev(n), []).append(l)
1932 def events():
1931 def events():
1933 b = "default"
1932 b = "default"
1934 for r in cl:
1933 for r in cl:
1935 if branches:
1934 if branches:
1936 newb = cl.read(cl.node(r))[5]['branch']
1935 newb = cl.read(cl.node(r))[5]['branch']
1937 if newb != b:
1936 if newb != b:
1938 yield 'a', newb
1937 yield 'a', newb
1939 b = newb
1938 b = newb
1940 yield 'n', (r, list(p for p in cl.parentrevs(r)
1939 yield 'n', (r, list(p for p in cl.parentrevs(r)
1941 if p != -1))
1940 if p != -1))
1942 if tags:
1941 if tags:
1943 ls = labels.get(r)
1942 ls = labels.get(r)
1944 if ls:
1943 if ls:
1945 for l in ls:
1944 for l in ls:
1946 yield 'l', (r, l)
1945 yield 'l', (r, l)
1947 else:
1946 else:
1948 raise util.Abort(_('need repo for changelog dag'))
1947 raise util.Abort(_('need repo for changelog dag'))
1949
1948
1950 for line in dagparser.dagtextlines(events(),
1949 for line in dagparser.dagtextlines(events(),
1951 addspaces=spaces,
1950 addspaces=spaces,
1952 wraplabels=True,
1951 wraplabels=True,
1953 wrapannotations=True,
1952 wrapannotations=True,
1954 wrapnonlinear=dots,
1953 wrapnonlinear=dots,
1955 usedots=dots,
1954 usedots=dots,
1956 maxlinewidth=70):
1955 maxlinewidth=70):
1957 ui.write(line)
1956 ui.write(line)
1958 ui.write("\n")
1957 ui.write("\n")
1959
1958
1960 @command('debugdata',
1959 @command('debugdata',
1961 [('c', 'changelog', False, _('open changelog')),
1960 [('c', 'changelog', False, _('open changelog')),
1962 ('m', 'manifest', False, _('open manifest'))],
1961 ('m', 'manifest', False, _('open manifest'))],
1963 _('-c|-m|FILE REV'))
1962 _('-c|-m|FILE REV'))
1964 def debugdata(ui, repo, file_, rev=None, **opts):
1963 def debugdata(ui, repo, file_, rev=None, **opts):
1965 """dump the contents of a data file revision"""
1964 """dump the contents of a data file revision"""
1966 if opts.get('changelog') or opts.get('manifest'):
1965 if opts.get('changelog') or opts.get('manifest'):
1967 file_, rev = None, file_
1966 file_, rev = None, file_
1968 elif rev is None:
1967 elif rev is None:
1969 raise error.CommandError('debugdata', _('invalid arguments'))
1968 raise error.CommandError('debugdata', _('invalid arguments'))
1970 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1969 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1971 try:
1970 try:
1972 ui.write(r.revision(r.lookup(rev)))
1971 ui.write(r.revision(r.lookup(rev)))
1973 except KeyError:
1972 except KeyError:
1974 raise util.Abort(_('invalid revision identifier %s') % rev)
1973 raise util.Abort(_('invalid revision identifier %s') % rev)
1975
1974
1976 @command('debugdate',
1975 @command('debugdate',
1977 [('e', 'extended', None, _('try extended date formats'))],
1976 [('e', 'extended', None, _('try extended date formats'))],
1978 _('[-e] DATE [RANGE]'),
1977 _('[-e] DATE [RANGE]'),
1979 norepo=True, optionalrepo=True)
1978 norepo=True, optionalrepo=True)
1980 def debugdate(ui, date, range=None, **opts):
1979 def debugdate(ui, date, range=None, **opts):
1981 """parse and display a date"""
1980 """parse and display a date"""
1982 if opts["extended"]:
1981 if opts["extended"]:
1983 d = util.parsedate(date, util.extendeddateformats)
1982 d = util.parsedate(date, util.extendeddateformats)
1984 else:
1983 else:
1985 d = util.parsedate(date)
1984 d = util.parsedate(date)
1986 ui.write(("internal: %s %s\n") % d)
1985 ui.write(("internal: %s %s\n") % d)
1987 ui.write(("standard: %s\n") % util.datestr(d))
1986 ui.write(("standard: %s\n") % util.datestr(d))
1988 if range:
1987 if range:
1989 m = util.matchdate(range)
1988 m = util.matchdate(range)
1990 ui.write(("match: %s\n") % m(d[0]))
1989 ui.write(("match: %s\n") % m(d[0]))
1991
1990
1992 @command('debugdiscovery',
1991 @command('debugdiscovery',
1993 [('', 'old', None, _('use old-style discovery')),
1992 [('', 'old', None, _('use old-style discovery')),
1994 ('', 'nonheads', None,
1993 ('', 'nonheads', None,
1995 _('use old-style discovery with non-heads included')),
1994 _('use old-style discovery with non-heads included')),
1996 ] + remoteopts,
1995 ] + remoteopts,
1997 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1996 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1998 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1997 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1999 """runs the changeset discovery protocol in isolation"""
1998 """runs the changeset discovery protocol in isolation"""
2000 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1999 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2001 opts.get('branch'))
2000 opts.get('branch'))
2002 remote = hg.peer(repo, opts, remoteurl)
2001 remote = hg.peer(repo, opts, remoteurl)
2003 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2002 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2004
2003
2005 # make sure tests are repeatable
2004 # make sure tests are repeatable
2006 random.seed(12323)
2005 random.seed(12323)
2007
2006
2008 def doit(localheads, remoteheads, remote=remote):
2007 def doit(localheads, remoteheads, remote=remote):
2009 if opts.get('old'):
2008 if opts.get('old'):
2010 if localheads:
2009 if localheads:
2011 raise util.Abort('cannot use localheads with old style '
2010 raise util.Abort('cannot use localheads with old style '
2012 'discovery')
2011 'discovery')
2013 if not util.safehasattr(remote, 'branches'):
2012 if not util.safehasattr(remote, 'branches'):
2014 # enable in-client legacy support
2013 # enable in-client legacy support
2015 remote = localrepo.locallegacypeer(remote.local())
2014 remote = localrepo.locallegacypeer(remote.local())
2016 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2015 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2017 force=True)
2016 force=True)
2018 common = set(common)
2017 common = set(common)
2019 if not opts.get('nonheads'):
2018 if not opts.get('nonheads'):
2020 ui.write(("unpruned common: %s\n") %
2019 ui.write(("unpruned common: %s\n") %
2021 " ".join(sorted(short(n) for n in common)))
2020 " ".join(sorted(short(n) for n in common)))
2022 dag = dagutil.revlogdag(repo.changelog)
2021 dag = dagutil.revlogdag(repo.changelog)
2023 all = dag.ancestorset(dag.internalizeall(common))
2022 all = dag.ancestorset(dag.internalizeall(common))
2024 common = dag.externalizeall(dag.headsetofconnecteds(all))
2023 common = dag.externalizeall(dag.headsetofconnecteds(all))
2025 else:
2024 else:
2026 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2025 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2027 common = set(common)
2026 common = set(common)
2028 rheads = set(hds)
2027 rheads = set(hds)
2029 lheads = set(repo.heads())
2028 lheads = set(repo.heads())
2030 ui.write(("common heads: %s\n") %
2029 ui.write(("common heads: %s\n") %
2031 " ".join(sorted(short(n) for n in common)))
2030 " ".join(sorted(short(n) for n in common)))
2032 if lheads <= common:
2031 if lheads <= common:
2033 ui.write(("local is subset\n"))
2032 ui.write(("local is subset\n"))
2034 elif rheads <= common:
2033 elif rheads <= common:
2035 ui.write(("remote is subset\n"))
2034 ui.write(("remote is subset\n"))
2036
2035
2037 serverlogs = opts.get('serverlog')
2036 serverlogs = opts.get('serverlog')
2038 if serverlogs:
2037 if serverlogs:
2039 for filename in serverlogs:
2038 for filename in serverlogs:
2040 logfile = open(filename, 'r')
2039 logfile = open(filename, 'r')
2041 try:
2040 try:
2042 line = logfile.readline()
2041 line = logfile.readline()
2043 while line:
2042 while line:
2044 parts = line.strip().split(';')
2043 parts = line.strip().split(';')
2045 op = parts[1]
2044 op = parts[1]
2046 if op == 'cg':
2045 if op == 'cg':
2047 pass
2046 pass
2048 elif op == 'cgss':
2047 elif op == 'cgss':
2049 doit(parts[2].split(' '), parts[3].split(' '))
2048 doit(parts[2].split(' '), parts[3].split(' '))
2050 elif op == 'unb':
2049 elif op == 'unb':
2051 doit(parts[3].split(' '), parts[2].split(' '))
2050 doit(parts[3].split(' '), parts[2].split(' '))
2052 line = logfile.readline()
2051 line = logfile.readline()
2053 finally:
2052 finally:
2054 logfile.close()
2053 logfile.close()
2055
2054
2056 else:
2055 else:
2057 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2056 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2058 opts.get('remote_head'))
2057 opts.get('remote_head'))
2059 localrevs = opts.get('local_head')
2058 localrevs = opts.get('local_head')
2060 doit(localrevs, remoterevs)
2059 doit(localrevs, remoterevs)
2061
2060
2062 @command('debugfileset',
2061 @command('debugfileset',
2063 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2062 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2064 _('[-r REV] FILESPEC'))
2063 _('[-r REV] FILESPEC'))
2065 def debugfileset(ui, repo, expr, **opts):
2064 def debugfileset(ui, repo, expr, **opts):
2066 '''parse and apply a fileset specification'''
2065 '''parse and apply a fileset specification'''
2067 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2066 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2068 if ui.verbose:
2067 if ui.verbose:
2069 tree = fileset.parse(expr)[0]
2068 tree = fileset.parse(expr)[0]
2070 ui.note(tree, "\n")
2069 ui.note(tree, "\n")
2071
2070
2072 for f in ctx.getfileset(expr):
2071 for f in ctx.getfileset(expr):
2073 ui.write("%s\n" % f)
2072 ui.write("%s\n" % f)
2074
2073
2075 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2074 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2076 def debugfsinfo(ui, path="."):
2075 def debugfsinfo(ui, path="."):
2077 """show information detected about current filesystem"""
2076 """show information detected about current filesystem"""
2078 util.writefile('.debugfsinfo', '')
2077 util.writefile('.debugfsinfo', '')
2079 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2078 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2080 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2079 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2081 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2080 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2082 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2081 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2083 and 'yes' or 'no'))
2082 and 'yes' or 'no'))
2084 os.unlink('.debugfsinfo')
2083 os.unlink('.debugfsinfo')
2085
2084
2086 @command('debuggetbundle',
2085 @command('debuggetbundle',
2087 [('H', 'head', [], _('id of head node'), _('ID')),
2086 [('H', 'head', [], _('id of head node'), _('ID')),
2088 ('C', 'common', [], _('id of common node'), _('ID')),
2087 ('C', 'common', [], _('id of common node'), _('ID')),
2089 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2088 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2090 _('REPO FILE [-H|-C ID]...'),
2089 _('REPO FILE [-H|-C ID]...'),
2091 norepo=True)
2090 norepo=True)
2092 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2091 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2093 """retrieves a bundle from a repo
2092 """retrieves a bundle from a repo
2094
2093
2095 Every ID must be a full-length hex node id string. Saves the bundle to the
2094 Every ID must be a full-length hex node id string. Saves the bundle to the
2096 given file.
2095 given file.
2097 """
2096 """
2098 repo = hg.peer(ui, opts, repopath)
2097 repo = hg.peer(ui, opts, repopath)
2099 if not repo.capable('getbundle'):
2098 if not repo.capable('getbundle'):
2100 raise util.Abort("getbundle() not supported by target repository")
2099 raise util.Abort("getbundle() not supported by target repository")
2101 args = {}
2100 args = {}
2102 if common:
2101 if common:
2103 args['common'] = [bin(s) for s in common]
2102 args['common'] = [bin(s) for s in common]
2104 if head:
2103 if head:
2105 args['heads'] = [bin(s) for s in head]
2104 args['heads'] = [bin(s) for s in head]
2106 # TODO: get desired bundlecaps from command line.
2105 # TODO: get desired bundlecaps from command line.
2107 args['bundlecaps'] = None
2106 args['bundlecaps'] = None
2108 bundle = repo.getbundle('debug', **args)
2107 bundle = repo.getbundle('debug', **args)
2109
2108
2110 bundletype = opts.get('type', 'bzip2').lower()
2109 bundletype = opts.get('type', 'bzip2').lower()
2111 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2110 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2112 bundletype = btypes.get(bundletype)
2111 bundletype = btypes.get(bundletype)
2113 if bundletype not in changegroup.bundletypes:
2112 if bundletype not in changegroup.bundletypes:
2114 raise util.Abort(_('unknown bundle type specified with --type'))
2113 raise util.Abort(_('unknown bundle type specified with --type'))
2115 changegroup.writebundle(bundle, bundlepath, bundletype)
2114 changegroup.writebundle(bundle, bundlepath, bundletype)
2116
2115
2117 @command('debugignore', [], '')
2116 @command('debugignore', [], '')
2118 def debugignore(ui, repo, *values, **opts):
2117 def debugignore(ui, repo, *values, **opts):
2119 """display the combined ignore pattern"""
2118 """display the combined ignore pattern"""
2120 ignore = repo.dirstate._ignore
2119 ignore = repo.dirstate._ignore
2121 includepat = getattr(ignore, 'includepat', None)
2120 includepat = getattr(ignore, 'includepat', None)
2122 if includepat is not None:
2121 if includepat is not None:
2123 ui.write("%s\n" % includepat)
2122 ui.write("%s\n" % includepat)
2124 else:
2123 else:
2125 raise util.Abort(_("no ignore patterns found"))
2124 raise util.Abort(_("no ignore patterns found"))
2126
2125
2127 @command('debugindex',
2126 @command('debugindex',
2128 [('c', 'changelog', False, _('open changelog')),
2127 [('c', 'changelog', False, _('open changelog')),
2129 ('m', 'manifest', False, _('open manifest')),
2128 ('m', 'manifest', False, _('open manifest')),
2130 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2129 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2131 _('[-f FORMAT] -c|-m|FILE'),
2130 _('[-f FORMAT] -c|-m|FILE'),
2132 optionalrepo=True)
2131 optionalrepo=True)
2133 def debugindex(ui, repo, file_=None, **opts):
2132 def debugindex(ui, repo, file_=None, **opts):
2134 """dump the contents of an index file"""
2133 """dump the contents of an index file"""
2135 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2134 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2136 format = opts.get('format', 0)
2135 format = opts.get('format', 0)
2137 if format not in (0, 1):
2136 if format not in (0, 1):
2138 raise util.Abort(_("unknown format %d") % format)
2137 raise util.Abort(_("unknown format %d") % format)
2139
2138
2140 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2139 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2141 if generaldelta:
2140 if generaldelta:
2142 basehdr = ' delta'
2141 basehdr = ' delta'
2143 else:
2142 else:
2144 basehdr = ' base'
2143 basehdr = ' base'
2145
2144
2146 if format == 0:
2145 if format == 0:
2147 ui.write(" rev offset length " + basehdr + " linkrev"
2146 ui.write(" rev offset length " + basehdr + " linkrev"
2148 " nodeid p1 p2\n")
2147 " nodeid p1 p2\n")
2149 elif format == 1:
2148 elif format == 1:
2150 ui.write(" rev flag offset length"
2149 ui.write(" rev flag offset length"
2151 " size " + basehdr + " link p1 p2"
2150 " size " + basehdr + " link p1 p2"
2152 " nodeid\n")
2151 " nodeid\n")
2153
2152
2154 for i in r:
2153 for i in r:
2155 node = r.node(i)
2154 node = r.node(i)
2156 if generaldelta:
2155 if generaldelta:
2157 base = r.deltaparent(i)
2156 base = r.deltaparent(i)
2158 else:
2157 else:
2159 base = r.chainbase(i)
2158 base = r.chainbase(i)
2160 if format == 0:
2159 if format == 0:
2161 try:
2160 try:
2162 pp = r.parents(node)
2161 pp = r.parents(node)
2163 except Exception:
2162 except Exception:
2164 pp = [nullid, nullid]
2163 pp = [nullid, nullid]
2165 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2164 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2166 i, r.start(i), r.length(i), base, r.linkrev(i),
2165 i, r.start(i), r.length(i), base, r.linkrev(i),
2167 short(node), short(pp[0]), short(pp[1])))
2166 short(node), short(pp[0]), short(pp[1])))
2168 elif format == 1:
2167 elif format == 1:
2169 pr = r.parentrevs(i)
2168 pr = r.parentrevs(i)
2170 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2169 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2171 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2170 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2172 base, r.linkrev(i), pr[0], pr[1], short(node)))
2171 base, r.linkrev(i), pr[0], pr[1], short(node)))
2173
2172
2174 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2173 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2175 def debugindexdot(ui, repo, file_):
2174 def debugindexdot(ui, repo, file_):
2176 """dump an index DAG as a graphviz dot file"""
2175 """dump an index DAG as a graphviz dot file"""
2177 r = None
2176 r = None
2178 if repo:
2177 if repo:
2179 filelog = repo.file(file_)
2178 filelog = repo.file(file_)
2180 if len(filelog):
2179 if len(filelog):
2181 r = filelog
2180 r = filelog
2182 if not r:
2181 if not r:
2183 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2182 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2184 ui.write(("digraph G {\n"))
2183 ui.write(("digraph G {\n"))
2185 for i in r:
2184 for i in r:
2186 node = r.node(i)
2185 node = r.node(i)
2187 pp = r.parents(node)
2186 pp = r.parents(node)
2188 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2187 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2189 if pp[1] != nullid:
2188 if pp[1] != nullid:
2190 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2189 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2191 ui.write("}\n")
2190 ui.write("}\n")
2192
2191
2193 @command('debuginstall', [], '', norepo=True)
2192 @command('debuginstall', [], '', norepo=True)
2194 def debuginstall(ui):
2193 def debuginstall(ui):
2195 '''test Mercurial installation
2194 '''test Mercurial installation
2196
2195
2197 Returns 0 on success.
2196 Returns 0 on success.
2198 '''
2197 '''
2199
2198
2200 def writetemp(contents):
2199 def writetemp(contents):
2201 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2200 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2202 f = os.fdopen(fd, "wb")
2201 f = os.fdopen(fd, "wb")
2203 f.write(contents)
2202 f.write(contents)
2204 f.close()
2203 f.close()
2205 return name
2204 return name
2206
2205
2207 problems = 0
2206 problems = 0
2208
2207
2209 # encoding
2208 # encoding
2210 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2209 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2211 try:
2210 try:
2212 encoding.fromlocal("test")
2211 encoding.fromlocal("test")
2213 except util.Abort, inst:
2212 except util.Abort, inst:
2214 ui.write(" %s\n" % inst)
2213 ui.write(" %s\n" % inst)
2215 ui.write(_(" (check that your locale is properly set)\n"))
2214 ui.write(_(" (check that your locale is properly set)\n"))
2216 problems += 1
2215 problems += 1
2217
2216
2218 # Python
2217 # Python
2219 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2218 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2220 ui.status(_("checking Python version (%s)\n")
2219 ui.status(_("checking Python version (%s)\n")
2221 % ("%s.%s.%s" % sys.version_info[:3]))
2220 % ("%s.%s.%s" % sys.version_info[:3]))
2222 ui.status(_("checking Python lib (%s)...\n")
2221 ui.status(_("checking Python lib (%s)...\n")
2223 % os.path.dirname(os.__file__))
2222 % os.path.dirname(os.__file__))
2224
2223
2225 # compiled modules
2224 # compiled modules
2226 ui.status(_("checking installed modules (%s)...\n")
2225 ui.status(_("checking installed modules (%s)...\n")
2227 % os.path.dirname(__file__))
2226 % os.path.dirname(__file__))
2228 try:
2227 try:
2229 import bdiff, mpatch, base85, osutil
2228 import bdiff, mpatch, base85, osutil
2230 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2229 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2231 except Exception, inst:
2230 except Exception, inst:
2232 ui.write(" %s\n" % inst)
2231 ui.write(" %s\n" % inst)
2233 ui.write(_(" One or more extensions could not be found"))
2232 ui.write(_(" One or more extensions could not be found"))
2234 ui.write(_(" (check that you compiled the extensions)\n"))
2233 ui.write(_(" (check that you compiled the extensions)\n"))
2235 problems += 1
2234 problems += 1
2236
2235
2237 # templates
2236 # templates
2238 import templater
2237 import templater
2239 p = templater.templatepath()
2238 p = templater.templatepath()
2240 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2239 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2241 if p:
2240 if p:
2242 m = templater.templatepath("map-cmdline.default")
2241 m = templater.templatepath("map-cmdline.default")
2243 if m:
2242 if m:
2244 # template found, check if it is working
2243 # template found, check if it is working
2245 try:
2244 try:
2246 templater.templater(m)
2245 templater.templater(m)
2247 except Exception, inst:
2246 except Exception, inst:
2248 ui.write(" %s\n" % inst)
2247 ui.write(" %s\n" % inst)
2249 p = None
2248 p = None
2250 else:
2249 else:
2251 ui.write(_(" template 'default' not found\n"))
2250 ui.write(_(" template 'default' not found\n"))
2252 p = None
2251 p = None
2253 else:
2252 else:
2254 ui.write(_(" no template directories found\n"))
2253 ui.write(_(" no template directories found\n"))
2255 if not p:
2254 if not p:
2256 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2255 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2257 problems += 1
2256 problems += 1
2258
2257
2259 # editor
2258 # editor
2260 ui.status(_("checking commit editor...\n"))
2259 ui.status(_("checking commit editor...\n"))
2261 editor = ui.geteditor()
2260 editor = ui.geteditor()
2262 cmdpath = util.findexe(shlex.split(editor)[0])
2261 cmdpath = util.findexe(shlex.split(editor)[0])
2263 if not cmdpath:
2262 if not cmdpath:
2264 if editor == 'vi':
2263 if editor == 'vi':
2265 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2264 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2266 ui.write(_(" (specify a commit editor in your configuration"
2265 ui.write(_(" (specify a commit editor in your configuration"
2267 " file)\n"))
2266 " file)\n"))
2268 else:
2267 else:
2269 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2268 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2270 ui.write(_(" (specify a commit editor in your configuration"
2269 ui.write(_(" (specify a commit editor in your configuration"
2271 " file)\n"))
2270 " file)\n"))
2272 problems += 1
2271 problems += 1
2273
2272
2274 # check username
2273 # check username
2275 ui.status(_("checking username...\n"))
2274 ui.status(_("checking username...\n"))
2276 try:
2275 try:
2277 ui.username()
2276 ui.username()
2278 except util.Abort, e:
2277 except util.Abort, e:
2279 ui.write(" %s\n" % e)
2278 ui.write(" %s\n" % e)
2280 ui.write(_(" (specify a username in your configuration file)\n"))
2279 ui.write(_(" (specify a username in your configuration file)\n"))
2281 problems += 1
2280 problems += 1
2282
2281
2283 if not problems:
2282 if not problems:
2284 ui.status(_("no problems detected\n"))
2283 ui.status(_("no problems detected\n"))
2285 else:
2284 else:
2286 ui.write(_("%s problems detected,"
2285 ui.write(_("%s problems detected,"
2287 " please check your install!\n") % problems)
2286 " please check your install!\n") % problems)
2288
2287
2289 return problems
2288 return problems
2290
2289
2291 @command('debugknown', [], _('REPO ID...'), norepo=True)
2290 @command('debugknown', [], _('REPO ID...'), norepo=True)
2292 def debugknown(ui, repopath, *ids, **opts):
2291 def debugknown(ui, repopath, *ids, **opts):
2293 """test whether node ids are known to a repo
2292 """test whether node ids are known to a repo
2294
2293
2295 Every ID must be a full-length hex node id string. Returns a list of 0s
2294 Every ID must be a full-length hex node id string. Returns a list of 0s
2296 and 1s indicating unknown/known.
2295 and 1s indicating unknown/known.
2297 """
2296 """
2298 repo = hg.peer(ui, opts, repopath)
2297 repo = hg.peer(ui, opts, repopath)
2299 if not repo.capable('known'):
2298 if not repo.capable('known'):
2300 raise util.Abort("known() not supported by target repository")
2299 raise util.Abort("known() not supported by target repository")
2301 flags = repo.known([bin(s) for s in ids])
2300 flags = repo.known([bin(s) for s in ids])
2302 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2301 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2303
2302
2304 @command('debuglabelcomplete', [], _('LABEL...'))
2303 @command('debuglabelcomplete', [], _('LABEL...'))
2305 def debuglabelcomplete(ui, repo, *args):
2304 def debuglabelcomplete(ui, repo, *args):
2306 '''complete "labels" - tags, open branch names, bookmark names'''
2305 '''complete "labels" - tags, open branch names, bookmark names'''
2307
2306
2308 labels = set()
2307 labels = set()
2309 labels.update(t[0] for t in repo.tagslist())
2308 labels.update(t[0] for t in repo.tagslist())
2310 labels.update(repo._bookmarks.keys())
2309 labels.update(repo._bookmarks.keys())
2311 labels.update(tag for (tag, heads, tip, closed)
2310 labels.update(tag for (tag, heads, tip, closed)
2312 in repo.branchmap().iterbranches() if not closed)
2311 in repo.branchmap().iterbranches() if not closed)
2313 completions = set()
2312 completions = set()
2314 if not args:
2313 if not args:
2315 args = ['']
2314 args = ['']
2316 for a in args:
2315 for a in args:
2317 completions.update(l for l in labels if l.startswith(a))
2316 completions.update(l for l in labels if l.startswith(a))
2318 ui.write('\n'.join(sorted(completions)))
2317 ui.write('\n'.join(sorted(completions)))
2319 ui.write('\n')
2318 ui.write('\n')
2320
2319
2321 @command('debugobsolete',
2320 @command('debugobsolete',
2322 [('', 'flags', 0, _('markers flag')),
2321 [('', 'flags', 0, _('markers flag')),
2323 ('', 'record-parents', False,
2322 ('', 'record-parents', False,
2324 _('record parent information for the precursor')),
2323 _('record parent information for the precursor')),
2325 ('r', 'rev', [], _('display markers relevant to REV')),
2324 ('r', 'rev', [], _('display markers relevant to REV')),
2326 ] + commitopts2,
2325 ] + commitopts2,
2327 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2326 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2328 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2327 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2329 """create arbitrary obsolete marker
2328 """create arbitrary obsolete marker
2330
2329
2331 With no arguments, displays the list of obsolescence markers."""
2330 With no arguments, displays the list of obsolescence markers."""
2332
2331
2333 def parsenodeid(s):
2332 def parsenodeid(s):
2334 try:
2333 try:
2335 # We do not use revsingle/revrange functions here to accept
2334 # We do not use revsingle/revrange functions here to accept
2336 # arbitrary node identifiers, possibly not present in the
2335 # arbitrary node identifiers, possibly not present in the
2337 # local repository.
2336 # local repository.
2338 n = bin(s)
2337 n = bin(s)
2339 if len(n) != len(nullid):
2338 if len(n) != len(nullid):
2340 raise TypeError()
2339 raise TypeError()
2341 return n
2340 return n
2342 except TypeError:
2341 except TypeError:
2343 raise util.Abort('changeset references must be full hexadecimal '
2342 raise util.Abort('changeset references must be full hexadecimal '
2344 'node identifiers')
2343 'node identifiers')
2345
2344
2346 if precursor is not None:
2345 if precursor is not None:
2347 if opts['rev']:
2346 if opts['rev']:
2348 raise util.Abort('cannot select revision when creating marker')
2347 raise util.Abort('cannot select revision when creating marker')
2349 metadata = {}
2348 metadata = {}
2350 metadata['user'] = opts['user'] or ui.username()
2349 metadata['user'] = opts['user'] or ui.username()
2351 succs = tuple(parsenodeid(succ) for succ in successors)
2350 succs = tuple(parsenodeid(succ) for succ in successors)
2352 l = repo.lock()
2351 l = repo.lock()
2353 try:
2352 try:
2354 tr = repo.transaction('debugobsolete')
2353 tr = repo.transaction('debugobsolete')
2355 try:
2354 try:
2356 try:
2355 try:
2357 date = opts.get('date')
2356 date = opts.get('date')
2358 if date:
2357 if date:
2359 date = util.parsedate(date)
2358 date = util.parsedate(date)
2360 else:
2359 else:
2361 date = None
2360 date = None
2362 prec = parsenodeid(precursor)
2361 prec = parsenodeid(precursor)
2363 parents = None
2362 parents = None
2364 if opts['record_parents']:
2363 if opts['record_parents']:
2365 if prec not in repo.unfiltered():
2364 if prec not in repo.unfiltered():
2366 raise util.Abort('cannot used --record-parents on '
2365 raise util.Abort('cannot used --record-parents on '
2367 'unknown changesets')
2366 'unknown changesets')
2368 parents = repo.unfiltered()[prec].parents()
2367 parents = repo.unfiltered()[prec].parents()
2369 parents = tuple(p.node() for p in parents)
2368 parents = tuple(p.node() for p in parents)
2370 repo.obsstore.create(tr, prec, succs, opts['flags'],
2369 repo.obsstore.create(tr, prec, succs, opts['flags'],
2371 parents=parents, date=date,
2370 parents=parents, date=date,
2372 metadata=metadata)
2371 metadata=metadata)
2373 tr.close()
2372 tr.close()
2374 except ValueError, exc:
2373 except ValueError, exc:
2375 raise util.Abort(_('bad obsmarker input: %s') % exc)
2374 raise util.Abort(_('bad obsmarker input: %s') % exc)
2376 finally:
2375 finally:
2377 tr.release()
2376 tr.release()
2378 finally:
2377 finally:
2379 l.release()
2378 l.release()
2380 else:
2379 else:
2381 if opts['rev']:
2380 if opts['rev']:
2382 revs = scmutil.revrange(repo, opts['rev'])
2381 revs = scmutil.revrange(repo, opts['rev'])
2383 nodes = [repo[r].node() for r in revs]
2382 nodes = [repo[r].node() for r in revs]
2384 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2383 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2385 markers.sort(key=lambda x: x._data)
2384 markers.sort(key=lambda x: x._data)
2386 else:
2385 else:
2387 markers = obsolete.getmarkers(repo)
2386 markers = obsolete.getmarkers(repo)
2388
2387
2389 for m in markers:
2388 for m in markers:
2390 cmdutil.showmarker(ui, m)
2389 cmdutil.showmarker(ui, m)
2391
2390
2392 @command('debugpathcomplete',
2391 @command('debugpathcomplete',
2393 [('f', 'full', None, _('complete an entire path')),
2392 [('f', 'full', None, _('complete an entire path')),
2394 ('n', 'normal', None, _('show only normal files')),
2393 ('n', 'normal', None, _('show only normal files')),
2395 ('a', 'added', None, _('show only added files')),
2394 ('a', 'added', None, _('show only added files')),
2396 ('r', 'removed', None, _('show only removed files'))],
2395 ('r', 'removed', None, _('show only removed files'))],
2397 _('FILESPEC...'))
2396 _('FILESPEC...'))
2398 def debugpathcomplete(ui, repo, *specs, **opts):
2397 def debugpathcomplete(ui, repo, *specs, **opts):
2399 '''complete part or all of a tracked path
2398 '''complete part or all of a tracked path
2400
2399
2401 This command supports shells that offer path name completion. It
2400 This command supports shells that offer path name completion. It
2402 currently completes only files already known to the dirstate.
2401 currently completes only files already known to the dirstate.
2403
2402
2404 Completion extends only to the next path segment unless
2403 Completion extends only to the next path segment unless
2405 --full is specified, in which case entire paths are used.'''
2404 --full is specified, in which case entire paths are used.'''
2406
2405
2407 def complete(path, acceptable):
2406 def complete(path, acceptable):
2408 dirstate = repo.dirstate
2407 dirstate = repo.dirstate
2409 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2408 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2410 rootdir = repo.root + os.sep
2409 rootdir = repo.root + os.sep
2411 if spec != repo.root and not spec.startswith(rootdir):
2410 if spec != repo.root and not spec.startswith(rootdir):
2412 return [], []
2411 return [], []
2413 if os.path.isdir(spec):
2412 if os.path.isdir(spec):
2414 spec += '/'
2413 spec += '/'
2415 spec = spec[len(rootdir):]
2414 spec = spec[len(rootdir):]
2416 fixpaths = os.sep != '/'
2415 fixpaths = os.sep != '/'
2417 if fixpaths:
2416 if fixpaths:
2418 spec = spec.replace(os.sep, '/')
2417 spec = spec.replace(os.sep, '/')
2419 speclen = len(spec)
2418 speclen = len(spec)
2420 fullpaths = opts['full']
2419 fullpaths = opts['full']
2421 files, dirs = set(), set()
2420 files, dirs = set(), set()
2422 adddir, addfile = dirs.add, files.add
2421 adddir, addfile = dirs.add, files.add
2423 for f, st in dirstate.iteritems():
2422 for f, st in dirstate.iteritems():
2424 if f.startswith(spec) and st[0] in acceptable:
2423 if f.startswith(spec) and st[0] in acceptable:
2425 if fixpaths:
2424 if fixpaths:
2426 f = f.replace('/', os.sep)
2425 f = f.replace('/', os.sep)
2427 if fullpaths:
2426 if fullpaths:
2428 addfile(f)
2427 addfile(f)
2429 continue
2428 continue
2430 s = f.find(os.sep, speclen)
2429 s = f.find(os.sep, speclen)
2431 if s >= 0:
2430 if s >= 0:
2432 adddir(f[:s])
2431 adddir(f[:s])
2433 else:
2432 else:
2434 addfile(f)
2433 addfile(f)
2435 return files, dirs
2434 return files, dirs
2436
2435
2437 acceptable = ''
2436 acceptable = ''
2438 if opts['normal']:
2437 if opts['normal']:
2439 acceptable += 'nm'
2438 acceptable += 'nm'
2440 if opts['added']:
2439 if opts['added']:
2441 acceptable += 'a'
2440 acceptable += 'a'
2442 if opts['removed']:
2441 if opts['removed']:
2443 acceptable += 'r'
2442 acceptable += 'r'
2444 cwd = repo.getcwd()
2443 cwd = repo.getcwd()
2445 if not specs:
2444 if not specs:
2446 specs = ['.']
2445 specs = ['.']
2447
2446
2448 files, dirs = set(), set()
2447 files, dirs = set(), set()
2449 for spec in specs:
2448 for spec in specs:
2450 f, d = complete(spec, acceptable or 'nmar')
2449 f, d = complete(spec, acceptable or 'nmar')
2451 files.update(f)
2450 files.update(f)
2452 dirs.update(d)
2451 dirs.update(d)
2453 files.update(dirs)
2452 files.update(dirs)
2454 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2453 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2455 ui.write('\n')
2454 ui.write('\n')
2456
2455
2457 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2456 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2458 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2457 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2459 '''access the pushkey key/value protocol
2458 '''access the pushkey key/value protocol
2460
2459
2461 With two args, list the keys in the given namespace.
2460 With two args, list the keys in the given namespace.
2462
2461
2463 With five args, set a key to new if it currently is set to old.
2462 With five args, set a key to new if it currently is set to old.
2464 Reports success or failure.
2463 Reports success or failure.
2465 '''
2464 '''
2466
2465
2467 target = hg.peer(ui, {}, repopath)
2466 target = hg.peer(ui, {}, repopath)
2468 if keyinfo:
2467 if keyinfo:
2469 key, old, new = keyinfo
2468 key, old, new = keyinfo
2470 r = target.pushkey(namespace, key, old, new)
2469 r = target.pushkey(namespace, key, old, new)
2471 ui.status(str(r) + '\n')
2470 ui.status(str(r) + '\n')
2472 return not r
2471 return not r
2473 else:
2472 else:
2474 for k, v in sorted(target.listkeys(namespace).iteritems()):
2473 for k, v in sorted(target.listkeys(namespace).iteritems()):
2475 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2474 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2476 v.encode('string-escape')))
2475 v.encode('string-escape')))
2477
2476
2478 @command('debugpvec', [], _('A B'))
2477 @command('debugpvec', [], _('A B'))
2479 def debugpvec(ui, repo, a, b=None):
2478 def debugpvec(ui, repo, a, b=None):
2480 ca = scmutil.revsingle(repo, a)
2479 ca = scmutil.revsingle(repo, a)
2481 cb = scmutil.revsingle(repo, b)
2480 cb = scmutil.revsingle(repo, b)
2482 pa = pvec.ctxpvec(ca)
2481 pa = pvec.ctxpvec(ca)
2483 pb = pvec.ctxpvec(cb)
2482 pb = pvec.ctxpvec(cb)
2484 if pa == pb:
2483 if pa == pb:
2485 rel = "="
2484 rel = "="
2486 elif pa > pb:
2485 elif pa > pb:
2487 rel = ">"
2486 rel = ">"
2488 elif pa < pb:
2487 elif pa < pb:
2489 rel = "<"
2488 rel = "<"
2490 elif pa | pb:
2489 elif pa | pb:
2491 rel = "|"
2490 rel = "|"
2492 ui.write(_("a: %s\n") % pa)
2491 ui.write(_("a: %s\n") % pa)
2493 ui.write(_("b: %s\n") % pb)
2492 ui.write(_("b: %s\n") % pb)
2494 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2493 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2495 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2494 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2496 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2495 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2497 pa.distance(pb), rel))
2496 pa.distance(pb), rel))
2498
2497
2499 @command('debugrebuilddirstate|debugrebuildstate',
2498 @command('debugrebuilddirstate|debugrebuildstate',
2500 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2499 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2501 _('[-r REV]'))
2500 _('[-r REV]'))
2502 def debugrebuilddirstate(ui, repo, rev):
2501 def debugrebuilddirstate(ui, repo, rev):
2503 """rebuild the dirstate as it would look like for the given revision
2502 """rebuild the dirstate as it would look like for the given revision
2504
2503
2505 If no revision is specified the first current parent will be used.
2504 If no revision is specified the first current parent will be used.
2506
2505
2507 The dirstate will be set to the files of the given revision.
2506 The dirstate will be set to the files of the given revision.
2508 The actual working directory content or existing dirstate
2507 The actual working directory content or existing dirstate
2509 information such as adds or removes is not considered.
2508 information such as adds or removes is not considered.
2510
2509
2511 One use of this command is to make the next :hg:`status` invocation
2510 One use of this command is to make the next :hg:`status` invocation
2512 check the actual file content.
2511 check the actual file content.
2513 """
2512 """
2514 ctx = scmutil.revsingle(repo, rev)
2513 ctx = scmutil.revsingle(repo, rev)
2515 wlock = repo.wlock()
2514 wlock = repo.wlock()
2516 try:
2515 try:
2517 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2516 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2518 finally:
2517 finally:
2519 wlock.release()
2518 wlock.release()
2520
2519
2521 @command('debugrename',
2520 @command('debugrename',
2522 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2521 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2523 _('[-r REV] FILE'))
2522 _('[-r REV] FILE'))
2524 def debugrename(ui, repo, file1, *pats, **opts):
2523 def debugrename(ui, repo, file1, *pats, **opts):
2525 """dump rename information"""
2524 """dump rename information"""
2526
2525
2527 ctx = scmutil.revsingle(repo, opts.get('rev'))
2526 ctx = scmutil.revsingle(repo, opts.get('rev'))
2528 m = scmutil.match(ctx, (file1,) + pats, opts)
2527 m = scmutil.match(ctx, (file1,) + pats, opts)
2529 for abs in ctx.walk(m):
2528 for abs in ctx.walk(m):
2530 fctx = ctx[abs]
2529 fctx = ctx[abs]
2531 o = fctx.filelog().renamed(fctx.filenode())
2530 o = fctx.filelog().renamed(fctx.filenode())
2532 rel = m.rel(abs)
2531 rel = m.rel(abs)
2533 if o:
2532 if o:
2534 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2533 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2535 else:
2534 else:
2536 ui.write(_("%s not renamed\n") % rel)
2535 ui.write(_("%s not renamed\n") % rel)
2537
2536
2538 @command('debugrevlog',
2537 @command('debugrevlog',
2539 [('c', 'changelog', False, _('open changelog')),
2538 [('c', 'changelog', False, _('open changelog')),
2540 ('m', 'manifest', False, _('open manifest')),
2539 ('m', 'manifest', False, _('open manifest')),
2541 ('d', 'dump', False, _('dump index data'))],
2540 ('d', 'dump', False, _('dump index data'))],
2542 _('-c|-m|FILE'),
2541 _('-c|-m|FILE'),
2543 optionalrepo=True)
2542 optionalrepo=True)
2544 def debugrevlog(ui, repo, file_=None, **opts):
2543 def debugrevlog(ui, repo, file_=None, **opts):
2545 """show data and statistics about a revlog"""
2544 """show data and statistics about a revlog"""
2546 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2545 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2547
2546
2548 if opts.get("dump"):
2547 if opts.get("dump"):
2549 numrevs = len(r)
2548 numrevs = len(r)
2550 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2549 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2551 " rawsize totalsize compression heads chainlen\n")
2550 " rawsize totalsize compression heads chainlen\n")
2552 ts = 0
2551 ts = 0
2553 heads = set()
2552 heads = set()
2554 rindex = r.index
2553 rindex = r.index
2555
2554
2556 def chainbaseandlen(rev):
2555 def chainbaseandlen(rev):
2557 clen = 0
2556 clen = 0
2558 base = rindex[rev][3]
2557 base = rindex[rev][3]
2559 while base != rev:
2558 while base != rev:
2560 clen += 1
2559 clen += 1
2561 rev = base
2560 rev = base
2562 base = rindex[rev][3]
2561 base = rindex[rev][3]
2563 return base, clen
2562 return base, clen
2564
2563
2565 for rev in xrange(numrevs):
2564 for rev in xrange(numrevs):
2566 dbase = r.deltaparent(rev)
2565 dbase = r.deltaparent(rev)
2567 if dbase == -1:
2566 if dbase == -1:
2568 dbase = rev
2567 dbase = rev
2569 cbase, clen = chainbaseandlen(rev)
2568 cbase, clen = chainbaseandlen(rev)
2570 p1, p2 = r.parentrevs(rev)
2569 p1, p2 = r.parentrevs(rev)
2571 rs = r.rawsize(rev)
2570 rs = r.rawsize(rev)
2572 ts = ts + rs
2571 ts = ts + rs
2573 heads -= set(r.parentrevs(rev))
2572 heads -= set(r.parentrevs(rev))
2574 heads.add(rev)
2573 heads.add(rev)
2575 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2574 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2576 "%11d %5d %8d\n" %
2575 "%11d %5d %8d\n" %
2577 (rev, p1, p2, r.start(rev), r.end(rev),
2576 (rev, p1, p2, r.start(rev), r.end(rev),
2578 r.start(dbase), r.start(cbase),
2577 r.start(dbase), r.start(cbase),
2579 r.start(p1), r.start(p2),
2578 r.start(p1), r.start(p2),
2580 rs, ts, ts / r.end(rev), len(heads), clen))
2579 rs, ts, ts / r.end(rev), len(heads), clen))
2581 return 0
2580 return 0
2582
2581
2583 v = r.version
2582 v = r.version
2584 format = v & 0xFFFF
2583 format = v & 0xFFFF
2585 flags = []
2584 flags = []
2586 gdelta = False
2585 gdelta = False
2587 if v & revlog.REVLOGNGINLINEDATA:
2586 if v & revlog.REVLOGNGINLINEDATA:
2588 flags.append('inline')
2587 flags.append('inline')
2589 if v & revlog.REVLOGGENERALDELTA:
2588 if v & revlog.REVLOGGENERALDELTA:
2590 gdelta = True
2589 gdelta = True
2591 flags.append('generaldelta')
2590 flags.append('generaldelta')
2592 if not flags:
2591 if not flags:
2593 flags = ['(none)']
2592 flags = ['(none)']
2594
2593
2595 nummerges = 0
2594 nummerges = 0
2596 numfull = 0
2595 numfull = 0
2597 numprev = 0
2596 numprev = 0
2598 nump1 = 0
2597 nump1 = 0
2599 nump2 = 0
2598 nump2 = 0
2600 numother = 0
2599 numother = 0
2601 nump1prev = 0
2600 nump1prev = 0
2602 nump2prev = 0
2601 nump2prev = 0
2603 chainlengths = []
2602 chainlengths = []
2604
2603
2605 datasize = [None, 0, 0L]
2604 datasize = [None, 0, 0L]
2606 fullsize = [None, 0, 0L]
2605 fullsize = [None, 0, 0L]
2607 deltasize = [None, 0, 0L]
2606 deltasize = [None, 0, 0L]
2608
2607
2609 def addsize(size, l):
2608 def addsize(size, l):
2610 if l[0] is None or size < l[0]:
2609 if l[0] is None or size < l[0]:
2611 l[0] = size
2610 l[0] = size
2612 if size > l[1]:
2611 if size > l[1]:
2613 l[1] = size
2612 l[1] = size
2614 l[2] += size
2613 l[2] += size
2615
2614
2616 numrevs = len(r)
2615 numrevs = len(r)
2617 for rev in xrange(numrevs):
2616 for rev in xrange(numrevs):
2618 p1, p2 = r.parentrevs(rev)
2617 p1, p2 = r.parentrevs(rev)
2619 delta = r.deltaparent(rev)
2618 delta = r.deltaparent(rev)
2620 if format > 0:
2619 if format > 0:
2621 addsize(r.rawsize(rev), datasize)
2620 addsize(r.rawsize(rev), datasize)
2622 if p2 != nullrev:
2621 if p2 != nullrev:
2623 nummerges += 1
2622 nummerges += 1
2624 size = r.length(rev)
2623 size = r.length(rev)
2625 if delta == nullrev:
2624 if delta == nullrev:
2626 chainlengths.append(0)
2625 chainlengths.append(0)
2627 numfull += 1
2626 numfull += 1
2628 addsize(size, fullsize)
2627 addsize(size, fullsize)
2629 else:
2628 else:
2630 chainlengths.append(chainlengths[delta] + 1)
2629 chainlengths.append(chainlengths[delta] + 1)
2631 addsize(size, deltasize)
2630 addsize(size, deltasize)
2632 if delta == rev - 1:
2631 if delta == rev - 1:
2633 numprev += 1
2632 numprev += 1
2634 if delta == p1:
2633 if delta == p1:
2635 nump1prev += 1
2634 nump1prev += 1
2636 elif delta == p2:
2635 elif delta == p2:
2637 nump2prev += 1
2636 nump2prev += 1
2638 elif delta == p1:
2637 elif delta == p1:
2639 nump1 += 1
2638 nump1 += 1
2640 elif delta == p2:
2639 elif delta == p2:
2641 nump2 += 1
2640 nump2 += 1
2642 elif delta != nullrev:
2641 elif delta != nullrev:
2643 numother += 1
2642 numother += 1
2644
2643
2645 # Adjust size min value for empty cases
2644 # Adjust size min value for empty cases
2646 for size in (datasize, fullsize, deltasize):
2645 for size in (datasize, fullsize, deltasize):
2647 if size[0] is None:
2646 if size[0] is None:
2648 size[0] = 0
2647 size[0] = 0
2649
2648
2650 numdeltas = numrevs - numfull
2649 numdeltas = numrevs - numfull
2651 numoprev = numprev - nump1prev - nump2prev
2650 numoprev = numprev - nump1prev - nump2prev
2652 totalrawsize = datasize[2]
2651 totalrawsize = datasize[2]
2653 datasize[2] /= numrevs
2652 datasize[2] /= numrevs
2654 fulltotal = fullsize[2]
2653 fulltotal = fullsize[2]
2655 fullsize[2] /= numfull
2654 fullsize[2] /= numfull
2656 deltatotal = deltasize[2]
2655 deltatotal = deltasize[2]
2657 if numrevs - numfull > 0:
2656 if numrevs - numfull > 0:
2658 deltasize[2] /= numrevs - numfull
2657 deltasize[2] /= numrevs - numfull
2659 totalsize = fulltotal + deltatotal
2658 totalsize = fulltotal + deltatotal
2660 avgchainlen = sum(chainlengths) / numrevs
2659 avgchainlen = sum(chainlengths) / numrevs
2661 compratio = totalrawsize / totalsize
2660 compratio = totalrawsize / totalsize
2662
2661
2663 basedfmtstr = '%%%dd\n'
2662 basedfmtstr = '%%%dd\n'
2664 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2663 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2665
2664
2666 def dfmtstr(max):
2665 def dfmtstr(max):
2667 return basedfmtstr % len(str(max))
2666 return basedfmtstr % len(str(max))
2668 def pcfmtstr(max, padding=0):
2667 def pcfmtstr(max, padding=0):
2669 return basepcfmtstr % (len(str(max)), ' ' * padding)
2668 return basepcfmtstr % (len(str(max)), ' ' * padding)
2670
2669
2671 def pcfmt(value, total):
2670 def pcfmt(value, total):
2672 return (value, 100 * float(value) / total)
2671 return (value, 100 * float(value) / total)
2673
2672
2674 ui.write(('format : %d\n') % format)
2673 ui.write(('format : %d\n') % format)
2675 ui.write(('flags : %s\n') % ', '.join(flags))
2674 ui.write(('flags : %s\n') % ', '.join(flags))
2676
2675
2677 ui.write('\n')
2676 ui.write('\n')
2678 fmt = pcfmtstr(totalsize)
2677 fmt = pcfmtstr(totalsize)
2679 fmt2 = dfmtstr(totalsize)
2678 fmt2 = dfmtstr(totalsize)
2680 ui.write(('revisions : ') + fmt2 % numrevs)
2679 ui.write(('revisions : ') + fmt2 % numrevs)
2681 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2680 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2682 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2681 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2683 ui.write(('revisions : ') + fmt2 % numrevs)
2682 ui.write(('revisions : ') + fmt2 % numrevs)
2684 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2683 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2685 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2684 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2686 ui.write(('revision size : ') + fmt2 % totalsize)
2685 ui.write(('revision size : ') + fmt2 % totalsize)
2687 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2686 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2688 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2687 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2689
2688
2690 ui.write('\n')
2689 ui.write('\n')
2691 fmt = dfmtstr(max(avgchainlen, compratio))
2690 fmt = dfmtstr(max(avgchainlen, compratio))
2692 ui.write(('avg chain length : ') + fmt % avgchainlen)
2691 ui.write(('avg chain length : ') + fmt % avgchainlen)
2693 ui.write(('compression ratio : ') + fmt % compratio)
2692 ui.write(('compression ratio : ') + fmt % compratio)
2694
2693
2695 if format > 0:
2694 if format > 0:
2696 ui.write('\n')
2695 ui.write('\n')
2697 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2696 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2698 % tuple(datasize))
2697 % tuple(datasize))
2699 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2698 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2700 % tuple(fullsize))
2699 % tuple(fullsize))
2701 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2700 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2702 % tuple(deltasize))
2701 % tuple(deltasize))
2703
2702
2704 if numdeltas > 0:
2703 if numdeltas > 0:
2705 ui.write('\n')
2704 ui.write('\n')
2706 fmt = pcfmtstr(numdeltas)
2705 fmt = pcfmtstr(numdeltas)
2707 fmt2 = pcfmtstr(numdeltas, 4)
2706 fmt2 = pcfmtstr(numdeltas, 4)
2708 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2707 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2709 if numprev > 0:
2708 if numprev > 0:
2710 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2709 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2711 numprev))
2710 numprev))
2712 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2711 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2713 numprev))
2712 numprev))
2714 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2713 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2715 numprev))
2714 numprev))
2716 if gdelta:
2715 if gdelta:
2717 ui.write(('deltas against p1 : ')
2716 ui.write(('deltas against p1 : ')
2718 + fmt % pcfmt(nump1, numdeltas))
2717 + fmt % pcfmt(nump1, numdeltas))
2719 ui.write(('deltas against p2 : ')
2718 ui.write(('deltas against p2 : ')
2720 + fmt % pcfmt(nump2, numdeltas))
2719 + fmt % pcfmt(nump2, numdeltas))
2721 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2720 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2722 numdeltas))
2721 numdeltas))
2723
2722
2724 @command('debugrevspec',
2723 @command('debugrevspec',
2725 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2724 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2726 ('REVSPEC'))
2725 ('REVSPEC'))
2727 def debugrevspec(ui, repo, expr, **opts):
2726 def debugrevspec(ui, repo, expr, **opts):
2728 """parse and apply a revision specification
2727 """parse and apply a revision specification
2729
2728
2730 Use --verbose to print the parsed tree before and after aliases
2729 Use --verbose to print the parsed tree before and after aliases
2731 expansion.
2730 expansion.
2732 """
2731 """
2733 if ui.verbose:
2732 if ui.verbose:
2734 tree = revset.parse(expr)[0]
2733 tree = revset.parse(expr)[0]
2735 ui.note(revset.prettyformat(tree), "\n")
2734 ui.note(revset.prettyformat(tree), "\n")
2736 newtree = revset.findaliases(ui, tree)
2735 newtree = revset.findaliases(ui, tree)
2737 if newtree != tree:
2736 if newtree != tree:
2738 ui.note(revset.prettyformat(newtree), "\n")
2737 ui.note(revset.prettyformat(newtree), "\n")
2739 if opts["optimize"]:
2738 if opts["optimize"]:
2740 weight, optimizedtree = revset.optimize(newtree, True)
2739 weight, optimizedtree = revset.optimize(newtree, True)
2741 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2740 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2742 func = revset.match(ui, expr)
2741 func = revset.match(ui, expr)
2743 for c in func(repo, revset.spanset(repo)):
2742 for c in func(repo, revset.spanset(repo)):
2744 ui.write("%s\n" % c)
2743 ui.write("%s\n" % c)
2745
2744
2746 @command('debugsetparents', [], _('REV1 [REV2]'))
2745 @command('debugsetparents', [], _('REV1 [REV2]'))
2747 def debugsetparents(ui, repo, rev1, rev2=None):
2746 def debugsetparents(ui, repo, rev1, rev2=None):
2748 """manually set the parents of the current working directory
2747 """manually set the parents of the current working directory
2749
2748
2750 This is useful for writing repository conversion tools, but should
2749 This is useful for writing repository conversion tools, but should
2751 be used with care.
2750 be used with care.
2752
2751
2753 Returns 0 on success.
2752 Returns 0 on success.
2754 """
2753 """
2755
2754
2756 r1 = scmutil.revsingle(repo, rev1).node()
2755 r1 = scmutil.revsingle(repo, rev1).node()
2757 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2756 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2758
2757
2759 wlock = repo.wlock()
2758 wlock = repo.wlock()
2760 try:
2759 try:
2761 repo.dirstate.beginparentchange()
2760 repo.dirstate.beginparentchange()
2762 repo.setparents(r1, r2)
2761 repo.setparents(r1, r2)
2763 repo.dirstate.endparentchange()
2762 repo.dirstate.endparentchange()
2764 finally:
2763 finally:
2765 wlock.release()
2764 wlock.release()
2766
2765
2767 @command('debugdirstate|debugstate',
2766 @command('debugdirstate|debugstate',
2768 [('', 'nodates', None, _('do not display the saved mtime')),
2767 [('', 'nodates', None, _('do not display the saved mtime')),
2769 ('', 'datesort', None, _('sort by saved mtime'))],
2768 ('', 'datesort', None, _('sort by saved mtime'))],
2770 _('[OPTION]...'))
2769 _('[OPTION]...'))
2771 def debugstate(ui, repo, nodates=None, datesort=None):
2770 def debugstate(ui, repo, nodates=None, datesort=None):
2772 """show the contents of the current dirstate"""
2771 """show the contents of the current dirstate"""
2773 timestr = ""
2772 timestr = ""
2774 showdate = not nodates
2773 showdate = not nodates
2775 if datesort:
2774 if datesort:
2776 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2775 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2777 else:
2776 else:
2778 keyfunc = None # sort by filename
2777 keyfunc = None # sort by filename
2779 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2778 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2780 if showdate:
2779 if showdate:
2781 if ent[3] == -1:
2780 if ent[3] == -1:
2782 # Pad or slice to locale representation
2781 # Pad or slice to locale representation
2783 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2782 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2784 time.localtime(0)))
2783 time.localtime(0)))
2785 timestr = 'unset'
2784 timestr = 'unset'
2786 timestr = (timestr[:locale_len] +
2785 timestr = (timestr[:locale_len] +
2787 ' ' * (locale_len - len(timestr)))
2786 ' ' * (locale_len - len(timestr)))
2788 else:
2787 else:
2789 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2788 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2790 time.localtime(ent[3]))
2789 time.localtime(ent[3]))
2791 if ent[1] & 020000:
2790 if ent[1] & 020000:
2792 mode = 'lnk'
2791 mode = 'lnk'
2793 else:
2792 else:
2794 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2793 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2795 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2794 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2796 for f in repo.dirstate.copies():
2795 for f in repo.dirstate.copies():
2797 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2796 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2798
2797
2799 @command('debugsub',
2798 @command('debugsub',
2800 [('r', 'rev', '',
2799 [('r', 'rev', '',
2801 _('revision to check'), _('REV'))],
2800 _('revision to check'), _('REV'))],
2802 _('[-r REV] [REV]'))
2801 _('[-r REV] [REV]'))
2803 def debugsub(ui, repo, rev=None):
2802 def debugsub(ui, repo, rev=None):
2804 ctx = scmutil.revsingle(repo, rev, None)
2803 ctx = scmutil.revsingle(repo, rev, None)
2805 for k, v in sorted(ctx.substate.items()):
2804 for k, v in sorted(ctx.substate.items()):
2806 ui.write(('path %s\n') % k)
2805 ui.write(('path %s\n') % k)
2807 ui.write((' source %s\n') % v[0])
2806 ui.write((' source %s\n') % v[0])
2808 ui.write((' revision %s\n') % v[1])
2807 ui.write((' revision %s\n') % v[1])
2809
2808
2810 @command('debugsuccessorssets',
2809 @command('debugsuccessorssets',
2811 [],
2810 [],
2812 _('[REV]'))
2811 _('[REV]'))
2813 def debugsuccessorssets(ui, repo, *revs):
2812 def debugsuccessorssets(ui, repo, *revs):
2814 """show set of successors for revision
2813 """show set of successors for revision
2815
2814
2816 A successors set of changeset A is a consistent group of revisions that
2815 A successors set of changeset A is a consistent group of revisions that
2817 succeed A. It contains non-obsolete changesets only.
2816 succeed A. It contains non-obsolete changesets only.
2818
2817
2819 In most cases a changeset A has a single successors set containing a single
2818 In most cases a changeset A has a single successors set containing a single
2820 successor (changeset A replaced by A').
2819 successor (changeset A replaced by A').
2821
2820
2822 A changeset that is made obsolete with no successors are called "pruned".
2821 A changeset that is made obsolete with no successors are called "pruned".
2823 Such changesets have no successors sets at all.
2822 Such changesets have no successors sets at all.
2824
2823
2825 A changeset that has been "split" will have a successors set containing
2824 A changeset that has been "split" will have a successors set containing
2826 more than one successor.
2825 more than one successor.
2827
2826
2828 A changeset that has been rewritten in multiple different ways is called
2827 A changeset that has been rewritten in multiple different ways is called
2829 "divergent". Such changesets have multiple successor sets (each of which
2828 "divergent". Such changesets have multiple successor sets (each of which
2830 may also be split, i.e. have multiple successors).
2829 may also be split, i.e. have multiple successors).
2831
2830
2832 Results are displayed as follows::
2831 Results are displayed as follows::
2833
2832
2834 <rev1>
2833 <rev1>
2835 <successors-1A>
2834 <successors-1A>
2836 <rev2>
2835 <rev2>
2837 <successors-2A>
2836 <successors-2A>
2838 <successors-2B1> <successors-2B2> <successors-2B3>
2837 <successors-2B1> <successors-2B2> <successors-2B3>
2839
2838
2840 Here rev2 has two possible (i.e. divergent) successors sets. The first
2839 Here rev2 has two possible (i.e. divergent) successors sets. The first
2841 holds one element, whereas the second holds three (i.e. the changeset has
2840 holds one element, whereas the second holds three (i.e. the changeset has
2842 been split).
2841 been split).
2843 """
2842 """
2844 # passed to successorssets caching computation from one call to another
2843 # passed to successorssets caching computation from one call to another
2845 cache = {}
2844 cache = {}
2846 ctx2str = str
2845 ctx2str = str
2847 node2str = short
2846 node2str = short
2848 if ui.debug():
2847 if ui.debug():
2849 def ctx2str(ctx):
2848 def ctx2str(ctx):
2850 return ctx.hex()
2849 return ctx.hex()
2851 node2str = hex
2850 node2str = hex
2852 for rev in scmutil.revrange(repo, revs):
2851 for rev in scmutil.revrange(repo, revs):
2853 ctx = repo[rev]
2852 ctx = repo[rev]
2854 ui.write('%s\n'% ctx2str(ctx))
2853 ui.write('%s\n'% ctx2str(ctx))
2855 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2854 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2856 if succsset:
2855 if succsset:
2857 ui.write(' ')
2856 ui.write(' ')
2858 ui.write(node2str(succsset[0]))
2857 ui.write(node2str(succsset[0]))
2859 for node in succsset[1:]:
2858 for node in succsset[1:]:
2860 ui.write(' ')
2859 ui.write(' ')
2861 ui.write(node2str(node))
2860 ui.write(node2str(node))
2862 ui.write('\n')
2861 ui.write('\n')
2863
2862
2864 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2863 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2865 def debugwalk(ui, repo, *pats, **opts):
2864 def debugwalk(ui, repo, *pats, **opts):
2866 """show how files match on given patterns"""
2865 """show how files match on given patterns"""
2867 m = scmutil.match(repo[None], pats, opts)
2866 m = scmutil.match(repo[None], pats, opts)
2868 items = list(repo.walk(m))
2867 items = list(repo.walk(m))
2869 if not items:
2868 if not items:
2870 return
2869 return
2871 f = lambda fn: fn
2870 f = lambda fn: fn
2872 if ui.configbool('ui', 'slash') and os.sep != '/':
2871 if ui.configbool('ui', 'slash') and os.sep != '/':
2873 f = lambda fn: util.normpath(fn)
2872 f = lambda fn: util.normpath(fn)
2874 fmt = 'f %%-%ds %%-%ds %%s' % (
2873 fmt = 'f %%-%ds %%-%ds %%s' % (
2875 max([len(abs) for abs in items]),
2874 max([len(abs) for abs in items]),
2876 max([len(m.rel(abs)) for abs in items]))
2875 max([len(m.rel(abs)) for abs in items]))
2877 for abs in items:
2876 for abs in items:
2878 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2877 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2879 ui.write("%s\n" % line.rstrip())
2878 ui.write("%s\n" % line.rstrip())
2880
2879
2881 @command('debugwireargs',
2880 @command('debugwireargs',
2882 [('', 'three', '', 'three'),
2881 [('', 'three', '', 'three'),
2883 ('', 'four', '', 'four'),
2882 ('', 'four', '', 'four'),
2884 ('', 'five', '', 'five'),
2883 ('', 'five', '', 'five'),
2885 ] + remoteopts,
2884 ] + remoteopts,
2886 _('REPO [OPTIONS]... [ONE [TWO]]'),
2885 _('REPO [OPTIONS]... [ONE [TWO]]'),
2887 norepo=True)
2886 norepo=True)
2888 def debugwireargs(ui, repopath, *vals, **opts):
2887 def debugwireargs(ui, repopath, *vals, **opts):
2889 repo = hg.peer(ui, opts, repopath)
2888 repo = hg.peer(ui, opts, repopath)
2890 for opt in remoteopts:
2889 for opt in remoteopts:
2891 del opts[opt[1]]
2890 del opts[opt[1]]
2892 args = {}
2891 args = {}
2893 for k, v in opts.iteritems():
2892 for k, v in opts.iteritems():
2894 if v:
2893 if v:
2895 args[k] = v
2894 args[k] = v
2896 # run twice to check that we don't mess up the stream for the next command
2895 # run twice to check that we don't mess up the stream for the next command
2897 res1 = repo.debugwireargs(*vals, **args)
2896 res1 = repo.debugwireargs(*vals, **args)
2898 res2 = repo.debugwireargs(*vals, **args)
2897 res2 = repo.debugwireargs(*vals, **args)
2899 ui.write("%s\n" % res1)
2898 ui.write("%s\n" % res1)
2900 if res1 != res2:
2899 if res1 != res2:
2901 ui.warn("%s\n" % res2)
2900 ui.warn("%s\n" % res2)
2902
2901
2903 @command('^diff',
2902 @command('^diff',
2904 [('r', 'rev', [], _('revision'), _('REV')),
2903 [('r', 'rev', [], _('revision'), _('REV')),
2905 ('c', 'change', '', _('change made by revision'), _('REV'))
2904 ('c', 'change', '', _('change made by revision'), _('REV'))
2906 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2905 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2907 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2906 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2908 inferrepo=True)
2907 inferrepo=True)
2909 def diff(ui, repo, *pats, **opts):
2908 def diff(ui, repo, *pats, **opts):
2910 """diff repository (or selected files)
2909 """diff repository (or selected files)
2911
2910
2912 Show differences between revisions for the specified files.
2911 Show differences between revisions for the specified files.
2913
2912
2914 Differences between files are shown using the unified diff format.
2913 Differences between files are shown using the unified diff format.
2915
2914
2916 .. note::
2915 .. note::
2917
2916
2918 diff may generate unexpected results for merges, as it will
2917 diff may generate unexpected results for merges, as it will
2919 default to comparing against the working directory's first
2918 default to comparing against the working directory's first
2920 parent changeset if no revisions are specified.
2919 parent changeset if no revisions are specified.
2921
2920
2922 When two revision arguments are given, then changes are shown
2921 When two revision arguments are given, then changes are shown
2923 between those revisions. If only one revision is specified then
2922 between those revisions. If only one revision is specified then
2924 that revision is compared to the working directory, and, when no
2923 that revision is compared to the working directory, and, when no
2925 revisions are specified, the working directory files are compared
2924 revisions are specified, the working directory files are compared
2926 to its parent.
2925 to its parent.
2927
2926
2928 Alternatively you can specify -c/--change with a revision to see
2927 Alternatively you can specify -c/--change with a revision to see
2929 the changes in that changeset relative to its first parent.
2928 the changes in that changeset relative to its first parent.
2930
2929
2931 Without the -a/--text option, diff will avoid generating diffs of
2930 Without the -a/--text option, diff will avoid generating diffs of
2932 files it detects as binary. With -a, diff will generate a diff
2931 files it detects as binary. With -a, diff will generate a diff
2933 anyway, probably with undesirable results.
2932 anyway, probably with undesirable results.
2934
2933
2935 Use the -g/--git option to generate diffs in the git extended diff
2934 Use the -g/--git option to generate diffs in the git extended diff
2936 format. For more information, read :hg:`help diffs`.
2935 format. For more information, read :hg:`help diffs`.
2937
2936
2938 .. container:: verbose
2937 .. container:: verbose
2939
2938
2940 Examples:
2939 Examples:
2941
2940
2942 - compare a file in the current working directory to its parent::
2941 - compare a file in the current working directory to its parent::
2943
2942
2944 hg diff foo.c
2943 hg diff foo.c
2945
2944
2946 - compare two historical versions of a directory, with rename info::
2945 - compare two historical versions of a directory, with rename info::
2947
2946
2948 hg diff --git -r 1.0:1.2 lib/
2947 hg diff --git -r 1.0:1.2 lib/
2949
2948
2950 - get change stats relative to the last change on some date::
2949 - get change stats relative to the last change on some date::
2951
2950
2952 hg diff --stat -r "date('may 2')"
2951 hg diff --stat -r "date('may 2')"
2953
2952
2954 - diff all newly-added files that contain a keyword::
2953 - diff all newly-added files that contain a keyword::
2955
2954
2956 hg diff "set:added() and grep(GNU)"
2955 hg diff "set:added() and grep(GNU)"
2957
2956
2958 - compare a revision and its parents::
2957 - compare a revision and its parents::
2959
2958
2960 hg diff -c 9353 # compare against first parent
2959 hg diff -c 9353 # compare against first parent
2961 hg diff -r 9353^:9353 # same using revset syntax
2960 hg diff -r 9353^:9353 # same using revset syntax
2962 hg diff -r 9353^2:9353 # compare against the second parent
2961 hg diff -r 9353^2:9353 # compare against the second parent
2963
2962
2964 Returns 0 on success.
2963 Returns 0 on success.
2965 """
2964 """
2966
2965
2967 revs = opts.get('rev')
2966 revs = opts.get('rev')
2968 change = opts.get('change')
2967 change = opts.get('change')
2969 stat = opts.get('stat')
2968 stat = opts.get('stat')
2970 reverse = opts.get('reverse')
2969 reverse = opts.get('reverse')
2971
2970
2972 if revs and change:
2971 if revs and change:
2973 msg = _('cannot specify --rev and --change at the same time')
2972 msg = _('cannot specify --rev and --change at the same time')
2974 raise util.Abort(msg)
2973 raise util.Abort(msg)
2975 elif change:
2974 elif change:
2976 node2 = scmutil.revsingle(repo, change, None).node()
2975 node2 = scmutil.revsingle(repo, change, None).node()
2977 node1 = repo[node2].p1().node()
2976 node1 = repo[node2].p1().node()
2978 else:
2977 else:
2979 node1, node2 = scmutil.revpair(repo, revs)
2978 node1, node2 = scmutil.revpair(repo, revs)
2980
2979
2981 if reverse:
2980 if reverse:
2982 node1, node2 = node2, node1
2981 node1, node2 = node2, node1
2983
2982
2984 diffopts = patch.diffopts(ui, opts)
2983 diffopts = patch.diffopts(ui, opts)
2985 m = scmutil.match(repo[node2], pats, opts)
2984 m = scmutil.match(repo[node2], pats, opts)
2986 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2985 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2987 listsubrepos=opts.get('subrepos'))
2986 listsubrepos=opts.get('subrepos'))
2988
2987
2989 @command('^export',
2988 @command('^export',
2990 [('o', 'output', '',
2989 [('o', 'output', '',
2991 _('print output to file with formatted name'), _('FORMAT')),
2990 _('print output to file with formatted name'), _('FORMAT')),
2992 ('', 'switch-parent', None, _('diff against the second parent')),
2991 ('', 'switch-parent', None, _('diff against the second parent')),
2993 ('r', 'rev', [], _('revisions to export'), _('REV')),
2992 ('r', 'rev', [], _('revisions to export'), _('REV')),
2994 ] + diffopts,
2993 ] + diffopts,
2995 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2994 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2996 def export(ui, repo, *changesets, **opts):
2995 def export(ui, repo, *changesets, **opts):
2997 """dump the header and diffs for one or more changesets
2996 """dump the header and diffs for one or more changesets
2998
2997
2999 Print the changeset header and diffs for one or more revisions.
2998 Print the changeset header and diffs for one or more revisions.
3000 If no revision is given, the parent of the working directory is used.
2999 If no revision is given, the parent of the working directory is used.
3001
3000
3002 The information shown in the changeset header is: author, date,
3001 The information shown in the changeset header is: author, date,
3003 branch name (if non-default), changeset hash, parent(s) and commit
3002 branch name (if non-default), changeset hash, parent(s) and commit
3004 comment.
3003 comment.
3005
3004
3006 .. note::
3005 .. note::
3007
3006
3008 export may generate unexpected diff output for merge
3007 export may generate unexpected diff output for merge
3009 changesets, as it will compare the merge changeset against its
3008 changesets, as it will compare the merge changeset against its
3010 first parent only.
3009 first parent only.
3011
3010
3012 Output may be to a file, in which case the name of the file is
3011 Output may be to a file, in which case the name of the file is
3013 given using a format string. The formatting rules are as follows:
3012 given using a format string. The formatting rules are as follows:
3014
3013
3015 :``%%``: literal "%" character
3014 :``%%``: literal "%" character
3016 :``%H``: changeset hash (40 hexadecimal digits)
3015 :``%H``: changeset hash (40 hexadecimal digits)
3017 :``%N``: number of patches being generated
3016 :``%N``: number of patches being generated
3018 :``%R``: changeset revision number
3017 :``%R``: changeset revision number
3019 :``%b``: basename of the exporting repository
3018 :``%b``: basename of the exporting repository
3020 :``%h``: short-form changeset hash (12 hexadecimal digits)
3019 :``%h``: short-form changeset hash (12 hexadecimal digits)
3021 :``%m``: first line of the commit message (only alphanumeric characters)
3020 :``%m``: first line of the commit message (only alphanumeric characters)
3022 :``%n``: zero-padded sequence number, starting at 1
3021 :``%n``: zero-padded sequence number, starting at 1
3023 :``%r``: zero-padded changeset revision number
3022 :``%r``: zero-padded changeset revision number
3024
3023
3025 Without the -a/--text option, export will avoid generating diffs
3024 Without the -a/--text option, export will avoid generating diffs
3026 of files it detects as binary. With -a, export will generate a
3025 of files it detects as binary. With -a, export will generate a
3027 diff anyway, probably with undesirable results.
3026 diff anyway, probably with undesirable results.
3028
3027
3029 Use the -g/--git option to generate diffs in the git extended diff
3028 Use the -g/--git option to generate diffs in the git extended diff
3030 format. See :hg:`help diffs` for more information.
3029 format. See :hg:`help diffs` for more information.
3031
3030
3032 With the --switch-parent option, the diff will be against the
3031 With the --switch-parent option, the diff will be against the
3033 second parent. It can be useful to review a merge.
3032 second parent. It can be useful to review a merge.
3034
3033
3035 .. container:: verbose
3034 .. container:: verbose
3036
3035
3037 Examples:
3036 Examples:
3038
3037
3039 - use export and import to transplant a bugfix to the current
3038 - use export and import to transplant a bugfix to the current
3040 branch::
3039 branch::
3041
3040
3042 hg export -r 9353 | hg import -
3041 hg export -r 9353 | hg import -
3043
3042
3044 - export all the changesets between two revisions to a file with
3043 - export all the changesets between two revisions to a file with
3045 rename information::
3044 rename information::
3046
3045
3047 hg export --git -r 123:150 > changes.txt
3046 hg export --git -r 123:150 > changes.txt
3048
3047
3049 - split outgoing changes into a series of patches with
3048 - split outgoing changes into a series of patches with
3050 descriptive names::
3049 descriptive names::
3051
3050
3052 hg export -r "outgoing()" -o "%n-%m.patch"
3051 hg export -r "outgoing()" -o "%n-%m.patch"
3053
3052
3054 Returns 0 on success.
3053 Returns 0 on success.
3055 """
3054 """
3056 changesets += tuple(opts.get('rev', []))
3055 changesets += tuple(opts.get('rev', []))
3057 if not changesets:
3056 if not changesets:
3058 changesets = ['.']
3057 changesets = ['.']
3059 revs = scmutil.revrange(repo, changesets)
3058 revs = scmutil.revrange(repo, changesets)
3060 if not revs:
3059 if not revs:
3061 raise util.Abort(_("export requires at least one changeset"))
3060 raise util.Abort(_("export requires at least one changeset"))
3062 if len(revs) > 1:
3061 if len(revs) > 1:
3063 ui.note(_('exporting patches:\n'))
3062 ui.note(_('exporting patches:\n'))
3064 else:
3063 else:
3065 ui.note(_('exporting patch:\n'))
3064 ui.note(_('exporting patch:\n'))
3066 cmdutil.export(repo, revs, template=opts.get('output'),
3065 cmdutil.export(repo, revs, template=opts.get('output'),
3067 switch_parent=opts.get('switch_parent'),
3066 switch_parent=opts.get('switch_parent'),
3068 opts=patch.diffopts(ui, opts))
3067 opts=patch.diffopts(ui, opts))
3069
3068
3070 @command('files',
3069 @command('files',
3071 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3070 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3072 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3071 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3073 ] + walkopts + formatteropts,
3072 ] + walkopts + formatteropts,
3074 _('[OPTION]... [PATTERN]...'))
3073 _('[OPTION]... [PATTERN]...'))
3075 def files(ui, repo, *pats, **opts):
3074 def files(ui, repo, *pats, **opts):
3076 """list tracked files
3075 """list tracked files
3077
3076
3078 Print files under Mercurial control in the working directory or
3077 Print files under Mercurial control in the working directory or
3079 specified revision whose names match the given patterns (excluding
3078 specified revision whose names match the given patterns (excluding
3080 removed files).
3079 removed files).
3081
3080
3082 If no patterns are given to match, this command prints the names
3081 If no patterns are given to match, this command prints the names
3083 of all files under Mercurial control in the working copy.
3082 of all files under Mercurial control in the working copy.
3084
3083
3085 .. container:: verbose
3084 .. container:: verbose
3086
3085
3087 Examples:
3086 Examples:
3088
3087
3089 - list all files under the current directory::
3088 - list all files under the current directory::
3090
3089
3091 hg files .
3090 hg files .
3092
3091
3093 - shows sizes and flags for current revision::
3092 - shows sizes and flags for current revision::
3094
3093
3095 hg files -vr .
3094 hg files -vr .
3096
3095
3097 - list all files named README::
3096 - list all files named README::
3098
3097
3099 hg files -I "**/README"
3098 hg files -I "**/README"
3100
3099
3101 - list all binary files::
3100 - list all binary files::
3102
3101
3103 hg files "set:binary()"
3102 hg files "set:binary()"
3104
3103
3105 - find files containing a regular expression:
3104 - find files containing a regular expression:
3106
3105
3107 hg files "set:grep('bob')"
3106 hg files "set:grep('bob')"
3108
3107
3109 - search tracked file contents with xargs and grep::
3108 - search tracked file contents with xargs and grep::
3110
3109
3111 hg files -0 | xargs -0 grep foo
3110 hg files -0 | xargs -0 grep foo
3112
3111
3113 See :hg:'help pattern' and :hg:'help revsets' for more information
3112 See :hg:'help pattern' and :hg:'help revsets' for more information
3114 on specifying file patterns.
3113 on specifying file patterns.
3115
3114
3116 Returns 0 if a match is found, 1 otherwise.
3115 Returns 0 if a match is found, 1 otherwise.
3117
3116
3118 """
3117 """
3119 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3118 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3120 rev = ctx.rev()
3119 rev = ctx.rev()
3121 ret = 1
3120 ret = 1
3122
3121
3123 end = '\n'
3122 end = '\n'
3124 if opts.get('print0'):
3123 if opts.get('print0'):
3125 end = '\0'
3124 end = '\0'
3126 fm = ui.formatter('status', opts)
3125 fm = ui.formatter('status', opts)
3127 fmt = '%s' + end
3126 fmt = '%s' + end
3128
3127
3129 m = scmutil.match(ctx, pats, opts)
3128 m = scmutil.match(ctx, pats, opts)
3130 for f in ctx.walk(m):
3129 for f in ctx.walk(m):
3131 if rev is None and repo.dirstate[f] in 'R?!':
3130 if rev is None and repo.dirstate[f] in 'R?!':
3132 continue
3131 continue
3133 fm.startitem()
3132 fm.startitem()
3134 if ui.verbose:
3133 if ui.verbose:
3135 fc = ctx[f]
3134 fc = ctx[f]
3136 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3135 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3137 fm.data(abspath=f)
3136 fm.data(abspath=f)
3138 fm.write('path', fmt, m.rel(f))
3137 fm.write('path', fmt, m.rel(f))
3139 ret = 0
3138 ret = 0
3140
3139
3141 fm.end()
3140 fm.end()
3142
3141
3143 return ret
3142 return ret
3144
3143
3145 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3144 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3146 def forget(ui, repo, *pats, **opts):
3145 def forget(ui, repo, *pats, **opts):
3147 """forget the specified files on the next commit
3146 """forget the specified files on the next commit
3148
3147
3149 Mark the specified files so they will no longer be tracked
3148 Mark the specified files so they will no longer be tracked
3150 after the next commit.
3149 after the next commit.
3151
3150
3152 This only removes files from the current branch, not from the
3151 This only removes files from the current branch, not from the
3153 entire project history, and it does not delete them from the
3152 entire project history, and it does not delete them from the
3154 working directory.
3153 working directory.
3155
3154
3156 To undo a forget before the next commit, see :hg:`add`.
3155 To undo a forget before the next commit, see :hg:`add`.
3157
3156
3158 .. container:: verbose
3157 .. container:: verbose
3159
3158
3160 Examples:
3159 Examples:
3161
3160
3162 - forget newly-added binary files::
3161 - forget newly-added binary files::
3163
3162
3164 hg forget "set:added() and binary()"
3163 hg forget "set:added() and binary()"
3165
3164
3166 - forget files that would be excluded by .hgignore::
3165 - forget files that would be excluded by .hgignore::
3167
3166
3168 hg forget "set:hgignore()"
3167 hg forget "set:hgignore()"
3169
3168
3170 Returns 0 on success.
3169 Returns 0 on success.
3171 """
3170 """
3172
3171
3173 if not pats:
3172 if not pats:
3174 raise util.Abort(_('no files specified'))
3173 raise util.Abort(_('no files specified'))
3175
3174
3176 m = scmutil.match(repo[None], pats, opts)
3175 m = scmutil.match(repo[None], pats, opts)
3177 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3176 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3178 return rejected and 1 or 0
3177 return rejected and 1 or 0
3179
3178
3180 @command(
3179 @command(
3181 'graft',
3180 'graft',
3182 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3181 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3183 ('c', 'continue', False, _('resume interrupted graft')),
3182 ('c', 'continue', False, _('resume interrupted graft')),
3184 ('e', 'edit', False, _('invoke editor on commit messages')),
3183 ('e', 'edit', False, _('invoke editor on commit messages')),
3185 ('', 'log', None, _('append graft info to log message')),
3184 ('', 'log', None, _('append graft info to log message')),
3186 ('f', 'force', False, _('force graft')),
3185 ('f', 'force', False, _('force graft')),
3187 ('D', 'currentdate', False,
3186 ('D', 'currentdate', False,
3188 _('record the current date as commit date')),
3187 _('record the current date as commit date')),
3189 ('U', 'currentuser', False,
3188 ('U', 'currentuser', False,
3190 _('record the current user as committer'), _('DATE'))]
3189 _('record the current user as committer'), _('DATE'))]
3191 + commitopts2 + mergetoolopts + dryrunopts,
3190 + commitopts2 + mergetoolopts + dryrunopts,
3192 _('[OPTION]... [-r] REV...'))
3191 _('[OPTION]... [-r] REV...'))
3193 def graft(ui, repo, *revs, **opts):
3192 def graft(ui, repo, *revs, **opts):
3194 '''copy changes from other branches onto the current branch
3193 '''copy changes from other branches onto the current branch
3195
3194
3196 This command uses Mercurial's merge logic to copy individual
3195 This command uses Mercurial's merge logic to copy individual
3197 changes from other branches without merging branches in the
3196 changes from other branches without merging branches in the
3198 history graph. This is sometimes known as 'backporting' or
3197 history graph. This is sometimes known as 'backporting' or
3199 'cherry-picking'. By default, graft will copy user, date, and
3198 'cherry-picking'. By default, graft will copy user, date, and
3200 description from the source changesets.
3199 description from the source changesets.
3201
3200
3202 Changesets that are ancestors of the current revision, that have
3201 Changesets that are ancestors of the current revision, that have
3203 already been grafted, or that are merges will be skipped.
3202 already been grafted, or that are merges will be skipped.
3204
3203
3205 If --log is specified, log messages will have a comment appended
3204 If --log is specified, log messages will have a comment appended
3206 of the form::
3205 of the form::
3207
3206
3208 (grafted from CHANGESETHASH)
3207 (grafted from CHANGESETHASH)
3209
3208
3210 If --force is specified, revisions will be grafted even if they
3209 If --force is specified, revisions will be grafted even if they
3211 are already ancestors of or have been grafted to the destination.
3210 are already ancestors of or have been grafted to the destination.
3212 This is useful when the revisions have since been backed out.
3211 This is useful when the revisions have since been backed out.
3213
3212
3214 If a graft merge results in conflicts, the graft process is
3213 If a graft merge results in conflicts, the graft process is
3215 interrupted so that the current merge can be manually resolved.
3214 interrupted so that the current merge can be manually resolved.
3216 Once all conflicts are addressed, the graft process can be
3215 Once all conflicts are addressed, the graft process can be
3217 continued with the -c/--continue option.
3216 continued with the -c/--continue option.
3218
3217
3219 .. note::
3218 .. note::
3220
3219
3221 The -c/--continue option does not reapply earlier options, except
3220 The -c/--continue option does not reapply earlier options, except
3222 for --force.
3221 for --force.
3223
3222
3224 .. container:: verbose
3223 .. container:: verbose
3225
3224
3226 Examples:
3225 Examples:
3227
3226
3228 - copy a single change to the stable branch and edit its description::
3227 - copy a single change to the stable branch and edit its description::
3229
3228
3230 hg update stable
3229 hg update stable
3231 hg graft --edit 9393
3230 hg graft --edit 9393
3232
3231
3233 - graft a range of changesets with one exception, updating dates::
3232 - graft a range of changesets with one exception, updating dates::
3234
3233
3235 hg graft -D "2085::2093 and not 2091"
3234 hg graft -D "2085::2093 and not 2091"
3236
3235
3237 - continue a graft after resolving conflicts::
3236 - continue a graft after resolving conflicts::
3238
3237
3239 hg graft -c
3238 hg graft -c
3240
3239
3241 - show the source of a grafted changeset::
3240 - show the source of a grafted changeset::
3242
3241
3243 hg log --debug -r .
3242 hg log --debug -r .
3244
3243
3245 See :hg:`help revisions` and :hg:`help revsets` for more about
3244 See :hg:`help revisions` and :hg:`help revsets` for more about
3246 specifying revisions.
3245 specifying revisions.
3247
3246
3248 Returns 0 on successful completion.
3247 Returns 0 on successful completion.
3249 '''
3248 '''
3250
3249
3251 revs = list(revs)
3250 revs = list(revs)
3252 revs.extend(opts['rev'])
3251 revs.extend(opts['rev'])
3253
3252
3254 if not opts.get('user') and opts.get('currentuser'):
3253 if not opts.get('user') and opts.get('currentuser'):
3255 opts['user'] = ui.username()
3254 opts['user'] = ui.username()
3256 if not opts.get('date') and opts.get('currentdate'):
3255 if not opts.get('date') and opts.get('currentdate'):
3257 opts['date'] = "%d %d" % util.makedate()
3256 opts['date'] = "%d %d" % util.makedate()
3258
3257
3259 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3258 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3260
3259
3261 cont = False
3260 cont = False
3262 if opts['continue']:
3261 if opts['continue']:
3263 cont = True
3262 cont = True
3264 if revs:
3263 if revs:
3265 raise util.Abort(_("can't specify --continue and revisions"))
3264 raise util.Abort(_("can't specify --continue and revisions"))
3266 # read in unfinished revisions
3265 # read in unfinished revisions
3267 try:
3266 try:
3268 nodes = repo.opener.read('graftstate').splitlines()
3267 nodes = repo.opener.read('graftstate').splitlines()
3269 revs = [repo[node].rev() for node in nodes]
3268 revs = [repo[node].rev() for node in nodes]
3270 except IOError, inst:
3269 except IOError, inst:
3271 if inst.errno != errno.ENOENT:
3270 if inst.errno != errno.ENOENT:
3272 raise
3271 raise
3273 raise util.Abort(_("no graft state found, can't continue"))
3272 raise util.Abort(_("no graft state found, can't continue"))
3274 else:
3273 else:
3275 cmdutil.checkunfinished(repo)
3274 cmdutil.checkunfinished(repo)
3276 cmdutil.bailifchanged(repo)
3275 cmdutil.bailifchanged(repo)
3277 if not revs:
3276 if not revs:
3278 raise util.Abort(_('no revisions specified'))
3277 raise util.Abort(_('no revisions specified'))
3279 revs = scmutil.revrange(repo, revs)
3278 revs = scmutil.revrange(repo, revs)
3280
3279
3281 # check for merges
3280 # check for merges
3282 for rev in repo.revs('%ld and merge()', revs):
3281 for rev in repo.revs('%ld and merge()', revs):
3283 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3282 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3284 revs.remove(rev)
3283 revs.remove(rev)
3285 if not revs:
3284 if not revs:
3286 return -1
3285 return -1
3287
3286
3288 # Don't check in the --continue case, in effect retaining --force across
3287 # Don't check in the --continue case, in effect retaining --force across
3289 # --continues. That's because without --force, any revisions we decided to
3288 # --continues. That's because without --force, any revisions we decided to
3290 # skip would have been filtered out here, so they wouldn't have made their
3289 # skip would have been filtered out here, so they wouldn't have made their
3291 # way to the graftstate. With --force, any revisions we would have otherwise
3290 # way to the graftstate. With --force, any revisions we would have otherwise
3292 # skipped would not have been filtered out, and if they hadn't been applied
3291 # skipped would not have been filtered out, and if they hadn't been applied
3293 # already, they'd have been in the graftstate.
3292 # already, they'd have been in the graftstate.
3294 if not (cont or opts.get('force')):
3293 if not (cont or opts.get('force')):
3295 # check for ancestors of dest branch
3294 # check for ancestors of dest branch
3296 crev = repo['.'].rev()
3295 crev = repo['.'].rev()
3297 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3296 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3298 # Cannot use x.remove(y) on smart set, this has to be a list.
3297 # Cannot use x.remove(y) on smart set, this has to be a list.
3299 # XXX make this lazy in the future
3298 # XXX make this lazy in the future
3300 revs = list(revs)
3299 revs = list(revs)
3301 # don't mutate while iterating, create a copy
3300 # don't mutate while iterating, create a copy
3302 for rev in list(revs):
3301 for rev in list(revs):
3303 if rev in ancestors:
3302 if rev in ancestors:
3304 ui.warn(_('skipping ancestor revision %s\n') % rev)
3303 ui.warn(_('skipping ancestor revision %s\n') % rev)
3305 # XXX remove on list is slow
3304 # XXX remove on list is slow
3306 revs.remove(rev)
3305 revs.remove(rev)
3307 if not revs:
3306 if not revs:
3308 return -1
3307 return -1
3309
3308
3310 # analyze revs for earlier grafts
3309 # analyze revs for earlier grafts
3311 ids = {}
3310 ids = {}
3312 for ctx in repo.set("%ld", revs):
3311 for ctx in repo.set("%ld", revs):
3313 ids[ctx.hex()] = ctx.rev()
3312 ids[ctx.hex()] = ctx.rev()
3314 n = ctx.extra().get('source')
3313 n = ctx.extra().get('source')
3315 if n:
3314 if n:
3316 ids[n] = ctx.rev()
3315 ids[n] = ctx.rev()
3317
3316
3318 # check ancestors for earlier grafts
3317 # check ancestors for earlier grafts
3319 ui.debug('scanning for duplicate grafts\n')
3318 ui.debug('scanning for duplicate grafts\n')
3320
3319
3321 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3320 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3322 ctx = repo[rev]
3321 ctx = repo[rev]
3323 n = ctx.extra().get('source')
3322 n = ctx.extra().get('source')
3324 if n in ids:
3323 if n in ids:
3325 try:
3324 try:
3326 r = repo[n].rev()
3325 r = repo[n].rev()
3327 except error.RepoLookupError:
3326 except error.RepoLookupError:
3328 r = None
3327 r = None
3329 if r in revs:
3328 if r in revs:
3330 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3329 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3331 % (r, rev))
3330 % (r, rev))
3332 revs.remove(r)
3331 revs.remove(r)
3333 elif ids[n] in revs:
3332 elif ids[n] in revs:
3334 if r is None:
3333 if r is None:
3335 ui.warn(_('skipping already grafted revision %s '
3334 ui.warn(_('skipping already grafted revision %s '
3336 '(%s also has unknown origin %s)\n')
3335 '(%s also has unknown origin %s)\n')
3337 % (ids[n], rev, n))
3336 % (ids[n], rev, n))
3338 else:
3337 else:
3339 ui.warn(_('skipping already grafted revision %s '
3338 ui.warn(_('skipping already grafted revision %s '
3340 '(%s also has origin %d)\n')
3339 '(%s also has origin %d)\n')
3341 % (ids[n], rev, r))
3340 % (ids[n], rev, r))
3342 revs.remove(ids[n])
3341 revs.remove(ids[n])
3343 elif ctx.hex() in ids:
3342 elif ctx.hex() in ids:
3344 r = ids[ctx.hex()]
3343 r = ids[ctx.hex()]
3345 ui.warn(_('skipping already grafted revision %s '
3344 ui.warn(_('skipping already grafted revision %s '
3346 '(was grafted from %d)\n') % (r, rev))
3345 '(was grafted from %d)\n') % (r, rev))
3347 revs.remove(r)
3346 revs.remove(r)
3348 if not revs:
3347 if not revs:
3349 return -1
3348 return -1
3350
3349
3351 wlock = repo.wlock()
3350 wlock = repo.wlock()
3352 try:
3351 try:
3353 current = repo['.']
3352 current = repo['.']
3354 for pos, ctx in enumerate(repo.set("%ld", revs)):
3353 for pos, ctx in enumerate(repo.set("%ld", revs)):
3355
3354
3356 ui.status(_('grafting revision %s\n') % ctx.rev())
3355 ui.status(_('grafting revision %s\n') % ctx.rev())
3357 if opts.get('dry_run'):
3356 if opts.get('dry_run'):
3358 continue
3357 continue
3359
3358
3360 source = ctx.extra().get('source')
3359 source = ctx.extra().get('source')
3361 if not source:
3360 if not source:
3362 source = ctx.hex()
3361 source = ctx.hex()
3363 extra = {'source': source}
3362 extra = {'source': source}
3364 user = ctx.user()
3363 user = ctx.user()
3365 if opts.get('user'):
3364 if opts.get('user'):
3366 user = opts['user']
3365 user = opts['user']
3367 date = ctx.date()
3366 date = ctx.date()
3368 if opts.get('date'):
3367 if opts.get('date'):
3369 date = opts['date']
3368 date = opts['date']
3370 message = ctx.description()
3369 message = ctx.description()
3371 if opts.get('log'):
3370 if opts.get('log'):
3372 message += '\n(grafted from %s)' % ctx.hex()
3371 message += '\n(grafted from %s)' % ctx.hex()
3373
3372
3374 # we don't merge the first commit when continuing
3373 # we don't merge the first commit when continuing
3375 if not cont:
3374 if not cont:
3376 # perform the graft merge with p1(rev) as 'ancestor'
3375 # perform the graft merge with p1(rev) as 'ancestor'
3377 try:
3376 try:
3378 # ui.forcemerge is an internal variable, do not document
3377 # ui.forcemerge is an internal variable, do not document
3379 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3378 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3380 'graft')
3379 'graft')
3381 stats = mergemod.update(repo, ctx.node(), True, True, False,
3380 stats = mergemod.update(repo, ctx.node(), True, True, False,
3382 ctx.p1().node(),
3381 ctx.p1().node(),
3383 labels=['local', 'graft'])
3382 labels=['local', 'graft'])
3384 finally:
3383 finally:
3385 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3384 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3386 # report any conflicts
3385 # report any conflicts
3387 if stats and stats[3] > 0:
3386 if stats and stats[3] > 0:
3388 # write out state for --continue
3387 # write out state for --continue
3389 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3388 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3390 repo.opener.write('graftstate', ''.join(nodelines))
3389 repo.opener.write('graftstate', ''.join(nodelines))
3391 raise util.Abort(
3390 raise util.Abort(
3392 _("unresolved conflicts, can't continue"),
3391 _("unresolved conflicts, can't continue"),
3393 hint=_('use hg resolve and hg graft --continue'))
3392 hint=_('use hg resolve and hg graft --continue'))
3394 else:
3393 else:
3395 cont = False
3394 cont = False
3396
3395
3397 # drop the second merge parent
3396 # drop the second merge parent
3398 repo.dirstate.beginparentchange()
3397 repo.dirstate.beginparentchange()
3399 repo.setparents(current.node(), nullid)
3398 repo.setparents(current.node(), nullid)
3400 repo.dirstate.write()
3399 repo.dirstate.write()
3401 # fix up dirstate for copies and renames
3400 # fix up dirstate for copies and renames
3402 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3401 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3403 repo.dirstate.endparentchange()
3402 repo.dirstate.endparentchange()
3404
3403
3405 # commit
3404 # commit
3406 node = repo.commit(text=message, user=user,
3405 node = repo.commit(text=message, user=user,
3407 date=date, extra=extra, editor=editor)
3406 date=date, extra=extra, editor=editor)
3408 if node is None:
3407 if node is None:
3409 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3408 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3410 else:
3409 else:
3411 current = repo[node]
3410 current = repo[node]
3412 finally:
3411 finally:
3413 wlock.release()
3412 wlock.release()
3414
3413
3415 # remove state when we complete successfully
3414 # remove state when we complete successfully
3416 if not opts.get('dry_run'):
3415 if not opts.get('dry_run'):
3417 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3416 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3418
3417
3419 return 0
3418 return 0
3420
3419
3421 @command('grep',
3420 @command('grep',
3422 [('0', 'print0', None, _('end fields with NUL')),
3421 [('0', 'print0', None, _('end fields with NUL')),
3423 ('', 'all', None, _('print all revisions that match')),
3422 ('', 'all', None, _('print all revisions that match')),
3424 ('a', 'text', None, _('treat all files as text')),
3423 ('a', 'text', None, _('treat all files as text')),
3425 ('f', 'follow', None,
3424 ('f', 'follow', None,
3426 _('follow changeset history,'
3425 _('follow changeset history,'
3427 ' or file history across copies and renames')),
3426 ' or file history across copies and renames')),
3428 ('i', 'ignore-case', None, _('ignore case when matching')),
3427 ('i', 'ignore-case', None, _('ignore case when matching')),
3429 ('l', 'files-with-matches', None,
3428 ('l', 'files-with-matches', None,
3430 _('print only filenames and revisions that match')),
3429 _('print only filenames and revisions that match')),
3431 ('n', 'line-number', None, _('print matching line numbers')),
3430 ('n', 'line-number', None, _('print matching line numbers')),
3432 ('r', 'rev', [],
3431 ('r', 'rev', [],
3433 _('only search files changed within revision range'), _('REV')),
3432 _('only search files changed within revision range'), _('REV')),
3434 ('u', 'user', None, _('list the author (long with -v)')),
3433 ('u', 'user', None, _('list the author (long with -v)')),
3435 ('d', 'date', None, _('list the date (short with -q)')),
3434 ('d', 'date', None, _('list the date (short with -q)')),
3436 ] + walkopts,
3435 ] + walkopts,
3437 _('[OPTION]... PATTERN [FILE]...'),
3436 _('[OPTION]... PATTERN [FILE]...'),
3438 inferrepo=True)
3437 inferrepo=True)
3439 def grep(ui, repo, pattern, *pats, **opts):
3438 def grep(ui, repo, pattern, *pats, **opts):
3440 """search for a pattern in specified files and revisions
3439 """search for a pattern in specified files and revisions
3441
3440
3442 Search revisions of files for a regular expression.
3441 Search revisions of files for a regular expression.
3443
3442
3444 This command behaves differently than Unix grep. It only accepts
3443 This command behaves differently than Unix grep. It only accepts
3445 Python/Perl regexps. It searches repository history, not the
3444 Python/Perl regexps. It searches repository history, not the
3446 working directory. It always prints the revision number in which a
3445 working directory. It always prints the revision number in which a
3447 match appears.
3446 match appears.
3448
3447
3449 By default, grep only prints output for the first revision of a
3448 By default, grep only prints output for the first revision of a
3450 file in which it finds a match. To get it to print every revision
3449 file in which it finds a match. To get it to print every revision
3451 that contains a change in match status ("-" for a match that
3450 that contains a change in match status ("-" for a match that
3452 becomes a non-match, or "+" for a non-match that becomes a match),
3451 becomes a non-match, or "+" for a non-match that becomes a match),
3453 use the --all flag.
3452 use the --all flag.
3454
3453
3455 Returns 0 if a match is found, 1 otherwise.
3454 Returns 0 if a match is found, 1 otherwise.
3456 """
3455 """
3457 reflags = re.M
3456 reflags = re.M
3458 if opts.get('ignore_case'):
3457 if opts.get('ignore_case'):
3459 reflags |= re.I
3458 reflags |= re.I
3460 try:
3459 try:
3461 regexp = util.re.compile(pattern, reflags)
3460 regexp = util.re.compile(pattern, reflags)
3462 except re.error, inst:
3461 except re.error, inst:
3463 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3462 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3464 return 1
3463 return 1
3465 sep, eol = ':', '\n'
3464 sep, eol = ':', '\n'
3466 if opts.get('print0'):
3465 if opts.get('print0'):
3467 sep = eol = '\0'
3466 sep = eol = '\0'
3468
3467
3469 getfile = util.lrucachefunc(repo.file)
3468 getfile = util.lrucachefunc(repo.file)
3470
3469
3471 def matchlines(body):
3470 def matchlines(body):
3472 begin = 0
3471 begin = 0
3473 linenum = 0
3472 linenum = 0
3474 while begin < len(body):
3473 while begin < len(body):
3475 match = regexp.search(body, begin)
3474 match = regexp.search(body, begin)
3476 if not match:
3475 if not match:
3477 break
3476 break
3478 mstart, mend = match.span()
3477 mstart, mend = match.span()
3479 linenum += body.count('\n', begin, mstart) + 1
3478 linenum += body.count('\n', begin, mstart) + 1
3480 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3479 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3481 begin = body.find('\n', mend) + 1 or len(body) + 1
3480 begin = body.find('\n', mend) + 1 or len(body) + 1
3482 lend = begin - 1
3481 lend = begin - 1
3483 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3482 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3484
3483
3485 class linestate(object):
3484 class linestate(object):
3486 def __init__(self, line, linenum, colstart, colend):
3485 def __init__(self, line, linenum, colstart, colend):
3487 self.line = line
3486 self.line = line
3488 self.linenum = linenum
3487 self.linenum = linenum
3489 self.colstart = colstart
3488 self.colstart = colstart
3490 self.colend = colend
3489 self.colend = colend
3491
3490
3492 def __hash__(self):
3491 def __hash__(self):
3493 return hash((self.linenum, self.line))
3492 return hash((self.linenum, self.line))
3494
3493
3495 def __eq__(self, other):
3494 def __eq__(self, other):
3496 return self.line == other.line
3495 return self.line == other.line
3497
3496
3498 def __iter__(self):
3497 def __iter__(self):
3499 yield (self.line[:self.colstart], '')
3498 yield (self.line[:self.colstart], '')
3500 yield (self.line[self.colstart:self.colend], 'grep.match')
3499 yield (self.line[self.colstart:self.colend], 'grep.match')
3501 rest = self.line[self.colend:]
3500 rest = self.line[self.colend:]
3502 while rest != '':
3501 while rest != '':
3503 match = regexp.search(rest)
3502 match = regexp.search(rest)
3504 if not match:
3503 if not match:
3505 yield (rest, '')
3504 yield (rest, '')
3506 break
3505 break
3507 mstart, mend = match.span()
3506 mstart, mend = match.span()
3508 yield (rest[:mstart], '')
3507 yield (rest[:mstart], '')
3509 yield (rest[mstart:mend], 'grep.match')
3508 yield (rest[mstart:mend], 'grep.match')
3510 rest = rest[mend:]
3509 rest = rest[mend:]
3511
3510
3512 matches = {}
3511 matches = {}
3513 copies = {}
3512 copies = {}
3514 def grepbody(fn, rev, body):
3513 def grepbody(fn, rev, body):
3515 matches[rev].setdefault(fn, [])
3514 matches[rev].setdefault(fn, [])
3516 m = matches[rev][fn]
3515 m = matches[rev][fn]
3517 for lnum, cstart, cend, line in matchlines(body):
3516 for lnum, cstart, cend, line in matchlines(body):
3518 s = linestate(line, lnum, cstart, cend)
3517 s = linestate(line, lnum, cstart, cend)
3519 m.append(s)
3518 m.append(s)
3520
3519
3521 def difflinestates(a, b):
3520 def difflinestates(a, b):
3522 sm = difflib.SequenceMatcher(None, a, b)
3521 sm = difflib.SequenceMatcher(None, a, b)
3523 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3522 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3524 if tag == 'insert':
3523 if tag == 'insert':
3525 for i in xrange(blo, bhi):
3524 for i in xrange(blo, bhi):
3526 yield ('+', b[i])
3525 yield ('+', b[i])
3527 elif tag == 'delete':
3526 elif tag == 'delete':
3528 for i in xrange(alo, ahi):
3527 for i in xrange(alo, ahi):
3529 yield ('-', a[i])
3528 yield ('-', a[i])
3530 elif tag == 'replace':
3529 elif tag == 'replace':
3531 for i in xrange(alo, ahi):
3530 for i in xrange(alo, ahi):
3532 yield ('-', a[i])
3531 yield ('-', a[i])
3533 for i in xrange(blo, bhi):
3532 for i in xrange(blo, bhi):
3534 yield ('+', b[i])
3533 yield ('+', b[i])
3535
3534
3536 def display(fn, ctx, pstates, states):
3535 def display(fn, ctx, pstates, states):
3537 rev = ctx.rev()
3536 rev = ctx.rev()
3538 datefunc = ui.quiet and util.shortdate or util.datestr
3537 datefunc = ui.quiet and util.shortdate or util.datestr
3539 found = False
3538 found = False
3540 @util.cachefunc
3539 @util.cachefunc
3541 def binary():
3540 def binary():
3542 flog = getfile(fn)
3541 flog = getfile(fn)
3543 return util.binary(flog.read(ctx.filenode(fn)))
3542 return util.binary(flog.read(ctx.filenode(fn)))
3544
3543
3545 if opts.get('all'):
3544 if opts.get('all'):
3546 iter = difflinestates(pstates, states)
3545 iter = difflinestates(pstates, states)
3547 else:
3546 else:
3548 iter = [('', l) for l in states]
3547 iter = [('', l) for l in states]
3549 for change, l in iter:
3548 for change, l in iter:
3550 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3549 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3551
3550
3552 if opts.get('line_number'):
3551 if opts.get('line_number'):
3553 cols.append((str(l.linenum), 'grep.linenumber'))
3552 cols.append((str(l.linenum), 'grep.linenumber'))
3554 if opts.get('all'):
3553 if opts.get('all'):
3555 cols.append((change, 'grep.change'))
3554 cols.append((change, 'grep.change'))
3556 if opts.get('user'):
3555 if opts.get('user'):
3557 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3556 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3558 if opts.get('date'):
3557 if opts.get('date'):
3559 cols.append((datefunc(ctx.date()), 'grep.date'))
3558 cols.append((datefunc(ctx.date()), 'grep.date'))
3560 for col, label in cols[:-1]:
3559 for col, label in cols[:-1]:
3561 ui.write(col, label=label)
3560 ui.write(col, label=label)
3562 ui.write(sep, label='grep.sep')
3561 ui.write(sep, label='grep.sep')
3563 ui.write(cols[-1][0], label=cols[-1][1])
3562 ui.write(cols[-1][0], label=cols[-1][1])
3564 if not opts.get('files_with_matches'):
3563 if not opts.get('files_with_matches'):
3565 ui.write(sep, label='grep.sep')
3564 ui.write(sep, label='grep.sep')
3566 if not opts.get('text') and binary():
3565 if not opts.get('text') and binary():
3567 ui.write(" Binary file matches")
3566 ui.write(" Binary file matches")
3568 else:
3567 else:
3569 for s, label in l:
3568 for s, label in l:
3570 ui.write(s, label=label)
3569 ui.write(s, label=label)
3571 ui.write(eol)
3570 ui.write(eol)
3572 found = True
3571 found = True
3573 if opts.get('files_with_matches'):
3572 if opts.get('files_with_matches'):
3574 break
3573 break
3575 return found
3574 return found
3576
3575
3577 skip = {}
3576 skip = {}
3578 revfiles = {}
3577 revfiles = {}
3579 matchfn = scmutil.match(repo[None], pats, opts)
3578 matchfn = scmutil.match(repo[None], pats, opts)
3580 found = False
3579 found = False
3581 follow = opts.get('follow')
3580 follow = opts.get('follow')
3582
3581
3583 def prep(ctx, fns):
3582 def prep(ctx, fns):
3584 rev = ctx.rev()
3583 rev = ctx.rev()
3585 pctx = ctx.p1()
3584 pctx = ctx.p1()
3586 parent = pctx.rev()
3585 parent = pctx.rev()
3587 matches.setdefault(rev, {})
3586 matches.setdefault(rev, {})
3588 matches.setdefault(parent, {})
3587 matches.setdefault(parent, {})
3589 files = revfiles.setdefault(rev, [])
3588 files = revfiles.setdefault(rev, [])
3590 for fn in fns:
3589 for fn in fns:
3591 flog = getfile(fn)
3590 flog = getfile(fn)
3592 try:
3591 try:
3593 fnode = ctx.filenode(fn)
3592 fnode = ctx.filenode(fn)
3594 except error.LookupError:
3593 except error.LookupError:
3595 continue
3594 continue
3596
3595
3597 copied = flog.renamed(fnode)
3596 copied = flog.renamed(fnode)
3598 copy = follow and copied and copied[0]
3597 copy = follow and copied and copied[0]
3599 if copy:
3598 if copy:
3600 copies.setdefault(rev, {})[fn] = copy
3599 copies.setdefault(rev, {})[fn] = copy
3601 if fn in skip:
3600 if fn in skip:
3602 if copy:
3601 if copy:
3603 skip[copy] = True
3602 skip[copy] = True
3604 continue
3603 continue
3605 files.append(fn)
3604 files.append(fn)
3606
3605
3607 if fn not in matches[rev]:
3606 if fn not in matches[rev]:
3608 grepbody(fn, rev, flog.read(fnode))
3607 grepbody(fn, rev, flog.read(fnode))
3609
3608
3610 pfn = copy or fn
3609 pfn = copy or fn
3611 if pfn not in matches[parent]:
3610 if pfn not in matches[parent]:
3612 try:
3611 try:
3613 fnode = pctx.filenode(pfn)
3612 fnode = pctx.filenode(pfn)
3614 grepbody(pfn, parent, flog.read(fnode))
3613 grepbody(pfn, parent, flog.read(fnode))
3615 except error.LookupError:
3614 except error.LookupError:
3616 pass
3615 pass
3617
3616
3618 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3617 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3619 rev = ctx.rev()
3618 rev = ctx.rev()
3620 parent = ctx.p1().rev()
3619 parent = ctx.p1().rev()
3621 for fn in sorted(revfiles.get(rev, [])):
3620 for fn in sorted(revfiles.get(rev, [])):
3622 states = matches[rev][fn]
3621 states = matches[rev][fn]
3623 copy = copies.get(rev, {}).get(fn)
3622 copy = copies.get(rev, {}).get(fn)
3624 if fn in skip:
3623 if fn in skip:
3625 if copy:
3624 if copy:
3626 skip[copy] = True
3625 skip[copy] = True
3627 continue
3626 continue
3628 pstates = matches.get(parent, {}).get(copy or fn, [])
3627 pstates = matches.get(parent, {}).get(copy or fn, [])
3629 if pstates or states:
3628 if pstates or states:
3630 r = display(fn, ctx, pstates, states)
3629 r = display(fn, ctx, pstates, states)
3631 found = found or r
3630 found = found or r
3632 if r and not opts.get('all'):
3631 if r and not opts.get('all'):
3633 skip[fn] = True
3632 skip[fn] = True
3634 if copy:
3633 if copy:
3635 skip[copy] = True
3634 skip[copy] = True
3636 del matches[rev]
3635 del matches[rev]
3637 del revfiles[rev]
3636 del revfiles[rev]
3638
3637
3639 return not found
3638 return not found
3640
3639
3641 @command('heads',
3640 @command('heads',
3642 [('r', 'rev', '',
3641 [('r', 'rev', '',
3643 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3642 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3644 ('t', 'topo', False, _('show topological heads only')),
3643 ('t', 'topo', False, _('show topological heads only')),
3645 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3644 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3646 ('c', 'closed', False, _('show normal and closed branch heads')),
3645 ('c', 'closed', False, _('show normal and closed branch heads')),
3647 ] + templateopts,
3646 ] + templateopts,
3648 _('[-ct] [-r STARTREV] [REV]...'))
3647 _('[-ct] [-r STARTREV] [REV]...'))
3649 def heads(ui, repo, *branchrevs, **opts):
3648 def heads(ui, repo, *branchrevs, **opts):
3650 """show branch heads
3649 """show branch heads
3651
3650
3652 With no arguments, show all open branch heads in the repository.
3651 With no arguments, show all open branch heads in the repository.
3653 Branch heads are changesets that have no descendants on the
3652 Branch heads are changesets that have no descendants on the
3654 same branch. They are where development generally takes place and
3653 same branch. They are where development generally takes place and
3655 are the usual targets for update and merge operations.
3654 are the usual targets for update and merge operations.
3656
3655
3657 If one or more REVs are given, only open branch heads on the
3656 If one or more REVs are given, only open branch heads on the
3658 branches associated with the specified changesets are shown. This
3657 branches associated with the specified changesets are shown. This
3659 means that you can use :hg:`heads .` to see the heads on the
3658 means that you can use :hg:`heads .` to see the heads on the
3660 currently checked-out branch.
3659 currently checked-out branch.
3661
3660
3662 If -c/--closed is specified, also show branch heads marked closed
3661 If -c/--closed is specified, also show branch heads marked closed
3663 (see :hg:`commit --close-branch`).
3662 (see :hg:`commit --close-branch`).
3664
3663
3665 If STARTREV is specified, only those heads that are descendants of
3664 If STARTREV is specified, only those heads that are descendants of
3666 STARTREV will be displayed.
3665 STARTREV will be displayed.
3667
3666
3668 If -t/--topo is specified, named branch mechanics will be ignored and only
3667 If -t/--topo is specified, named branch mechanics will be ignored and only
3669 topological heads (changesets with no children) will be shown.
3668 topological heads (changesets with no children) will be shown.
3670
3669
3671 Returns 0 if matching heads are found, 1 if not.
3670 Returns 0 if matching heads are found, 1 if not.
3672 """
3671 """
3673
3672
3674 start = None
3673 start = None
3675 if 'rev' in opts:
3674 if 'rev' in opts:
3676 start = scmutil.revsingle(repo, opts['rev'], None).node()
3675 start = scmutil.revsingle(repo, opts['rev'], None).node()
3677
3676
3678 if opts.get('topo'):
3677 if opts.get('topo'):
3679 heads = [repo[h] for h in repo.heads(start)]
3678 heads = [repo[h] for h in repo.heads(start)]
3680 else:
3679 else:
3681 heads = []
3680 heads = []
3682 for branch in repo.branchmap():
3681 for branch in repo.branchmap():
3683 heads += repo.branchheads(branch, start, opts.get('closed'))
3682 heads += repo.branchheads(branch, start, opts.get('closed'))
3684 heads = [repo[h] for h in heads]
3683 heads = [repo[h] for h in heads]
3685
3684
3686 if branchrevs:
3685 if branchrevs:
3687 branches = set(repo[br].branch() for br in branchrevs)
3686 branches = set(repo[br].branch() for br in branchrevs)
3688 heads = [h for h in heads if h.branch() in branches]
3687 heads = [h for h in heads if h.branch() in branches]
3689
3688
3690 if opts.get('active') and branchrevs:
3689 if opts.get('active') and branchrevs:
3691 dagheads = repo.heads(start)
3690 dagheads = repo.heads(start)
3692 heads = [h for h in heads if h.node() in dagheads]
3691 heads = [h for h in heads if h.node() in dagheads]
3693
3692
3694 if branchrevs:
3693 if branchrevs:
3695 haveheads = set(h.branch() for h in heads)
3694 haveheads = set(h.branch() for h in heads)
3696 if branches - haveheads:
3695 if branches - haveheads:
3697 headless = ', '.join(b for b in branches - haveheads)
3696 headless = ', '.join(b for b in branches - haveheads)
3698 msg = _('no open branch heads found on branches %s')
3697 msg = _('no open branch heads found on branches %s')
3699 if opts.get('rev'):
3698 if opts.get('rev'):
3700 msg += _(' (started at %s)') % opts['rev']
3699 msg += _(' (started at %s)') % opts['rev']
3701 ui.warn((msg + '\n') % headless)
3700 ui.warn((msg + '\n') % headless)
3702
3701
3703 if not heads:
3702 if not heads:
3704 return 1
3703 return 1
3705
3704
3706 heads = sorted(heads, key=lambda x: -x.rev())
3705 heads = sorted(heads, key=lambda x: -x.rev())
3707 displayer = cmdutil.show_changeset(ui, repo, opts)
3706 displayer = cmdutil.show_changeset(ui, repo, opts)
3708 for ctx in heads:
3707 for ctx in heads:
3709 displayer.show(ctx)
3708 displayer.show(ctx)
3710 displayer.close()
3709 displayer.close()
3711
3710
3712 @command('help',
3711 @command('help',
3713 [('e', 'extension', None, _('show only help for extensions')),
3712 [('e', 'extension', None, _('show only help for extensions')),
3714 ('c', 'command', None, _('show only help for commands')),
3713 ('c', 'command', None, _('show only help for commands')),
3715 ('k', 'keyword', '', _('show topics matching keyword')),
3714 ('k', 'keyword', '', _('show topics matching keyword')),
3716 ],
3715 ],
3717 _('[-ec] [TOPIC]'),
3716 _('[-ec] [TOPIC]'),
3718 norepo=True)
3717 norepo=True)
3719 def help_(ui, name=None, **opts):
3718 def help_(ui, name=None, **opts):
3720 """show help for a given topic or a help overview
3719 """show help for a given topic or a help overview
3721
3720
3722 With no arguments, print a list of commands with short help messages.
3721 With no arguments, print a list of commands with short help messages.
3723
3722
3724 Given a topic, extension, or command name, print help for that
3723 Given a topic, extension, or command name, print help for that
3725 topic.
3724 topic.
3726
3725
3727 Returns 0 if successful.
3726 Returns 0 if successful.
3728 """
3727 """
3729
3728
3730 textwidth = min(ui.termwidth(), 80) - 2
3729 textwidth = min(ui.termwidth(), 80) - 2
3731
3730
3732 keep = ui.verbose and ['verbose'] or []
3731 keep = ui.verbose and ['verbose'] or []
3733 text = help.help_(ui, name, **opts)
3732 text = help.help_(ui, name, **opts)
3734
3733
3735 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3734 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3736 if 'verbose' in pruned:
3735 if 'verbose' in pruned:
3737 keep.append('omitted')
3736 keep.append('omitted')
3738 else:
3737 else:
3739 keep.append('notomitted')
3738 keep.append('notomitted')
3740 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3739 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3741 ui.write(formatted)
3740 ui.write(formatted)
3742
3741
3743
3742
3744 @command('identify|id',
3743 @command('identify|id',
3745 [('r', 'rev', '',
3744 [('r', 'rev', '',
3746 _('identify the specified revision'), _('REV')),
3745 _('identify the specified revision'), _('REV')),
3747 ('n', 'num', None, _('show local revision number')),
3746 ('n', 'num', None, _('show local revision number')),
3748 ('i', 'id', None, _('show global revision id')),
3747 ('i', 'id', None, _('show global revision id')),
3749 ('b', 'branch', None, _('show branch')),
3748 ('b', 'branch', None, _('show branch')),
3750 ('t', 'tags', None, _('show tags')),
3749 ('t', 'tags', None, _('show tags')),
3751 ('B', 'bookmarks', None, _('show bookmarks')),
3750 ('B', 'bookmarks', None, _('show bookmarks')),
3752 ] + remoteopts,
3751 ] + remoteopts,
3753 _('[-nibtB] [-r REV] [SOURCE]'),
3752 _('[-nibtB] [-r REV] [SOURCE]'),
3754 optionalrepo=True)
3753 optionalrepo=True)
3755 def identify(ui, repo, source=None, rev=None,
3754 def identify(ui, repo, source=None, rev=None,
3756 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3755 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3757 """identify the working copy or specified revision
3756 """identify the working copy or specified revision
3758
3757
3759 Print a summary identifying the repository state at REV using one or
3758 Print a summary identifying the repository state at REV using one or
3760 two parent hash identifiers, followed by a "+" if the working
3759 two parent hash identifiers, followed by a "+" if the working
3761 directory has uncommitted changes, the branch name (if not default),
3760 directory has uncommitted changes, the branch name (if not default),
3762 a list of tags, and a list of bookmarks.
3761 a list of tags, and a list of bookmarks.
3763
3762
3764 When REV is not given, print a summary of the current state of the
3763 When REV is not given, print a summary of the current state of the
3765 repository.
3764 repository.
3766
3765
3767 Specifying a path to a repository root or Mercurial bundle will
3766 Specifying a path to a repository root or Mercurial bundle will
3768 cause lookup to operate on that repository/bundle.
3767 cause lookup to operate on that repository/bundle.
3769
3768
3770 .. container:: verbose
3769 .. container:: verbose
3771
3770
3772 Examples:
3771 Examples:
3773
3772
3774 - generate a build identifier for the working directory::
3773 - generate a build identifier for the working directory::
3775
3774
3776 hg id --id > build-id.dat
3775 hg id --id > build-id.dat
3777
3776
3778 - find the revision corresponding to a tag::
3777 - find the revision corresponding to a tag::
3779
3778
3780 hg id -n -r 1.3
3779 hg id -n -r 1.3
3781
3780
3782 - check the most recent revision of a remote repository::
3781 - check the most recent revision of a remote repository::
3783
3782
3784 hg id -r tip http://selenic.com/hg/
3783 hg id -r tip http://selenic.com/hg/
3785
3784
3786 Returns 0 if successful.
3785 Returns 0 if successful.
3787 """
3786 """
3788
3787
3789 if not repo and not source:
3788 if not repo and not source:
3790 raise util.Abort(_("there is no Mercurial repository here "
3789 raise util.Abort(_("there is no Mercurial repository here "
3791 "(.hg not found)"))
3790 "(.hg not found)"))
3792
3791
3793 hexfunc = ui.debugflag and hex or short
3792 hexfunc = ui.debugflag and hex or short
3794 default = not (num or id or branch or tags or bookmarks)
3793 default = not (num or id or branch or tags or bookmarks)
3795 output = []
3794 output = []
3796 revs = []
3795 revs = []
3797
3796
3798 if source:
3797 if source:
3799 source, branches = hg.parseurl(ui.expandpath(source))
3798 source, branches = hg.parseurl(ui.expandpath(source))
3800 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3799 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3801 repo = peer.local()
3800 repo = peer.local()
3802 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3801 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3803
3802
3804 if not repo:
3803 if not repo:
3805 if num or branch or tags:
3804 if num or branch or tags:
3806 raise util.Abort(
3805 raise util.Abort(
3807 _("can't query remote revision number, branch, or tags"))
3806 _("can't query remote revision number, branch, or tags"))
3808 if not rev and revs:
3807 if not rev and revs:
3809 rev = revs[0]
3808 rev = revs[0]
3810 if not rev:
3809 if not rev:
3811 rev = "tip"
3810 rev = "tip"
3812
3811
3813 remoterev = peer.lookup(rev)
3812 remoterev = peer.lookup(rev)
3814 if default or id:
3813 if default or id:
3815 output = [hexfunc(remoterev)]
3814 output = [hexfunc(remoterev)]
3816
3815
3817 def getbms():
3816 def getbms():
3818 bms = []
3817 bms = []
3819
3818
3820 if 'bookmarks' in peer.listkeys('namespaces'):
3819 if 'bookmarks' in peer.listkeys('namespaces'):
3821 hexremoterev = hex(remoterev)
3820 hexremoterev = hex(remoterev)
3822 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3821 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3823 if bmr == hexremoterev]
3822 if bmr == hexremoterev]
3824
3823
3825 return sorted(bms)
3824 return sorted(bms)
3826
3825
3827 if bookmarks:
3826 if bookmarks:
3828 output.extend(getbms())
3827 output.extend(getbms())
3829 elif default and not ui.quiet:
3828 elif default and not ui.quiet:
3830 # multiple bookmarks for a single parent separated by '/'
3829 # multiple bookmarks for a single parent separated by '/'
3831 bm = '/'.join(getbms())
3830 bm = '/'.join(getbms())
3832 if bm:
3831 if bm:
3833 output.append(bm)
3832 output.append(bm)
3834 else:
3833 else:
3835 if not rev:
3834 if not rev:
3836 ctx = repo[None]
3835 ctx = repo[None]
3837 parents = ctx.parents()
3836 parents = ctx.parents()
3838 changed = ""
3837 changed = ""
3839 if default or id or num:
3838 if default or id or num:
3840 if (util.any(repo.status())
3839 if (util.any(repo.status())
3841 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3840 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3842 changed = '+'
3841 changed = '+'
3843 if default or id:
3842 if default or id:
3844 output = ["%s%s" %
3843 output = ["%s%s" %
3845 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3844 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3846 if num:
3845 if num:
3847 output.append("%s%s" %
3846 output.append("%s%s" %
3848 ('+'.join([str(p.rev()) for p in parents]), changed))
3847 ('+'.join([str(p.rev()) for p in parents]), changed))
3849 else:
3848 else:
3850 ctx = scmutil.revsingle(repo, rev)
3849 ctx = scmutil.revsingle(repo, rev)
3851 if default or id:
3850 if default or id:
3852 output = [hexfunc(ctx.node())]
3851 output = [hexfunc(ctx.node())]
3853 if num:
3852 if num:
3854 output.append(str(ctx.rev()))
3853 output.append(str(ctx.rev()))
3855
3854
3856 if default and not ui.quiet:
3855 if default and not ui.quiet:
3857 b = ctx.branch()
3856 b = ctx.branch()
3858 if b != 'default':
3857 if b != 'default':
3859 output.append("(%s)" % b)
3858 output.append("(%s)" % b)
3860
3859
3861 # multiple tags for a single parent separated by '/'
3860 # multiple tags for a single parent separated by '/'
3862 t = '/'.join(ctx.tags())
3861 t = '/'.join(ctx.tags())
3863 if t:
3862 if t:
3864 output.append(t)
3863 output.append(t)
3865
3864
3866 # multiple bookmarks for a single parent separated by '/'
3865 # multiple bookmarks for a single parent separated by '/'
3867 bm = '/'.join(ctx.bookmarks())
3866 bm = '/'.join(ctx.bookmarks())
3868 if bm:
3867 if bm:
3869 output.append(bm)
3868 output.append(bm)
3870 else:
3869 else:
3871 if branch:
3870 if branch:
3872 output.append(ctx.branch())
3871 output.append(ctx.branch())
3873
3872
3874 if tags:
3873 if tags:
3875 output.extend(ctx.tags())
3874 output.extend(ctx.tags())
3876
3875
3877 if bookmarks:
3876 if bookmarks:
3878 output.extend(ctx.bookmarks())
3877 output.extend(ctx.bookmarks())
3879
3878
3880 ui.write("%s\n" % ' '.join(output))
3879 ui.write("%s\n" % ' '.join(output))
3881
3880
3882 @command('import|patch',
3881 @command('import|patch',
3883 [('p', 'strip', 1,
3882 [('p', 'strip', 1,
3884 _('directory strip option for patch. This has the same '
3883 _('directory strip option for patch. This has the same '
3885 'meaning as the corresponding patch option'), _('NUM')),
3884 'meaning as the corresponding patch option'), _('NUM')),
3886 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3885 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3887 ('e', 'edit', False, _('invoke editor on commit messages')),
3886 ('e', 'edit', False, _('invoke editor on commit messages')),
3888 ('f', 'force', None,
3887 ('f', 'force', None,
3889 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3888 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3890 ('', 'no-commit', None,
3889 ('', 'no-commit', None,
3891 _("don't commit, just update the working directory")),
3890 _("don't commit, just update the working directory")),
3892 ('', 'bypass', None,
3891 ('', 'bypass', None,
3893 _("apply patch without touching the working directory")),
3892 _("apply patch without touching the working directory")),
3894 ('', 'partial', None,
3893 ('', 'partial', None,
3895 _('commit even if some hunks fail')),
3894 _('commit even if some hunks fail')),
3896 ('', 'exact', None,
3895 ('', 'exact', None,
3897 _('apply patch to the nodes from which it was generated')),
3896 _('apply patch to the nodes from which it was generated')),
3898 ('', 'import-branch', None,
3897 ('', 'import-branch', None,
3899 _('use any branch information in patch (implied by --exact)'))] +
3898 _('use any branch information in patch (implied by --exact)'))] +
3900 commitopts + commitopts2 + similarityopts,
3899 commitopts + commitopts2 + similarityopts,
3901 _('[OPTION]... PATCH...'))
3900 _('[OPTION]... PATCH...'))
3902 def import_(ui, repo, patch1=None, *patches, **opts):
3901 def import_(ui, repo, patch1=None, *patches, **opts):
3903 """import an ordered set of patches
3902 """import an ordered set of patches
3904
3903
3905 Import a list of patches and commit them individually (unless
3904 Import a list of patches and commit them individually (unless
3906 --no-commit is specified).
3905 --no-commit is specified).
3907
3906
3908 Because import first applies changes to the working directory,
3907 Because import first applies changes to the working directory,
3909 import will abort if there are outstanding changes.
3908 import will abort if there are outstanding changes.
3910
3909
3911 You can import a patch straight from a mail message. Even patches
3910 You can import a patch straight from a mail message. Even patches
3912 as attachments work (to use the body part, it must have type
3911 as attachments work (to use the body part, it must have type
3913 text/plain or text/x-patch). From and Subject headers of email
3912 text/plain or text/x-patch). From and Subject headers of email
3914 message are used as default committer and commit message. All
3913 message are used as default committer and commit message. All
3915 text/plain body parts before first diff are added to commit
3914 text/plain body parts before first diff are added to commit
3916 message.
3915 message.
3917
3916
3918 If the imported patch was generated by :hg:`export`, user and
3917 If the imported patch was generated by :hg:`export`, user and
3919 description from patch override values from message headers and
3918 description from patch override values from message headers and
3920 body. Values given on command line with -m/--message and -u/--user
3919 body. Values given on command line with -m/--message and -u/--user
3921 override these.
3920 override these.
3922
3921
3923 If --exact is specified, import will set the working directory to
3922 If --exact is specified, import will set the working directory to
3924 the parent of each patch before applying it, and will abort if the
3923 the parent of each patch before applying it, and will abort if the
3925 resulting changeset has a different ID than the one recorded in
3924 resulting changeset has a different ID than the one recorded in
3926 the patch. This may happen due to character set problems or other
3925 the patch. This may happen due to character set problems or other
3927 deficiencies in the text patch format.
3926 deficiencies in the text patch format.
3928
3927
3929 Use --bypass to apply and commit patches directly to the
3928 Use --bypass to apply and commit patches directly to the
3930 repository, not touching the working directory. Without --exact,
3929 repository, not touching the working directory. Without --exact,
3931 patches will be applied on top of the working directory parent
3930 patches will be applied on top of the working directory parent
3932 revision.
3931 revision.
3933
3932
3934 With -s/--similarity, hg will attempt to discover renames and
3933 With -s/--similarity, hg will attempt to discover renames and
3935 copies in the patch in the same way as :hg:`addremove`.
3934 copies in the patch in the same way as :hg:`addremove`.
3936
3935
3937 Use --partial to ensure a changeset will be created from the patch
3936 Use --partial to ensure a changeset will be created from the patch
3938 even if some hunks fail to apply. Hunks that fail to apply will be
3937 even if some hunks fail to apply. Hunks that fail to apply will be
3939 written to a <target-file>.rej file. Conflicts can then be resolved
3938 written to a <target-file>.rej file. Conflicts can then be resolved
3940 by hand before :hg:`commit --amend` is run to update the created
3939 by hand before :hg:`commit --amend` is run to update the created
3941 changeset. This flag exists to let people import patches that
3940 changeset. This flag exists to let people import patches that
3942 partially apply without losing the associated metadata (author,
3941 partially apply without losing the associated metadata (author,
3943 date, description, ...). Note that when none of the hunk applies
3942 date, description, ...). Note that when none of the hunk applies
3944 cleanly, :hg:`import --partial` will create an empty changeset,
3943 cleanly, :hg:`import --partial` will create an empty changeset,
3945 importing only the patch metadata.
3944 importing only the patch metadata.
3946
3945
3947 To read a patch from standard input, use "-" as the patch name. If
3946 To read a patch from standard input, use "-" as the patch name. If
3948 a URL is specified, the patch will be downloaded from it.
3947 a URL is specified, the patch will be downloaded from it.
3949 See :hg:`help dates` for a list of formats valid for -d/--date.
3948 See :hg:`help dates` for a list of formats valid for -d/--date.
3950
3949
3951 .. container:: verbose
3950 .. container:: verbose
3952
3951
3953 Examples:
3952 Examples:
3954
3953
3955 - import a traditional patch from a website and detect renames::
3954 - import a traditional patch from a website and detect renames::
3956
3955
3957 hg import -s 80 http://example.com/bugfix.patch
3956 hg import -s 80 http://example.com/bugfix.patch
3958
3957
3959 - import a changeset from an hgweb server::
3958 - import a changeset from an hgweb server::
3960
3959
3961 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3960 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3962
3961
3963 - import all the patches in an Unix-style mbox::
3962 - import all the patches in an Unix-style mbox::
3964
3963
3965 hg import incoming-patches.mbox
3964 hg import incoming-patches.mbox
3966
3965
3967 - attempt to exactly restore an exported changeset (not always
3966 - attempt to exactly restore an exported changeset (not always
3968 possible)::
3967 possible)::
3969
3968
3970 hg import --exact proposed-fix.patch
3969 hg import --exact proposed-fix.patch
3971
3970
3972 Returns 0 on success, 1 on partial success (see --partial).
3971 Returns 0 on success, 1 on partial success (see --partial).
3973 """
3972 """
3974
3973
3975 if not patch1:
3974 if not patch1:
3976 raise util.Abort(_('need at least one patch to import'))
3975 raise util.Abort(_('need at least one patch to import'))
3977
3976
3978 patches = (patch1,) + patches
3977 patches = (patch1,) + patches
3979
3978
3980 date = opts.get('date')
3979 date = opts.get('date')
3981 if date:
3980 if date:
3982 opts['date'] = util.parsedate(date)
3981 opts['date'] = util.parsedate(date)
3983
3982
3984 update = not opts.get('bypass')
3983 update = not opts.get('bypass')
3985 if not update and opts.get('no_commit'):
3984 if not update and opts.get('no_commit'):
3986 raise util.Abort(_('cannot use --no-commit with --bypass'))
3985 raise util.Abort(_('cannot use --no-commit with --bypass'))
3987 try:
3986 try:
3988 sim = float(opts.get('similarity') or 0)
3987 sim = float(opts.get('similarity') or 0)
3989 except ValueError:
3988 except ValueError:
3990 raise util.Abort(_('similarity must be a number'))
3989 raise util.Abort(_('similarity must be a number'))
3991 if sim < 0 or sim > 100:
3990 if sim < 0 or sim > 100:
3992 raise util.Abort(_('similarity must be between 0 and 100'))
3991 raise util.Abort(_('similarity must be between 0 and 100'))
3993 if sim and not update:
3992 if sim and not update:
3994 raise util.Abort(_('cannot use --similarity with --bypass'))
3993 raise util.Abort(_('cannot use --similarity with --bypass'))
3995 if opts.get('exact') and opts.get('edit'):
3994 if opts.get('exact') and opts.get('edit'):
3996 raise util.Abort(_('cannot use --exact with --edit'))
3995 raise util.Abort(_('cannot use --exact with --edit'))
3997
3996
3998 if update:
3997 if update:
3999 cmdutil.checkunfinished(repo)
3998 cmdutil.checkunfinished(repo)
4000 if (opts.get('exact') or not opts.get('force')) and update:
3999 if (opts.get('exact') or not opts.get('force')) and update:
4001 cmdutil.bailifchanged(repo)
4000 cmdutil.bailifchanged(repo)
4002
4001
4003 base = opts["base"]
4002 base = opts["base"]
4004 wlock = lock = tr = None
4003 wlock = lock = tr = None
4005 msgs = []
4004 msgs = []
4006 ret = 0
4005 ret = 0
4007
4006
4008
4007
4009 try:
4008 try:
4010 try:
4009 try:
4011 wlock = repo.wlock()
4010 wlock = repo.wlock()
4012 repo.dirstate.beginparentchange()
4011 repo.dirstate.beginparentchange()
4013 if not opts.get('no_commit'):
4012 if not opts.get('no_commit'):
4014 lock = repo.lock()
4013 lock = repo.lock()
4015 tr = repo.transaction('import')
4014 tr = repo.transaction('import')
4016 parents = repo.parents()
4015 parents = repo.parents()
4017 for patchurl in patches:
4016 for patchurl in patches:
4018 if patchurl == '-':
4017 if patchurl == '-':
4019 ui.status(_('applying patch from stdin\n'))
4018 ui.status(_('applying patch from stdin\n'))
4020 patchfile = ui.fin
4019 patchfile = ui.fin
4021 patchurl = 'stdin' # for error message
4020 patchurl = 'stdin' # for error message
4022 else:
4021 else:
4023 patchurl = os.path.join(base, patchurl)
4022 patchurl = os.path.join(base, patchurl)
4024 ui.status(_('applying %s\n') % patchurl)
4023 ui.status(_('applying %s\n') % patchurl)
4025 patchfile = hg.openpath(ui, patchurl)
4024 patchfile = hg.openpath(ui, patchurl)
4026
4025
4027 haspatch = False
4026 haspatch = False
4028 for hunk in patch.split(patchfile):
4027 for hunk in patch.split(patchfile):
4029 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4028 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4030 parents, opts,
4029 parents, opts,
4031 msgs, hg.clean)
4030 msgs, hg.clean)
4032 if msg:
4031 if msg:
4033 haspatch = True
4032 haspatch = True
4034 ui.note(msg + '\n')
4033 ui.note(msg + '\n')
4035 if update or opts.get('exact'):
4034 if update or opts.get('exact'):
4036 parents = repo.parents()
4035 parents = repo.parents()
4037 else:
4036 else:
4038 parents = [repo[node]]
4037 parents = [repo[node]]
4039 if rej:
4038 if rej:
4040 ui.write_err(_("patch applied partially\n"))
4039 ui.write_err(_("patch applied partially\n"))
4041 ui.write_err(_("(fix the .rej files and run "
4040 ui.write_err(_("(fix the .rej files and run "
4042 "`hg commit --amend`)\n"))
4041 "`hg commit --amend`)\n"))
4043 ret = 1
4042 ret = 1
4044 break
4043 break
4045
4044
4046 if not haspatch:
4045 if not haspatch:
4047 raise util.Abort(_('%s: no diffs found') % patchurl)
4046 raise util.Abort(_('%s: no diffs found') % patchurl)
4048
4047
4049 if tr:
4048 if tr:
4050 tr.close()
4049 tr.close()
4051 if msgs:
4050 if msgs:
4052 repo.savecommitmessage('\n* * *\n'.join(msgs))
4051 repo.savecommitmessage('\n* * *\n'.join(msgs))
4053 repo.dirstate.endparentchange()
4052 repo.dirstate.endparentchange()
4054 return ret
4053 return ret
4055 except: # re-raises
4054 except: # re-raises
4056 # wlock.release() indirectly calls dirstate.write(): since
4055 # wlock.release() indirectly calls dirstate.write(): since
4057 # we're crashing, we do not want to change the working dir
4056 # we're crashing, we do not want to change the working dir
4058 # parent after all, so make sure it writes nothing
4057 # parent after all, so make sure it writes nothing
4059 repo.dirstate.invalidate()
4058 repo.dirstate.invalidate()
4060 raise
4059 raise
4061 finally:
4060 finally:
4062 if tr:
4061 if tr:
4063 tr.release()
4062 tr.release()
4064 release(lock, wlock)
4063 release(lock, wlock)
4065
4064
4066 @command('incoming|in',
4065 @command('incoming|in',
4067 [('f', 'force', None,
4066 [('f', 'force', None,
4068 _('run even if remote repository is unrelated')),
4067 _('run even if remote repository is unrelated')),
4069 ('n', 'newest-first', None, _('show newest record first')),
4068 ('n', 'newest-first', None, _('show newest record first')),
4070 ('', 'bundle', '',
4069 ('', 'bundle', '',
4071 _('file to store the bundles into'), _('FILE')),
4070 _('file to store the bundles into'), _('FILE')),
4072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4071 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4073 ('B', 'bookmarks', False, _("compare bookmarks")),
4072 ('B', 'bookmarks', False, _("compare bookmarks")),
4074 ('b', 'branch', [],
4073 ('b', 'branch', [],
4075 _('a specific branch you would like to pull'), _('BRANCH')),
4074 _('a specific branch you would like to pull'), _('BRANCH')),
4076 ] + logopts + remoteopts + subrepoopts,
4075 ] + logopts + remoteopts + subrepoopts,
4077 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4076 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4078 def incoming(ui, repo, source="default", **opts):
4077 def incoming(ui, repo, source="default", **opts):
4079 """show new changesets found in source
4078 """show new changesets found in source
4080
4079
4081 Show new changesets found in the specified path/URL or the default
4080 Show new changesets found in the specified path/URL or the default
4082 pull location. These are the changesets that would have been pulled
4081 pull location. These are the changesets that would have been pulled
4083 if a pull at the time you issued this command.
4082 if a pull at the time you issued this command.
4084
4083
4085 For remote repository, using --bundle avoids downloading the
4084 For remote repository, using --bundle avoids downloading the
4086 changesets twice if the incoming is followed by a pull.
4085 changesets twice if the incoming is followed by a pull.
4087
4086
4088 See pull for valid source format details.
4087 See pull for valid source format details.
4089
4088
4090 .. container:: verbose
4089 .. container:: verbose
4091
4090
4092 Examples:
4091 Examples:
4093
4092
4094 - show incoming changes with patches and full description::
4093 - show incoming changes with patches and full description::
4095
4094
4096 hg incoming -vp
4095 hg incoming -vp
4097
4096
4098 - show incoming changes excluding merges, store a bundle::
4097 - show incoming changes excluding merges, store a bundle::
4099
4098
4100 hg in -vpM --bundle incoming.hg
4099 hg in -vpM --bundle incoming.hg
4101 hg pull incoming.hg
4100 hg pull incoming.hg
4102
4101
4103 - briefly list changes inside a bundle::
4102 - briefly list changes inside a bundle::
4104
4103
4105 hg in changes.hg -T "{desc|firstline}\\n"
4104 hg in changes.hg -T "{desc|firstline}\\n"
4106
4105
4107 Returns 0 if there are incoming changes, 1 otherwise.
4106 Returns 0 if there are incoming changes, 1 otherwise.
4108 """
4107 """
4109 if opts.get('graph'):
4108 if opts.get('graph'):
4110 cmdutil.checkunsupportedgraphflags([], opts)
4109 cmdutil.checkunsupportedgraphflags([], opts)
4111 def display(other, chlist, displayer):
4110 def display(other, chlist, displayer):
4112 revdag = cmdutil.graphrevs(other, chlist, opts)
4111 revdag = cmdutil.graphrevs(other, chlist, opts)
4113 showparents = [ctx.node() for ctx in repo[None].parents()]
4112 showparents = [ctx.node() for ctx in repo[None].parents()]
4114 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4113 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4115 graphmod.asciiedges)
4114 graphmod.asciiedges)
4116
4115
4117 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4116 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4118 return 0
4117 return 0
4119
4118
4120 if opts.get('bundle') and opts.get('subrepos'):
4119 if opts.get('bundle') and opts.get('subrepos'):
4121 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4120 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4122
4121
4123 if opts.get('bookmarks'):
4122 if opts.get('bookmarks'):
4124 source, branches = hg.parseurl(ui.expandpath(source),
4123 source, branches = hg.parseurl(ui.expandpath(source),
4125 opts.get('branch'))
4124 opts.get('branch'))
4126 other = hg.peer(repo, opts, source)
4125 other = hg.peer(repo, opts, source)
4127 if 'bookmarks' not in other.listkeys('namespaces'):
4126 if 'bookmarks' not in other.listkeys('namespaces'):
4128 ui.warn(_("remote doesn't support bookmarks\n"))
4127 ui.warn(_("remote doesn't support bookmarks\n"))
4129 return 0
4128 return 0
4130 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4129 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4131 return bookmarks.diff(ui, repo, other)
4130 return bookmarks.diff(ui, repo, other)
4132
4131
4133 repo._subtoppath = ui.expandpath(source)
4132 repo._subtoppath = ui.expandpath(source)
4134 try:
4133 try:
4135 return hg.incoming(ui, repo, source, opts)
4134 return hg.incoming(ui, repo, source, opts)
4136 finally:
4135 finally:
4137 del repo._subtoppath
4136 del repo._subtoppath
4138
4137
4139
4138
4140 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4139 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4141 norepo=True)
4140 norepo=True)
4142 def init(ui, dest=".", **opts):
4141 def init(ui, dest=".", **opts):
4143 """create a new repository in the given directory
4142 """create a new repository in the given directory
4144
4143
4145 Initialize a new repository in the given directory. If the given
4144 Initialize a new repository in the given directory. If the given
4146 directory does not exist, it will be created.
4145 directory does not exist, it will be created.
4147
4146
4148 If no directory is given, the current directory is used.
4147 If no directory is given, the current directory is used.
4149
4148
4150 It is possible to specify an ``ssh://`` URL as the destination.
4149 It is possible to specify an ``ssh://`` URL as the destination.
4151 See :hg:`help urls` for more information.
4150 See :hg:`help urls` for more information.
4152
4151
4153 Returns 0 on success.
4152 Returns 0 on success.
4154 """
4153 """
4155 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4154 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4156
4155
4157 @command('locate',
4156 @command('locate',
4158 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4157 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4159 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4158 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4160 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4159 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4161 ] + walkopts,
4160 ] + walkopts,
4162 _('[OPTION]... [PATTERN]...'))
4161 _('[OPTION]... [PATTERN]...'))
4163 def locate(ui, repo, *pats, **opts):
4162 def locate(ui, repo, *pats, **opts):
4164 """locate files matching specific patterns (DEPRECATED)
4163 """locate files matching specific patterns (DEPRECATED)
4165
4164
4166 Print files under Mercurial control in the working directory whose
4165 Print files under Mercurial control in the working directory whose
4167 names match the given patterns.
4166 names match the given patterns.
4168
4167
4169 By default, this command searches all directories in the working
4168 By default, this command searches all directories in the working
4170 directory. To search just the current directory and its
4169 directory. To search just the current directory and its
4171 subdirectories, use "--include .".
4170 subdirectories, use "--include .".
4172
4171
4173 If no patterns are given to match, this command prints the names
4172 If no patterns are given to match, this command prints the names
4174 of all files under Mercurial control in the working directory.
4173 of all files under Mercurial control in the working directory.
4175
4174
4176 If you want to feed the output of this command into the "xargs"
4175 If you want to feed the output of this command into the "xargs"
4177 command, use the -0 option to both this command and "xargs". This
4176 command, use the -0 option to both this command and "xargs". This
4178 will avoid the problem of "xargs" treating single filenames that
4177 will avoid the problem of "xargs" treating single filenames that
4179 contain whitespace as multiple filenames.
4178 contain whitespace as multiple filenames.
4180
4179
4181 See :hg:`help files` for a more versatile command.
4180 See :hg:`help files` for a more versatile command.
4182
4181
4183 Returns 0 if a match is found, 1 otherwise.
4182 Returns 0 if a match is found, 1 otherwise.
4184 """
4183 """
4185 end = opts.get('print0') and '\0' or '\n'
4184 end = opts.get('print0') and '\0' or '\n'
4186 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4185 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4187
4186
4188 ret = 1
4187 ret = 1
4189 ctx = repo[rev]
4188 ctx = repo[rev]
4190 m = scmutil.match(ctx, pats, opts, default='relglob')
4189 m = scmutil.match(ctx, pats, opts, default='relglob')
4191 m.bad = lambda x, y: False
4190 m.bad = lambda x, y: False
4192
4191
4193 for abs in ctx.matches(m):
4192 for abs in ctx.matches(m):
4194 if opts.get('fullpath'):
4193 if opts.get('fullpath'):
4195 ui.write(repo.wjoin(abs), end)
4194 ui.write(repo.wjoin(abs), end)
4196 else:
4195 else:
4197 ui.write(((pats and m.rel(abs)) or abs), end)
4196 ui.write(((pats and m.rel(abs)) or abs), end)
4198 ret = 0
4197 ret = 0
4199
4198
4200 return ret
4199 return ret
4201
4200
4202 @command('^log|history',
4201 @command('^log|history',
4203 [('f', 'follow', None,
4202 [('f', 'follow', None,
4204 _('follow changeset history, or file history across copies and renames')),
4203 _('follow changeset history, or file history across copies and renames')),
4205 ('', 'follow-first', None,
4204 ('', 'follow-first', None,
4206 _('only follow the first parent of merge changesets (DEPRECATED)')),
4205 _('only follow the first parent of merge changesets (DEPRECATED)')),
4207 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4206 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4208 ('C', 'copies', None, _('show copied files')),
4207 ('C', 'copies', None, _('show copied files')),
4209 ('k', 'keyword', [],
4208 ('k', 'keyword', [],
4210 _('do case-insensitive search for a given text'), _('TEXT')),
4209 _('do case-insensitive search for a given text'), _('TEXT')),
4211 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4210 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4212 ('', 'removed', None, _('include revisions where files were removed')),
4211 ('', 'removed', None, _('include revisions where files were removed')),
4213 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4212 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4214 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4213 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4215 ('', 'only-branch', [],
4214 ('', 'only-branch', [],
4216 _('show only changesets within the given named branch (DEPRECATED)'),
4215 _('show only changesets within the given named branch (DEPRECATED)'),
4217 _('BRANCH')),
4216 _('BRANCH')),
4218 ('b', 'branch', [],
4217 ('b', 'branch', [],
4219 _('show changesets within the given named branch'), _('BRANCH')),
4218 _('show changesets within the given named branch'), _('BRANCH')),
4220 ('P', 'prune', [],
4219 ('P', 'prune', [],
4221 _('do not display revision or any of its ancestors'), _('REV')),
4220 _('do not display revision or any of its ancestors'), _('REV')),
4222 ] + logopts + walkopts,
4221 ] + logopts + walkopts,
4223 _('[OPTION]... [FILE]'),
4222 _('[OPTION]... [FILE]'),
4224 inferrepo=True)
4223 inferrepo=True)
4225 def log(ui, repo, *pats, **opts):
4224 def log(ui, repo, *pats, **opts):
4226 """show revision history of entire repository or files
4225 """show revision history of entire repository or files
4227
4226
4228 Print the revision history of the specified files or the entire
4227 Print the revision history of the specified files or the entire
4229 project.
4228 project.
4230
4229
4231 If no revision range is specified, the default is ``tip:0`` unless
4230 If no revision range is specified, the default is ``tip:0`` unless
4232 --follow is set, in which case the working directory parent is
4231 --follow is set, in which case the working directory parent is
4233 used as the starting revision.
4232 used as the starting revision.
4234
4233
4235 File history is shown without following rename or copy history of
4234 File history is shown without following rename or copy history of
4236 files. Use -f/--follow with a filename to follow history across
4235 files. Use -f/--follow with a filename to follow history across
4237 renames and copies. --follow without a filename will only show
4236 renames and copies. --follow without a filename will only show
4238 ancestors or descendants of the starting revision.
4237 ancestors or descendants of the starting revision.
4239
4238
4240 By default this command prints revision number and changeset id,
4239 By default this command prints revision number and changeset id,
4241 tags, non-trivial parents, user, date and time, and a summary for
4240 tags, non-trivial parents, user, date and time, and a summary for
4242 each commit. When the -v/--verbose switch is used, the list of
4241 each commit. When the -v/--verbose switch is used, the list of
4243 changed files and full commit message are shown.
4242 changed files and full commit message are shown.
4244
4243
4245 With --graph the revisions are shown as an ASCII art DAG with the most
4244 With --graph the revisions are shown as an ASCII art DAG with the most
4246 recent changeset at the top.
4245 recent changeset at the top.
4247 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4246 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4248 and '+' represents a fork where the changeset from the lines below is a
4247 and '+' represents a fork where the changeset from the lines below is a
4249 parent of the 'o' merge on the same line.
4248 parent of the 'o' merge on the same line.
4250
4249
4251 .. note::
4250 .. note::
4252
4251
4253 log -p/--patch may generate unexpected diff output for merge
4252 log -p/--patch may generate unexpected diff output for merge
4254 changesets, as it will only compare the merge changeset against
4253 changesets, as it will only compare the merge changeset against
4255 its first parent. Also, only files different from BOTH parents
4254 its first parent. Also, only files different from BOTH parents
4256 will appear in files:.
4255 will appear in files:.
4257
4256
4258 .. note::
4257 .. note::
4259
4258
4260 for performance reasons, log FILE may omit duplicate changes
4259 for performance reasons, log FILE may omit duplicate changes
4261 made on branches and will not show deletions. To see all
4260 made on branches and will not show deletions. To see all
4262 changes including duplicates and deletions, use the --removed
4261 changes including duplicates and deletions, use the --removed
4263 switch.
4262 switch.
4264
4263
4265 .. container:: verbose
4264 .. container:: verbose
4266
4265
4267 Some examples:
4266 Some examples:
4268
4267
4269 - changesets with full descriptions and file lists::
4268 - changesets with full descriptions and file lists::
4270
4269
4271 hg log -v
4270 hg log -v
4272
4271
4273 - changesets ancestral to the working directory::
4272 - changesets ancestral to the working directory::
4274
4273
4275 hg log -f
4274 hg log -f
4276
4275
4277 - last 10 commits on the current branch::
4276 - last 10 commits on the current branch::
4278
4277
4279 hg log -l 10 -b .
4278 hg log -l 10 -b .
4280
4279
4281 - changesets showing all modifications of a file, including removals::
4280 - changesets showing all modifications of a file, including removals::
4282
4281
4283 hg log --removed file.c
4282 hg log --removed file.c
4284
4283
4285 - all changesets that touch a directory, with diffs, excluding merges::
4284 - all changesets that touch a directory, with diffs, excluding merges::
4286
4285
4287 hg log -Mp lib/
4286 hg log -Mp lib/
4288
4287
4289 - all revision numbers that match a keyword::
4288 - all revision numbers that match a keyword::
4290
4289
4291 hg log -k bug --template "{rev}\\n"
4290 hg log -k bug --template "{rev}\\n"
4292
4291
4293 - list available log templates::
4292 - list available log templates::
4294
4293
4295 hg log -T list
4294 hg log -T list
4296
4295
4297 - check if a given changeset is included is a tagged release::
4296 - check if a given changeset is included is a tagged release::
4298
4297
4299 hg log -r "a21ccf and ancestor(1.9)"
4298 hg log -r "a21ccf and ancestor(1.9)"
4300
4299
4301 - find all changesets by some user in a date range::
4300 - find all changesets by some user in a date range::
4302
4301
4303 hg log -k alice -d "may 2008 to jul 2008"
4302 hg log -k alice -d "may 2008 to jul 2008"
4304
4303
4305 - summary of all changesets after the last tag::
4304 - summary of all changesets after the last tag::
4306
4305
4307 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4306 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4308
4307
4309 See :hg:`help dates` for a list of formats valid for -d/--date.
4308 See :hg:`help dates` for a list of formats valid for -d/--date.
4310
4309
4311 See :hg:`help revisions` and :hg:`help revsets` for more about
4310 See :hg:`help revisions` and :hg:`help revsets` for more about
4312 specifying revisions.
4311 specifying revisions.
4313
4312
4314 See :hg:`help templates` for more about pre-packaged styles and
4313 See :hg:`help templates` for more about pre-packaged styles and
4315 specifying custom templates.
4314 specifying custom templates.
4316
4315
4317 Returns 0 on success.
4316 Returns 0 on success.
4318 """
4317 """
4319 if opts.get('graph'):
4318 if opts.get('graph'):
4320 return cmdutil.graphlog(ui, repo, *pats, **opts)
4319 return cmdutil.graphlog(ui, repo, *pats, **opts)
4321
4320
4322 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4321 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4323 limit = cmdutil.loglimit(opts)
4322 limit = cmdutil.loglimit(opts)
4324 count = 0
4323 count = 0
4325
4324
4326 getrenamed = None
4325 getrenamed = None
4327 if opts.get('copies'):
4326 if opts.get('copies'):
4328 endrev = None
4327 endrev = None
4329 if opts.get('rev'):
4328 if opts.get('rev'):
4330 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4329 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4331 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4330 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4332
4331
4333 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4332 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4334 for rev in revs:
4333 for rev in revs:
4335 if count == limit:
4334 if count == limit:
4336 break
4335 break
4337 ctx = repo[rev]
4336 ctx = repo[rev]
4338 copies = None
4337 copies = None
4339 if getrenamed is not None and rev:
4338 if getrenamed is not None and rev:
4340 copies = []
4339 copies = []
4341 for fn in ctx.files():
4340 for fn in ctx.files():
4342 rename = getrenamed(fn, rev)
4341 rename = getrenamed(fn, rev)
4343 if rename:
4342 if rename:
4344 copies.append((fn, rename[0]))
4343 copies.append((fn, rename[0]))
4345 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4344 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4346 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4345 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4347 if displayer.flush(rev):
4346 if displayer.flush(rev):
4348 count += 1
4347 count += 1
4349
4348
4350 displayer.close()
4349 displayer.close()
4351
4350
4352 @command('manifest',
4351 @command('manifest',
4353 [('r', 'rev', '', _('revision to display'), _('REV')),
4352 [('r', 'rev', '', _('revision to display'), _('REV')),
4354 ('', 'all', False, _("list files from all revisions"))]
4353 ('', 'all', False, _("list files from all revisions"))]
4355 + formatteropts,
4354 + formatteropts,
4356 _('[-r REV]'))
4355 _('[-r REV]'))
4357 def manifest(ui, repo, node=None, rev=None, **opts):
4356 def manifest(ui, repo, node=None, rev=None, **opts):
4358 """output the current or given revision of the project manifest
4357 """output the current or given revision of the project manifest
4359
4358
4360 Print a list of version controlled files for the given revision.
4359 Print a list of version controlled files for the given revision.
4361 If no revision is given, the first parent of the working directory
4360 If no revision is given, the first parent of the working directory
4362 is used, or the null revision if no revision is checked out.
4361 is used, or the null revision if no revision is checked out.
4363
4362
4364 With -v, print file permissions, symlink and executable bits.
4363 With -v, print file permissions, symlink and executable bits.
4365 With --debug, print file revision hashes.
4364 With --debug, print file revision hashes.
4366
4365
4367 If option --all is specified, the list of all files from all revisions
4366 If option --all is specified, the list of all files from all revisions
4368 is printed. This includes deleted and renamed files.
4367 is printed. This includes deleted and renamed files.
4369
4368
4370 Returns 0 on success.
4369 Returns 0 on success.
4371 """
4370 """
4372
4371
4373 fm = ui.formatter('manifest', opts)
4372 fm = ui.formatter('manifest', opts)
4374
4373
4375 if opts.get('all'):
4374 if opts.get('all'):
4376 if rev or node:
4375 if rev or node:
4377 raise util.Abort(_("can't specify a revision with --all"))
4376 raise util.Abort(_("can't specify a revision with --all"))
4378
4377
4379 res = []
4378 res = []
4380 prefix = "data/"
4379 prefix = "data/"
4381 suffix = ".i"
4380 suffix = ".i"
4382 plen = len(prefix)
4381 plen = len(prefix)
4383 slen = len(suffix)
4382 slen = len(suffix)
4384 lock = repo.lock()
4383 lock = repo.lock()
4385 try:
4384 try:
4386 for fn, b, size in repo.store.datafiles():
4385 for fn, b, size in repo.store.datafiles():
4387 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4386 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4388 res.append(fn[plen:-slen])
4387 res.append(fn[plen:-slen])
4389 finally:
4388 finally:
4390 lock.release()
4389 lock.release()
4391 for f in res:
4390 for f in res:
4392 fm.startitem()
4391 fm.startitem()
4393 fm.write("path", '%s\n', f)
4392 fm.write("path", '%s\n', f)
4394 fm.end()
4393 fm.end()
4395 return
4394 return
4396
4395
4397 if rev and node:
4396 if rev and node:
4398 raise util.Abort(_("please specify just one revision"))
4397 raise util.Abort(_("please specify just one revision"))
4399
4398
4400 if not node:
4399 if not node:
4401 node = rev
4400 node = rev
4402
4401
4403 char = {'l': '@', 'x': '*', '': ''}
4402 char = {'l': '@', 'x': '*', '': ''}
4404 mode = {'l': '644', 'x': '755', '': '644'}
4403 mode = {'l': '644', 'x': '755', '': '644'}
4405 ctx = scmutil.revsingle(repo, node)
4404 ctx = scmutil.revsingle(repo, node)
4406 mf = ctx.manifest()
4405 mf = ctx.manifest()
4407 for f in ctx:
4406 for f in ctx:
4408 fm.startitem()
4407 fm.startitem()
4409 fl = ctx[f].flags()
4408 fl = ctx[f].flags()
4410 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4409 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4411 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4410 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4412 fm.write('path', '%s\n', f)
4411 fm.write('path', '%s\n', f)
4413 fm.end()
4412 fm.end()
4414
4413
4415 @command('^merge',
4414 @command('^merge',
4416 [('f', 'force', None,
4415 [('f', 'force', None,
4417 _('force a merge including outstanding changes (DEPRECATED)')),
4416 _('force a merge including outstanding changes (DEPRECATED)')),
4418 ('r', 'rev', '', _('revision to merge'), _('REV')),
4417 ('r', 'rev', '', _('revision to merge'), _('REV')),
4419 ('P', 'preview', None,
4418 ('P', 'preview', None,
4420 _('review revisions to merge (no merge is performed)'))
4419 _('review revisions to merge (no merge is performed)'))
4421 ] + mergetoolopts,
4420 ] + mergetoolopts,
4422 _('[-P] [-f] [[-r] REV]'))
4421 _('[-P] [-f] [[-r] REV]'))
4423 def merge(ui, repo, node=None, **opts):
4422 def merge(ui, repo, node=None, **opts):
4424 """merge working directory with another revision
4423 """merge working directory with another revision
4425
4424
4426 The current working directory is updated with all changes made in
4425 The current working directory is updated with all changes made in
4427 the requested revision since the last common predecessor revision.
4426 the requested revision since the last common predecessor revision.
4428
4427
4429 Files that changed between either parent are marked as changed for
4428 Files that changed between either parent are marked as changed for
4430 the next commit and a commit must be performed before any further
4429 the next commit and a commit must be performed before any further
4431 updates to the repository are allowed. The next commit will have
4430 updates to the repository are allowed. The next commit will have
4432 two parents.
4431 two parents.
4433
4432
4434 ``--tool`` can be used to specify the merge tool used for file
4433 ``--tool`` can be used to specify the merge tool used for file
4435 merges. It overrides the HGMERGE environment variable and your
4434 merges. It overrides the HGMERGE environment variable and your
4436 configuration files. See :hg:`help merge-tools` for options.
4435 configuration files. See :hg:`help merge-tools` for options.
4437
4436
4438 If no revision is specified, the working directory's parent is a
4437 If no revision is specified, the working directory's parent is a
4439 head revision, and the current branch contains exactly one other
4438 head revision, and the current branch contains exactly one other
4440 head, the other head is merged with by default. Otherwise, an
4439 head, the other head is merged with by default. Otherwise, an
4441 explicit revision with which to merge with must be provided.
4440 explicit revision with which to merge with must be provided.
4442
4441
4443 :hg:`resolve` must be used to resolve unresolved files.
4442 :hg:`resolve` must be used to resolve unresolved files.
4444
4443
4445 To undo an uncommitted merge, use :hg:`update --clean .` which
4444 To undo an uncommitted merge, use :hg:`update --clean .` which
4446 will check out a clean copy of the original merge parent, losing
4445 will check out a clean copy of the original merge parent, losing
4447 all changes.
4446 all changes.
4448
4447
4449 Returns 0 on success, 1 if there are unresolved files.
4448 Returns 0 on success, 1 if there are unresolved files.
4450 """
4449 """
4451
4450
4452 if opts.get('rev') and node:
4451 if opts.get('rev') and node:
4453 raise util.Abort(_("please specify just one revision"))
4452 raise util.Abort(_("please specify just one revision"))
4454 if not node:
4453 if not node:
4455 node = opts.get('rev')
4454 node = opts.get('rev')
4456
4455
4457 if node:
4456 if node:
4458 node = scmutil.revsingle(repo, node).node()
4457 node = scmutil.revsingle(repo, node).node()
4459
4458
4460 if not node and repo._bookmarkcurrent:
4459 if not node and repo._bookmarkcurrent:
4461 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4460 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4462 curhead = repo[repo._bookmarkcurrent].node()
4461 curhead = repo[repo._bookmarkcurrent].node()
4463 if len(bmheads) == 2:
4462 if len(bmheads) == 2:
4464 if curhead == bmheads[0]:
4463 if curhead == bmheads[0]:
4465 node = bmheads[1]
4464 node = bmheads[1]
4466 else:
4465 else:
4467 node = bmheads[0]
4466 node = bmheads[0]
4468 elif len(bmheads) > 2:
4467 elif len(bmheads) > 2:
4469 raise util.Abort(_("multiple matching bookmarks to merge - "
4468 raise util.Abort(_("multiple matching bookmarks to merge - "
4470 "please merge with an explicit rev or bookmark"),
4469 "please merge with an explicit rev or bookmark"),
4471 hint=_("run 'hg heads' to see all heads"))
4470 hint=_("run 'hg heads' to see all heads"))
4472 elif len(bmheads) <= 1:
4471 elif len(bmheads) <= 1:
4473 raise util.Abort(_("no matching bookmark to merge - "
4472 raise util.Abort(_("no matching bookmark to merge - "
4474 "please merge with an explicit rev or bookmark"),
4473 "please merge with an explicit rev or bookmark"),
4475 hint=_("run 'hg heads' to see all heads"))
4474 hint=_("run 'hg heads' to see all heads"))
4476
4475
4477 if not node and not repo._bookmarkcurrent:
4476 if not node and not repo._bookmarkcurrent:
4478 branch = repo[None].branch()
4477 branch = repo[None].branch()
4479 bheads = repo.branchheads(branch)
4478 bheads = repo.branchheads(branch)
4480 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4479 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4481
4480
4482 if len(nbhs) > 2:
4481 if len(nbhs) > 2:
4483 raise util.Abort(_("branch '%s' has %d heads - "
4482 raise util.Abort(_("branch '%s' has %d heads - "
4484 "please merge with an explicit rev")
4483 "please merge with an explicit rev")
4485 % (branch, len(bheads)),
4484 % (branch, len(bheads)),
4486 hint=_("run 'hg heads .' to see heads"))
4485 hint=_("run 'hg heads .' to see heads"))
4487
4486
4488 parent = repo.dirstate.p1()
4487 parent = repo.dirstate.p1()
4489 if len(nbhs) <= 1:
4488 if len(nbhs) <= 1:
4490 if len(bheads) > 1:
4489 if len(bheads) > 1:
4491 raise util.Abort(_("heads are bookmarked - "
4490 raise util.Abort(_("heads are bookmarked - "
4492 "please merge with an explicit rev"),
4491 "please merge with an explicit rev"),
4493 hint=_("run 'hg heads' to see all heads"))
4492 hint=_("run 'hg heads' to see all heads"))
4494 if len(repo.heads()) > 1:
4493 if len(repo.heads()) > 1:
4495 raise util.Abort(_("branch '%s' has one head - "
4494 raise util.Abort(_("branch '%s' has one head - "
4496 "please merge with an explicit rev")
4495 "please merge with an explicit rev")
4497 % branch,
4496 % branch,
4498 hint=_("run 'hg heads' to see all heads"))
4497 hint=_("run 'hg heads' to see all heads"))
4499 msg, hint = _('nothing to merge'), None
4498 msg, hint = _('nothing to merge'), None
4500 if parent != repo.lookup(branch):
4499 if parent != repo.lookup(branch):
4501 hint = _("use 'hg update' instead")
4500 hint = _("use 'hg update' instead")
4502 raise util.Abort(msg, hint=hint)
4501 raise util.Abort(msg, hint=hint)
4503
4502
4504 if parent not in bheads:
4503 if parent not in bheads:
4505 raise util.Abort(_('working directory not at a head revision'),
4504 raise util.Abort(_('working directory not at a head revision'),
4506 hint=_("use 'hg update' or merge with an "
4505 hint=_("use 'hg update' or merge with an "
4507 "explicit revision"))
4506 "explicit revision"))
4508 if parent == nbhs[0]:
4507 if parent == nbhs[0]:
4509 node = nbhs[-1]
4508 node = nbhs[-1]
4510 else:
4509 else:
4511 node = nbhs[0]
4510 node = nbhs[0]
4512
4511
4513 if opts.get('preview'):
4512 if opts.get('preview'):
4514 # find nodes that are ancestors of p2 but not of p1
4513 # find nodes that are ancestors of p2 but not of p1
4515 p1 = repo.lookup('.')
4514 p1 = repo.lookup('.')
4516 p2 = repo.lookup(node)
4515 p2 = repo.lookup(node)
4517 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4516 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4518
4517
4519 displayer = cmdutil.show_changeset(ui, repo, opts)
4518 displayer = cmdutil.show_changeset(ui, repo, opts)
4520 for node in nodes:
4519 for node in nodes:
4521 displayer.show(repo[node])
4520 displayer.show(repo[node])
4522 displayer.close()
4521 displayer.close()
4523 return 0
4522 return 0
4524
4523
4525 try:
4524 try:
4526 # ui.forcemerge is an internal variable, do not document
4525 # ui.forcemerge is an internal variable, do not document
4527 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4526 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4528 return hg.merge(repo, node, force=opts.get('force'))
4527 return hg.merge(repo, node, force=opts.get('force'))
4529 finally:
4528 finally:
4530 ui.setconfig('ui', 'forcemerge', '', 'merge')
4529 ui.setconfig('ui', 'forcemerge', '', 'merge')
4531
4530
4532 @command('outgoing|out',
4531 @command('outgoing|out',
4533 [('f', 'force', None, _('run even when the destination is unrelated')),
4532 [('f', 'force', None, _('run even when the destination is unrelated')),
4534 ('r', 'rev', [],
4533 ('r', 'rev', [],
4535 _('a changeset intended to be included in the destination'), _('REV')),
4534 _('a changeset intended to be included in the destination'), _('REV')),
4536 ('n', 'newest-first', None, _('show newest record first')),
4535 ('n', 'newest-first', None, _('show newest record first')),
4537 ('B', 'bookmarks', False, _('compare bookmarks')),
4536 ('B', 'bookmarks', False, _('compare bookmarks')),
4538 ('b', 'branch', [], _('a specific branch you would like to push'),
4537 ('b', 'branch', [], _('a specific branch you would like to push'),
4539 _('BRANCH')),
4538 _('BRANCH')),
4540 ] + logopts + remoteopts + subrepoopts,
4539 ] + logopts + remoteopts + subrepoopts,
4541 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4540 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4542 def outgoing(ui, repo, dest=None, **opts):
4541 def outgoing(ui, repo, dest=None, **opts):
4543 """show changesets not found in the destination
4542 """show changesets not found in the destination
4544
4543
4545 Show changesets not found in the specified destination repository
4544 Show changesets not found in the specified destination repository
4546 or the default push location. These are the changesets that would
4545 or the default push location. These are the changesets that would
4547 be pushed if a push was requested.
4546 be pushed if a push was requested.
4548
4547
4549 See pull for details of valid destination formats.
4548 See pull for details of valid destination formats.
4550
4549
4551 Returns 0 if there are outgoing changes, 1 otherwise.
4550 Returns 0 if there are outgoing changes, 1 otherwise.
4552 """
4551 """
4553 if opts.get('graph'):
4552 if opts.get('graph'):
4554 cmdutil.checkunsupportedgraphflags([], opts)
4553 cmdutil.checkunsupportedgraphflags([], opts)
4555 o, other = hg._outgoing(ui, repo, dest, opts)
4554 o, other = hg._outgoing(ui, repo, dest, opts)
4556 if not o:
4555 if not o:
4557 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4556 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4558 return
4557 return
4559
4558
4560 revdag = cmdutil.graphrevs(repo, o, opts)
4559 revdag = cmdutil.graphrevs(repo, o, opts)
4561 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4560 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4562 showparents = [ctx.node() for ctx in repo[None].parents()]
4561 showparents = [ctx.node() for ctx in repo[None].parents()]
4563 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4562 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4564 graphmod.asciiedges)
4563 graphmod.asciiedges)
4565 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4564 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4566 return 0
4565 return 0
4567
4566
4568 if opts.get('bookmarks'):
4567 if opts.get('bookmarks'):
4569 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4568 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4570 dest, branches = hg.parseurl(dest, opts.get('branch'))
4569 dest, branches = hg.parseurl(dest, opts.get('branch'))
4571 other = hg.peer(repo, opts, dest)
4570 other = hg.peer(repo, opts, dest)
4572 if 'bookmarks' not in other.listkeys('namespaces'):
4571 if 'bookmarks' not in other.listkeys('namespaces'):
4573 ui.warn(_("remote doesn't support bookmarks\n"))
4572 ui.warn(_("remote doesn't support bookmarks\n"))
4574 return 0
4573 return 0
4575 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4574 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4576 return bookmarks.diff(ui, other, repo)
4575 return bookmarks.diff(ui, other, repo)
4577
4576
4578 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4577 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4579 try:
4578 try:
4580 return hg.outgoing(ui, repo, dest, opts)
4579 return hg.outgoing(ui, repo, dest, opts)
4581 finally:
4580 finally:
4582 del repo._subtoppath
4581 del repo._subtoppath
4583
4582
4584 @command('parents',
4583 @command('parents',
4585 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4584 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4586 ] + templateopts,
4585 ] + templateopts,
4587 _('[-r REV] [FILE]'),
4586 _('[-r REV] [FILE]'),
4588 inferrepo=True)
4587 inferrepo=True)
4589 def parents(ui, repo, file_=None, **opts):
4588 def parents(ui, repo, file_=None, **opts):
4590 """show the parents of the working directory or revision
4589 """show the parents of the working directory or revision
4591
4590
4592 Print the working directory's parent revisions. If a revision is
4591 Print the working directory's parent revisions. If a revision is
4593 given via -r/--rev, the parent of that revision will be printed.
4592 given via -r/--rev, the parent of that revision will be printed.
4594 If a file argument is given, the revision in which the file was
4593 If a file argument is given, the revision in which the file was
4595 last changed (before the working directory revision or the
4594 last changed (before the working directory revision or the
4596 argument to --rev if given) is printed.
4595 argument to --rev if given) is printed.
4597
4596
4598 Returns 0 on success.
4597 Returns 0 on success.
4599 """
4598 """
4600
4599
4601 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4600 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4602
4601
4603 if file_:
4602 if file_:
4604 m = scmutil.match(ctx, (file_,), opts)
4603 m = scmutil.match(ctx, (file_,), opts)
4605 if m.anypats() or len(m.files()) != 1:
4604 if m.anypats() or len(m.files()) != 1:
4606 raise util.Abort(_('can only specify an explicit filename'))
4605 raise util.Abort(_('can only specify an explicit filename'))
4607 file_ = m.files()[0]
4606 file_ = m.files()[0]
4608 filenodes = []
4607 filenodes = []
4609 for cp in ctx.parents():
4608 for cp in ctx.parents():
4610 if not cp:
4609 if not cp:
4611 continue
4610 continue
4612 try:
4611 try:
4613 filenodes.append(cp.filenode(file_))
4612 filenodes.append(cp.filenode(file_))
4614 except error.LookupError:
4613 except error.LookupError:
4615 pass
4614 pass
4616 if not filenodes:
4615 if not filenodes:
4617 raise util.Abort(_("'%s' not found in manifest!") % file_)
4616 raise util.Abort(_("'%s' not found in manifest!") % file_)
4618 p = []
4617 p = []
4619 for fn in filenodes:
4618 for fn in filenodes:
4620 fctx = repo.filectx(file_, fileid=fn)
4619 fctx = repo.filectx(file_, fileid=fn)
4621 p.append(fctx.node())
4620 p.append(fctx.node())
4622 else:
4621 else:
4623 p = [cp.node() for cp in ctx.parents()]
4622 p = [cp.node() for cp in ctx.parents()]
4624
4623
4625 displayer = cmdutil.show_changeset(ui, repo, opts)
4624 displayer = cmdutil.show_changeset(ui, repo, opts)
4626 for n in p:
4625 for n in p:
4627 if n != nullid:
4626 if n != nullid:
4628 displayer.show(repo[n])
4627 displayer.show(repo[n])
4629 displayer.close()
4628 displayer.close()
4630
4629
4631 @command('paths', [], _('[NAME]'), optionalrepo=True)
4630 @command('paths', [], _('[NAME]'), optionalrepo=True)
4632 def paths(ui, repo, search=None):
4631 def paths(ui, repo, search=None):
4633 """show aliases for remote repositories
4632 """show aliases for remote repositories
4634
4633
4635 Show definition of symbolic path name NAME. If no name is given,
4634 Show definition of symbolic path name NAME. If no name is given,
4636 show definition of all available names.
4635 show definition of all available names.
4637
4636
4638 Option -q/--quiet suppresses all output when searching for NAME
4637 Option -q/--quiet suppresses all output when searching for NAME
4639 and shows only the path names when listing all definitions.
4638 and shows only the path names when listing all definitions.
4640
4639
4641 Path names are defined in the [paths] section of your
4640 Path names are defined in the [paths] section of your
4642 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4641 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4643 repository, ``.hg/hgrc`` is used, too.
4642 repository, ``.hg/hgrc`` is used, too.
4644
4643
4645 The path names ``default`` and ``default-push`` have a special
4644 The path names ``default`` and ``default-push`` have a special
4646 meaning. When performing a push or pull operation, they are used
4645 meaning. When performing a push or pull operation, they are used
4647 as fallbacks if no location is specified on the command-line.
4646 as fallbacks if no location is specified on the command-line.
4648 When ``default-push`` is set, it will be used for push and
4647 When ``default-push`` is set, it will be used for push and
4649 ``default`` will be used for pull; otherwise ``default`` is used
4648 ``default`` will be used for pull; otherwise ``default`` is used
4650 as the fallback for both. When cloning a repository, the clone
4649 as the fallback for both. When cloning a repository, the clone
4651 source is written as ``default`` in ``.hg/hgrc``. Note that
4650 source is written as ``default`` in ``.hg/hgrc``. Note that
4652 ``default`` and ``default-push`` apply to all inbound (e.g.
4651 ``default`` and ``default-push`` apply to all inbound (e.g.
4653 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4652 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4654 :hg:`bundle`) operations.
4653 :hg:`bundle`) operations.
4655
4654
4656 See :hg:`help urls` for more information.
4655 See :hg:`help urls` for more information.
4657
4656
4658 Returns 0 on success.
4657 Returns 0 on success.
4659 """
4658 """
4660 if search:
4659 if search:
4661 for name, path in ui.configitems("paths"):
4660 for name, path in ui.configitems("paths"):
4662 if name == search:
4661 if name == search:
4663 ui.status("%s\n" % util.hidepassword(path))
4662 ui.status("%s\n" % util.hidepassword(path))
4664 return
4663 return
4665 if not ui.quiet:
4664 if not ui.quiet:
4666 ui.warn(_("not found!\n"))
4665 ui.warn(_("not found!\n"))
4667 return 1
4666 return 1
4668 else:
4667 else:
4669 for name, path in ui.configitems("paths"):
4668 for name, path in ui.configitems("paths"):
4670 if ui.quiet:
4669 if ui.quiet:
4671 ui.write("%s\n" % name)
4670 ui.write("%s\n" % name)
4672 else:
4671 else:
4673 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4672 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4674
4673
4675 @command('phase',
4674 @command('phase',
4676 [('p', 'public', False, _('set changeset phase to public')),
4675 [('p', 'public', False, _('set changeset phase to public')),
4677 ('d', 'draft', False, _('set changeset phase to draft')),
4676 ('d', 'draft', False, _('set changeset phase to draft')),
4678 ('s', 'secret', False, _('set changeset phase to secret')),
4677 ('s', 'secret', False, _('set changeset phase to secret')),
4679 ('f', 'force', False, _('allow to move boundary backward')),
4678 ('f', 'force', False, _('allow to move boundary backward')),
4680 ('r', 'rev', [], _('target revision'), _('REV')),
4679 ('r', 'rev', [], _('target revision'), _('REV')),
4681 ],
4680 ],
4682 _('[-p|-d|-s] [-f] [-r] REV...'))
4681 _('[-p|-d|-s] [-f] [-r] REV...'))
4683 def phase(ui, repo, *revs, **opts):
4682 def phase(ui, repo, *revs, **opts):
4684 """set or show the current phase name
4683 """set or show the current phase name
4685
4684
4686 With no argument, show the phase name of specified revisions.
4685 With no argument, show the phase name of specified revisions.
4687
4686
4688 With one of -p/--public, -d/--draft or -s/--secret, change the
4687 With one of -p/--public, -d/--draft or -s/--secret, change the
4689 phase value of the specified revisions.
4688 phase value of the specified revisions.
4690
4689
4691 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4690 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4692 lower phase to an higher phase. Phases are ordered as follows::
4691 lower phase to an higher phase. Phases are ordered as follows::
4693
4692
4694 public < draft < secret
4693 public < draft < secret
4695
4694
4696 Returns 0 on success, 1 if no phases were changed or some could not
4695 Returns 0 on success, 1 if no phases were changed or some could not
4697 be changed.
4696 be changed.
4698 """
4697 """
4699 # search for a unique phase argument
4698 # search for a unique phase argument
4700 targetphase = None
4699 targetphase = None
4701 for idx, name in enumerate(phases.phasenames):
4700 for idx, name in enumerate(phases.phasenames):
4702 if opts[name]:
4701 if opts[name]:
4703 if targetphase is not None:
4702 if targetphase is not None:
4704 raise util.Abort(_('only one phase can be specified'))
4703 raise util.Abort(_('only one phase can be specified'))
4705 targetphase = idx
4704 targetphase = idx
4706
4705
4707 # look for specified revision
4706 # look for specified revision
4708 revs = list(revs)
4707 revs = list(revs)
4709 revs.extend(opts['rev'])
4708 revs.extend(opts['rev'])
4710 if not revs:
4709 if not revs:
4711 raise util.Abort(_('no revisions specified'))
4710 raise util.Abort(_('no revisions specified'))
4712
4711
4713 revs = scmutil.revrange(repo, revs)
4712 revs = scmutil.revrange(repo, revs)
4714
4713
4715 lock = None
4714 lock = None
4716 ret = 0
4715 ret = 0
4717 if targetphase is None:
4716 if targetphase is None:
4718 # display
4717 # display
4719 for r in revs:
4718 for r in revs:
4720 ctx = repo[r]
4719 ctx = repo[r]
4721 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4720 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4722 else:
4721 else:
4723 tr = None
4722 tr = None
4724 lock = repo.lock()
4723 lock = repo.lock()
4725 try:
4724 try:
4726 tr = repo.transaction("phase")
4725 tr = repo.transaction("phase")
4727 # set phase
4726 # set phase
4728 if not revs:
4727 if not revs:
4729 raise util.Abort(_('empty revision set'))
4728 raise util.Abort(_('empty revision set'))
4730 nodes = [repo[r].node() for r in revs]
4729 nodes = [repo[r].node() for r in revs]
4731 olddata = repo._phasecache.getphaserevs(repo)[:]
4730 olddata = repo._phasecache.getphaserevs(repo)[:]
4732 phases.advanceboundary(repo, tr, targetphase, nodes)
4731 phases.advanceboundary(repo, tr, targetphase, nodes)
4733 if opts['force']:
4732 if opts['force']:
4734 phases.retractboundary(repo, tr, targetphase, nodes)
4733 phases.retractboundary(repo, tr, targetphase, nodes)
4735 tr.close()
4734 tr.close()
4736 finally:
4735 finally:
4737 if tr is not None:
4736 if tr is not None:
4738 tr.release()
4737 tr.release()
4739 lock.release()
4738 lock.release()
4740 # moving revision from public to draft may hide them
4739 # moving revision from public to draft may hide them
4741 # We have to check result on an unfiltered repository
4740 # We have to check result on an unfiltered repository
4742 unfi = repo.unfiltered()
4741 unfi = repo.unfiltered()
4743 newdata = repo._phasecache.getphaserevs(unfi)
4742 newdata = repo._phasecache.getphaserevs(unfi)
4744 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4743 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4745 cl = unfi.changelog
4744 cl = unfi.changelog
4746 rejected = [n for n in nodes
4745 rejected = [n for n in nodes
4747 if newdata[cl.rev(n)] < targetphase]
4746 if newdata[cl.rev(n)] < targetphase]
4748 if rejected:
4747 if rejected:
4749 ui.warn(_('cannot move %i changesets to a higher '
4748 ui.warn(_('cannot move %i changesets to a higher '
4750 'phase, use --force\n') % len(rejected))
4749 'phase, use --force\n') % len(rejected))
4751 ret = 1
4750 ret = 1
4752 if changes:
4751 if changes:
4753 msg = _('phase changed for %i changesets\n') % changes
4752 msg = _('phase changed for %i changesets\n') % changes
4754 if ret:
4753 if ret:
4755 ui.status(msg)
4754 ui.status(msg)
4756 else:
4755 else:
4757 ui.note(msg)
4756 ui.note(msg)
4758 else:
4757 else:
4759 ui.warn(_('no phases changed\n'))
4758 ui.warn(_('no phases changed\n'))
4760 ret = 1
4759 ret = 1
4761 return ret
4760 return ret
4762
4761
4763 def postincoming(ui, repo, modheads, optupdate, checkout):
4762 def postincoming(ui, repo, modheads, optupdate, checkout):
4764 if modheads == 0:
4763 if modheads == 0:
4765 return
4764 return
4766 if optupdate:
4765 if optupdate:
4767 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4766 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4768 try:
4767 try:
4769 ret = hg.update(repo, checkout)
4768 ret = hg.update(repo, checkout)
4770 except util.Abort, inst:
4769 except util.Abort, inst:
4771 ui.warn(_("not updating: %s\n") % str(inst))
4770 ui.warn(_("not updating: %s\n") % str(inst))
4772 if inst.hint:
4771 if inst.hint:
4773 ui.warn(_("(%s)\n") % inst.hint)
4772 ui.warn(_("(%s)\n") % inst.hint)
4774 return 0
4773 return 0
4775 if not ret and not checkout:
4774 if not ret and not checkout:
4776 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4775 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4777 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4776 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4778 return ret
4777 return ret
4779 if modheads > 1:
4778 if modheads > 1:
4780 currentbranchheads = len(repo.branchheads())
4779 currentbranchheads = len(repo.branchheads())
4781 if currentbranchheads == modheads:
4780 if currentbranchheads == modheads:
4782 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4781 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4783 elif currentbranchheads > 1:
4782 elif currentbranchheads > 1:
4784 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4783 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4785 "merge)\n"))
4784 "merge)\n"))
4786 else:
4785 else:
4787 ui.status(_("(run 'hg heads' to see heads)\n"))
4786 ui.status(_("(run 'hg heads' to see heads)\n"))
4788 else:
4787 else:
4789 ui.status(_("(run 'hg update' to get a working copy)\n"))
4788 ui.status(_("(run 'hg update' to get a working copy)\n"))
4790
4789
4791 @command('^pull',
4790 @command('^pull',
4792 [('u', 'update', None,
4791 [('u', 'update', None,
4793 _('update to new branch head if changesets were pulled')),
4792 _('update to new branch head if changesets were pulled')),
4794 ('f', 'force', None, _('run even when remote repository is unrelated')),
4793 ('f', 'force', None, _('run even when remote repository is unrelated')),
4795 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4794 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4796 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4795 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4797 ('b', 'branch', [], _('a specific branch you would like to pull'),
4796 ('b', 'branch', [], _('a specific branch you would like to pull'),
4798 _('BRANCH')),
4797 _('BRANCH')),
4799 ] + remoteopts,
4798 ] + remoteopts,
4800 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4799 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4801 def pull(ui, repo, source="default", **opts):
4800 def pull(ui, repo, source="default", **opts):
4802 """pull changes from the specified source
4801 """pull changes from the specified source
4803
4802
4804 Pull changes from a remote repository to a local one.
4803 Pull changes from a remote repository to a local one.
4805
4804
4806 This finds all changes from the repository at the specified path
4805 This finds all changes from the repository at the specified path
4807 or URL and adds them to a local repository (the current one unless
4806 or URL and adds them to a local repository (the current one unless
4808 -R is specified). By default, this does not update the copy of the
4807 -R is specified). By default, this does not update the copy of the
4809 project in the working directory.
4808 project in the working directory.
4810
4809
4811 Use :hg:`incoming` if you want to see what would have been added
4810 Use :hg:`incoming` if you want to see what would have been added
4812 by a pull at the time you issued this command. If you then decide
4811 by a pull at the time you issued this command. If you then decide
4813 to add those changes to the repository, you should use :hg:`pull
4812 to add those changes to the repository, you should use :hg:`pull
4814 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4813 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4815
4814
4816 If SOURCE is omitted, the 'default' path will be used.
4815 If SOURCE is omitted, the 'default' path will be used.
4817 See :hg:`help urls` for more information.
4816 See :hg:`help urls` for more information.
4818
4817
4819 Returns 0 on success, 1 if an update had unresolved files.
4818 Returns 0 on success, 1 if an update had unresolved files.
4820 """
4819 """
4821 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4820 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4822 other = hg.peer(repo, opts, source)
4821 other = hg.peer(repo, opts, source)
4823 try:
4822 try:
4824 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4823 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4825 revs, checkout = hg.addbranchrevs(repo, other, branches,
4824 revs, checkout = hg.addbranchrevs(repo, other, branches,
4826 opts.get('rev'))
4825 opts.get('rev'))
4827
4826
4828 remotebookmarks = other.listkeys('bookmarks')
4827 remotebookmarks = other.listkeys('bookmarks')
4829
4828
4830 if opts.get('bookmark'):
4829 if opts.get('bookmark'):
4831 if not revs:
4830 if not revs:
4832 revs = []
4831 revs = []
4833 for b in opts['bookmark']:
4832 for b in opts['bookmark']:
4834 if b not in remotebookmarks:
4833 if b not in remotebookmarks:
4835 raise util.Abort(_('remote bookmark %s not found!') % b)
4834 raise util.Abort(_('remote bookmark %s not found!') % b)
4836 revs.append(remotebookmarks[b])
4835 revs.append(remotebookmarks[b])
4837
4836
4838 if revs:
4837 if revs:
4839 try:
4838 try:
4840 revs = [other.lookup(rev) for rev in revs]
4839 revs = [other.lookup(rev) for rev in revs]
4841 except error.CapabilityError:
4840 except error.CapabilityError:
4842 err = _("other repository doesn't support revision lookup, "
4841 err = _("other repository doesn't support revision lookup, "
4843 "so a rev cannot be specified.")
4842 "so a rev cannot be specified.")
4844 raise util.Abort(err)
4843 raise util.Abort(err)
4845
4844
4846 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4845 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4847 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4846 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4848 if checkout:
4847 if checkout:
4849 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4848 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4850 repo._subtoppath = source
4849 repo._subtoppath = source
4851 try:
4850 try:
4852 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4851 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4853
4852
4854 finally:
4853 finally:
4855 del repo._subtoppath
4854 del repo._subtoppath
4856
4855
4857 # update specified bookmarks
4856 # update specified bookmarks
4858 if opts.get('bookmark'):
4857 if opts.get('bookmark'):
4859 marks = repo._bookmarks
4858 marks = repo._bookmarks
4860 for b in opts['bookmark']:
4859 for b in opts['bookmark']:
4861 # explicit pull overrides local bookmark if any
4860 # explicit pull overrides local bookmark if any
4862 ui.status(_("importing bookmark %s\n") % b)
4861 ui.status(_("importing bookmark %s\n") % b)
4863 marks[b] = repo[remotebookmarks[b]].node()
4862 marks[b] = repo[remotebookmarks[b]].node()
4864 marks.write()
4863 marks.write()
4865 finally:
4864 finally:
4866 other.close()
4865 other.close()
4867 return ret
4866 return ret
4868
4867
4869 @command('^push',
4868 @command('^push',
4870 [('f', 'force', None, _('force push')),
4869 [('f', 'force', None, _('force push')),
4871 ('r', 'rev', [],
4870 ('r', 'rev', [],
4872 _('a changeset intended to be included in the destination'),
4871 _('a changeset intended to be included in the destination'),
4873 _('REV')),
4872 _('REV')),
4874 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4873 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4875 ('b', 'branch', [],
4874 ('b', 'branch', [],
4876 _('a specific branch you would like to push'), _('BRANCH')),
4875 _('a specific branch you would like to push'), _('BRANCH')),
4877 ('', 'new-branch', False, _('allow pushing a new branch')),
4876 ('', 'new-branch', False, _('allow pushing a new branch')),
4878 ] + remoteopts,
4877 ] + remoteopts,
4879 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4878 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4880 def push(ui, repo, dest=None, **opts):
4879 def push(ui, repo, dest=None, **opts):
4881 """push changes to the specified destination
4880 """push changes to the specified destination
4882
4881
4883 Push changesets from the local repository to the specified
4882 Push changesets from the local repository to the specified
4884 destination.
4883 destination.
4885
4884
4886 This operation is symmetrical to pull: it is identical to a pull
4885 This operation is symmetrical to pull: it is identical to a pull
4887 in the destination repository from the current one.
4886 in the destination repository from the current one.
4888
4887
4889 By default, push will not allow creation of new heads at the
4888 By default, push will not allow creation of new heads at the
4890 destination, since multiple heads would make it unclear which head
4889 destination, since multiple heads would make it unclear which head
4891 to use. In this situation, it is recommended to pull and merge
4890 to use. In this situation, it is recommended to pull and merge
4892 before pushing.
4891 before pushing.
4893
4892
4894 Use --new-branch if you want to allow push to create a new named
4893 Use --new-branch if you want to allow push to create a new named
4895 branch that is not present at the destination. This allows you to
4894 branch that is not present at the destination. This allows you to
4896 only create a new branch without forcing other changes.
4895 only create a new branch without forcing other changes.
4897
4896
4898 .. note::
4897 .. note::
4899
4898
4900 Extra care should be taken with the -f/--force option,
4899 Extra care should be taken with the -f/--force option,
4901 which will push all new heads on all branches, an action which will
4900 which will push all new heads on all branches, an action which will
4902 almost always cause confusion for collaborators.
4901 almost always cause confusion for collaborators.
4903
4902
4904 If -r/--rev is used, the specified revision and all its ancestors
4903 If -r/--rev is used, the specified revision and all its ancestors
4905 will be pushed to the remote repository.
4904 will be pushed to the remote repository.
4906
4905
4907 If -B/--bookmark is used, the specified bookmarked revision, its
4906 If -B/--bookmark is used, the specified bookmarked revision, its
4908 ancestors, and the bookmark will be pushed to the remote
4907 ancestors, and the bookmark will be pushed to the remote
4909 repository.
4908 repository.
4910
4909
4911 Please see :hg:`help urls` for important details about ``ssh://``
4910 Please see :hg:`help urls` for important details about ``ssh://``
4912 URLs. If DESTINATION is omitted, a default path will be used.
4911 URLs. If DESTINATION is omitted, a default path will be used.
4913
4912
4914 Returns 0 if push was successful, 1 if nothing to push.
4913 Returns 0 if push was successful, 1 if nothing to push.
4915 """
4914 """
4916
4915
4917 if opts.get('bookmark'):
4916 if opts.get('bookmark'):
4918 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4917 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4919 for b in opts['bookmark']:
4918 for b in opts['bookmark']:
4920 # translate -B options to -r so changesets get pushed
4919 # translate -B options to -r so changesets get pushed
4921 if b in repo._bookmarks:
4920 if b in repo._bookmarks:
4922 opts.setdefault('rev', []).append(b)
4921 opts.setdefault('rev', []).append(b)
4923 else:
4922 else:
4924 # if we try to push a deleted bookmark, translate it to null
4923 # if we try to push a deleted bookmark, translate it to null
4925 # this lets simultaneous -r, -b options continue working
4924 # this lets simultaneous -r, -b options continue working
4926 opts.setdefault('rev', []).append("null")
4925 opts.setdefault('rev', []).append("null")
4927
4926
4928 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4927 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4929 dest, branches = hg.parseurl(dest, opts.get('branch'))
4928 dest, branches = hg.parseurl(dest, opts.get('branch'))
4930 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4929 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4931 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4930 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4932 try:
4931 try:
4933 other = hg.peer(repo, opts, dest)
4932 other = hg.peer(repo, opts, dest)
4934 except error.RepoError:
4933 except error.RepoError:
4935 if dest == "default-push":
4934 if dest == "default-push":
4936 raise util.Abort(_("default repository not configured!"),
4935 raise util.Abort(_("default repository not configured!"),
4937 hint=_('see the "path" section in "hg help config"'))
4936 hint=_('see the "path" section in "hg help config"'))
4938 else:
4937 else:
4939 raise
4938 raise
4940
4939
4941 if revs:
4940 if revs:
4942 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4941 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4943
4942
4944 repo._subtoppath = dest
4943 repo._subtoppath = dest
4945 try:
4944 try:
4946 # push subrepos depth-first for coherent ordering
4945 # push subrepos depth-first for coherent ordering
4947 c = repo['']
4946 c = repo['']
4948 subs = c.substate # only repos that are committed
4947 subs = c.substate # only repos that are committed
4949 for s in sorted(subs):
4948 for s in sorted(subs):
4950 result = c.sub(s).push(opts)
4949 result = c.sub(s).push(opts)
4951 if result == 0:
4950 if result == 0:
4952 return not result
4951 return not result
4953 finally:
4952 finally:
4954 del repo._subtoppath
4953 del repo._subtoppath
4955 result = repo.push(other, opts.get('force'), revs=revs,
4954 result = repo.push(other, opts.get('force'), revs=revs,
4956 newbranch=opts.get('new_branch'))
4955 newbranch=opts.get('new_branch'))
4957
4956
4958 result = not result
4957 result = not result
4959
4958
4960 if opts.get('bookmark'):
4959 if opts.get('bookmark'):
4961 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4960 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4962 if bresult == 2:
4961 if bresult == 2:
4963 return 2
4962 return 2
4964 if not result and bresult:
4963 if not result and bresult:
4965 result = 2
4964 result = 2
4966
4965
4967 return result
4966 return result
4968
4967
4969 @command('recover', [])
4968 @command('recover', [])
4970 def recover(ui, repo):
4969 def recover(ui, repo):
4971 """roll back an interrupted transaction
4970 """roll back an interrupted transaction
4972
4971
4973 Recover from an interrupted commit or pull.
4972 Recover from an interrupted commit or pull.
4974
4973
4975 This command tries to fix the repository status after an
4974 This command tries to fix the repository status after an
4976 interrupted operation. It should only be necessary when Mercurial
4975 interrupted operation. It should only be necessary when Mercurial
4977 suggests it.
4976 suggests it.
4978
4977
4979 Returns 0 if successful, 1 if nothing to recover or verify fails.
4978 Returns 0 if successful, 1 if nothing to recover or verify fails.
4980 """
4979 """
4981 if repo.recover():
4980 if repo.recover():
4982 return hg.verify(repo)
4981 return hg.verify(repo)
4983 return 1
4982 return 1
4984
4983
4985 @command('^remove|rm',
4984 @command('^remove|rm',
4986 [('A', 'after', None, _('record delete for missing files')),
4985 [('A', 'after', None, _('record delete for missing files')),
4987 ('f', 'force', None,
4986 ('f', 'force', None,
4988 _('remove (and delete) file even if added or modified')),
4987 _('remove (and delete) file even if added or modified')),
4989 ] + walkopts,
4988 ] + walkopts,
4990 _('[OPTION]... FILE...'),
4989 _('[OPTION]... FILE...'),
4991 inferrepo=True)
4990 inferrepo=True)
4992 def remove(ui, repo, *pats, **opts):
4991 def remove(ui, repo, *pats, **opts):
4993 """remove the specified files on the next commit
4992 """remove the specified files on the next commit
4994
4993
4995 Schedule the indicated files for removal from the current branch.
4994 Schedule the indicated files for removal from the current branch.
4996
4995
4997 This command schedules the files to be removed at the next commit.
4996 This command schedules the files to be removed at the next commit.
4998 To undo a remove before that, see :hg:`revert`. To undo added
4997 To undo a remove before that, see :hg:`revert`. To undo added
4999 files, see :hg:`forget`.
4998 files, see :hg:`forget`.
5000
4999
5001 .. container:: verbose
5000 .. container:: verbose
5002
5001
5003 -A/--after can be used to remove only files that have already
5002 -A/--after can be used to remove only files that have already
5004 been deleted, -f/--force can be used to force deletion, and -Af
5003 been deleted, -f/--force can be used to force deletion, and -Af
5005 can be used to remove files from the next revision without
5004 can be used to remove files from the next revision without
5006 deleting them from the working directory.
5005 deleting them from the working directory.
5007
5006
5008 The following table details the behavior of remove for different
5007 The following table details the behavior of remove for different
5009 file states (columns) and option combinations (rows). The file
5008 file states (columns) and option combinations (rows). The file
5010 states are Added [A], Clean [C], Modified [M] and Missing [!]
5009 states are Added [A], Clean [C], Modified [M] and Missing [!]
5011 (as reported by :hg:`status`). The actions are Warn, Remove
5010 (as reported by :hg:`status`). The actions are Warn, Remove
5012 (from branch) and Delete (from disk):
5011 (from branch) and Delete (from disk):
5013
5012
5014 ========= == == == ==
5013 ========= == == == ==
5015 opt/state A C M !
5014 opt/state A C M !
5016 ========= == == == ==
5015 ========= == == == ==
5017 none W RD W R
5016 none W RD W R
5018 -f R RD RD R
5017 -f R RD RD R
5019 -A W W W R
5018 -A W W W R
5020 -Af R R R R
5019 -Af R R R R
5021 ========= == == == ==
5020 ========= == == == ==
5022
5021
5023 Note that remove never deletes files in Added [A] state from the
5022 Note that remove never deletes files in Added [A] state from the
5024 working directory, not even if option --force is specified.
5023 working directory, not even if option --force is specified.
5025
5024
5026 Returns 0 on success, 1 if any warnings encountered.
5025 Returns 0 on success, 1 if any warnings encountered.
5027 """
5026 """
5028
5027
5029 ret = 0
5028 ret = 0
5030 after, force = opts.get('after'), opts.get('force')
5029 after, force = opts.get('after'), opts.get('force')
5031 if not pats and not after:
5030 if not pats and not after:
5032 raise util.Abort(_('no files specified'))
5031 raise util.Abort(_('no files specified'))
5033
5032
5034 m = scmutil.match(repo[None], pats, opts)
5033 m = scmutil.match(repo[None], pats, opts)
5035 s = repo.status(match=m, clean=True)
5034 s = repo.status(match=m, clean=True)
5036 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5035 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5037
5036
5038 # warn about failure to delete explicit files/dirs
5037 # warn about failure to delete explicit files/dirs
5039 wctx = repo[None]
5038 wctx = repo[None]
5040 for f in m.files():
5039 for f in m.files():
5041 if f in repo.dirstate or f in wctx.dirs():
5040 if f in repo.dirstate or f in wctx.dirs():
5042 continue
5041 continue
5043 if os.path.exists(m.rel(f)):
5042 if os.path.exists(m.rel(f)):
5044 if os.path.isdir(m.rel(f)):
5043 if os.path.isdir(m.rel(f)):
5045 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5044 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5046 else:
5045 else:
5047 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5046 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5048 # missing files will generate a warning elsewhere
5047 # missing files will generate a warning elsewhere
5049 ret = 1
5048 ret = 1
5050
5049
5051 if force:
5050 if force:
5052 list = modified + deleted + clean + added
5051 list = modified + deleted + clean + added
5053 elif after:
5052 elif after:
5054 list = deleted
5053 list = deleted
5055 for f in modified + added + clean:
5054 for f in modified + added + clean:
5056 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5055 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5057 ret = 1
5056 ret = 1
5058 else:
5057 else:
5059 list = deleted + clean
5058 list = deleted + clean
5060 for f in modified:
5059 for f in modified:
5061 ui.warn(_('not removing %s: file is modified (use -f'
5060 ui.warn(_('not removing %s: file is modified (use -f'
5062 ' to force removal)\n') % m.rel(f))
5061 ' to force removal)\n') % m.rel(f))
5063 ret = 1
5062 ret = 1
5064 for f in added:
5063 for f in added:
5065 ui.warn(_('not removing %s: file has been marked for add'
5064 ui.warn(_('not removing %s: file has been marked for add'
5066 ' (use forget to undo)\n') % m.rel(f))
5065 ' (use forget to undo)\n') % m.rel(f))
5067 ret = 1
5066 ret = 1
5068
5067
5069 for f in sorted(list):
5068 for f in sorted(list):
5070 if ui.verbose or not m.exact(f):
5069 if ui.verbose or not m.exact(f):
5071 ui.status(_('removing %s\n') % m.rel(f))
5070 ui.status(_('removing %s\n') % m.rel(f))
5072
5071
5073 wlock = repo.wlock()
5072 wlock = repo.wlock()
5074 try:
5073 try:
5075 if not after:
5074 if not after:
5076 for f in list:
5075 for f in list:
5077 if f in added:
5076 if f in added:
5078 continue # we never unlink added files on remove
5077 continue # we never unlink added files on remove
5079 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5078 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5080 repo[None].forget(list)
5079 repo[None].forget(list)
5081 finally:
5080 finally:
5082 wlock.release()
5081 wlock.release()
5083
5082
5084 return ret
5083 return ret
5085
5084
5086 @command('rename|move|mv',
5085 @command('rename|move|mv',
5087 [('A', 'after', None, _('record a rename that has already occurred')),
5086 [('A', 'after', None, _('record a rename that has already occurred')),
5088 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5087 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5089 ] + walkopts + dryrunopts,
5088 ] + walkopts + dryrunopts,
5090 _('[OPTION]... SOURCE... DEST'))
5089 _('[OPTION]... SOURCE... DEST'))
5091 def rename(ui, repo, *pats, **opts):
5090 def rename(ui, repo, *pats, **opts):
5092 """rename files; equivalent of copy + remove
5091 """rename files; equivalent of copy + remove
5093
5092
5094 Mark dest as copies of sources; mark sources for deletion. If dest
5093 Mark dest as copies of sources; mark sources for deletion. If dest
5095 is a directory, copies are put in that directory. If dest is a
5094 is a directory, copies are put in that directory. If dest is a
5096 file, there can only be one source.
5095 file, there can only be one source.
5097
5096
5098 By default, this command copies the contents of files as they
5097 By default, this command copies the contents of files as they
5099 exist in the working directory. If invoked with -A/--after, the
5098 exist in the working directory. If invoked with -A/--after, the
5100 operation is recorded, but no copying is performed.
5099 operation is recorded, but no copying is performed.
5101
5100
5102 This command takes effect at the next commit. To undo a rename
5101 This command takes effect at the next commit. To undo a rename
5103 before that, see :hg:`revert`.
5102 before that, see :hg:`revert`.
5104
5103
5105 Returns 0 on success, 1 if errors are encountered.
5104 Returns 0 on success, 1 if errors are encountered.
5106 """
5105 """
5107 wlock = repo.wlock(False)
5106 wlock = repo.wlock(False)
5108 try:
5107 try:
5109 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5108 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5110 finally:
5109 finally:
5111 wlock.release()
5110 wlock.release()
5112
5111
5113 @command('resolve',
5112 @command('resolve',
5114 [('a', 'all', None, _('select all unresolved files')),
5113 [('a', 'all', None, _('select all unresolved files')),
5115 ('l', 'list', None, _('list state of files needing merge')),
5114 ('l', 'list', None, _('list state of files needing merge')),
5116 ('m', 'mark', None, _('mark files as resolved')),
5115 ('m', 'mark', None, _('mark files as resolved')),
5117 ('u', 'unmark', None, _('mark files as unresolved')),
5116 ('u', 'unmark', None, _('mark files as unresolved')),
5118 ('n', 'no-status', None, _('hide status prefix'))]
5117 ('n', 'no-status', None, _('hide status prefix'))]
5119 + mergetoolopts + walkopts,
5118 + mergetoolopts + walkopts,
5120 _('[OPTION]... [FILE]...'),
5119 _('[OPTION]... [FILE]...'),
5121 inferrepo=True)
5120 inferrepo=True)
5122 def resolve(ui, repo, *pats, **opts):
5121 def resolve(ui, repo, *pats, **opts):
5123 """redo merges or set/view the merge status of files
5122 """redo merges or set/view the merge status of files
5124
5123
5125 Merges with unresolved conflicts are often the result of
5124 Merges with unresolved conflicts are often the result of
5126 non-interactive merging using the ``internal:merge`` configuration
5125 non-interactive merging using the ``internal:merge`` configuration
5127 setting, or a command-line merge tool like ``diff3``. The resolve
5126 setting, or a command-line merge tool like ``diff3``. The resolve
5128 command is used to manage the files involved in a merge, after
5127 command is used to manage the files involved in a merge, after
5129 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5128 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5130 working directory must have two parents). See :hg:`help
5129 working directory must have two parents). See :hg:`help
5131 merge-tools` for information on configuring merge tools.
5130 merge-tools` for information on configuring merge tools.
5132
5131
5133 The resolve command can be used in the following ways:
5132 The resolve command can be used in the following ways:
5134
5133
5135 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5134 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5136 files, discarding any previous merge attempts. Re-merging is not
5135 files, discarding any previous merge attempts. Re-merging is not
5137 performed for files already marked as resolved. Use ``--all/-a``
5136 performed for files already marked as resolved. Use ``--all/-a``
5138 to select all unresolved files. ``--tool`` can be used to specify
5137 to select all unresolved files. ``--tool`` can be used to specify
5139 the merge tool used for the given files. It overrides the HGMERGE
5138 the merge tool used for the given files. It overrides the HGMERGE
5140 environment variable and your configuration files. Previous file
5139 environment variable and your configuration files. Previous file
5141 contents are saved with a ``.orig`` suffix.
5140 contents are saved with a ``.orig`` suffix.
5142
5141
5143 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5142 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5144 (e.g. after having manually fixed-up the files). The default is
5143 (e.g. after having manually fixed-up the files). The default is
5145 to mark all unresolved files.
5144 to mark all unresolved files.
5146
5145
5147 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5146 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5148 default is to mark all resolved files.
5147 default is to mark all resolved files.
5149
5148
5150 - :hg:`resolve -l`: list files which had or still have conflicts.
5149 - :hg:`resolve -l`: list files which had or still have conflicts.
5151 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5150 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5152
5151
5153 Note that Mercurial will not let you commit files with unresolved
5152 Note that Mercurial will not let you commit files with unresolved
5154 merge conflicts. You must use :hg:`resolve -m ...` before you can
5153 merge conflicts. You must use :hg:`resolve -m ...` before you can
5155 commit after a conflicting merge.
5154 commit after a conflicting merge.
5156
5155
5157 Returns 0 on success, 1 if any files fail a resolve attempt.
5156 Returns 0 on success, 1 if any files fail a resolve attempt.
5158 """
5157 """
5159
5158
5160 all, mark, unmark, show, nostatus = \
5159 all, mark, unmark, show, nostatus = \
5161 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5160 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5162
5161
5163 if (show and (mark or unmark)) or (mark and unmark):
5162 if (show and (mark or unmark)) or (mark and unmark):
5164 raise util.Abort(_("too many options specified"))
5163 raise util.Abort(_("too many options specified"))
5165 if pats and all:
5164 if pats and all:
5166 raise util.Abort(_("can't specify --all and patterns"))
5165 raise util.Abort(_("can't specify --all and patterns"))
5167 if not (all or pats or show or mark or unmark):
5166 if not (all or pats or show or mark or unmark):
5168 raise util.Abort(_('no files or directories specified'),
5167 raise util.Abort(_('no files or directories specified'),
5169 hint=('use --all to remerge all files'))
5168 hint=('use --all to remerge all files'))
5170
5169
5171 wlock = repo.wlock()
5170 wlock = repo.wlock()
5172 try:
5171 try:
5173 ms = mergemod.mergestate(repo)
5172 ms = mergemod.mergestate(repo)
5174
5173
5175 if not ms.active() and not show:
5174 if not ms.active() and not show:
5176 raise util.Abort(
5175 raise util.Abort(
5177 _('resolve command not applicable when not merging'))
5176 _('resolve command not applicable when not merging'))
5178
5177
5179 m = scmutil.match(repo[None], pats, opts)
5178 m = scmutil.match(repo[None], pats, opts)
5180 ret = 0
5179 ret = 0
5181 didwork = False
5180 didwork = False
5182
5181
5183 for f in ms:
5182 for f in ms:
5184 if not m(f):
5183 if not m(f):
5185 continue
5184 continue
5186
5185
5187 didwork = True
5186 didwork = True
5188
5187
5189 if show:
5188 if show:
5190 if nostatus:
5189 if nostatus:
5191 ui.write("%s\n" % f)
5190 ui.write("%s\n" % f)
5192 else:
5191 else:
5193 ui.write("%s %s\n" % (ms[f].upper(), f),
5192 ui.write("%s %s\n" % (ms[f].upper(), f),
5194 label='resolve.' +
5193 label='resolve.' +
5195 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5194 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5196 elif mark:
5195 elif mark:
5197 ms.mark(f, "r")
5196 ms.mark(f, "r")
5198 elif unmark:
5197 elif unmark:
5199 ms.mark(f, "u")
5198 ms.mark(f, "u")
5200 else:
5199 else:
5201 wctx = repo[None]
5200 wctx = repo[None]
5202
5201
5203 # backup pre-resolve (merge uses .orig for its own purposes)
5202 # backup pre-resolve (merge uses .orig for its own purposes)
5204 a = repo.wjoin(f)
5203 a = repo.wjoin(f)
5205 util.copyfile(a, a + ".resolve")
5204 util.copyfile(a, a + ".resolve")
5206
5205
5207 try:
5206 try:
5208 # resolve file
5207 # resolve file
5209 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5208 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5210 'resolve')
5209 'resolve')
5211 if ms.resolve(f, wctx):
5210 if ms.resolve(f, wctx):
5212 ret = 1
5211 ret = 1
5213 finally:
5212 finally:
5214 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5213 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5215 ms.commit()
5214 ms.commit()
5216
5215
5217 # replace filemerge's .orig file with our resolve file
5216 # replace filemerge's .orig file with our resolve file
5218 util.rename(a + ".resolve", a + ".orig")
5217 util.rename(a + ".resolve", a + ".orig")
5219
5218
5220 ms.commit()
5219 ms.commit()
5221
5220
5222 if not didwork and pats:
5221 if not didwork and pats:
5223 ui.warn(_("arguments do not match paths that need resolving\n"))
5222 ui.warn(_("arguments do not match paths that need resolving\n"))
5224
5223
5225 finally:
5224 finally:
5226 wlock.release()
5225 wlock.release()
5227
5226
5228 # Nudge users into finishing an unfinished operation. We don't print
5227 # Nudge users into finishing an unfinished operation. We don't print
5229 # this with the list/show operation because we want list/show to remain
5228 # this with the list/show operation because we want list/show to remain
5230 # machine readable.
5229 # machine readable.
5231 if not list(ms.unresolved()) and not show:
5230 if not list(ms.unresolved()) and not show:
5232 ui.status(_('(no more unresolved files)\n'))
5231 ui.status(_('(no more unresolved files)\n'))
5233
5232
5234 return ret
5233 return ret
5235
5234
5236 @command('revert',
5235 @command('revert',
5237 [('a', 'all', None, _('revert all changes when no arguments given')),
5236 [('a', 'all', None, _('revert all changes when no arguments given')),
5238 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5237 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5239 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5238 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5240 ('C', 'no-backup', None, _('do not save backup copies of files')),
5239 ('C', 'no-backup', None, _('do not save backup copies of files')),
5241 ] + walkopts + dryrunopts,
5240 ] + walkopts + dryrunopts,
5242 _('[OPTION]... [-r REV] [NAME]...'))
5241 _('[OPTION]... [-r REV] [NAME]...'))
5243 def revert(ui, repo, *pats, **opts):
5242 def revert(ui, repo, *pats, **opts):
5244 """restore files to their checkout state
5243 """restore files to their checkout state
5245
5244
5246 .. note::
5245 .. note::
5247
5246
5248 To check out earlier revisions, you should use :hg:`update REV`.
5247 To check out earlier revisions, you should use :hg:`update REV`.
5249 To cancel an uncommitted merge (and lose your changes),
5248 To cancel an uncommitted merge (and lose your changes),
5250 use :hg:`update --clean .`.
5249 use :hg:`update --clean .`.
5251
5250
5252 With no revision specified, revert the specified files or directories
5251 With no revision specified, revert the specified files or directories
5253 to the contents they had in the parent of the working directory.
5252 to the contents they had in the parent of the working directory.
5254 This restores the contents of files to an unmodified
5253 This restores the contents of files to an unmodified
5255 state and unschedules adds, removes, copies, and renames. If the
5254 state and unschedules adds, removes, copies, and renames. If the
5256 working directory has two parents, you must explicitly specify a
5255 working directory has two parents, you must explicitly specify a
5257 revision.
5256 revision.
5258
5257
5259 Using the -r/--rev or -d/--date options, revert the given files or
5258 Using the -r/--rev or -d/--date options, revert the given files or
5260 directories to their states as of a specific revision. Because
5259 directories to their states as of a specific revision. Because
5261 revert does not change the working directory parents, this will
5260 revert does not change the working directory parents, this will
5262 cause these files to appear modified. This can be helpful to "back
5261 cause these files to appear modified. This can be helpful to "back
5263 out" some or all of an earlier change. See :hg:`backout` for a
5262 out" some or all of an earlier change. See :hg:`backout` for a
5264 related method.
5263 related method.
5265
5264
5266 Modified files are saved with a .orig suffix before reverting.
5265 Modified files are saved with a .orig suffix before reverting.
5267 To disable these backups, use --no-backup.
5266 To disable these backups, use --no-backup.
5268
5267
5269 See :hg:`help dates` for a list of formats valid for -d/--date.
5268 See :hg:`help dates` for a list of formats valid for -d/--date.
5270
5269
5271 Returns 0 on success.
5270 Returns 0 on success.
5272 """
5271 """
5273
5272
5274 if opts.get("date"):
5273 if opts.get("date"):
5275 if opts.get("rev"):
5274 if opts.get("rev"):
5276 raise util.Abort(_("you can't specify a revision and a date"))
5275 raise util.Abort(_("you can't specify a revision and a date"))
5277 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5276 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5278
5277
5279 parent, p2 = repo.dirstate.parents()
5278 parent, p2 = repo.dirstate.parents()
5280 if not opts.get('rev') and p2 != nullid:
5279 if not opts.get('rev') and p2 != nullid:
5281 # revert after merge is a trap for new users (issue2915)
5280 # revert after merge is a trap for new users (issue2915)
5282 raise util.Abort(_('uncommitted merge with no revision specified'),
5281 raise util.Abort(_('uncommitted merge with no revision specified'),
5283 hint=_('use "hg update" or see "hg help revert"'))
5282 hint=_('use "hg update" or see "hg help revert"'))
5284
5283
5285 ctx = scmutil.revsingle(repo, opts.get('rev'))
5284 ctx = scmutil.revsingle(repo, opts.get('rev'))
5286
5285
5287 if not pats and not opts.get('all'):
5286 if not pats and not opts.get('all'):
5288 msg = _("no files or directories specified")
5287 msg = _("no files or directories specified")
5289 if p2 != nullid:
5288 if p2 != nullid:
5290 hint = _("uncommitted merge, use --all to discard all changes,"
5289 hint = _("uncommitted merge, use --all to discard all changes,"
5291 " or 'hg update -C .' to abort the merge")
5290 " or 'hg update -C .' to abort the merge")
5292 raise util.Abort(msg, hint=hint)
5291 raise util.Abort(msg, hint=hint)
5293 dirty = util.any(repo.status())
5292 dirty = util.any(repo.status())
5294 node = ctx.node()
5293 node = ctx.node()
5295 if node != parent:
5294 if node != parent:
5296 if dirty:
5295 if dirty:
5297 hint = _("uncommitted changes, use --all to discard all"
5296 hint = _("uncommitted changes, use --all to discard all"
5298 " changes, or 'hg update %s' to update") % ctx.rev()
5297 " changes, or 'hg update %s' to update") % ctx.rev()
5299 else:
5298 else:
5300 hint = _("use --all to revert all files,"
5299 hint = _("use --all to revert all files,"
5301 " or 'hg update %s' to update") % ctx.rev()
5300 " or 'hg update %s' to update") % ctx.rev()
5302 elif dirty:
5301 elif dirty:
5303 hint = _("uncommitted changes, use --all to discard all changes")
5302 hint = _("uncommitted changes, use --all to discard all changes")
5304 else:
5303 else:
5305 hint = _("use --all to revert all files")
5304 hint = _("use --all to revert all files")
5306 raise util.Abort(msg, hint=hint)
5305 raise util.Abort(msg, hint=hint)
5307
5306
5308 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5307 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5309
5308
5310 @command('rollback', dryrunopts +
5309 @command('rollback', dryrunopts +
5311 [('f', 'force', False, _('ignore safety measures'))])
5310 [('f', 'force', False, _('ignore safety measures'))])
5312 def rollback(ui, repo, **opts):
5311 def rollback(ui, repo, **opts):
5313 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5312 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5314
5313
5315 Please use :hg:`commit --amend` instead of rollback to correct
5314 Please use :hg:`commit --amend` instead of rollback to correct
5316 mistakes in the last commit.
5315 mistakes in the last commit.
5317
5316
5318 This command should be used with care. There is only one level of
5317 This command should be used with care. There is only one level of
5319 rollback, and there is no way to undo a rollback. It will also
5318 rollback, and there is no way to undo a rollback. It will also
5320 restore the dirstate at the time of the last transaction, losing
5319 restore the dirstate at the time of the last transaction, losing
5321 any dirstate changes since that time. This command does not alter
5320 any dirstate changes since that time. This command does not alter
5322 the working directory.
5321 the working directory.
5323
5322
5324 Transactions are used to encapsulate the effects of all commands
5323 Transactions are used to encapsulate the effects of all commands
5325 that create new changesets or propagate existing changesets into a
5324 that create new changesets or propagate existing changesets into a
5326 repository.
5325 repository.
5327
5326
5328 .. container:: verbose
5327 .. container:: verbose
5329
5328
5330 For example, the following commands are transactional, and their
5329 For example, the following commands are transactional, and their
5331 effects can be rolled back:
5330 effects can be rolled back:
5332
5331
5333 - commit
5332 - commit
5334 - import
5333 - import
5335 - pull
5334 - pull
5336 - push (with this repository as the destination)
5335 - push (with this repository as the destination)
5337 - unbundle
5336 - unbundle
5338
5337
5339 To avoid permanent data loss, rollback will refuse to rollback a
5338 To avoid permanent data loss, rollback will refuse to rollback a
5340 commit transaction if it isn't checked out. Use --force to
5339 commit transaction if it isn't checked out. Use --force to
5341 override this protection.
5340 override this protection.
5342
5341
5343 This command is not intended for use on public repositories. Once
5342 This command is not intended for use on public repositories. Once
5344 changes are visible for pull by other users, rolling a transaction
5343 changes are visible for pull by other users, rolling a transaction
5345 back locally is ineffective (someone else may already have pulled
5344 back locally is ineffective (someone else may already have pulled
5346 the changes). Furthermore, a race is possible with readers of the
5345 the changes). Furthermore, a race is possible with readers of the
5347 repository; for example an in-progress pull from the repository
5346 repository; for example an in-progress pull from the repository
5348 may fail if a rollback is performed.
5347 may fail if a rollback is performed.
5349
5348
5350 Returns 0 on success, 1 if no rollback data is available.
5349 Returns 0 on success, 1 if no rollback data is available.
5351 """
5350 """
5352 return repo.rollback(dryrun=opts.get('dry_run'),
5351 return repo.rollback(dryrun=opts.get('dry_run'),
5353 force=opts.get('force'))
5352 force=opts.get('force'))
5354
5353
5355 @command('root', [])
5354 @command('root', [])
5356 def root(ui, repo):
5355 def root(ui, repo):
5357 """print the root (top) of the current working directory
5356 """print the root (top) of the current working directory
5358
5357
5359 Print the root directory of the current repository.
5358 Print the root directory of the current repository.
5360
5359
5361 Returns 0 on success.
5360 Returns 0 on success.
5362 """
5361 """
5363 ui.write(repo.root + "\n")
5362 ui.write(repo.root + "\n")
5364
5363
5365 @command('^serve',
5364 @command('^serve',
5366 [('A', 'accesslog', '', _('name of access log file to write to'),
5365 [('A', 'accesslog', '', _('name of access log file to write to'),
5367 _('FILE')),
5366 _('FILE')),
5368 ('d', 'daemon', None, _('run server in background')),
5367 ('d', 'daemon', None, _('run server in background')),
5369 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5368 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5370 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5369 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5371 # use string type, then we can check if something was passed
5370 # use string type, then we can check if something was passed
5372 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5371 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5373 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5372 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5374 _('ADDR')),
5373 _('ADDR')),
5375 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5374 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5376 _('PREFIX')),
5375 _('PREFIX')),
5377 ('n', 'name', '',
5376 ('n', 'name', '',
5378 _('name to show in web pages (default: working directory)'), _('NAME')),
5377 _('name to show in web pages (default: working directory)'), _('NAME')),
5379 ('', 'web-conf', '',
5378 ('', 'web-conf', '',
5380 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5379 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5381 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5380 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5382 _('FILE')),
5381 _('FILE')),
5383 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5382 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5384 ('', 'stdio', None, _('for remote clients')),
5383 ('', 'stdio', None, _('for remote clients')),
5385 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5384 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5386 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5385 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5387 ('', 'style', '', _('template style to use'), _('STYLE')),
5386 ('', 'style', '', _('template style to use'), _('STYLE')),
5388 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5387 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5389 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5388 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5390 _('[OPTION]...'),
5389 _('[OPTION]...'),
5391 optionalrepo=True)
5390 optionalrepo=True)
5392 def serve(ui, repo, **opts):
5391 def serve(ui, repo, **opts):
5393 """start stand-alone webserver
5392 """start stand-alone webserver
5394
5393
5395 Start a local HTTP repository browser and pull server. You can use
5394 Start a local HTTP repository browser and pull server. You can use
5396 this for ad-hoc sharing and browsing of repositories. It is
5395 this for ad-hoc sharing and browsing of repositories. It is
5397 recommended to use a real web server to serve a repository for
5396 recommended to use a real web server to serve a repository for
5398 longer periods of time.
5397 longer periods of time.
5399
5398
5400 Please note that the server does not implement access control.
5399 Please note that the server does not implement access control.
5401 This means that, by default, anybody can read from the server and
5400 This means that, by default, anybody can read from the server and
5402 nobody can write to it by default. Set the ``web.allow_push``
5401 nobody can write to it by default. Set the ``web.allow_push``
5403 option to ``*`` to allow everybody to push to the server. You
5402 option to ``*`` to allow everybody to push to the server. You
5404 should use a real web server if you need to authenticate users.
5403 should use a real web server if you need to authenticate users.
5405
5404
5406 By default, the server logs accesses to stdout and errors to
5405 By default, the server logs accesses to stdout and errors to
5407 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5406 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5408 files.
5407 files.
5409
5408
5410 To have the server choose a free port number to listen on, specify
5409 To have the server choose a free port number to listen on, specify
5411 a port number of 0; in this case, the server will print the port
5410 a port number of 0; in this case, the server will print the port
5412 number it uses.
5411 number it uses.
5413
5412
5414 Returns 0 on success.
5413 Returns 0 on success.
5415 """
5414 """
5416
5415
5417 if opts["stdio"] and opts["cmdserver"]:
5416 if opts["stdio"] and opts["cmdserver"]:
5418 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5417 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5419
5418
5420 if opts["stdio"]:
5419 if opts["stdio"]:
5421 if repo is None:
5420 if repo is None:
5422 raise error.RepoError(_("there is no Mercurial repository here"
5421 raise error.RepoError(_("there is no Mercurial repository here"
5423 " (.hg not found)"))
5422 " (.hg not found)"))
5424 s = sshserver.sshserver(ui, repo)
5423 s = sshserver.sshserver(ui, repo)
5425 s.serve_forever()
5424 s.serve_forever()
5426
5425
5427 if opts["cmdserver"]:
5426 if opts["cmdserver"]:
5428 s = commandserver.server(ui, repo, opts["cmdserver"])
5427 s = commandserver.server(ui, repo, opts["cmdserver"])
5429 return s.serve()
5428 return s.serve()
5430
5429
5431 # this way we can check if something was given in the command-line
5430 # this way we can check if something was given in the command-line
5432 if opts.get('port'):
5431 if opts.get('port'):
5433 opts['port'] = util.getport(opts.get('port'))
5432 opts['port'] = util.getport(opts.get('port'))
5434
5433
5435 baseui = repo and repo.baseui or ui
5434 baseui = repo and repo.baseui or ui
5436 optlist = ("name templates style address port prefix ipv6"
5435 optlist = ("name templates style address port prefix ipv6"
5437 " accesslog errorlog certificate encoding")
5436 " accesslog errorlog certificate encoding")
5438 for o in optlist.split():
5437 for o in optlist.split():
5439 val = opts.get(o, '')
5438 val = opts.get(o, '')
5440 if val in (None, ''): # should check against default options instead
5439 if val in (None, ''): # should check against default options instead
5441 continue
5440 continue
5442 baseui.setconfig("web", o, val, 'serve')
5441 baseui.setconfig("web", o, val, 'serve')
5443 if repo and repo.ui != baseui:
5442 if repo and repo.ui != baseui:
5444 repo.ui.setconfig("web", o, val, 'serve')
5443 repo.ui.setconfig("web", o, val, 'serve')
5445
5444
5446 o = opts.get('web_conf') or opts.get('webdir_conf')
5445 o = opts.get('web_conf') or opts.get('webdir_conf')
5447 if not o:
5446 if not o:
5448 if not repo:
5447 if not repo:
5449 raise error.RepoError(_("there is no Mercurial repository"
5448 raise error.RepoError(_("there is no Mercurial repository"
5450 " here (.hg not found)"))
5449 " here (.hg not found)"))
5451 o = repo
5450 o = repo
5452
5451
5453 app = hgweb.hgweb(o, baseui=baseui)
5452 app = hgweb.hgweb(o, baseui=baseui)
5454 service = httpservice(ui, app, opts)
5453 service = httpservice(ui, app, opts)
5455 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5454 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5456
5455
5457 class httpservice(object):
5456 class httpservice(object):
5458 def __init__(self, ui, app, opts):
5457 def __init__(self, ui, app, opts):
5459 self.ui = ui
5458 self.ui = ui
5460 self.app = app
5459 self.app = app
5461 self.opts = opts
5460 self.opts = opts
5462
5461
5463 def init(self):
5462 def init(self):
5464 util.setsignalhandler()
5463 util.setsignalhandler()
5465 self.httpd = hgweb_server.create_server(self.ui, self.app)
5464 self.httpd = hgweb_server.create_server(self.ui, self.app)
5466
5465
5467 if self.opts['port'] and not self.ui.verbose:
5466 if self.opts['port'] and not self.ui.verbose:
5468 return
5467 return
5469
5468
5470 if self.httpd.prefix:
5469 if self.httpd.prefix:
5471 prefix = self.httpd.prefix.strip('/') + '/'
5470 prefix = self.httpd.prefix.strip('/') + '/'
5472 else:
5471 else:
5473 prefix = ''
5472 prefix = ''
5474
5473
5475 port = ':%d' % self.httpd.port
5474 port = ':%d' % self.httpd.port
5476 if port == ':80':
5475 if port == ':80':
5477 port = ''
5476 port = ''
5478
5477
5479 bindaddr = self.httpd.addr
5478 bindaddr = self.httpd.addr
5480 if bindaddr == '0.0.0.0':
5479 if bindaddr == '0.0.0.0':
5481 bindaddr = '*'
5480 bindaddr = '*'
5482 elif ':' in bindaddr: # IPv6
5481 elif ':' in bindaddr: # IPv6
5483 bindaddr = '[%s]' % bindaddr
5482 bindaddr = '[%s]' % bindaddr
5484
5483
5485 fqaddr = self.httpd.fqaddr
5484 fqaddr = self.httpd.fqaddr
5486 if ':' in fqaddr:
5485 if ':' in fqaddr:
5487 fqaddr = '[%s]' % fqaddr
5486 fqaddr = '[%s]' % fqaddr
5488 if self.opts['port']:
5487 if self.opts['port']:
5489 write = self.ui.status
5488 write = self.ui.status
5490 else:
5489 else:
5491 write = self.ui.write
5490 write = self.ui.write
5492 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5491 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5493 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5492 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5494 self.ui.flush() # avoid buffering of status message
5493 self.ui.flush() # avoid buffering of status message
5495
5494
5496 def run(self):
5495 def run(self):
5497 self.httpd.serve_forever()
5496 self.httpd.serve_forever()
5498
5497
5499
5498
5500 @command('^status|st',
5499 @command('^status|st',
5501 [('A', 'all', None, _('show status of all files')),
5500 [('A', 'all', None, _('show status of all files')),
5502 ('m', 'modified', None, _('show only modified files')),
5501 ('m', 'modified', None, _('show only modified files')),
5503 ('a', 'added', None, _('show only added files')),
5502 ('a', 'added', None, _('show only added files')),
5504 ('r', 'removed', None, _('show only removed files')),
5503 ('r', 'removed', None, _('show only removed files')),
5505 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5504 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5506 ('c', 'clean', None, _('show only files without changes')),
5505 ('c', 'clean', None, _('show only files without changes')),
5507 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5506 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5508 ('i', 'ignored', None, _('show only ignored files')),
5507 ('i', 'ignored', None, _('show only ignored files')),
5509 ('n', 'no-status', None, _('hide status prefix')),
5508 ('n', 'no-status', None, _('hide status prefix')),
5510 ('C', 'copies', None, _('show source of copied files')),
5509 ('C', 'copies', None, _('show source of copied files')),
5511 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5510 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5512 ('', 'rev', [], _('show difference from revision'), _('REV')),
5511 ('', 'rev', [], _('show difference from revision'), _('REV')),
5513 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5512 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5514 ] + walkopts + subrepoopts + formatteropts,
5513 ] + walkopts + subrepoopts + formatteropts,
5515 _('[OPTION]... [FILE]...'),
5514 _('[OPTION]... [FILE]...'),
5516 inferrepo=True)
5515 inferrepo=True)
5517 def status(ui, repo, *pats, **opts):
5516 def status(ui, repo, *pats, **opts):
5518 """show changed files in the working directory
5517 """show changed files in the working directory
5519
5518
5520 Show status of files in the repository. If names are given, only
5519 Show status of files in the repository. If names are given, only
5521 files that match are shown. Files that are clean or ignored or
5520 files that match are shown. Files that are clean or ignored or
5522 the source of a copy/move operation, are not listed unless
5521 the source of a copy/move operation, are not listed unless
5523 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5522 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5524 Unless options described with "show only ..." are given, the
5523 Unless options described with "show only ..." are given, the
5525 options -mardu are used.
5524 options -mardu are used.
5526
5525
5527 Option -q/--quiet hides untracked (unknown and ignored) files
5526 Option -q/--quiet hides untracked (unknown and ignored) files
5528 unless explicitly requested with -u/--unknown or -i/--ignored.
5527 unless explicitly requested with -u/--unknown or -i/--ignored.
5529
5528
5530 .. note::
5529 .. note::
5531
5530
5532 status may appear to disagree with diff if permissions have
5531 status may appear to disagree with diff if permissions have
5533 changed or a merge has occurred. The standard diff format does
5532 changed or a merge has occurred. The standard diff format does
5534 not report permission changes and diff only reports changes
5533 not report permission changes and diff only reports changes
5535 relative to one merge parent.
5534 relative to one merge parent.
5536
5535
5537 If one revision is given, it is used as the base revision.
5536 If one revision is given, it is used as the base revision.
5538 If two revisions are given, the differences between them are
5537 If two revisions are given, the differences between them are
5539 shown. The --change option can also be used as a shortcut to list
5538 shown. The --change option can also be used as a shortcut to list
5540 the changed files of a revision from its first parent.
5539 the changed files of a revision from its first parent.
5541
5540
5542 The codes used to show the status of files are::
5541 The codes used to show the status of files are::
5543
5542
5544 M = modified
5543 M = modified
5545 A = added
5544 A = added
5546 R = removed
5545 R = removed
5547 C = clean
5546 C = clean
5548 ! = missing (deleted by non-hg command, but still tracked)
5547 ! = missing (deleted by non-hg command, but still tracked)
5549 ? = not tracked
5548 ? = not tracked
5550 I = ignored
5549 I = ignored
5551 = origin of the previous file (with --copies)
5550 = origin of the previous file (with --copies)
5552
5551
5553 .. container:: verbose
5552 .. container:: verbose
5554
5553
5555 Examples:
5554 Examples:
5556
5555
5557 - show changes in the working directory relative to a
5556 - show changes in the working directory relative to a
5558 changeset::
5557 changeset::
5559
5558
5560 hg status --rev 9353
5559 hg status --rev 9353
5561
5560
5562 - show all changes including copies in an existing changeset::
5561 - show all changes including copies in an existing changeset::
5563
5562
5564 hg status --copies --change 9353
5563 hg status --copies --change 9353
5565
5564
5566 - get a NUL separated list of added files, suitable for xargs::
5565 - get a NUL separated list of added files, suitable for xargs::
5567
5566
5568 hg status -an0
5567 hg status -an0
5569
5568
5570 Returns 0 on success.
5569 Returns 0 on success.
5571 """
5570 """
5572
5571
5573 revs = opts.get('rev')
5572 revs = opts.get('rev')
5574 change = opts.get('change')
5573 change = opts.get('change')
5575
5574
5576 if revs and change:
5575 if revs and change:
5577 msg = _('cannot specify --rev and --change at the same time')
5576 msg = _('cannot specify --rev and --change at the same time')
5578 raise util.Abort(msg)
5577 raise util.Abort(msg)
5579 elif change:
5578 elif change:
5580 node2 = scmutil.revsingle(repo, change, None).node()
5579 node2 = scmutil.revsingle(repo, change, None).node()
5581 node1 = repo[node2].p1().node()
5580 node1 = repo[node2].p1().node()
5582 else:
5581 else:
5583 node1, node2 = scmutil.revpair(repo, revs)
5582 node1, node2 = scmutil.revpair(repo, revs)
5584
5583
5585 cwd = (pats and repo.getcwd()) or ''
5584 cwd = (pats and repo.getcwd()) or ''
5586 end = opts.get('print0') and '\0' or '\n'
5585 end = opts.get('print0') and '\0' or '\n'
5587 copy = {}
5586 copy = {}
5588 states = 'modified added removed deleted unknown ignored clean'.split()
5587 states = 'modified added removed deleted unknown ignored clean'.split()
5589 show = [k for k in states if opts.get(k)]
5588 show = [k for k in states if opts.get(k)]
5590 if opts.get('all'):
5589 if opts.get('all'):
5591 show += ui.quiet and (states[:4] + ['clean']) or states
5590 show += ui.quiet and (states[:4] + ['clean']) or states
5592 if not show:
5591 if not show:
5593 show = ui.quiet and states[:4] or states[:5]
5592 show = ui.quiet and states[:4] or states[:5]
5594
5593
5595 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5594 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5596 'ignored' in show, 'clean' in show, 'unknown' in show,
5595 'ignored' in show, 'clean' in show, 'unknown' in show,
5597 opts.get('subrepos'))
5596 opts.get('subrepos'))
5598 changestates = zip(states, 'MAR!?IC', stat)
5597 changestates = zip(states, 'MAR!?IC', stat)
5599
5598
5600 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5599 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5601 copy = copies.pathcopies(repo[node1], repo[node2])
5600 copy = copies.pathcopies(repo[node1], repo[node2])
5602
5601
5603 fm = ui.formatter('status', opts)
5602 fm = ui.formatter('status', opts)
5604 fmt = '%s' + end
5603 fmt = '%s' + end
5605 showchar = not opts.get('no_status')
5604 showchar = not opts.get('no_status')
5606
5605
5607 for state, char, files in changestates:
5606 for state, char, files in changestates:
5608 if state in show:
5607 if state in show:
5609 label = 'status.' + state
5608 label = 'status.' + state
5610 for f in files:
5609 for f in files:
5611 fm.startitem()
5610 fm.startitem()
5612 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5611 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5613 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5612 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5614 if f in copy:
5613 if f in copy:
5615 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5614 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5616 label='status.copied')
5615 label='status.copied')
5617 fm.end()
5616 fm.end()
5618
5617
5619 @command('^summary|sum',
5618 @command('^summary|sum',
5620 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5619 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5621 def summary(ui, repo, **opts):
5620 def summary(ui, repo, **opts):
5622 """summarize working directory state
5621 """summarize working directory state
5623
5622
5624 This generates a brief summary of the working directory state,
5623 This generates a brief summary of the working directory state,
5625 including parents, branch, commit status, and available updates.
5624 including parents, branch, commit status, and available updates.
5626
5625
5627 With the --remote option, this will check the default paths for
5626 With the --remote option, this will check the default paths for
5628 incoming and outgoing changes. This can be time-consuming.
5627 incoming and outgoing changes. This can be time-consuming.
5629
5628
5630 Returns 0 on success.
5629 Returns 0 on success.
5631 """
5630 """
5632
5631
5633 ctx = repo[None]
5632 ctx = repo[None]
5634 parents = ctx.parents()
5633 parents = ctx.parents()
5635 pnode = parents[0].node()
5634 pnode = parents[0].node()
5636 marks = []
5635 marks = []
5637
5636
5638 for p in parents:
5637 for p in parents:
5639 # label with log.changeset (instead of log.parent) since this
5638 # label with log.changeset (instead of log.parent) since this
5640 # shows a working directory parent *changeset*:
5639 # shows a working directory parent *changeset*:
5641 # i18n: column positioning for "hg summary"
5640 # i18n: column positioning for "hg summary"
5642 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5641 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5643 label='log.changeset changeset.%s' % p.phasestr())
5642 label='log.changeset changeset.%s' % p.phasestr())
5644 ui.write(' '.join(p.tags()), label='log.tag')
5643 ui.write(' '.join(p.tags()), label='log.tag')
5645 if p.bookmarks():
5644 if p.bookmarks():
5646 marks.extend(p.bookmarks())
5645 marks.extend(p.bookmarks())
5647 if p.rev() == -1:
5646 if p.rev() == -1:
5648 if not len(repo):
5647 if not len(repo):
5649 ui.write(_(' (empty repository)'))
5648 ui.write(_(' (empty repository)'))
5650 else:
5649 else:
5651 ui.write(_(' (no revision checked out)'))
5650 ui.write(_(' (no revision checked out)'))
5652 ui.write('\n')
5651 ui.write('\n')
5653 if p.description():
5652 if p.description():
5654 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5653 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5655 label='log.summary')
5654 label='log.summary')
5656
5655
5657 branch = ctx.branch()
5656 branch = ctx.branch()
5658 bheads = repo.branchheads(branch)
5657 bheads = repo.branchheads(branch)
5659 # i18n: column positioning for "hg summary"
5658 # i18n: column positioning for "hg summary"
5660 m = _('branch: %s\n') % branch
5659 m = _('branch: %s\n') % branch
5661 if branch != 'default':
5660 if branch != 'default':
5662 ui.write(m, label='log.branch')
5661 ui.write(m, label='log.branch')
5663 else:
5662 else:
5664 ui.status(m, label='log.branch')
5663 ui.status(m, label='log.branch')
5665
5664
5666 if marks:
5665 if marks:
5667 current = repo._bookmarkcurrent
5666 current = repo._bookmarkcurrent
5668 # i18n: column positioning for "hg summary"
5667 # i18n: column positioning for "hg summary"
5669 ui.write(_('bookmarks:'), label='log.bookmark')
5668 ui.write(_('bookmarks:'), label='log.bookmark')
5670 if current is not None:
5669 if current is not None:
5671 if current in marks:
5670 if current in marks:
5672 ui.write(' *' + current, label='bookmarks.current')
5671 ui.write(' *' + current, label='bookmarks.current')
5673 marks.remove(current)
5672 marks.remove(current)
5674 else:
5673 else:
5675 ui.write(' [%s]' % current, label='bookmarks.current')
5674 ui.write(' [%s]' % current, label='bookmarks.current')
5676 for m in marks:
5675 for m in marks:
5677 ui.write(' ' + m, label='log.bookmark')
5676 ui.write(' ' + m, label='log.bookmark')
5678 ui.write('\n', label='log.bookmark')
5677 ui.write('\n', label='log.bookmark')
5679
5678
5680 st = list(repo.status(unknown=True))[:6]
5679 st = list(repo.status(unknown=True))[:6]
5681
5680
5682 c = repo.dirstate.copies()
5681 c = repo.dirstate.copies()
5683 copied, renamed = [], []
5682 copied, renamed = [], []
5684 for d, s in c.iteritems():
5683 for d, s in c.iteritems():
5685 if s in st[2]:
5684 if s in st[2]:
5686 st[2].remove(s)
5685 st[2].remove(s)
5687 renamed.append(d)
5686 renamed.append(d)
5688 else:
5687 else:
5689 copied.append(d)
5688 copied.append(d)
5690 if d in st[1]:
5689 if d in st[1]:
5691 st[1].remove(d)
5690 st[1].remove(d)
5692 st.insert(3, renamed)
5691 st.insert(3, renamed)
5693 st.insert(4, copied)
5692 st.insert(4, copied)
5694
5693
5695 ms = mergemod.mergestate(repo)
5694 ms = mergemod.mergestate(repo)
5696 st.append([f for f in ms if ms[f] == 'u'])
5695 st.append([f for f in ms if ms[f] == 'u'])
5697
5696
5698 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5697 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5699 st.append(subs)
5698 st.append(subs)
5700
5699
5701 labels = [ui.label(_('%d modified'), 'status.modified'),
5700 labels = [ui.label(_('%d modified'), 'status.modified'),
5702 ui.label(_('%d added'), 'status.added'),
5701 ui.label(_('%d added'), 'status.added'),
5703 ui.label(_('%d removed'), 'status.removed'),
5702 ui.label(_('%d removed'), 'status.removed'),
5704 ui.label(_('%d renamed'), 'status.copied'),
5703 ui.label(_('%d renamed'), 'status.copied'),
5705 ui.label(_('%d copied'), 'status.copied'),
5704 ui.label(_('%d copied'), 'status.copied'),
5706 ui.label(_('%d deleted'), 'status.deleted'),
5705 ui.label(_('%d deleted'), 'status.deleted'),
5707 ui.label(_('%d unknown'), 'status.unknown'),
5706 ui.label(_('%d unknown'), 'status.unknown'),
5708 ui.label(_('%d ignored'), 'status.ignored'),
5707 ui.label(_('%d ignored'), 'status.ignored'),
5709 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5708 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5710 ui.label(_('%d subrepos'), 'status.modified')]
5709 ui.label(_('%d subrepos'), 'status.modified')]
5711 t = []
5710 t = []
5712 for s, l in zip(st, labels):
5711 for s, l in zip(st, labels):
5713 if s:
5712 if s:
5714 t.append(l % len(s))
5713 t.append(l % len(s))
5715
5714
5716 t = ', '.join(t)
5715 t = ', '.join(t)
5717 cleanworkdir = False
5716 cleanworkdir = False
5718
5717
5719 if repo.vfs.exists('updatestate'):
5718 if repo.vfs.exists('updatestate'):
5720 t += _(' (interrupted update)')
5719 t += _(' (interrupted update)')
5721 elif len(parents) > 1:
5720 elif len(parents) > 1:
5722 t += _(' (merge)')
5721 t += _(' (merge)')
5723 elif branch != parents[0].branch():
5722 elif branch != parents[0].branch():
5724 t += _(' (new branch)')
5723 t += _(' (new branch)')
5725 elif (parents[0].closesbranch() and
5724 elif (parents[0].closesbranch() and
5726 pnode in repo.branchheads(branch, closed=True)):
5725 pnode in repo.branchheads(branch, closed=True)):
5727 t += _(' (head closed)')
5726 t += _(' (head closed)')
5728 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5727 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5729 t += _(' (clean)')
5728 t += _(' (clean)')
5730 cleanworkdir = True
5729 cleanworkdir = True
5731 elif pnode not in bheads:
5730 elif pnode not in bheads:
5732 t += _(' (new branch head)')
5731 t += _(' (new branch head)')
5733
5732
5734 if cleanworkdir:
5733 if cleanworkdir:
5735 # i18n: column positioning for "hg summary"
5734 # i18n: column positioning for "hg summary"
5736 ui.status(_('commit: %s\n') % t.strip())
5735 ui.status(_('commit: %s\n') % t.strip())
5737 else:
5736 else:
5738 # i18n: column positioning for "hg summary"
5737 # i18n: column positioning for "hg summary"
5739 ui.write(_('commit: %s\n') % t.strip())
5738 ui.write(_('commit: %s\n') % t.strip())
5740
5739
5741 # all ancestors of branch heads - all ancestors of parent = new csets
5740 # all ancestors of branch heads - all ancestors of parent = new csets
5742 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5741 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5743 bheads))
5742 bheads))
5744
5743
5745 if new == 0:
5744 if new == 0:
5746 # i18n: column positioning for "hg summary"
5745 # i18n: column positioning for "hg summary"
5747 ui.status(_('update: (current)\n'))
5746 ui.status(_('update: (current)\n'))
5748 elif pnode not in bheads:
5747 elif pnode not in bheads:
5749 # i18n: column positioning for "hg summary"
5748 # i18n: column positioning for "hg summary"
5750 ui.write(_('update: %d new changesets (update)\n') % new)
5749 ui.write(_('update: %d new changesets (update)\n') % new)
5751 else:
5750 else:
5752 # i18n: column positioning for "hg summary"
5751 # i18n: column positioning for "hg summary"
5753 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5752 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5754 (new, len(bheads)))
5753 (new, len(bheads)))
5755
5754
5756 cmdutil.summaryhooks(ui, repo)
5755 cmdutil.summaryhooks(ui, repo)
5757
5756
5758 if opts.get('remote'):
5757 if opts.get('remote'):
5759 needsincoming, needsoutgoing = True, True
5758 needsincoming, needsoutgoing = True, True
5760 else:
5759 else:
5761 needsincoming, needsoutgoing = False, False
5760 needsincoming, needsoutgoing = False, False
5762 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5761 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5763 if i:
5762 if i:
5764 needsincoming = True
5763 needsincoming = True
5765 if o:
5764 if o:
5766 needsoutgoing = True
5765 needsoutgoing = True
5767 if not needsincoming and not needsoutgoing:
5766 if not needsincoming and not needsoutgoing:
5768 return
5767 return
5769
5768
5770 def getincoming():
5769 def getincoming():
5771 source, branches = hg.parseurl(ui.expandpath('default'))
5770 source, branches = hg.parseurl(ui.expandpath('default'))
5772 sbranch = branches[0]
5771 sbranch = branches[0]
5773 try:
5772 try:
5774 other = hg.peer(repo, {}, source)
5773 other = hg.peer(repo, {}, source)
5775 except error.RepoError:
5774 except error.RepoError:
5776 if opts.get('remote'):
5775 if opts.get('remote'):
5777 raise
5776 raise
5778 return source, sbranch, None, None, None
5777 return source, sbranch, None, None, None
5779 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5778 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5780 if revs:
5779 if revs:
5781 revs = [other.lookup(rev) for rev in revs]
5780 revs = [other.lookup(rev) for rev in revs]
5782 ui.debug('comparing with %s\n' % util.hidepassword(source))
5781 ui.debug('comparing with %s\n' % util.hidepassword(source))
5783 repo.ui.pushbuffer()
5782 repo.ui.pushbuffer()
5784 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5783 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5785 repo.ui.popbuffer()
5784 repo.ui.popbuffer()
5786 return source, sbranch, other, commoninc, commoninc[1]
5785 return source, sbranch, other, commoninc, commoninc[1]
5787
5786
5788 if needsincoming:
5787 if needsincoming:
5789 source, sbranch, sother, commoninc, incoming = getincoming()
5788 source, sbranch, sother, commoninc, incoming = getincoming()
5790 else:
5789 else:
5791 source = sbranch = sother = commoninc = incoming = None
5790 source = sbranch = sother = commoninc = incoming = None
5792
5791
5793 def getoutgoing():
5792 def getoutgoing():
5794 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5793 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5795 dbranch = branches[0]
5794 dbranch = branches[0]
5796 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5795 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5797 if source != dest:
5796 if source != dest:
5798 try:
5797 try:
5799 dother = hg.peer(repo, {}, dest)
5798 dother = hg.peer(repo, {}, dest)
5800 except error.RepoError:
5799 except error.RepoError:
5801 if opts.get('remote'):
5800 if opts.get('remote'):
5802 raise
5801 raise
5803 return dest, dbranch, None, None
5802 return dest, dbranch, None, None
5804 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5803 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5805 elif sother is None:
5804 elif sother is None:
5806 # there is no explicit destination peer, but source one is invalid
5805 # there is no explicit destination peer, but source one is invalid
5807 return dest, dbranch, None, None
5806 return dest, dbranch, None, None
5808 else:
5807 else:
5809 dother = sother
5808 dother = sother
5810 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5809 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5811 common = None
5810 common = None
5812 else:
5811 else:
5813 common = commoninc
5812 common = commoninc
5814 if revs:
5813 if revs:
5815 revs = [repo.lookup(rev) for rev in revs]
5814 revs = [repo.lookup(rev) for rev in revs]
5816 repo.ui.pushbuffer()
5815 repo.ui.pushbuffer()
5817 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5816 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5818 commoninc=common)
5817 commoninc=common)
5819 repo.ui.popbuffer()
5818 repo.ui.popbuffer()
5820 return dest, dbranch, dother, outgoing
5819 return dest, dbranch, dother, outgoing
5821
5820
5822 if needsoutgoing:
5821 if needsoutgoing:
5823 dest, dbranch, dother, outgoing = getoutgoing()
5822 dest, dbranch, dother, outgoing = getoutgoing()
5824 else:
5823 else:
5825 dest = dbranch = dother = outgoing = None
5824 dest = dbranch = dother = outgoing = None
5826
5825
5827 if opts.get('remote'):
5826 if opts.get('remote'):
5828 t = []
5827 t = []
5829 if incoming:
5828 if incoming:
5830 t.append(_('1 or more incoming'))
5829 t.append(_('1 or more incoming'))
5831 o = outgoing.missing
5830 o = outgoing.missing
5832 if o:
5831 if o:
5833 t.append(_('%d outgoing') % len(o))
5832 t.append(_('%d outgoing') % len(o))
5834 other = dother or sother
5833 other = dother or sother
5835 if 'bookmarks' in other.listkeys('namespaces'):
5834 if 'bookmarks' in other.listkeys('namespaces'):
5836 lmarks = repo.listkeys('bookmarks')
5835 lmarks = repo.listkeys('bookmarks')
5837 rmarks = other.listkeys('bookmarks')
5836 rmarks = other.listkeys('bookmarks')
5838 diff = set(rmarks) - set(lmarks)
5837 diff = set(rmarks) - set(lmarks)
5839 if len(diff) > 0:
5838 if len(diff) > 0:
5840 t.append(_('%d incoming bookmarks') % len(diff))
5839 t.append(_('%d incoming bookmarks') % len(diff))
5841 diff = set(lmarks) - set(rmarks)
5840 diff = set(lmarks) - set(rmarks)
5842 if len(diff) > 0:
5841 if len(diff) > 0:
5843 t.append(_('%d outgoing bookmarks') % len(diff))
5842 t.append(_('%d outgoing bookmarks') % len(diff))
5844
5843
5845 if t:
5844 if t:
5846 # i18n: column positioning for "hg summary"
5845 # i18n: column positioning for "hg summary"
5847 ui.write(_('remote: %s\n') % (', '.join(t)))
5846 ui.write(_('remote: %s\n') % (', '.join(t)))
5848 else:
5847 else:
5849 # i18n: column positioning for "hg summary"
5848 # i18n: column positioning for "hg summary"
5850 ui.status(_('remote: (synced)\n'))
5849 ui.status(_('remote: (synced)\n'))
5851
5850
5852 cmdutil.summaryremotehooks(ui, repo, opts,
5851 cmdutil.summaryremotehooks(ui, repo, opts,
5853 ((source, sbranch, sother, commoninc),
5852 ((source, sbranch, sother, commoninc),
5854 (dest, dbranch, dother, outgoing)))
5853 (dest, dbranch, dother, outgoing)))
5855
5854
5856 @command('tag',
5855 @command('tag',
5857 [('f', 'force', None, _('force tag')),
5856 [('f', 'force', None, _('force tag')),
5858 ('l', 'local', None, _('make the tag local')),
5857 ('l', 'local', None, _('make the tag local')),
5859 ('r', 'rev', '', _('revision to tag'), _('REV')),
5858 ('r', 'rev', '', _('revision to tag'), _('REV')),
5860 ('', 'remove', None, _('remove a tag')),
5859 ('', 'remove', None, _('remove a tag')),
5861 # -l/--local is already there, commitopts cannot be used
5860 # -l/--local is already there, commitopts cannot be used
5862 ('e', 'edit', None, _('invoke editor on commit messages')),
5861 ('e', 'edit', None, _('invoke editor on commit messages')),
5863 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5862 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5864 ] + commitopts2,
5863 ] + commitopts2,
5865 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5864 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5866 def tag(ui, repo, name1, *names, **opts):
5865 def tag(ui, repo, name1, *names, **opts):
5867 """add one or more tags for the current or given revision
5866 """add one or more tags for the current or given revision
5868
5867
5869 Name a particular revision using <name>.
5868 Name a particular revision using <name>.
5870
5869
5871 Tags are used to name particular revisions of the repository and are
5870 Tags are used to name particular revisions of the repository and are
5872 very useful to compare different revisions, to go back to significant
5871 very useful to compare different revisions, to go back to significant
5873 earlier versions or to mark branch points as releases, etc. Changing
5872 earlier versions or to mark branch points as releases, etc. Changing
5874 an existing tag is normally disallowed; use -f/--force to override.
5873 an existing tag is normally disallowed; use -f/--force to override.
5875
5874
5876 If no revision is given, the parent of the working directory is
5875 If no revision is given, the parent of the working directory is
5877 used.
5876 used.
5878
5877
5879 To facilitate version control, distribution, and merging of tags,
5878 To facilitate version control, distribution, and merging of tags,
5880 they are stored as a file named ".hgtags" which is managed similarly
5879 they are stored as a file named ".hgtags" which is managed similarly
5881 to other project files and can be hand-edited if necessary. This
5880 to other project files and can be hand-edited if necessary. This
5882 also means that tagging creates a new commit. The file
5881 also means that tagging creates a new commit. The file
5883 ".hg/localtags" is used for local tags (not shared among
5882 ".hg/localtags" is used for local tags (not shared among
5884 repositories).
5883 repositories).
5885
5884
5886 Tag commits are usually made at the head of a branch. If the parent
5885 Tag commits are usually made at the head of a branch. If the parent
5887 of the working directory is not a branch head, :hg:`tag` aborts; use
5886 of the working directory is not a branch head, :hg:`tag` aborts; use
5888 -f/--force to force the tag commit to be based on a non-head
5887 -f/--force to force the tag commit to be based on a non-head
5889 changeset.
5888 changeset.
5890
5889
5891 See :hg:`help dates` for a list of formats valid for -d/--date.
5890 See :hg:`help dates` for a list of formats valid for -d/--date.
5892
5891
5893 Since tag names have priority over branch names during revision
5892 Since tag names have priority over branch names during revision
5894 lookup, using an existing branch name as a tag name is discouraged.
5893 lookup, using an existing branch name as a tag name is discouraged.
5895
5894
5896 Returns 0 on success.
5895 Returns 0 on success.
5897 """
5896 """
5898 wlock = lock = None
5897 wlock = lock = None
5899 try:
5898 try:
5900 wlock = repo.wlock()
5899 wlock = repo.wlock()
5901 lock = repo.lock()
5900 lock = repo.lock()
5902 rev_ = "."
5901 rev_ = "."
5903 names = [t.strip() for t in (name1,) + names]
5902 names = [t.strip() for t in (name1,) + names]
5904 if len(names) != len(set(names)):
5903 if len(names) != len(set(names)):
5905 raise util.Abort(_('tag names must be unique'))
5904 raise util.Abort(_('tag names must be unique'))
5906 for n in names:
5905 for n in names:
5907 scmutil.checknewlabel(repo, n, 'tag')
5906 scmutil.checknewlabel(repo, n, 'tag')
5908 if not n:
5907 if not n:
5909 raise util.Abort(_('tag names cannot consist entirely of '
5908 raise util.Abort(_('tag names cannot consist entirely of '
5910 'whitespace'))
5909 'whitespace'))
5911 if opts.get('rev') and opts.get('remove'):
5910 if opts.get('rev') and opts.get('remove'):
5912 raise util.Abort(_("--rev and --remove are incompatible"))
5911 raise util.Abort(_("--rev and --remove are incompatible"))
5913 if opts.get('rev'):
5912 if opts.get('rev'):
5914 rev_ = opts['rev']
5913 rev_ = opts['rev']
5915 message = opts.get('message')
5914 message = opts.get('message')
5916 if opts.get('remove'):
5915 if opts.get('remove'):
5917 expectedtype = opts.get('local') and 'local' or 'global'
5916 expectedtype = opts.get('local') and 'local' or 'global'
5918 for n in names:
5917 for n in names:
5919 if not repo.tagtype(n):
5918 if not repo.tagtype(n):
5920 raise util.Abort(_("tag '%s' does not exist") % n)
5919 raise util.Abort(_("tag '%s' does not exist") % n)
5921 if repo.tagtype(n) != expectedtype:
5920 if repo.tagtype(n) != expectedtype:
5922 if expectedtype == 'global':
5921 if expectedtype == 'global':
5923 raise util.Abort(_("tag '%s' is not a global tag") % n)
5922 raise util.Abort(_("tag '%s' is not a global tag") % n)
5924 else:
5923 else:
5925 raise util.Abort(_("tag '%s' is not a local tag") % n)
5924 raise util.Abort(_("tag '%s' is not a local tag") % n)
5926 rev_ = nullid
5925 rev_ = nullid
5927 if not message:
5926 if not message:
5928 # we don't translate commit messages
5927 # we don't translate commit messages
5929 message = 'Removed tag %s' % ', '.join(names)
5928 message = 'Removed tag %s' % ', '.join(names)
5930 elif not opts.get('force'):
5929 elif not opts.get('force'):
5931 for n in names:
5930 for n in names:
5932 if n in repo.tags():
5931 if n in repo.tags():
5933 raise util.Abort(_("tag '%s' already exists "
5932 raise util.Abort(_("tag '%s' already exists "
5934 "(use -f to force)") % n)
5933 "(use -f to force)") % n)
5935 if not opts.get('local'):
5934 if not opts.get('local'):
5936 p1, p2 = repo.dirstate.parents()
5935 p1, p2 = repo.dirstate.parents()
5937 if p2 != nullid:
5936 if p2 != nullid:
5938 raise util.Abort(_('uncommitted merge'))
5937 raise util.Abort(_('uncommitted merge'))
5939 bheads = repo.branchheads()
5938 bheads = repo.branchheads()
5940 if not opts.get('force') and bheads and p1 not in bheads:
5939 if not opts.get('force') and bheads and p1 not in bheads:
5941 raise util.Abort(_('not at a branch head (use -f to force)'))
5940 raise util.Abort(_('not at a branch head (use -f to force)'))
5942 r = scmutil.revsingle(repo, rev_).node()
5941 r = scmutil.revsingle(repo, rev_).node()
5943
5942
5944 if not message:
5943 if not message:
5945 # we don't translate commit messages
5944 # we don't translate commit messages
5946 message = ('Added tag %s for changeset %s' %
5945 message = ('Added tag %s for changeset %s' %
5947 (', '.join(names), short(r)))
5946 (', '.join(names), short(r)))
5948
5947
5949 date = opts.get('date')
5948 date = opts.get('date')
5950 if date:
5949 if date:
5951 date = util.parsedate(date)
5950 date = util.parsedate(date)
5952
5951
5953 if opts.get('remove'):
5952 if opts.get('remove'):
5954 editform = 'tag.remove'
5953 editform = 'tag.remove'
5955 else:
5954 else:
5956 editform = 'tag.add'
5955 editform = 'tag.add'
5957 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5956 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5958
5957
5959 # don't allow tagging the null rev
5958 # don't allow tagging the null rev
5960 if (not opts.get('remove') and
5959 if (not opts.get('remove') and
5961 scmutil.revsingle(repo, rev_).rev() == nullrev):
5960 scmutil.revsingle(repo, rev_).rev() == nullrev):
5962 raise util.Abort(_("cannot tag null revision"))
5961 raise util.Abort(_("cannot tag null revision"))
5963
5962
5964 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5963 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5965 editor=editor)
5964 editor=editor)
5966 finally:
5965 finally:
5967 release(lock, wlock)
5966 release(lock, wlock)
5968
5967
5969 @command('tags', formatteropts, '')
5968 @command('tags', formatteropts, '')
5970 def tags(ui, repo, **opts):
5969 def tags(ui, repo, **opts):
5971 """list repository tags
5970 """list repository tags
5972
5971
5973 This lists both regular and local tags. When the -v/--verbose
5972 This lists both regular and local tags. When the -v/--verbose
5974 switch is used, a third column "local" is printed for local tags.
5973 switch is used, a third column "local" is printed for local tags.
5975
5974
5976 Returns 0 on success.
5975 Returns 0 on success.
5977 """
5976 """
5978
5977
5979 fm = ui.formatter('tags', opts)
5978 fm = ui.formatter('tags', opts)
5980 hexfunc = ui.debugflag and hex or short
5979 hexfunc = ui.debugflag and hex or short
5981 tagtype = ""
5980 tagtype = ""
5982
5981
5983 for t, n in reversed(repo.tagslist()):
5982 for t, n in reversed(repo.tagslist()):
5984 hn = hexfunc(n)
5983 hn = hexfunc(n)
5985 label = 'tags.normal'
5984 label = 'tags.normal'
5986 tagtype = ''
5985 tagtype = ''
5987 if repo.tagtype(t) == 'local':
5986 if repo.tagtype(t) == 'local':
5988 label = 'tags.local'
5987 label = 'tags.local'
5989 tagtype = 'local'
5988 tagtype = 'local'
5990
5989
5991 fm.startitem()
5990 fm.startitem()
5992 fm.write('tag', '%s', t, label=label)
5991 fm.write('tag', '%s', t, label=label)
5993 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5992 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5994 fm.condwrite(not ui.quiet, 'rev id', fmt,
5993 fm.condwrite(not ui.quiet, 'rev id', fmt,
5995 repo.changelog.rev(n), hn, label=label)
5994 repo.changelog.rev(n), hn, label=label)
5996 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5995 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5997 tagtype, label=label)
5996 tagtype, label=label)
5998 fm.plain('\n')
5997 fm.plain('\n')
5999 fm.end()
5998 fm.end()
6000
5999
6001 @command('tip',
6000 @command('tip',
6002 [('p', 'patch', None, _('show patch')),
6001 [('p', 'patch', None, _('show patch')),
6003 ('g', 'git', None, _('use git extended diff format')),
6002 ('g', 'git', None, _('use git extended diff format')),
6004 ] + templateopts,
6003 ] + templateopts,
6005 _('[-p] [-g]'))
6004 _('[-p] [-g]'))
6006 def tip(ui, repo, **opts):
6005 def tip(ui, repo, **opts):
6007 """show the tip revision (DEPRECATED)
6006 """show the tip revision (DEPRECATED)
6008
6007
6009 The tip revision (usually just called the tip) is the changeset
6008 The tip revision (usually just called the tip) is the changeset
6010 most recently added to the repository (and therefore the most
6009 most recently added to the repository (and therefore the most
6011 recently changed head).
6010 recently changed head).
6012
6011
6013 If you have just made a commit, that commit will be the tip. If
6012 If you have just made a commit, that commit will be the tip. If
6014 you have just pulled changes from another repository, the tip of
6013 you have just pulled changes from another repository, the tip of
6015 that repository becomes the current tip. The "tip" tag is special
6014 that repository becomes the current tip. The "tip" tag is special
6016 and cannot be renamed or assigned to a different changeset.
6015 and cannot be renamed or assigned to a different changeset.
6017
6016
6018 This command is deprecated, please use :hg:`heads` instead.
6017 This command is deprecated, please use :hg:`heads` instead.
6019
6018
6020 Returns 0 on success.
6019 Returns 0 on success.
6021 """
6020 """
6022 displayer = cmdutil.show_changeset(ui, repo, opts)
6021 displayer = cmdutil.show_changeset(ui, repo, opts)
6023 displayer.show(repo['tip'])
6022 displayer.show(repo['tip'])
6024 displayer.close()
6023 displayer.close()
6025
6024
6026 @command('unbundle',
6025 @command('unbundle',
6027 [('u', 'update', None,
6026 [('u', 'update', None,
6028 _('update to new branch head if changesets were unbundled'))],
6027 _('update to new branch head if changesets were unbundled'))],
6029 _('[-u] FILE...'))
6028 _('[-u] FILE...'))
6030 def unbundle(ui, repo, fname1, *fnames, **opts):
6029 def unbundle(ui, repo, fname1, *fnames, **opts):
6031 """apply one or more changegroup files
6030 """apply one or more changegroup files
6032
6031
6033 Apply one or more compressed changegroup files generated by the
6032 Apply one or more compressed changegroup files generated by the
6034 bundle command.
6033 bundle command.
6035
6034
6036 Returns 0 on success, 1 if an update has unresolved files.
6035 Returns 0 on success, 1 if an update has unresolved files.
6037 """
6036 """
6038 fnames = (fname1,) + fnames
6037 fnames = (fname1,) + fnames
6039
6038
6040 lock = repo.lock()
6039 lock = repo.lock()
6041 try:
6040 try:
6042 for fname in fnames:
6041 for fname in fnames:
6043 f = hg.openpath(ui, fname)
6042 f = hg.openpath(ui, fname)
6044 gen = exchange.readbundle(ui, f, fname)
6043 gen = exchange.readbundle(ui, f, fname)
6045 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6044 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6046 'bundle:' + fname)
6045 'bundle:' + fname)
6047 finally:
6046 finally:
6048 lock.release()
6047 lock.release()
6049
6048
6050 return postincoming(ui, repo, modheads, opts.get('update'), None)
6049 return postincoming(ui, repo, modheads, opts.get('update'), None)
6051
6050
6052 @command('^update|up|checkout|co',
6051 @command('^update|up|checkout|co',
6053 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6052 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6054 ('c', 'check', None,
6053 ('c', 'check', None,
6055 _('update across branches if no uncommitted changes')),
6054 _('update across branches if no uncommitted changes')),
6056 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6055 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6057 ('r', 'rev', '', _('revision'), _('REV'))
6056 ('r', 'rev', '', _('revision'), _('REV'))
6058 ] + mergetoolopts,
6057 ] + mergetoolopts,
6059 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6058 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6060 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6059 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6061 tool=None):
6060 tool=None):
6062 """update working directory (or switch revisions)
6061 """update working directory (or switch revisions)
6063
6062
6064 Update the repository's working directory to the specified
6063 Update the repository's working directory to the specified
6065 changeset. If no changeset is specified, update to the tip of the
6064 changeset. If no changeset is specified, update to the tip of the
6066 current named branch and move the current bookmark (see :hg:`help
6065 current named branch and move the current bookmark (see :hg:`help
6067 bookmarks`).
6066 bookmarks`).
6068
6067
6069 Update sets the working directory's parent revision to the specified
6068 Update sets the working directory's parent revision to the specified
6070 changeset (see :hg:`help parents`).
6069 changeset (see :hg:`help parents`).
6071
6070
6072 If the changeset is not a descendant or ancestor of the working
6071 If the changeset is not a descendant or ancestor of the working
6073 directory's parent, the update is aborted. With the -c/--check
6072 directory's parent, the update is aborted. With the -c/--check
6074 option, the working directory is checked for uncommitted changes; if
6073 option, the working directory is checked for uncommitted changes; if
6075 none are found, the working directory is updated to the specified
6074 none are found, the working directory is updated to the specified
6076 changeset.
6075 changeset.
6077
6076
6078 .. container:: verbose
6077 .. container:: verbose
6079
6078
6080 The following rules apply when the working directory contains
6079 The following rules apply when the working directory contains
6081 uncommitted changes:
6080 uncommitted changes:
6082
6081
6083 1. If neither -c/--check nor -C/--clean is specified, and if
6082 1. If neither -c/--check nor -C/--clean is specified, and if
6084 the requested changeset is an ancestor or descendant of
6083 the requested changeset is an ancestor or descendant of
6085 the working directory's parent, the uncommitted changes
6084 the working directory's parent, the uncommitted changes
6086 are merged into the requested changeset and the merged
6085 are merged into the requested changeset and the merged
6087 result is left uncommitted. If the requested changeset is
6086 result is left uncommitted. If the requested changeset is
6088 not an ancestor or descendant (that is, it is on another
6087 not an ancestor or descendant (that is, it is on another
6089 branch), the update is aborted and the uncommitted changes
6088 branch), the update is aborted and the uncommitted changes
6090 are preserved.
6089 are preserved.
6091
6090
6092 2. With the -c/--check option, the update is aborted and the
6091 2. With the -c/--check option, the update is aborted and the
6093 uncommitted changes are preserved.
6092 uncommitted changes are preserved.
6094
6093
6095 3. With the -C/--clean option, uncommitted changes are discarded and
6094 3. With the -C/--clean option, uncommitted changes are discarded and
6096 the working directory is updated to the requested changeset.
6095 the working directory is updated to the requested changeset.
6097
6096
6098 To cancel an uncommitted merge (and lose your changes), use
6097 To cancel an uncommitted merge (and lose your changes), use
6099 :hg:`update --clean .`.
6098 :hg:`update --clean .`.
6100
6099
6101 Use null as the changeset to remove the working directory (like
6100 Use null as the changeset to remove the working directory (like
6102 :hg:`clone -U`).
6101 :hg:`clone -U`).
6103
6102
6104 If you want to revert just one file to an older revision, use
6103 If you want to revert just one file to an older revision, use
6105 :hg:`revert [-r REV] NAME`.
6104 :hg:`revert [-r REV] NAME`.
6106
6105
6107 See :hg:`help dates` for a list of formats valid for -d/--date.
6106 See :hg:`help dates` for a list of formats valid for -d/--date.
6108
6107
6109 Returns 0 on success, 1 if there are unresolved files.
6108 Returns 0 on success, 1 if there are unresolved files.
6110 """
6109 """
6111 if rev and node:
6110 if rev and node:
6112 raise util.Abort(_("please specify just one revision"))
6111 raise util.Abort(_("please specify just one revision"))
6113
6112
6114 if rev is None or rev == '':
6113 if rev is None or rev == '':
6115 rev = node
6114 rev = node
6116
6115
6117 cmdutil.clearunfinished(repo)
6116 cmdutil.clearunfinished(repo)
6118
6117
6119 # with no argument, we also move the current bookmark, if any
6118 # with no argument, we also move the current bookmark, if any
6120 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6119 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6121
6120
6122 # if we defined a bookmark, we have to remember the original bookmark name
6121 # if we defined a bookmark, we have to remember the original bookmark name
6123 brev = rev
6122 brev = rev
6124 rev = scmutil.revsingle(repo, rev, rev).rev()
6123 rev = scmutil.revsingle(repo, rev, rev).rev()
6125
6124
6126 if check and clean:
6125 if check and clean:
6127 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6126 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6128
6127
6129 if date:
6128 if date:
6130 if rev is not None:
6129 if rev is not None:
6131 raise util.Abort(_("you can't specify a revision and a date"))
6130 raise util.Abort(_("you can't specify a revision and a date"))
6132 rev = cmdutil.finddate(ui, repo, date)
6131 rev = cmdutil.finddate(ui, repo, date)
6133
6132
6134 if check:
6133 if check:
6135 c = repo[None]
6134 c = repo[None]
6136 if c.dirty(merge=False, branch=False, missing=True):
6135 if c.dirty(merge=False, branch=False, missing=True):
6137 raise util.Abort(_("uncommitted changes"))
6136 raise util.Abort(_("uncommitted changes"))
6138 if rev is None:
6137 if rev is None:
6139 rev = repo[repo[None].branch()].rev()
6138 rev = repo[repo[None].branch()].rev()
6140 mergemod._checkunknown(repo, repo[None], repo[rev])
6139 mergemod._checkunknown(repo, repo[None], repo[rev])
6141
6140
6142 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6141 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6143
6142
6144 if clean:
6143 if clean:
6145 ret = hg.clean(repo, rev)
6144 ret = hg.clean(repo, rev)
6146 else:
6145 else:
6147 ret = hg.update(repo, rev)
6146 ret = hg.update(repo, rev)
6148
6147
6149 if not ret and movemarkfrom:
6148 if not ret and movemarkfrom:
6150 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6149 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6151 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6150 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6152 elif brev in repo._bookmarks:
6151 elif brev in repo._bookmarks:
6153 bookmarks.setcurrent(repo, brev)
6152 bookmarks.setcurrent(repo, brev)
6154 ui.status(_("(activating bookmark %s)\n") % brev)
6153 ui.status(_("(activating bookmark %s)\n") % brev)
6155 elif brev:
6154 elif brev:
6156 if repo._bookmarkcurrent:
6155 if repo._bookmarkcurrent:
6157 ui.status(_("(leaving bookmark %s)\n") %
6156 ui.status(_("(leaving bookmark %s)\n") %
6158 repo._bookmarkcurrent)
6157 repo._bookmarkcurrent)
6159 bookmarks.unsetcurrent(repo)
6158 bookmarks.unsetcurrent(repo)
6160
6159
6161 return ret
6160 return ret
6162
6161
6163 @command('verify', [])
6162 @command('verify', [])
6164 def verify(ui, repo):
6163 def verify(ui, repo):
6165 """verify the integrity of the repository
6164 """verify the integrity of the repository
6166
6165
6167 Verify the integrity of the current repository.
6166 Verify the integrity of the current repository.
6168
6167
6169 This will perform an extensive check of the repository's
6168 This will perform an extensive check of the repository's
6170 integrity, validating the hashes and checksums of each entry in
6169 integrity, validating the hashes and checksums of each entry in
6171 the changelog, manifest, and tracked files, as well as the
6170 the changelog, manifest, and tracked files, as well as the
6172 integrity of their crosslinks and indices.
6171 integrity of their crosslinks and indices.
6173
6172
6174 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6173 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6175 for more information about recovery from corruption of the
6174 for more information about recovery from corruption of the
6176 repository.
6175 repository.
6177
6176
6178 Returns 0 on success, 1 if errors are encountered.
6177 Returns 0 on success, 1 if errors are encountered.
6179 """
6178 """
6180 return hg.verify(repo)
6179 return hg.verify(repo)
6181
6180
6182 @command('version', [], norepo=True)
6181 @command('version', [], norepo=True)
6183 def version_(ui):
6182 def version_(ui):
6184 """output version and copyright information"""
6183 """output version and copyright information"""
6185 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6184 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6186 % util.version())
6185 % util.version())
6187 ui.status(_(
6186 ui.status(_(
6188 "(see http://mercurial.selenic.com for more information)\n"
6187 "(see http://mercurial.selenic.com for more information)\n"
6189 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6188 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6190 "This is free software; see the source for copying conditions. "
6189 "This is free software; see the source for copying conditions. "
6191 "There is NO\nwarranty; "
6190 "There is NO\nwarranty; "
6192 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6191 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6193 ))
6192 ))
6194
6193
6195 ui.note(_("\nEnabled extensions:\n\n"))
6194 ui.note(_("\nEnabled extensions:\n\n"))
6196 if ui.verbose:
6195 if ui.verbose:
6197 # format names and versions into columns
6196 # format names and versions into columns
6198 names = []
6197 names = []
6199 vers = []
6198 vers = []
6200 for name, module in extensions.extensions():
6199 for name, module in extensions.extensions():
6201 names.append(name)
6200 names.append(name)
6202 vers.append(extensions.moduleversion(module))
6201 vers.append(extensions.moduleversion(module))
6203 if names:
6202 if names:
6204 maxnamelen = max(len(n) for n in names)
6203 maxnamelen = max(len(n) for n in names)
6205 for i, name in enumerate(names):
6204 for i, name in enumerate(names):
6206 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6205 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now