##// END OF EJS Templates
annotate: build format string separately from annotation data...
Yuya Nishihara -
r22477:3c8ae79e default
parent child Browse files
Show More
@@ -1,6205 +1,6208 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 formats = []
316 pieces = []
317 pieces = []
317
318
318 for f, sep in funcmap:
319 for f, sep in funcmap:
319 l = [f(n) for n, dummy in lines]
320 l = [f(n) for n, dummy in lines]
320 if l:
321 if l:
321 sized = [(x, encoding.colwidth(x)) for x in l]
322 sized = [(x, encoding.colwidth(x)) for x in l]
322 ml = max([w for x, w in sized])
323 ml = max([w for x, w in sized])
323 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
324 formats.append([sep + ' ' * (ml - w) + '%s'
324 for x, w in sized])
325 for x, w in sized])
325
326 pieces.append(l)
326 for p, l in zip(zip(*pieces), lines):
327
327 ui.write("%s: %s" % ("".join(p), l[1]))
328 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
329 ui.write("".join(f) % p)
330 ui.write(": %s" % l[1])
328
331
329 if lines and not lines[-1][1].endswith('\n'):
332 if lines and not lines[-1][1].endswith('\n'):
330 ui.write('\n')
333 ui.write('\n')
331
334
332 @command('archive',
335 @command('archive',
333 [('', 'no-decode', None, _('do not pass files through decoders')),
336 [('', 'no-decode', None, _('do not pass files through decoders')),
334 ('p', 'prefix', '', _('directory prefix for files in archive'),
337 ('p', 'prefix', '', _('directory prefix for files in archive'),
335 _('PREFIX')),
338 _('PREFIX')),
336 ('r', 'rev', '', _('revision to distribute'), _('REV')),
339 ('r', 'rev', '', _('revision to distribute'), _('REV')),
337 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
340 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
338 ] + subrepoopts + walkopts,
341 ] + subrepoopts + walkopts,
339 _('[OPTION]... DEST'))
342 _('[OPTION]... DEST'))
340 def archive(ui, repo, dest, **opts):
343 def archive(ui, repo, dest, **opts):
341 '''create an unversioned archive of a repository revision
344 '''create an unversioned archive of a repository revision
342
345
343 By default, the revision used is the parent of the working
346 By default, the revision used is the parent of the working
344 directory; use -r/--rev to specify a different revision.
347 directory; use -r/--rev to specify a different revision.
345
348
346 The archive type is automatically detected based on file
349 The archive type is automatically detected based on file
347 extension (or override using -t/--type).
350 extension (or override using -t/--type).
348
351
349 .. container:: verbose
352 .. container:: verbose
350
353
351 Examples:
354 Examples:
352
355
353 - create a zip file containing the 1.0 release::
356 - create a zip file containing the 1.0 release::
354
357
355 hg archive -r 1.0 project-1.0.zip
358 hg archive -r 1.0 project-1.0.zip
356
359
357 - create a tarball excluding .hg files::
360 - create a tarball excluding .hg files::
358
361
359 hg archive project.tar.gz -X ".hg*"
362 hg archive project.tar.gz -X ".hg*"
360
363
361 Valid types are:
364 Valid types are:
362
365
363 :``files``: a directory full of files (default)
366 :``files``: a directory full of files (default)
364 :``tar``: tar archive, uncompressed
367 :``tar``: tar archive, uncompressed
365 :``tbz2``: tar archive, compressed using bzip2
368 :``tbz2``: tar archive, compressed using bzip2
366 :``tgz``: tar archive, compressed using gzip
369 :``tgz``: tar archive, compressed using gzip
367 :``uzip``: zip archive, uncompressed
370 :``uzip``: zip archive, uncompressed
368 :``zip``: zip archive, compressed using deflate
371 :``zip``: zip archive, compressed using deflate
369
372
370 The exact name of the destination archive or directory is given
373 The exact name of the destination archive or directory is given
371 using a format string; see :hg:`help export` for details.
374 using a format string; see :hg:`help export` for details.
372
375
373 Each member added to an archive file has a directory prefix
376 Each member added to an archive file has a directory prefix
374 prepended. Use -p/--prefix to specify a format string for the
377 prepended. Use -p/--prefix to specify a format string for the
375 prefix. The default is the basename of the archive, with suffixes
378 prefix. The default is the basename of the archive, with suffixes
376 removed.
379 removed.
377
380
378 Returns 0 on success.
381 Returns 0 on success.
379 '''
382 '''
380
383
381 ctx = scmutil.revsingle(repo, opts.get('rev'))
384 ctx = scmutil.revsingle(repo, opts.get('rev'))
382 if not ctx:
385 if not ctx:
383 raise util.Abort(_('no working directory: please specify a revision'))
386 raise util.Abort(_('no working directory: please specify a revision'))
384 node = ctx.node()
387 node = ctx.node()
385 dest = cmdutil.makefilename(repo, dest, node)
388 dest = cmdutil.makefilename(repo, dest, node)
386 if os.path.realpath(dest) == repo.root:
389 if os.path.realpath(dest) == repo.root:
387 raise util.Abort(_('repository root cannot be destination'))
390 raise util.Abort(_('repository root cannot be destination'))
388
391
389 kind = opts.get('type') or archival.guesskind(dest) or 'files'
392 kind = opts.get('type') or archival.guesskind(dest) or 'files'
390 prefix = opts.get('prefix')
393 prefix = opts.get('prefix')
391
394
392 if dest == '-':
395 if dest == '-':
393 if kind == 'files':
396 if kind == 'files':
394 raise util.Abort(_('cannot archive plain files to stdout'))
397 raise util.Abort(_('cannot archive plain files to stdout'))
395 dest = cmdutil.makefileobj(repo, dest)
398 dest = cmdutil.makefileobj(repo, dest)
396 if not prefix:
399 if not prefix:
397 prefix = os.path.basename(repo.root) + '-%h'
400 prefix = os.path.basename(repo.root) + '-%h'
398
401
399 prefix = cmdutil.makefilename(repo, prefix, node)
402 prefix = cmdutil.makefilename(repo, prefix, node)
400 matchfn = scmutil.match(ctx, [], opts)
403 matchfn = scmutil.match(ctx, [], opts)
401 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
404 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
402 matchfn, prefix, subrepos=opts.get('subrepos'))
405 matchfn, prefix, subrepos=opts.get('subrepos'))
403
406
404 @command('backout',
407 @command('backout',
405 [('', 'merge', None, _('merge with old dirstate parent after backout')),
408 [('', 'merge', None, _('merge with old dirstate parent after backout')),
406 ('', 'parent', '',
409 ('', 'parent', '',
407 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
410 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
408 ('r', 'rev', '', _('revision to backout'), _('REV')),
411 ('r', 'rev', '', _('revision to backout'), _('REV')),
409 ('e', 'edit', False, _('invoke editor on commit messages')),
412 ('e', 'edit', False, _('invoke editor on commit messages')),
410 ] + mergetoolopts + walkopts + commitopts + commitopts2,
413 ] + mergetoolopts + walkopts + commitopts + commitopts2,
411 _('[OPTION]... [-r] REV'))
414 _('[OPTION]... [-r] REV'))
412 def backout(ui, repo, node=None, rev=None, **opts):
415 def backout(ui, repo, node=None, rev=None, **opts):
413 '''reverse effect of earlier changeset
416 '''reverse effect of earlier changeset
414
417
415 Prepare a new changeset with the effect of REV undone in the
418 Prepare a new changeset with the effect of REV undone in the
416 current working directory.
419 current working directory.
417
420
418 If REV is the parent of the working directory, then this new changeset
421 If REV is the parent of the working directory, then this new changeset
419 is committed automatically. Otherwise, hg needs to merge the
422 is committed automatically. Otherwise, hg needs to merge the
420 changes and the merged result is left uncommitted.
423 changes and the merged result is left uncommitted.
421
424
422 .. note::
425 .. note::
423
426
424 backout cannot be used to fix either an unwanted or
427 backout cannot be used to fix either an unwanted or
425 incorrect merge.
428 incorrect merge.
426
429
427 .. container:: verbose
430 .. container:: verbose
428
431
429 By default, the pending changeset will have one parent,
432 By default, the pending changeset will have one parent,
430 maintaining a linear history. With --merge, the pending
433 maintaining a linear history. With --merge, the pending
431 changeset will instead have two parents: the old parent of the
434 changeset will instead have two parents: the old parent of the
432 working directory and a new child of REV that simply undoes REV.
435 working directory and a new child of REV that simply undoes REV.
433
436
434 Before version 1.7, the behavior without --merge was equivalent
437 Before version 1.7, the behavior without --merge was equivalent
435 to specifying --merge followed by :hg:`update --clean .` to
438 to specifying --merge followed by :hg:`update --clean .` to
436 cancel the merge and leave the child of REV as a head to be
439 cancel the merge and leave the child of REV as a head to be
437 merged separately.
440 merged separately.
438
441
439 See :hg:`help dates` for a list of formats valid for -d/--date.
442 See :hg:`help dates` for a list of formats valid for -d/--date.
440
443
441 Returns 0 on success, 1 if nothing to backout or there are unresolved
444 Returns 0 on success, 1 if nothing to backout or there are unresolved
442 files.
445 files.
443 '''
446 '''
444 if rev and node:
447 if rev and node:
445 raise util.Abort(_("please specify just one revision"))
448 raise util.Abort(_("please specify just one revision"))
446
449
447 if not rev:
450 if not rev:
448 rev = node
451 rev = node
449
452
450 if not rev:
453 if not rev:
451 raise util.Abort(_("please specify a revision to backout"))
454 raise util.Abort(_("please specify a revision to backout"))
452
455
453 date = opts.get('date')
456 date = opts.get('date')
454 if date:
457 if date:
455 opts['date'] = util.parsedate(date)
458 opts['date'] = util.parsedate(date)
456
459
457 cmdutil.checkunfinished(repo)
460 cmdutil.checkunfinished(repo)
458 cmdutil.bailifchanged(repo)
461 cmdutil.bailifchanged(repo)
459 node = scmutil.revsingle(repo, rev).node()
462 node = scmutil.revsingle(repo, rev).node()
460
463
461 op1, op2 = repo.dirstate.parents()
464 op1, op2 = repo.dirstate.parents()
462 if not repo.changelog.isancestor(node, op1):
465 if not repo.changelog.isancestor(node, op1):
463 raise util.Abort(_('cannot backout change that is not an ancestor'))
466 raise util.Abort(_('cannot backout change that is not an ancestor'))
464
467
465 p1, p2 = repo.changelog.parents(node)
468 p1, p2 = repo.changelog.parents(node)
466 if p1 == nullid:
469 if p1 == nullid:
467 raise util.Abort(_('cannot backout a change with no parents'))
470 raise util.Abort(_('cannot backout a change with no parents'))
468 if p2 != nullid:
471 if p2 != nullid:
469 if not opts.get('parent'):
472 if not opts.get('parent'):
470 raise util.Abort(_('cannot backout a merge changeset'))
473 raise util.Abort(_('cannot backout a merge changeset'))
471 p = repo.lookup(opts['parent'])
474 p = repo.lookup(opts['parent'])
472 if p not in (p1, p2):
475 if p not in (p1, p2):
473 raise util.Abort(_('%s is not a parent of %s') %
476 raise util.Abort(_('%s is not a parent of %s') %
474 (short(p), short(node)))
477 (short(p), short(node)))
475 parent = p
478 parent = p
476 else:
479 else:
477 if opts.get('parent'):
480 if opts.get('parent'):
478 raise util.Abort(_('cannot use --parent on non-merge changeset'))
481 raise util.Abort(_('cannot use --parent on non-merge changeset'))
479 parent = p1
482 parent = p1
480
483
481 # the backout should appear on the same branch
484 # the backout should appear on the same branch
482 wlock = repo.wlock()
485 wlock = repo.wlock()
483 try:
486 try:
484 branch = repo.dirstate.branch()
487 branch = repo.dirstate.branch()
485 bheads = repo.branchheads(branch)
488 bheads = repo.branchheads(branch)
486 rctx = scmutil.revsingle(repo, hex(parent))
489 rctx = scmutil.revsingle(repo, hex(parent))
487 if not opts.get('merge') and op1 != node:
490 if not opts.get('merge') and op1 != node:
488 try:
491 try:
489 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
492 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
490 'backout')
493 'backout')
491 repo.dirstate.beginparentchange()
494 repo.dirstate.beginparentchange()
492 stats = mergemod.update(repo, parent, True, True, False,
495 stats = mergemod.update(repo, parent, True, True, False,
493 node, False)
496 node, False)
494 repo.setparents(op1, op2)
497 repo.setparents(op1, op2)
495 repo.dirstate.endparentchange()
498 repo.dirstate.endparentchange()
496 hg._showstats(repo, stats)
499 hg._showstats(repo, stats)
497 if stats[3]:
500 if stats[3]:
498 repo.ui.status(_("use 'hg resolve' to retry unresolved "
501 repo.ui.status(_("use 'hg resolve' to retry unresolved "
499 "file merges\n"))
502 "file merges\n"))
500 else:
503 else:
501 msg = _("changeset %s backed out, "
504 msg = _("changeset %s backed out, "
502 "don't forget to commit.\n")
505 "don't forget to commit.\n")
503 ui.status(msg % short(node))
506 ui.status(msg % short(node))
504 return stats[3] > 0
507 return stats[3] > 0
505 finally:
508 finally:
506 ui.setconfig('ui', 'forcemerge', '', '')
509 ui.setconfig('ui', 'forcemerge', '', '')
507 else:
510 else:
508 hg.clean(repo, node, show_stats=False)
511 hg.clean(repo, node, show_stats=False)
509 repo.dirstate.setbranch(branch)
512 repo.dirstate.setbranch(branch)
510 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
513 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
511
514
512
515
513 def commitfunc(ui, repo, message, match, opts):
516 def commitfunc(ui, repo, message, match, opts):
514 editform = 'backout'
517 editform = 'backout'
515 e = cmdutil.getcommiteditor(editform=editform, **opts)
518 e = cmdutil.getcommiteditor(editform=editform, **opts)
516 if not message:
519 if not message:
517 # we don't translate commit messages
520 # we don't translate commit messages
518 message = "Backed out changeset %s" % short(node)
521 message = "Backed out changeset %s" % short(node)
519 e = cmdutil.getcommiteditor(edit=True, editform=editform)
522 e = cmdutil.getcommiteditor(edit=True, editform=editform)
520 return repo.commit(message, opts.get('user'), opts.get('date'),
523 return repo.commit(message, opts.get('user'), opts.get('date'),
521 match, editor=e)
524 match, editor=e)
522 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
525 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
523 if not newnode:
526 if not newnode:
524 ui.status(_("nothing changed\n"))
527 ui.status(_("nothing changed\n"))
525 return 1
528 return 1
526 cmdutil.commitstatus(repo, newnode, branch, bheads)
529 cmdutil.commitstatus(repo, newnode, branch, bheads)
527
530
528 def nice(node):
531 def nice(node):
529 return '%d:%s' % (repo.changelog.rev(node), short(node))
532 return '%d:%s' % (repo.changelog.rev(node), short(node))
530 ui.status(_('changeset %s backs out changeset %s\n') %
533 ui.status(_('changeset %s backs out changeset %s\n') %
531 (nice(repo.changelog.tip()), nice(node)))
534 (nice(repo.changelog.tip()), nice(node)))
532 if opts.get('merge') and op1 != node:
535 if opts.get('merge') and op1 != node:
533 hg.clean(repo, op1, show_stats=False)
536 hg.clean(repo, op1, show_stats=False)
534 ui.status(_('merging with changeset %s\n')
537 ui.status(_('merging with changeset %s\n')
535 % nice(repo.changelog.tip()))
538 % nice(repo.changelog.tip()))
536 try:
539 try:
537 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
540 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
538 'backout')
541 'backout')
539 return hg.merge(repo, hex(repo.changelog.tip()))
542 return hg.merge(repo, hex(repo.changelog.tip()))
540 finally:
543 finally:
541 ui.setconfig('ui', 'forcemerge', '', '')
544 ui.setconfig('ui', 'forcemerge', '', '')
542 finally:
545 finally:
543 wlock.release()
546 wlock.release()
544 return 0
547 return 0
545
548
546 @command('bisect',
549 @command('bisect',
547 [('r', 'reset', False, _('reset bisect state')),
550 [('r', 'reset', False, _('reset bisect state')),
548 ('g', 'good', False, _('mark changeset good')),
551 ('g', 'good', False, _('mark changeset good')),
549 ('b', 'bad', False, _('mark changeset bad')),
552 ('b', 'bad', False, _('mark changeset bad')),
550 ('s', 'skip', False, _('skip testing changeset')),
553 ('s', 'skip', False, _('skip testing changeset')),
551 ('e', 'extend', False, _('extend the bisect range')),
554 ('e', 'extend', False, _('extend the bisect range')),
552 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
555 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
553 ('U', 'noupdate', False, _('do not update to target'))],
556 ('U', 'noupdate', False, _('do not update to target'))],
554 _("[-gbsr] [-U] [-c CMD] [REV]"))
557 _("[-gbsr] [-U] [-c CMD] [REV]"))
555 def bisect(ui, repo, rev=None, extra=None, command=None,
558 def bisect(ui, repo, rev=None, extra=None, command=None,
556 reset=None, good=None, bad=None, skip=None, extend=None,
559 reset=None, good=None, bad=None, skip=None, extend=None,
557 noupdate=None):
560 noupdate=None):
558 """subdivision search of changesets
561 """subdivision search of changesets
559
562
560 This command helps to find changesets which introduce problems. To
563 This command helps to find changesets which introduce problems. To
561 use, mark the earliest changeset you know exhibits the problem as
564 use, mark the earliest changeset you know exhibits the problem as
562 bad, then mark the latest changeset which is free from the problem
565 bad, then mark the latest changeset which is free from the problem
563 as good. Bisect will update your working directory to a revision
566 as good. Bisect will update your working directory to a revision
564 for testing (unless the -U/--noupdate option is specified). Once
567 for testing (unless the -U/--noupdate option is specified). Once
565 you have performed tests, mark the working directory as good or
568 you have performed tests, mark the working directory as good or
566 bad, and bisect will either update to another candidate changeset
569 bad, and bisect will either update to another candidate changeset
567 or announce that it has found the bad revision.
570 or announce that it has found the bad revision.
568
571
569 As a shortcut, you can also use the revision argument to mark a
572 As a shortcut, you can also use the revision argument to mark a
570 revision as good or bad without checking it out first.
573 revision as good or bad without checking it out first.
571
574
572 If you supply a command, it will be used for automatic bisection.
575 If you supply a command, it will be used for automatic bisection.
573 The environment variable HG_NODE will contain the ID of the
576 The environment variable HG_NODE will contain the ID of the
574 changeset being tested. The exit status of the command will be
577 changeset being tested. The exit status of the command will be
575 used to mark revisions as good or bad: status 0 means good, 125
578 used to mark revisions as good or bad: status 0 means good, 125
576 means to skip the revision, 127 (command not found) will abort the
579 means to skip the revision, 127 (command not found) will abort the
577 bisection, and any other non-zero exit status means the revision
580 bisection, and any other non-zero exit status means the revision
578 is bad.
581 is bad.
579
582
580 .. container:: verbose
583 .. container:: verbose
581
584
582 Some examples:
585 Some examples:
583
586
584 - start a bisection with known bad revision 34, and good revision 12::
587 - start a bisection with known bad revision 34, and good revision 12::
585
588
586 hg bisect --bad 34
589 hg bisect --bad 34
587 hg bisect --good 12
590 hg bisect --good 12
588
591
589 - advance the current bisection by marking current revision as good or
592 - advance the current bisection by marking current revision as good or
590 bad::
593 bad::
591
594
592 hg bisect --good
595 hg bisect --good
593 hg bisect --bad
596 hg bisect --bad
594
597
595 - mark the current revision, or a known revision, to be skipped (e.g. if
598 - mark the current revision, or a known revision, to be skipped (e.g. if
596 that revision is not usable because of another issue)::
599 that revision is not usable because of another issue)::
597
600
598 hg bisect --skip
601 hg bisect --skip
599 hg bisect --skip 23
602 hg bisect --skip 23
600
603
601 - skip all revisions that do not touch directories ``foo`` or ``bar``::
604 - skip all revisions that do not touch directories ``foo`` or ``bar``::
602
605
603 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
606 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
604
607
605 - forget the current bisection::
608 - forget the current bisection::
606
609
607 hg bisect --reset
610 hg bisect --reset
608
611
609 - use 'make && make tests' to automatically find the first broken
612 - use 'make && make tests' to automatically find the first broken
610 revision::
613 revision::
611
614
612 hg bisect --reset
615 hg bisect --reset
613 hg bisect --bad 34
616 hg bisect --bad 34
614 hg bisect --good 12
617 hg bisect --good 12
615 hg bisect --command "make && make tests"
618 hg bisect --command "make && make tests"
616
619
617 - see all changesets whose states are already known in the current
620 - see all changesets whose states are already known in the current
618 bisection::
621 bisection::
619
622
620 hg log -r "bisect(pruned)"
623 hg log -r "bisect(pruned)"
621
624
622 - see the changeset currently being bisected (especially useful
625 - see the changeset currently being bisected (especially useful
623 if running with -U/--noupdate)::
626 if running with -U/--noupdate)::
624
627
625 hg log -r "bisect(current)"
628 hg log -r "bisect(current)"
626
629
627 - see all changesets that took part in the current bisection::
630 - see all changesets that took part in the current bisection::
628
631
629 hg log -r "bisect(range)"
632 hg log -r "bisect(range)"
630
633
631 - you can even get a nice graph::
634 - you can even get a nice graph::
632
635
633 hg log --graph -r "bisect(range)"
636 hg log --graph -r "bisect(range)"
634
637
635 See :hg:`help revsets` for more about the `bisect()` keyword.
638 See :hg:`help revsets` for more about the `bisect()` keyword.
636
639
637 Returns 0 on success.
640 Returns 0 on success.
638 """
641 """
639 def extendbisectrange(nodes, good):
642 def extendbisectrange(nodes, good):
640 # bisect is incomplete when it ends on a merge node and
643 # bisect is incomplete when it ends on a merge node and
641 # one of the parent was not checked.
644 # one of the parent was not checked.
642 parents = repo[nodes[0]].parents()
645 parents = repo[nodes[0]].parents()
643 if len(parents) > 1:
646 if len(parents) > 1:
644 side = good and state['bad'] or state['good']
647 side = good and state['bad'] or state['good']
645 num = len(set(i.node() for i in parents) & set(side))
648 num = len(set(i.node() for i in parents) & set(side))
646 if num == 1:
649 if num == 1:
647 return parents[0].ancestor(parents[1])
650 return parents[0].ancestor(parents[1])
648 return None
651 return None
649
652
650 def print_result(nodes, good):
653 def print_result(nodes, good):
651 displayer = cmdutil.show_changeset(ui, repo, {})
654 displayer = cmdutil.show_changeset(ui, repo, {})
652 if len(nodes) == 1:
655 if len(nodes) == 1:
653 # narrowed it down to a single revision
656 # narrowed it down to a single revision
654 if good:
657 if good:
655 ui.write(_("The first good revision is:\n"))
658 ui.write(_("The first good revision is:\n"))
656 else:
659 else:
657 ui.write(_("The first bad revision is:\n"))
660 ui.write(_("The first bad revision is:\n"))
658 displayer.show(repo[nodes[0]])
661 displayer.show(repo[nodes[0]])
659 extendnode = extendbisectrange(nodes, good)
662 extendnode = extendbisectrange(nodes, good)
660 if extendnode is not None:
663 if extendnode is not None:
661 ui.write(_('Not all ancestors of this changeset have been'
664 ui.write(_('Not all ancestors of this changeset have been'
662 ' checked.\nUse bisect --extend to continue the '
665 ' checked.\nUse bisect --extend to continue the '
663 'bisection from\nthe common ancestor, %s.\n')
666 'bisection from\nthe common ancestor, %s.\n')
664 % extendnode)
667 % extendnode)
665 else:
668 else:
666 # multiple possible revisions
669 # multiple possible revisions
667 if good:
670 if good:
668 ui.write(_("Due to skipped revisions, the first "
671 ui.write(_("Due to skipped revisions, the first "
669 "good revision could be any of:\n"))
672 "good revision could be any of:\n"))
670 else:
673 else:
671 ui.write(_("Due to skipped revisions, the first "
674 ui.write(_("Due to skipped revisions, the first "
672 "bad revision could be any of:\n"))
675 "bad revision could be any of:\n"))
673 for n in nodes:
676 for n in nodes:
674 displayer.show(repo[n])
677 displayer.show(repo[n])
675 displayer.close()
678 displayer.close()
676
679
677 def check_state(state, interactive=True):
680 def check_state(state, interactive=True):
678 if not state['good'] or not state['bad']:
681 if not state['good'] or not state['bad']:
679 if (good or bad or skip or reset) and interactive:
682 if (good or bad or skip or reset) and interactive:
680 return
683 return
681 if not state['good']:
684 if not state['good']:
682 raise util.Abort(_('cannot bisect (no known good revisions)'))
685 raise util.Abort(_('cannot bisect (no known good revisions)'))
683 else:
686 else:
684 raise util.Abort(_('cannot bisect (no known bad revisions)'))
687 raise util.Abort(_('cannot bisect (no known bad revisions)'))
685 return True
688 return True
686
689
687 # backward compatibility
690 # backward compatibility
688 if rev in "good bad reset init".split():
691 if rev in "good bad reset init".split():
689 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
692 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
690 cmd, rev, extra = rev, extra, None
693 cmd, rev, extra = rev, extra, None
691 if cmd == "good":
694 if cmd == "good":
692 good = True
695 good = True
693 elif cmd == "bad":
696 elif cmd == "bad":
694 bad = True
697 bad = True
695 else:
698 else:
696 reset = True
699 reset = True
697 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
700 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
698 raise util.Abort(_('incompatible arguments'))
701 raise util.Abort(_('incompatible arguments'))
699
702
700 cmdutil.checkunfinished(repo)
703 cmdutil.checkunfinished(repo)
701
704
702 if reset:
705 if reset:
703 p = repo.join("bisect.state")
706 p = repo.join("bisect.state")
704 if os.path.exists(p):
707 if os.path.exists(p):
705 os.unlink(p)
708 os.unlink(p)
706 return
709 return
707
710
708 state = hbisect.load_state(repo)
711 state = hbisect.load_state(repo)
709
712
710 if command:
713 if command:
711 changesets = 1
714 changesets = 1
712 if noupdate:
715 if noupdate:
713 try:
716 try:
714 node = state['current'][0]
717 node = state['current'][0]
715 except LookupError:
718 except LookupError:
716 raise util.Abort(_('current bisect revision is unknown - '
719 raise util.Abort(_('current bisect revision is unknown - '
717 'start a new bisect to fix'))
720 'start a new bisect to fix'))
718 else:
721 else:
719 node, p2 = repo.dirstate.parents()
722 node, p2 = repo.dirstate.parents()
720 if p2 != nullid:
723 if p2 != nullid:
721 raise util.Abort(_('current bisect revision is a merge'))
724 raise util.Abort(_('current bisect revision is a merge'))
722 try:
725 try:
723 while changesets:
726 while changesets:
724 # update state
727 # update state
725 state['current'] = [node]
728 state['current'] = [node]
726 hbisect.save_state(repo, state)
729 hbisect.save_state(repo, state)
727 status = util.system(command,
730 status = util.system(command,
728 environ={'HG_NODE': hex(node)},
731 environ={'HG_NODE': hex(node)},
729 out=ui.fout)
732 out=ui.fout)
730 if status == 125:
733 if status == 125:
731 transition = "skip"
734 transition = "skip"
732 elif status == 0:
735 elif status == 0:
733 transition = "good"
736 transition = "good"
734 # status < 0 means process was killed
737 # status < 0 means process was killed
735 elif status == 127:
738 elif status == 127:
736 raise util.Abort(_("failed to execute %s") % command)
739 raise util.Abort(_("failed to execute %s") % command)
737 elif status < 0:
740 elif status < 0:
738 raise util.Abort(_("%s killed") % command)
741 raise util.Abort(_("%s killed") % command)
739 else:
742 else:
740 transition = "bad"
743 transition = "bad"
741 ctx = scmutil.revsingle(repo, rev, node)
744 ctx = scmutil.revsingle(repo, rev, node)
742 rev = None # clear for future iterations
745 rev = None # clear for future iterations
743 state[transition].append(ctx.node())
746 state[transition].append(ctx.node())
744 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
747 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
745 check_state(state, interactive=False)
748 check_state(state, interactive=False)
746 # bisect
749 # bisect
747 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
750 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
748 # update to next check
751 # update to next check
749 node = nodes[0]
752 node = nodes[0]
750 if not noupdate:
753 if not noupdate:
751 cmdutil.bailifchanged(repo)
754 cmdutil.bailifchanged(repo)
752 hg.clean(repo, node, show_stats=False)
755 hg.clean(repo, node, show_stats=False)
753 finally:
756 finally:
754 state['current'] = [node]
757 state['current'] = [node]
755 hbisect.save_state(repo, state)
758 hbisect.save_state(repo, state)
756 print_result(nodes, bgood)
759 print_result(nodes, bgood)
757 return
760 return
758
761
759 # update state
762 # update state
760
763
761 if rev:
764 if rev:
762 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
765 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
763 else:
766 else:
764 nodes = [repo.lookup('.')]
767 nodes = [repo.lookup('.')]
765
768
766 if good or bad or skip:
769 if good or bad or skip:
767 if good:
770 if good:
768 state['good'] += nodes
771 state['good'] += nodes
769 elif bad:
772 elif bad:
770 state['bad'] += nodes
773 state['bad'] += nodes
771 elif skip:
774 elif skip:
772 state['skip'] += nodes
775 state['skip'] += nodes
773 hbisect.save_state(repo, state)
776 hbisect.save_state(repo, state)
774
777
775 if not check_state(state):
778 if not check_state(state):
776 return
779 return
777
780
778 # actually bisect
781 # actually bisect
779 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
782 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
780 if extend:
783 if extend:
781 if not changesets:
784 if not changesets:
782 extendnode = extendbisectrange(nodes, good)
785 extendnode = extendbisectrange(nodes, good)
783 if extendnode is not None:
786 if extendnode is not None:
784 ui.write(_("Extending search to changeset %d:%s\n")
787 ui.write(_("Extending search to changeset %d:%s\n")
785 % (extendnode.rev(), extendnode))
788 % (extendnode.rev(), extendnode))
786 state['current'] = [extendnode.node()]
789 state['current'] = [extendnode.node()]
787 hbisect.save_state(repo, state)
790 hbisect.save_state(repo, state)
788 if noupdate:
791 if noupdate:
789 return
792 return
790 cmdutil.bailifchanged(repo)
793 cmdutil.bailifchanged(repo)
791 return hg.clean(repo, extendnode.node())
794 return hg.clean(repo, extendnode.node())
792 raise util.Abort(_("nothing to extend"))
795 raise util.Abort(_("nothing to extend"))
793
796
794 if changesets == 0:
797 if changesets == 0:
795 print_result(nodes, good)
798 print_result(nodes, good)
796 else:
799 else:
797 assert len(nodes) == 1 # only a single node can be tested next
800 assert len(nodes) == 1 # only a single node can be tested next
798 node = nodes[0]
801 node = nodes[0]
799 # compute the approximate number of remaining tests
802 # compute the approximate number of remaining tests
800 tests, size = 0, 2
803 tests, size = 0, 2
801 while size <= changesets:
804 while size <= changesets:
802 tests, size = tests + 1, size * 2
805 tests, size = tests + 1, size * 2
803 rev = repo.changelog.rev(node)
806 rev = repo.changelog.rev(node)
804 ui.write(_("Testing changeset %d:%s "
807 ui.write(_("Testing changeset %d:%s "
805 "(%d changesets remaining, ~%d tests)\n")
808 "(%d changesets remaining, ~%d tests)\n")
806 % (rev, short(node), changesets, tests))
809 % (rev, short(node), changesets, tests))
807 state['current'] = [node]
810 state['current'] = [node]
808 hbisect.save_state(repo, state)
811 hbisect.save_state(repo, state)
809 if not noupdate:
812 if not noupdate:
810 cmdutil.bailifchanged(repo)
813 cmdutil.bailifchanged(repo)
811 return hg.clean(repo, node)
814 return hg.clean(repo, node)
812
815
813 @command('bookmarks|bookmark',
816 @command('bookmarks|bookmark',
814 [('f', 'force', False, _('force')),
817 [('f', 'force', False, _('force')),
815 ('r', 'rev', '', _('revision'), _('REV')),
818 ('r', 'rev', '', _('revision'), _('REV')),
816 ('d', 'delete', False, _('delete a given bookmark')),
819 ('d', 'delete', False, _('delete a given bookmark')),
817 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
820 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
818 ('i', 'inactive', False, _('mark a bookmark inactive'))],
821 ('i', 'inactive', False, _('mark a bookmark inactive'))],
819 _('hg bookmarks [OPTIONS]... [NAME]...'))
822 _('hg bookmarks [OPTIONS]... [NAME]...'))
820 def bookmark(ui, repo, *names, **opts):
823 def bookmark(ui, repo, *names, **opts):
821 '''create a new bookmark or list existing bookmarks
824 '''create a new bookmark or list existing bookmarks
822
825
823 Bookmarks are labels on changesets to help track lines of development.
826 Bookmarks are labels on changesets to help track lines of development.
824 Bookmarks are unversioned and can be moved, renamed and deleted.
827 Bookmarks are unversioned and can be moved, renamed and deleted.
825 Deleting or moving a bookmark has no effect on the associated changesets.
828 Deleting or moving a bookmark has no effect on the associated changesets.
826
829
827 Creating or updating to a bookmark causes it to be marked as 'active'.
830 Creating or updating to a bookmark causes it to be marked as 'active'.
828 The active bookmark is indicated with a '*'.
831 The active bookmark is indicated with a '*'.
829 When a commit is made, the active bookmark will advance to the new commit.
832 When a commit is made, the active bookmark will advance to the new commit.
830 A plain :hg:`update` will also advance an active bookmark, if possible.
833 A plain :hg:`update` will also advance an active bookmark, if possible.
831 Updating away from a bookmark will cause it to be deactivated.
834 Updating away from a bookmark will cause it to be deactivated.
832
835
833 Bookmarks can be pushed and pulled between repositories (see
836 Bookmarks can be pushed and pulled between repositories (see
834 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
837 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
835 diverged, a new 'divergent bookmark' of the form 'name@path' will
838 diverged, a new 'divergent bookmark' of the form 'name@path' will
836 be created. Using :hg:'merge' will resolve the divergence.
839 be created. Using :hg:'merge' will resolve the divergence.
837
840
838 A bookmark named '@' has the special property that :hg:`clone` will
841 A bookmark named '@' has the special property that :hg:`clone` will
839 check it out by default if it exists.
842 check it out by default if it exists.
840
843
841 .. container:: verbose
844 .. container:: verbose
842
845
843 Examples:
846 Examples:
844
847
845 - create an active bookmark for a new line of development::
848 - create an active bookmark for a new line of development::
846
849
847 hg book new-feature
850 hg book new-feature
848
851
849 - create an inactive bookmark as a place marker::
852 - create an inactive bookmark as a place marker::
850
853
851 hg book -i reviewed
854 hg book -i reviewed
852
855
853 - create an inactive bookmark on another changeset::
856 - create an inactive bookmark on another changeset::
854
857
855 hg book -r .^ tested
858 hg book -r .^ tested
856
859
857 - move the '@' bookmark from another branch::
860 - move the '@' bookmark from another branch::
858
861
859 hg book -f @
862 hg book -f @
860 '''
863 '''
861 force = opts.get('force')
864 force = opts.get('force')
862 rev = opts.get('rev')
865 rev = opts.get('rev')
863 delete = opts.get('delete')
866 delete = opts.get('delete')
864 rename = opts.get('rename')
867 rename = opts.get('rename')
865 inactive = opts.get('inactive')
868 inactive = opts.get('inactive')
866
869
867 def checkformat(mark):
870 def checkformat(mark):
868 mark = mark.strip()
871 mark = mark.strip()
869 if not mark:
872 if not mark:
870 raise util.Abort(_("bookmark names cannot consist entirely of "
873 raise util.Abort(_("bookmark names cannot consist entirely of "
871 "whitespace"))
874 "whitespace"))
872 scmutil.checknewlabel(repo, mark, 'bookmark')
875 scmutil.checknewlabel(repo, mark, 'bookmark')
873 return mark
876 return mark
874
877
875 def checkconflict(repo, mark, cur, force=False, target=None):
878 def checkconflict(repo, mark, cur, force=False, target=None):
876 if mark in marks and not force:
879 if mark in marks and not force:
877 if target:
880 if target:
878 if marks[mark] == target and target == cur:
881 if marks[mark] == target and target == cur:
879 # re-activating a bookmark
882 # re-activating a bookmark
880 return
883 return
881 anc = repo.changelog.ancestors([repo[target].rev()])
884 anc = repo.changelog.ancestors([repo[target].rev()])
882 bmctx = repo[marks[mark]]
885 bmctx = repo[marks[mark]]
883 divs = [repo[b].node() for b in marks
886 divs = [repo[b].node() for b in marks
884 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
887 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
885
888
886 # allow resolving a single divergent bookmark even if moving
889 # allow resolving a single divergent bookmark even if moving
887 # the bookmark across branches when a revision is specified
890 # the bookmark across branches when a revision is specified
888 # that contains a divergent bookmark
891 # that contains a divergent bookmark
889 if bmctx.rev() not in anc and target in divs:
892 if bmctx.rev() not in anc and target in divs:
890 bookmarks.deletedivergent(repo, [target], mark)
893 bookmarks.deletedivergent(repo, [target], mark)
891 return
894 return
892
895
893 deletefrom = [b for b in divs
896 deletefrom = [b for b in divs
894 if repo[b].rev() in anc or b == target]
897 if repo[b].rev() in anc or b == target]
895 bookmarks.deletedivergent(repo, deletefrom, mark)
898 bookmarks.deletedivergent(repo, deletefrom, mark)
896 if bookmarks.validdest(repo, bmctx, repo[target]):
899 if bookmarks.validdest(repo, bmctx, repo[target]):
897 ui.status(_("moving bookmark '%s' forward from %s\n") %
900 ui.status(_("moving bookmark '%s' forward from %s\n") %
898 (mark, short(bmctx.node())))
901 (mark, short(bmctx.node())))
899 return
902 return
900 raise util.Abort(_("bookmark '%s' already exists "
903 raise util.Abort(_("bookmark '%s' already exists "
901 "(use -f to force)") % mark)
904 "(use -f to force)") % mark)
902 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
905 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
903 and not force):
906 and not force):
904 raise util.Abort(
907 raise util.Abort(
905 _("a bookmark cannot have the name of an existing branch"))
908 _("a bookmark cannot have the name of an existing branch"))
906
909
907 if delete and rename:
910 if delete and rename:
908 raise util.Abort(_("--delete and --rename are incompatible"))
911 raise util.Abort(_("--delete and --rename are incompatible"))
909 if delete and rev:
912 if delete and rev:
910 raise util.Abort(_("--rev is incompatible with --delete"))
913 raise util.Abort(_("--rev is incompatible with --delete"))
911 if rename and rev:
914 if rename and rev:
912 raise util.Abort(_("--rev is incompatible with --rename"))
915 raise util.Abort(_("--rev is incompatible with --rename"))
913 if not names and (delete or rev):
916 if not names and (delete or rev):
914 raise util.Abort(_("bookmark name required"))
917 raise util.Abort(_("bookmark name required"))
915
918
916 if delete or rename or names or inactive:
919 if delete or rename or names or inactive:
917 wlock = repo.wlock()
920 wlock = repo.wlock()
918 try:
921 try:
919 cur = repo.changectx('.').node()
922 cur = repo.changectx('.').node()
920 marks = repo._bookmarks
923 marks = repo._bookmarks
921 if delete:
924 if delete:
922 for mark in names:
925 for mark in names:
923 if mark not in marks:
926 if mark not in marks:
924 raise util.Abort(_("bookmark '%s' does not exist") %
927 raise util.Abort(_("bookmark '%s' does not exist") %
925 mark)
928 mark)
926 if mark == repo._bookmarkcurrent:
929 if mark == repo._bookmarkcurrent:
927 bookmarks.unsetcurrent(repo)
930 bookmarks.unsetcurrent(repo)
928 del marks[mark]
931 del marks[mark]
929 marks.write()
932 marks.write()
930
933
931 elif rename:
934 elif rename:
932 if not names:
935 if not names:
933 raise util.Abort(_("new bookmark name required"))
936 raise util.Abort(_("new bookmark name required"))
934 elif len(names) > 1:
937 elif len(names) > 1:
935 raise util.Abort(_("only one new bookmark name allowed"))
938 raise util.Abort(_("only one new bookmark name allowed"))
936 mark = checkformat(names[0])
939 mark = checkformat(names[0])
937 if rename not in marks:
940 if rename not in marks:
938 raise util.Abort(_("bookmark '%s' does not exist") % rename)
941 raise util.Abort(_("bookmark '%s' does not exist") % rename)
939 checkconflict(repo, mark, cur, force)
942 checkconflict(repo, mark, cur, force)
940 marks[mark] = marks[rename]
943 marks[mark] = marks[rename]
941 if repo._bookmarkcurrent == rename and not inactive:
944 if repo._bookmarkcurrent == rename and not inactive:
942 bookmarks.setcurrent(repo, mark)
945 bookmarks.setcurrent(repo, mark)
943 del marks[rename]
946 del marks[rename]
944 marks.write()
947 marks.write()
945
948
946 elif names:
949 elif names:
947 newact = None
950 newact = None
948 for mark in names:
951 for mark in names:
949 mark = checkformat(mark)
952 mark = checkformat(mark)
950 if newact is None:
953 if newact is None:
951 newact = mark
954 newact = mark
952 if inactive and mark == repo._bookmarkcurrent:
955 if inactive and mark == repo._bookmarkcurrent:
953 bookmarks.unsetcurrent(repo)
956 bookmarks.unsetcurrent(repo)
954 return
957 return
955 tgt = cur
958 tgt = cur
956 if rev:
959 if rev:
957 tgt = scmutil.revsingle(repo, rev).node()
960 tgt = scmutil.revsingle(repo, rev).node()
958 checkconflict(repo, mark, cur, force, tgt)
961 checkconflict(repo, mark, cur, force, tgt)
959 marks[mark] = tgt
962 marks[mark] = tgt
960 if not inactive and cur == marks[newact] and not rev:
963 if not inactive and cur == marks[newact] and not rev:
961 bookmarks.setcurrent(repo, newact)
964 bookmarks.setcurrent(repo, newact)
962 elif cur != tgt and newact == repo._bookmarkcurrent:
965 elif cur != tgt and newact == repo._bookmarkcurrent:
963 bookmarks.unsetcurrent(repo)
966 bookmarks.unsetcurrent(repo)
964 marks.write()
967 marks.write()
965
968
966 elif inactive:
969 elif inactive:
967 if len(marks) == 0:
970 if len(marks) == 0:
968 ui.status(_("no bookmarks set\n"))
971 ui.status(_("no bookmarks set\n"))
969 elif not repo._bookmarkcurrent:
972 elif not repo._bookmarkcurrent:
970 ui.status(_("no active bookmark\n"))
973 ui.status(_("no active bookmark\n"))
971 else:
974 else:
972 bookmarks.unsetcurrent(repo)
975 bookmarks.unsetcurrent(repo)
973 finally:
976 finally:
974 wlock.release()
977 wlock.release()
975 else: # show bookmarks
978 else: # show bookmarks
976 hexfn = ui.debugflag and hex or short
979 hexfn = ui.debugflag and hex or short
977 marks = repo._bookmarks
980 marks = repo._bookmarks
978 if len(marks) == 0:
981 if len(marks) == 0:
979 ui.status(_("no bookmarks set\n"))
982 ui.status(_("no bookmarks set\n"))
980 else:
983 else:
981 for bmark, n in sorted(marks.iteritems()):
984 for bmark, n in sorted(marks.iteritems()):
982 current = repo._bookmarkcurrent
985 current = repo._bookmarkcurrent
983 if bmark == current:
986 if bmark == current:
984 prefix, label = '*', 'bookmarks.current'
987 prefix, label = '*', 'bookmarks.current'
985 else:
988 else:
986 prefix, label = ' ', ''
989 prefix, label = ' ', ''
987
990
988 if ui.quiet:
991 if ui.quiet:
989 ui.write("%s\n" % bmark, label=label)
992 ui.write("%s\n" % bmark, label=label)
990 else:
993 else:
991 pad = " " * (25 - encoding.colwidth(bmark))
994 pad = " " * (25 - encoding.colwidth(bmark))
992 ui.write(" %s %s%s %d:%s\n" % (
995 ui.write(" %s %s%s %d:%s\n" % (
993 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
996 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
994 label=label)
997 label=label)
995
998
996 @command('branch',
999 @command('branch',
997 [('f', 'force', None,
1000 [('f', 'force', None,
998 _('set branch name even if it shadows an existing branch')),
1001 _('set branch name even if it shadows an existing branch')),
999 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1002 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1000 _('[-fC] [NAME]'))
1003 _('[-fC] [NAME]'))
1001 def branch(ui, repo, label=None, **opts):
1004 def branch(ui, repo, label=None, **opts):
1002 """set or show the current branch name
1005 """set or show the current branch name
1003
1006
1004 .. note::
1007 .. note::
1005
1008
1006 Branch names are permanent and global. Use :hg:`bookmark` to create a
1009 Branch names are permanent and global. Use :hg:`bookmark` to create a
1007 light-weight bookmark instead. See :hg:`help glossary` for more
1010 light-weight bookmark instead. See :hg:`help glossary` for more
1008 information about named branches and bookmarks.
1011 information about named branches and bookmarks.
1009
1012
1010 With no argument, show the current branch name. With one argument,
1013 With no argument, show the current branch name. With one argument,
1011 set the working directory branch name (the branch will not exist
1014 set the working directory branch name (the branch will not exist
1012 in the repository until the next commit). Standard practice
1015 in the repository until the next commit). Standard practice
1013 recommends that primary development take place on the 'default'
1016 recommends that primary development take place on the 'default'
1014 branch.
1017 branch.
1015
1018
1016 Unless -f/--force is specified, branch will not let you set a
1019 Unless -f/--force is specified, branch will not let you set a
1017 branch name that already exists, even if it's inactive.
1020 branch name that already exists, even if it's inactive.
1018
1021
1019 Use -C/--clean to reset the working directory branch to that of
1022 Use -C/--clean to reset the working directory branch to that of
1020 the parent of the working directory, negating a previous branch
1023 the parent of the working directory, negating a previous branch
1021 change.
1024 change.
1022
1025
1023 Use the command :hg:`update` to switch to an existing branch. Use
1026 Use the command :hg:`update` to switch to an existing branch. Use
1024 :hg:`commit --close-branch` to mark this branch as closed.
1027 :hg:`commit --close-branch` to mark this branch as closed.
1025
1028
1026 Returns 0 on success.
1029 Returns 0 on success.
1027 """
1030 """
1028 if label:
1031 if label:
1029 label = label.strip()
1032 label = label.strip()
1030
1033
1031 if not opts.get('clean') and not label:
1034 if not opts.get('clean') and not label:
1032 ui.write("%s\n" % repo.dirstate.branch())
1035 ui.write("%s\n" % repo.dirstate.branch())
1033 return
1036 return
1034
1037
1035 wlock = repo.wlock()
1038 wlock = repo.wlock()
1036 try:
1039 try:
1037 if opts.get('clean'):
1040 if opts.get('clean'):
1038 label = repo[None].p1().branch()
1041 label = repo[None].p1().branch()
1039 repo.dirstate.setbranch(label)
1042 repo.dirstate.setbranch(label)
1040 ui.status(_('reset working directory to branch %s\n') % label)
1043 ui.status(_('reset working directory to branch %s\n') % label)
1041 elif label:
1044 elif label:
1042 if not opts.get('force') and label in repo.branchmap():
1045 if not opts.get('force') and label in repo.branchmap():
1043 if label not in [p.branch() for p in repo.parents()]:
1046 if label not in [p.branch() for p in repo.parents()]:
1044 raise util.Abort(_('a branch of the same name already'
1047 raise util.Abort(_('a branch of the same name already'
1045 ' exists'),
1048 ' exists'),
1046 # i18n: "it" refers to an existing branch
1049 # i18n: "it" refers to an existing branch
1047 hint=_("use 'hg update' to switch to it"))
1050 hint=_("use 'hg update' to switch to it"))
1048 scmutil.checknewlabel(repo, label, 'branch')
1051 scmutil.checknewlabel(repo, label, 'branch')
1049 repo.dirstate.setbranch(label)
1052 repo.dirstate.setbranch(label)
1050 ui.status(_('marked working directory as branch %s\n') % label)
1053 ui.status(_('marked working directory as branch %s\n') % label)
1051 ui.status(_('(branches are permanent and global, '
1054 ui.status(_('(branches are permanent and global, '
1052 'did you want a bookmark?)\n'))
1055 'did you want a bookmark?)\n'))
1053 finally:
1056 finally:
1054 wlock.release()
1057 wlock.release()
1055
1058
1056 @command('branches',
1059 @command('branches',
1057 [('a', 'active', False, _('show only branches that have unmerged heads')),
1060 [('a', 'active', False, _('show only branches that have unmerged heads')),
1058 ('c', 'closed', False, _('show normal and closed branches'))],
1061 ('c', 'closed', False, _('show normal and closed branches'))],
1059 _('[-ac]'))
1062 _('[-ac]'))
1060 def branches(ui, repo, active=False, closed=False):
1063 def branches(ui, repo, active=False, closed=False):
1061 """list repository named branches
1064 """list repository named branches
1062
1065
1063 List the repository's named branches, indicating which ones are
1066 List the repository's named branches, indicating which ones are
1064 inactive. If -c/--closed is specified, also list branches which have
1067 inactive. If -c/--closed is specified, also list branches which have
1065 been marked closed (see :hg:`commit --close-branch`).
1068 been marked closed (see :hg:`commit --close-branch`).
1066
1069
1067 If -a/--active is specified, only show active branches. A branch
1070 If -a/--active is specified, only show active branches. A branch
1068 is considered active if it contains repository heads.
1071 is considered active if it contains repository heads.
1069
1072
1070 Use the command :hg:`update` to switch to an existing branch.
1073 Use the command :hg:`update` to switch to an existing branch.
1071
1074
1072 Returns 0.
1075 Returns 0.
1073 """
1076 """
1074
1077
1075 hexfunc = ui.debugflag and hex or short
1078 hexfunc = ui.debugflag and hex or short
1076
1079
1077 allheads = set(repo.heads())
1080 allheads = set(repo.heads())
1078 branches = []
1081 branches = []
1079 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1082 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1080 isactive = not isclosed and bool(set(heads) & allheads)
1083 isactive = not isclosed and bool(set(heads) & allheads)
1081 branches.append((tag, repo[tip], isactive, not isclosed))
1084 branches.append((tag, repo[tip], isactive, not isclosed))
1082 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1085 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1083 reverse=True)
1086 reverse=True)
1084
1087
1085 for tag, ctx, isactive, isopen in branches:
1088 for tag, ctx, isactive, isopen in branches:
1086 if (not active) or isactive:
1089 if (not active) or isactive:
1087 if isactive:
1090 if isactive:
1088 label = 'branches.active'
1091 label = 'branches.active'
1089 notice = ''
1092 notice = ''
1090 elif not isopen:
1093 elif not isopen:
1091 if not closed:
1094 if not closed:
1092 continue
1095 continue
1093 label = 'branches.closed'
1096 label = 'branches.closed'
1094 notice = _(' (closed)')
1097 notice = _(' (closed)')
1095 else:
1098 else:
1096 label = 'branches.inactive'
1099 label = 'branches.inactive'
1097 notice = _(' (inactive)')
1100 notice = _(' (inactive)')
1098 if tag == repo.dirstate.branch():
1101 if tag == repo.dirstate.branch():
1099 label = 'branches.current'
1102 label = 'branches.current'
1100 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1103 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1101 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1104 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1102 'log.changeset changeset.%s' % ctx.phasestr())
1105 'log.changeset changeset.%s' % ctx.phasestr())
1103 labeledtag = ui.label(tag, label)
1106 labeledtag = ui.label(tag, label)
1104 if ui.quiet:
1107 if ui.quiet:
1105 ui.write("%s\n" % labeledtag)
1108 ui.write("%s\n" % labeledtag)
1106 else:
1109 else:
1107 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1110 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1108
1111
1109 @command('bundle',
1112 @command('bundle',
1110 [('f', 'force', None, _('run even when the destination is unrelated')),
1113 [('f', 'force', None, _('run even when the destination is unrelated')),
1111 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1114 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1112 _('REV')),
1115 _('REV')),
1113 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1116 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1114 _('BRANCH')),
1117 _('BRANCH')),
1115 ('', 'base', [],
1118 ('', 'base', [],
1116 _('a base changeset assumed to be available at the destination'),
1119 _('a base changeset assumed to be available at the destination'),
1117 _('REV')),
1120 _('REV')),
1118 ('a', 'all', None, _('bundle all changesets in the repository')),
1121 ('a', 'all', None, _('bundle all changesets in the repository')),
1119 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1122 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1120 ] + remoteopts,
1123 ] + remoteopts,
1121 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1124 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1122 def bundle(ui, repo, fname, dest=None, **opts):
1125 def bundle(ui, repo, fname, dest=None, **opts):
1123 """create a changegroup file
1126 """create a changegroup file
1124
1127
1125 Generate a compressed changegroup file collecting changesets not
1128 Generate a compressed changegroup file collecting changesets not
1126 known to be in another repository.
1129 known to be in another repository.
1127
1130
1128 If you omit the destination repository, then hg assumes the
1131 If you omit the destination repository, then hg assumes the
1129 destination will have all the nodes you specify with --base
1132 destination will have all the nodes you specify with --base
1130 parameters. To create a bundle containing all changesets, use
1133 parameters. To create a bundle containing all changesets, use
1131 -a/--all (or --base null).
1134 -a/--all (or --base null).
1132
1135
1133 You can change compression method with the -t/--type option.
1136 You can change compression method with the -t/--type option.
1134 The available compression methods are: none, bzip2, and
1137 The available compression methods are: none, bzip2, and
1135 gzip (by default, bundles are compressed using bzip2).
1138 gzip (by default, bundles are compressed using bzip2).
1136
1139
1137 The bundle file can then be transferred using conventional means
1140 The bundle file can then be transferred using conventional means
1138 and applied to another repository with the unbundle or pull
1141 and applied to another repository with the unbundle or pull
1139 command. This is useful when direct push and pull are not
1142 command. This is useful when direct push and pull are not
1140 available or when exporting an entire repository is undesirable.
1143 available or when exporting an entire repository is undesirable.
1141
1144
1142 Applying bundles preserves all changeset contents including
1145 Applying bundles preserves all changeset contents including
1143 permissions, copy/rename information, and revision history.
1146 permissions, copy/rename information, and revision history.
1144
1147
1145 Returns 0 on success, 1 if no changes found.
1148 Returns 0 on success, 1 if no changes found.
1146 """
1149 """
1147 revs = None
1150 revs = None
1148 if 'rev' in opts:
1151 if 'rev' in opts:
1149 revs = scmutil.revrange(repo, opts['rev'])
1152 revs = scmutil.revrange(repo, opts['rev'])
1150
1153
1151 bundletype = opts.get('type', 'bzip2').lower()
1154 bundletype = opts.get('type', 'bzip2').lower()
1152 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1155 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1153 bundletype = btypes.get(bundletype)
1156 bundletype = btypes.get(bundletype)
1154 if bundletype not in changegroup.bundletypes:
1157 if bundletype not in changegroup.bundletypes:
1155 raise util.Abort(_('unknown bundle type specified with --type'))
1158 raise util.Abort(_('unknown bundle type specified with --type'))
1156
1159
1157 if opts.get('all'):
1160 if opts.get('all'):
1158 base = ['null']
1161 base = ['null']
1159 else:
1162 else:
1160 base = scmutil.revrange(repo, opts.get('base'))
1163 base = scmutil.revrange(repo, opts.get('base'))
1161 # TODO: get desired bundlecaps from command line.
1164 # TODO: get desired bundlecaps from command line.
1162 bundlecaps = None
1165 bundlecaps = None
1163 if base:
1166 if base:
1164 if dest:
1167 if dest:
1165 raise util.Abort(_("--base is incompatible with specifying "
1168 raise util.Abort(_("--base is incompatible with specifying "
1166 "a destination"))
1169 "a destination"))
1167 common = [repo.lookup(rev) for rev in base]
1170 common = [repo.lookup(rev) for rev in base]
1168 heads = revs and map(repo.lookup, revs) or revs
1171 heads = revs and map(repo.lookup, revs) or revs
1169 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1172 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1170 common=common, bundlecaps=bundlecaps)
1173 common=common, bundlecaps=bundlecaps)
1171 outgoing = None
1174 outgoing = None
1172 else:
1175 else:
1173 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1176 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1174 dest, branches = hg.parseurl(dest, opts.get('branch'))
1177 dest, branches = hg.parseurl(dest, opts.get('branch'))
1175 other = hg.peer(repo, opts, dest)
1178 other = hg.peer(repo, opts, dest)
1176 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1179 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1177 heads = revs and map(repo.lookup, revs) or revs
1180 heads = revs and map(repo.lookup, revs) or revs
1178 outgoing = discovery.findcommonoutgoing(repo, other,
1181 outgoing = discovery.findcommonoutgoing(repo, other,
1179 onlyheads=heads,
1182 onlyheads=heads,
1180 force=opts.get('force'),
1183 force=opts.get('force'),
1181 portable=True)
1184 portable=True)
1182 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1185 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1183 bundlecaps)
1186 bundlecaps)
1184 if not cg:
1187 if not cg:
1185 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1188 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1186 return 1
1189 return 1
1187
1190
1188 changegroup.writebundle(cg, fname, bundletype)
1191 changegroup.writebundle(cg, fname, bundletype)
1189
1192
1190 @command('cat',
1193 @command('cat',
1191 [('o', 'output', '',
1194 [('o', 'output', '',
1192 _('print output to file with formatted name'), _('FORMAT')),
1195 _('print output to file with formatted name'), _('FORMAT')),
1193 ('r', 'rev', '', _('print the given revision'), _('REV')),
1196 ('r', 'rev', '', _('print the given revision'), _('REV')),
1194 ('', 'decode', None, _('apply any matching decode filter')),
1197 ('', 'decode', None, _('apply any matching decode filter')),
1195 ] + walkopts,
1198 ] + walkopts,
1196 _('[OPTION]... FILE...'),
1199 _('[OPTION]... FILE...'),
1197 inferrepo=True)
1200 inferrepo=True)
1198 def cat(ui, repo, file1, *pats, **opts):
1201 def cat(ui, repo, file1, *pats, **opts):
1199 """output the current or given revision of files
1202 """output the current or given revision of files
1200
1203
1201 Print the specified files as they were at the given revision. If
1204 Print the specified files as they were at the given revision. If
1202 no revision is given, the parent of the working directory is used.
1205 no revision is given, the parent of the working directory is used.
1203
1206
1204 Output may be to a file, in which case the name of the file is
1207 Output may be to a file, in which case the name of the file is
1205 given using a format string. The formatting rules as follows:
1208 given using a format string. The formatting rules as follows:
1206
1209
1207 :``%%``: literal "%" character
1210 :``%%``: literal "%" character
1208 :``%s``: basename of file being printed
1211 :``%s``: basename of file being printed
1209 :``%d``: dirname of file being printed, or '.' if in repository root
1212 :``%d``: dirname of file being printed, or '.' if in repository root
1210 :``%p``: root-relative path name of file being printed
1213 :``%p``: root-relative path name of file being printed
1211 :``%H``: changeset hash (40 hexadecimal digits)
1214 :``%H``: changeset hash (40 hexadecimal digits)
1212 :``%R``: changeset revision number
1215 :``%R``: changeset revision number
1213 :``%h``: short-form changeset hash (12 hexadecimal digits)
1216 :``%h``: short-form changeset hash (12 hexadecimal digits)
1214 :``%r``: zero-padded changeset revision number
1217 :``%r``: zero-padded changeset revision number
1215 :``%b``: basename of the exporting repository
1218 :``%b``: basename of the exporting repository
1216
1219
1217 Returns 0 on success.
1220 Returns 0 on success.
1218 """
1221 """
1219 ctx = scmutil.revsingle(repo, opts.get('rev'))
1222 ctx = scmutil.revsingle(repo, opts.get('rev'))
1220 m = scmutil.match(ctx, (file1,) + pats, opts)
1223 m = scmutil.match(ctx, (file1,) + pats, opts)
1221
1224
1222 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1225 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1223
1226
1224 @command('^clone',
1227 @command('^clone',
1225 [('U', 'noupdate', None,
1228 [('U', 'noupdate', None,
1226 _('the clone will include an empty working copy (only a repository)')),
1229 _('the clone will include an empty working copy (only a repository)')),
1227 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1230 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1228 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1231 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1229 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1232 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1230 ('', 'pull', None, _('use pull protocol to copy metadata')),
1233 ('', 'pull', None, _('use pull protocol to copy metadata')),
1231 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1234 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1232 ] + remoteopts,
1235 ] + remoteopts,
1233 _('[OPTION]... SOURCE [DEST]'),
1236 _('[OPTION]... SOURCE [DEST]'),
1234 norepo=True)
1237 norepo=True)
1235 def clone(ui, source, dest=None, **opts):
1238 def clone(ui, source, dest=None, **opts):
1236 """make a copy of an existing repository
1239 """make a copy of an existing repository
1237
1240
1238 Create a copy of an existing repository in a new directory.
1241 Create a copy of an existing repository in a new directory.
1239
1242
1240 If no destination directory name is specified, it defaults to the
1243 If no destination directory name is specified, it defaults to the
1241 basename of the source.
1244 basename of the source.
1242
1245
1243 The location of the source is added to the new repository's
1246 The location of the source is added to the new repository's
1244 ``.hg/hgrc`` file, as the default to be used for future pulls.
1247 ``.hg/hgrc`` file, as the default to be used for future pulls.
1245
1248
1246 Only local paths and ``ssh://`` URLs are supported as
1249 Only local paths and ``ssh://`` URLs are supported as
1247 destinations. For ``ssh://`` destinations, no working directory or
1250 destinations. For ``ssh://`` destinations, no working directory or
1248 ``.hg/hgrc`` will be created on the remote side.
1251 ``.hg/hgrc`` will be created on the remote side.
1249
1252
1250 To pull only a subset of changesets, specify one or more revisions
1253 To pull only a subset of changesets, specify one or more revisions
1251 identifiers with -r/--rev or branches with -b/--branch. The
1254 identifiers with -r/--rev or branches with -b/--branch. The
1252 resulting clone will contain only the specified changesets and
1255 resulting clone will contain only the specified changesets and
1253 their ancestors. These options (or 'clone src#rev dest') imply
1256 their ancestors. These options (or 'clone src#rev dest') imply
1254 --pull, even for local source repositories. Note that specifying a
1257 --pull, even for local source repositories. Note that specifying a
1255 tag will include the tagged changeset but not the changeset
1258 tag will include the tagged changeset but not the changeset
1256 containing the tag.
1259 containing the tag.
1257
1260
1258 If the source repository has a bookmark called '@' set, that
1261 If the source repository has a bookmark called '@' set, that
1259 revision will be checked out in the new repository by default.
1262 revision will be checked out in the new repository by default.
1260
1263
1261 To check out a particular version, use -u/--update, or
1264 To check out a particular version, use -u/--update, or
1262 -U/--noupdate to create a clone with no working directory.
1265 -U/--noupdate to create a clone with no working directory.
1263
1266
1264 .. container:: verbose
1267 .. container:: verbose
1265
1268
1266 For efficiency, hardlinks are used for cloning whenever the
1269 For efficiency, hardlinks are used for cloning whenever the
1267 source and destination are on the same filesystem (note this
1270 source and destination are on the same filesystem (note this
1268 applies only to the repository data, not to the working
1271 applies only to the repository data, not to the working
1269 directory). Some filesystems, such as AFS, implement hardlinking
1272 directory). Some filesystems, such as AFS, implement hardlinking
1270 incorrectly, but do not report errors. In these cases, use the
1273 incorrectly, but do not report errors. In these cases, use the
1271 --pull option to avoid hardlinking.
1274 --pull option to avoid hardlinking.
1272
1275
1273 In some cases, you can clone repositories and the working
1276 In some cases, you can clone repositories and the working
1274 directory using full hardlinks with ::
1277 directory using full hardlinks with ::
1275
1278
1276 $ cp -al REPO REPOCLONE
1279 $ cp -al REPO REPOCLONE
1277
1280
1278 This is the fastest way to clone, but it is not always safe. The
1281 This is the fastest way to clone, but it is not always safe. The
1279 operation is not atomic (making sure REPO is not modified during
1282 operation is not atomic (making sure REPO is not modified during
1280 the operation is up to you) and you have to make sure your
1283 the operation is up to you) and you have to make sure your
1281 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1284 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1282 so). Also, this is not compatible with certain extensions that
1285 so). Also, this is not compatible with certain extensions that
1283 place their metadata under the .hg directory, such as mq.
1286 place their metadata under the .hg directory, such as mq.
1284
1287
1285 Mercurial will update the working directory to the first applicable
1288 Mercurial will update the working directory to the first applicable
1286 revision from this list:
1289 revision from this list:
1287
1290
1288 a) null if -U or the source repository has no changesets
1291 a) null if -U or the source repository has no changesets
1289 b) if -u . and the source repository is local, the first parent of
1292 b) if -u . and the source repository is local, the first parent of
1290 the source repository's working directory
1293 the source repository's working directory
1291 c) the changeset specified with -u (if a branch name, this means the
1294 c) the changeset specified with -u (if a branch name, this means the
1292 latest head of that branch)
1295 latest head of that branch)
1293 d) the changeset specified with -r
1296 d) the changeset specified with -r
1294 e) the tipmost head specified with -b
1297 e) the tipmost head specified with -b
1295 f) the tipmost head specified with the url#branch source syntax
1298 f) the tipmost head specified with the url#branch source syntax
1296 g) the revision marked with the '@' bookmark, if present
1299 g) the revision marked with the '@' bookmark, if present
1297 h) the tipmost head of the default branch
1300 h) the tipmost head of the default branch
1298 i) tip
1301 i) tip
1299
1302
1300 Examples:
1303 Examples:
1301
1304
1302 - clone a remote repository to a new directory named hg/::
1305 - clone a remote repository to a new directory named hg/::
1303
1306
1304 hg clone http://selenic.com/hg
1307 hg clone http://selenic.com/hg
1305
1308
1306 - create a lightweight local clone::
1309 - create a lightweight local clone::
1307
1310
1308 hg clone project/ project-feature/
1311 hg clone project/ project-feature/
1309
1312
1310 - clone from an absolute path on an ssh server (note double-slash)::
1313 - clone from an absolute path on an ssh server (note double-slash)::
1311
1314
1312 hg clone ssh://user@server//home/projects/alpha/
1315 hg clone ssh://user@server//home/projects/alpha/
1313
1316
1314 - do a high-speed clone over a LAN while checking out a
1317 - do a high-speed clone over a LAN while checking out a
1315 specified version::
1318 specified version::
1316
1319
1317 hg clone --uncompressed http://server/repo -u 1.5
1320 hg clone --uncompressed http://server/repo -u 1.5
1318
1321
1319 - create a repository without changesets after a particular revision::
1322 - create a repository without changesets after a particular revision::
1320
1323
1321 hg clone -r 04e544 experimental/ good/
1324 hg clone -r 04e544 experimental/ good/
1322
1325
1323 - clone (and track) a particular named branch::
1326 - clone (and track) a particular named branch::
1324
1327
1325 hg clone http://selenic.com/hg#stable
1328 hg clone http://selenic.com/hg#stable
1326
1329
1327 See :hg:`help urls` for details on specifying URLs.
1330 See :hg:`help urls` for details on specifying URLs.
1328
1331
1329 Returns 0 on success.
1332 Returns 0 on success.
1330 """
1333 """
1331 if opts.get('noupdate') and opts.get('updaterev'):
1334 if opts.get('noupdate') and opts.get('updaterev'):
1332 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1335 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1333
1336
1334 r = hg.clone(ui, opts, source, dest,
1337 r = hg.clone(ui, opts, source, dest,
1335 pull=opts.get('pull'),
1338 pull=opts.get('pull'),
1336 stream=opts.get('uncompressed'),
1339 stream=opts.get('uncompressed'),
1337 rev=opts.get('rev'),
1340 rev=opts.get('rev'),
1338 update=opts.get('updaterev') or not opts.get('noupdate'),
1341 update=opts.get('updaterev') or not opts.get('noupdate'),
1339 branch=opts.get('branch'))
1342 branch=opts.get('branch'))
1340
1343
1341 return r is None
1344 return r is None
1342
1345
1343 @command('^commit|ci',
1346 @command('^commit|ci',
1344 [('A', 'addremove', None,
1347 [('A', 'addremove', None,
1345 _('mark new/missing files as added/removed before committing')),
1348 _('mark new/missing files as added/removed before committing')),
1346 ('', 'close-branch', None,
1349 ('', 'close-branch', None,
1347 _('mark a branch as closed, hiding it from the branch list')),
1350 _('mark a branch as closed, hiding it from the branch list')),
1348 ('', 'amend', None, _('amend the parent of the working dir')),
1351 ('', 'amend', None, _('amend the parent of the working dir')),
1349 ('s', 'secret', None, _('use the secret phase for committing')),
1352 ('s', 'secret', None, _('use the secret phase for committing')),
1350 ('e', 'edit', None, _('invoke editor on commit messages')),
1353 ('e', 'edit', None, _('invoke editor on commit messages')),
1351 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1354 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1352 _('[OPTION]... [FILE]...'),
1355 _('[OPTION]... [FILE]...'),
1353 inferrepo=True)
1356 inferrepo=True)
1354 def commit(ui, repo, *pats, **opts):
1357 def commit(ui, repo, *pats, **opts):
1355 """commit the specified files or all outstanding changes
1358 """commit the specified files or all outstanding changes
1356
1359
1357 Commit changes to the given files into the repository. Unlike a
1360 Commit changes to the given files into the repository. Unlike a
1358 centralized SCM, this operation is a local operation. See
1361 centralized SCM, this operation is a local operation. See
1359 :hg:`push` for a way to actively distribute your changes.
1362 :hg:`push` for a way to actively distribute your changes.
1360
1363
1361 If a list of files is omitted, all changes reported by :hg:`status`
1364 If a list of files is omitted, all changes reported by :hg:`status`
1362 will be committed.
1365 will be committed.
1363
1366
1364 If you are committing the result of a merge, do not provide any
1367 If you are committing the result of a merge, do not provide any
1365 filenames or -I/-X filters.
1368 filenames or -I/-X filters.
1366
1369
1367 If no commit message is specified, Mercurial starts your
1370 If no commit message is specified, Mercurial starts your
1368 configured editor where you can enter a message. In case your
1371 configured editor where you can enter a message. In case your
1369 commit fails, you will find a backup of your message in
1372 commit fails, you will find a backup of your message in
1370 ``.hg/last-message.txt``.
1373 ``.hg/last-message.txt``.
1371
1374
1372 The --amend flag can be used to amend the parent of the
1375 The --amend flag can be used to amend the parent of the
1373 working directory with a new commit that contains the changes
1376 working directory with a new commit that contains the changes
1374 in the parent in addition to those currently reported by :hg:`status`,
1377 in the parent in addition to those currently reported by :hg:`status`,
1375 if there are any. The old commit is stored in a backup bundle in
1378 if there are any. The old commit is stored in a backup bundle in
1376 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1379 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1377 on how to restore it).
1380 on how to restore it).
1378
1381
1379 Message, user and date are taken from the amended commit unless
1382 Message, user and date are taken from the amended commit unless
1380 specified. When a message isn't specified on the command line,
1383 specified. When a message isn't specified on the command line,
1381 the editor will open with the message of the amended commit.
1384 the editor will open with the message of the amended commit.
1382
1385
1383 It is not possible to amend public changesets (see :hg:`help phases`)
1386 It is not possible to amend public changesets (see :hg:`help phases`)
1384 or changesets that have children.
1387 or changesets that have children.
1385
1388
1386 See :hg:`help dates` for a list of formats valid for -d/--date.
1389 See :hg:`help dates` for a list of formats valid for -d/--date.
1387
1390
1388 Returns 0 on success, 1 if nothing changed.
1391 Returns 0 on success, 1 if nothing changed.
1389 """
1392 """
1390 if opts.get('subrepos'):
1393 if opts.get('subrepos'):
1391 if opts.get('amend'):
1394 if opts.get('amend'):
1392 raise util.Abort(_('cannot amend with --subrepos'))
1395 raise util.Abort(_('cannot amend with --subrepos'))
1393 # Let --subrepos on the command line override config setting.
1396 # Let --subrepos on the command line override config setting.
1394 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1397 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1395
1398
1396 cmdutil.checkunfinished(repo, commit=True)
1399 cmdutil.checkunfinished(repo, commit=True)
1397
1400
1398 branch = repo[None].branch()
1401 branch = repo[None].branch()
1399 bheads = repo.branchheads(branch)
1402 bheads = repo.branchheads(branch)
1400
1403
1401 extra = {}
1404 extra = {}
1402 if opts.get('close_branch'):
1405 if opts.get('close_branch'):
1403 extra['close'] = 1
1406 extra['close'] = 1
1404
1407
1405 if not bheads:
1408 if not bheads:
1406 raise util.Abort(_('can only close branch heads'))
1409 raise util.Abort(_('can only close branch heads'))
1407 elif opts.get('amend'):
1410 elif opts.get('amend'):
1408 if repo.parents()[0].p1().branch() != branch and \
1411 if repo.parents()[0].p1().branch() != branch and \
1409 repo.parents()[0].p2().branch() != branch:
1412 repo.parents()[0].p2().branch() != branch:
1410 raise util.Abort(_('can only close branch heads'))
1413 raise util.Abort(_('can only close branch heads'))
1411
1414
1412 if opts.get('amend'):
1415 if opts.get('amend'):
1413 if ui.configbool('ui', 'commitsubrepos'):
1416 if ui.configbool('ui', 'commitsubrepos'):
1414 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1417 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1415
1418
1416 old = repo['.']
1419 old = repo['.']
1417 if not old.mutable():
1420 if not old.mutable():
1418 raise util.Abort(_('cannot amend public changesets'))
1421 raise util.Abort(_('cannot amend public changesets'))
1419 if len(repo[None].parents()) > 1:
1422 if len(repo[None].parents()) > 1:
1420 raise util.Abort(_('cannot amend while merging'))
1423 raise util.Abort(_('cannot amend while merging'))
1421 if (not obsolete._enabled) and old.children():
1424 if (not obsolete._enabled) and old.children():
1422 raise util.Abort(_('cannot amend changeset with children'))
1425 raise util.Abort(_('cannot amend changeset with children'))
1423
1426
1424 # commitfunc is used only for temporary amend commit by cmdutil.amend
1427 # commitfunc is used only for temporary amend commit by cmdutil.amend
1425 def commitfunc(ui, repo, message, match, opts):
1428 def commitfunc(ui, repo, message, match, opts):
1426 return repo.commit(message,
1429 return repo.commit(message,
1427 opts.get('user') or old.user(),
1430 opts.get('user') or old.user(),
1428 opts.get('date') or old.date(),
1431 opts.get('date') or old.date(),
1429 match,
1432 match,
1430 extra=extra)
1433 extra=extra)
1431
1434
1432 current = repo._bookmarkcurrent
1435 current = repo._bookmarkcurrent
1433 marks = old.bookmarks()
1436 marks = old.bookmarks()
1434 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1437 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1435 if node == old.node():
1438 if node == old.node():
1436 ui.status(_("nothing changed\n"))
1439 ui.status(_("nothing changed\n"))
1437 return 1
1440 return 1
1438 elif marks:
1441 elif marks:
1439 ui.debug('moving bookmarks %r from %s to %s\n' %
1442 ui.debug('moving bookmarks %r from %s to %s\n' %
1440 (marks, old.hex(), hex(node)))
1443 (marks, old.hex(), hex(node)))
1441 newmarks = repo._bookmarks
1444 newmarks = repo._bookmarks
1442 for bm in marks:
1445 for bm in marks:
1443 newmarks[bm] = node
1446 newmarks[bm] = node
1444 if bm == current:
1447 if bm == current:
1445 bookmarks.setcurrent(repo, bm)
1448 bookmarks.setcurrent(repo, bm)
1446 newmarks.write()
1449 newmarks.write()
1447 else:
1450 else:
1448 def commitfunc(ui, repo, message, match, opts):
1451 def commitfunc(ui, repo, message, match, opts):
1449 backup = ui.backupconfig('phases', 'new-commit')
1452 backup = ui.backupconfig('phases', 'new-commit')
1450 baseui = repo.baseui
1453 baseui = repo.baseui
1451 basebackup = baseui.backupconfig('phases', 'new-commit')
1454 basebackup = baseui.backupconfig('phases', 'new-commit')
1452 try:
1455 try:
1453 if opts.get('secret'):
1456 if opts.get('secret'):
1454 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1457 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1455 # Propagate to subrepos
1458 # Propagate to subrepos
1456 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1459 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1457
1460
1458 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1461 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1459 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1462 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1460 return repo.commit(message, opts.get('user'), opts.get('date'),
1463 return repo.commit(message, opts.get('user'), opts.get('date'),
1461 match,
1464 match,
1462 editor=editor,
1465 editor=editor,
1463 extra=extra)
1466 extra=extra)
1464 finally:
1467 finally:
1465 ui.restoreconfig(backup)
1468 ui.restoreconfig(backup)
1466 repo.baseui.restoreconfig(basebackup)
1469 repo.baseui.restoreconfig(basebackup)
1467
1470
1468
1471
1469 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1472 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1470
1473
1471 if not node:
1474 if not node:
1472 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1475 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1473 if stat[3]:
1476 if stat[3]:
1474 ui.status(_("nothing changed (%d missing files, see "
1477 ui.status(_("nothing changed (%d missing files, see "
1475 "'hg status')\n") % len(stat[3]))
1478 "'hg status')\n") % len(stat[3]))
1476 else:
1479 else:
1477 ui.status(_("nothing changed\n"))
1480 ui.status(_("nothing changed\n"))
1478 return 1
1481 return 1
1479
1482
1480 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1483 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1481
1484
1482 @command('config|showconfig|debugconfig',
1485 @command('config|showconfig|debugconfig',
1483 [('u', 'untrusted', None, _('show untrusted configuration options')),
1486 [('u', 'untrusted', None, _('show untrusted configuration options')),
1484 ('e', 'edit', None, _('edit user config')),
1487 ('e', 'edit', None, _('edit user config')),
1485 ('l', 'local', None, _('edit repository config')),
1488 ('l', 'local', None, _('edit repository config')),
1486 ('g', 'global', None, _('edit global config'))],
1489 ('g', 'global', None, _('edit global config'))],
1487 _('[-u] [NAME]...'),
1490 _('[-u] [NAME]...'),
1488 optionalrepo=True)
1491 optionalrepo=True)
1489 def config(ui, repo, *values, **opts):
1492 def config(ui, repo, *values, **opts):
1490 """show combined config settings from all hgrc files
1493 """show combined config settings from all hgrc files
1491
1494
1492 With no arguments, print names and values of all config items.
1495 With no arguments, print names and values of all config items.
1493
1496
1494 With one argument of the form section.name, print just the value
1497 With one argument of the form section.name, print just the value
1495 of that config item.
1498 of that config item.
1496
1499
1497 With multiple arguments, print names and values of all config
1500 With multiple arguments, print names and values of all config
1498 items with matching section names.
1501 items with matching section names.
1499
1502
1500 With --edit, start an editor on the user-level config file. With
1503 With --edit, start an editor on the user-level config file. With
1501 --global, edit the system-wide config file. With --local, edit the
1504 --global, edit the system-wide config file. With --local, edit the
1502 repository-level config file.
1505 repository-level config file.
1503
1506
1504 With --debug, the source (filename and line number) is printed
1507 With --debug, the source (filename and line number) is printed
1505 for each config item.
1508 for each config item.
1506
1509
1507 See :hg:`help config` for more information about config files.
1510 See :hg:`help config` for more information about config files.
1508
1511
1509 Returns 0 on success, 1 if NAME does not exist.
1512 Returns 0 on success, 1 if NAME does not exist.
1510
1513
1511 """
1514 """
1512
1515
1513 if opts.get('edit') or opts.get('local') or opts.get('global'):
1516 if opts.get('edit') or opts.get('local') or opts.get('global'):
1514 if opts.get('local') and opts.get('global'):
1517 if opts.get('local') and opts.get('global'):
1515 raise util.Abort(_("can't use --local and --global together"))
1518 raise util.Abort(_("can't use --local and --global together"))
1516
1519
1517 if opts.get('local'):
1520 if opts.get('local'):
1518 if not repo:
1521 if not repo:
1519 raise util.Abort(_("can't use --local outside a repository"))
1522 raise util.Abort(_("can't use --local outside a repository"))
1520 paths = [repo.join('hgrc')]
1523 paths = [repo.join('hgrc')]
1521 elif opts.get('global'):
1524 elif opts.get('global'):
1522 paths = scmutil.systemrcpath()
1525 paths = scmutil.systemrcpath()
1523 else:
1526 else:
1524 paths = scmutil.userrcpath()
1527 paths = scmutil.userrcpath()
1525
1528
1526 for f in paths:
1529 for f in paths:
1527 if os.path.exists(f):
1530 if os.path.exists(f):
1528 break
1531 break
1529 else:
1532 else:
1530 from ui import samplehgrcs
1533 from ui import samplehgrcs
1531
1534
1532 if opts.get('global'):
1535 if opts.get('global'):
1533 samplehgrc = samplehgrcs['global']
1536 samplehgrc = samplehgrcs['global']
1534 elif opts.get('local'):
1537 elif opts.get('local'):
1535 samplehgrc = samplehgrcs['local']
1538 samplehgrc = samplehgrcs['local']
1536 else:
1539 else:
1537 samplehgrc = samplehgrcs['user']
1540 samplehgrc = samplehgrcs['user']
1538
1541
1539 f = paths[0]
1542 f = paths[0]
1540 fp = open(f, "w")
1543 fp = open(f, "w")
1541 fp.write(samplehgrc)
1544 fp.write(samplehgrc)
1542 fp.close()
1545 fp.close()
1543
1546
1544 editor = ui.geteditor()
1547 editor = ui.geteditor()
1545 util.system("%s \"%s\"" % (editor, f),
1548 util.system("%s \"%s\"" % (editor, f),
1546 onerr=util.Abort, errprefix=_("edit failed"),
1549 onerr=util.Abort, errprefix=_("edit failed"),
1547 out=ui.fout)
1550 out=ui.fout)
1548 return
1551 return
1549
1552
1550 for f in scmutil.rcpath():
1553 for f in scmutil.rcpath():
1551 ui.debug('read config from: %s\n' % f)
1554 ui.debug('read config from: %s\n' % f)
1552 untrusted = bool(opts.get('untrusted'))
1555 untrusted = bool(opts.get('untrusted'))
1553 if values:
1556 if values:
1554 sections = [v for v in values if '.' not in v]
1557 sections = [v for v in values if '.' not in v]
1555 items = [v for v in values if '.' in v]
1558 items = [v for v in values if '.' in v]
1556 if len(items) > 1 or items and sections:
1559 if len(items) > 1 or items and sections:
1557 raise util.Abort(_('only one config item permitted'))
1560 raise util.Abort(_('only one config item permitted'))
1558 matched = False
1561 matched = False
1559 for section, name, value in ui.walkconfig(untrusted=untrusted):
1562 for section, name, value in ui.walkconfig(untrusted=untrusted):
1560 value = str(value).replace('\n', '\\n')
1563 value = str(value).replace('\n', '\\n')
1561 sectname = section + '.' + name
1564 sectname = section + '.' + name
1562 if values:
1565 if values:
1563 for v in values:
1566 for v in values:
1564 if v == section:
1567 if v == section:
1565 ui.debug('%s: ' %
1568 ui.debug('%s: ' %
1566 ui.configsource(section, name, untrusted))
1569 ui.configsource(section, name, untrusted))
1567 ui.write('%s=%s\n' % (sectname, value))
1570 ui.write('%s=%s\n' % (sectname, value))
1568 matched = True
1571 matched = True
1569 elif v == sectname:
1572 elif v == sectname:
1570 ui.debug('%s: ' %
1573 ui.debug('%s: ' %
1571 ui.configsource(section, name, untrusted))
1574 ui.configsource(section, name, untrusted))
1572 ui.write(value, '\n')
1575 ui.write(value, '\n')
1573 matched = True
1576 matched = True
1574 else:
1577 else:
1575 ui.debug('%s: ' %
1578 ui.debug('%s: ' %
1576 ui.configsource(section, name, untrusted))
1579 ui.configsource(section, name, untrusted))
1577 ui.write('%s=%s\n' % (sectname, value))
1580 ui.write('%s=%s\n' % (sectname, value))
1578 matched = True
1581 matched = True
1579 if matched:
1582 if matched:
1580 return 0
1583 return 0
1581 return 1
1584 return 1
1582
1585
1583 @command('copy|cp',
1586 @command('copy|cp',
1584 [('A', 'after', None, _('record a copy that has already occurred')),
1587 [('A', 'after', None, _('record a copy that has already occurred')),
1585 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1588 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1586 ] + walkopts + dryrunopts,
1589 ] + walkopts + dryrunopts,
1587 _('[OPTION]... [SOURCE]... DEST'))
1590 _('[OPTION]... [SOURCE]... DEST'))
1588 def copy(ui, repo, *pats, **opts):
1591 def copy(ui, repo, *pats, **opts):
1589 """mark files as copied for the next commit
1592 """mark files as copied for the next commit
1590
1593
1591 Mark dest as having copies of source files. If dest is a
1594 Mark dest as having copies of source files. If dest is a
1592 directory, copies are put in that directory. If dest is a file,
1595 directory, copies are put in that directory. If dest is a file,
1593 the source must be a single file.
1596 the source must be a single file.
1594
1597
1595 By default, this command copies the contents of files as they
1598 By default, this command copies the contents of files as they
1596 exist in the working directory. If invoked with -A/--after, the
1599 exist in the working directory. If invoked with -A/--after, the
1597 operation is recorded, but no copying is performed.
1600 operation is recorded, but no copying is performed.
1598
1601
1599 This command takes effect with the next commit. To undo a copy
1602 This command takes effect with the next commit. To undo a copy
1600 before that, see :hg:`revert`.
1603 before that, see :hg:`revert`.
1601
1604
1602 Returns 0 on success, 1 if errors are encountered.
1605 Returns 0 on success, 1 if errors are encountered.
1603 """
1606 """
1604 wlock = repo.wlock(False)
1607 wlock = repo.wlock(False)
1605 try:
1608 try:
1606 return cmdutil.copy(ui, repo, pats, opts)
1609 return cmdutil.copy(ui, repo, pats, opts)
1607 finally:
1610 finally:
1608 wlock.release()
1611 wlock.release()
1609
1612
1610 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1613 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1611 def debugancestor(ui, repo, *args):
1614 def debugancestor(ui, repo, *args):
1612 """find the ancestor revision of two revisions in a given index"""
1615 """find the ancestor revision of two revisions in a given index"""
1613 if len(args) == 3:
1616 if len(args) == 3:
1614 index, rev1, rev2 = args
1617 index, rev1, rev2 = args
1615 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1618 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1616 lookup = r.lookup
1619 lookup = r.lookup
1617 elif len(args) == 2:
1620 elif len(args) == 2:
1618 if not repo:
1621 if not repo:
1619 raise util.Abort(_("there is no Mercurial repository here "
1622 raise util.Abort(_("there is no Mercurial repository here "
1620 "(.hg not found)"))
1623 "(.hg not found)"))
1621 rev1, rev2 = args
1624 rev1, rev2 = args
1622 r = repo.changelog
1625 r = repo.changelog
1623 lookup = repo.lookup
1626 lookup = repo.lookup
1624 else:
1627 else:
1625 raise util.Abort(_('either two or three arguments required'))
1628 raise util.Abort(_('either two or three arguments required'))
1626 a = r.ancestor(lookup(rev1), lookup(rev2))
1629 a = r.ancestor(lookup(rev1), lookup(rev2))
1627 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1630 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1628
1631
1629 @command('debugbuilddag',
1632 @command('debugbuilddag',
1630 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1633 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1631 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1634 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1632 ('n', 'new-file', None, _('add new file at each rev'))],
1635 ('n', 'new-file', None, _('add new file at each rev'))],
1633 _('[OPTION]... [TEXT]'))
1636 _('[OPTION]... [TEXT]'))
1634 def debugbuilddag(ui, repo, text=None,
1637 def debugbuilddag(ui, repo, text=None,
1635 mergeable_file=False,
1638 mergeable_file=False,
1636 overwritten_file=False,
1639 overwritten_file=False,
1637 new_file=False):
1640 new_file=False):
1638 """builds a repo with a given DAG from scratch in the current empty repo
1641 """builds a repo with a given DAG from scratch in the current empty repo
1639
1642
1640 The description of the DAG is read from stdin if not given on the
1643 The description of the DAG is read from stdin if not given on the
1641 command line.
1644 command line.
1642
1645
1643 Elements:
1646 Elements:
1644
1647
1645 - "+n" is a linear run of n nodes based on the current default parent
1648 - "+n" is a linear run of n nodes based on the current default parent
1646 - "." is a single node based on the current default parent
1649 - "." is a single node based on the current default parent
1647 - "$" resets the default parent to null (implied at the start);
1650 - "$" resets the default parent to null (implied at the start);
1648 otherwise the default parent is always the last node created
1651 otherwise the default parent is always the last node created
1649 - "<p" sets the default parent to the backref p
1652 - "<p" sets the default parent to the backref p
1650 - "*p" is a fork at parent p, which is a backref
1653 - "*p" is a fork at parent p, which is a backref
1651 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1654 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1652 - "/p2" is a merge of the preceding node and p2
1655 - "/p2" is a merge of the preceding node and p2
1653 - ":tag" defines a local tag for the preceding node
1656 - ":tag" defines a local tag for the preceding node
1654 - "@branch" sets the named branch for subsequent nodes
1657 - "@branch" sets the named branch for subsequent nodes
1655 - "#...\\n" is a comment up to the end of the line
1658 - "#...\\n" is a comment up to the end of the line
1656
1659
1657 Whitespace between the above elements is ignored.
1660 Whitespace between the above elements is ignored.
1658
1661
1659 A backref is either
1662 A backref is either
1660
1663
1661 - a number n, which references the node curr-n, where curr is the current
1664 - a number n, which references the node curr-n, where curr is the current
1662 node, or
1665 node, or
1663 - the name of a local tag you placed earlier using ":tag", or
1666 - the name of a local tag you placed earlier using ":tag", or
1664 - empty to denote the default parent.
1667 - empty to denote the default parent.
1665
1668
1666 All string valued-elements are either strictly alphanumeric, or must
1669 All string valued-elements are either strictly alphanumeric, or must
1667 be enclosed in double quotes ("..."), with "\\" as escape character.
1670 be enclosed in double quotes ("..."), with "\\" as escape character.
1668 """
1671 """
1669
1672
1670 if text is None:
1673 if text is None:
1671 ui.status(_("reading DAG from stdin\n"))
1674 ui.status(_("reading DAG from stdin\n"))
1672 text = ui.fin.read()
1675 text = ui.fin.read()
1673
1676
1674 cl = repo.changelog
1677 cl = repo.changelog
1675 if len(cl) > 0:
1678 if len(cl) > 0:
1676 raise util.Abort(_('repository is not empty'))
1679 raise util.Abort(_('repository is not empty'))
1677
1680
1678 # determine number of revs in DAG
1681 # determine number of revs in DAG
1679 total = 0
1682 total = 0
1680 for type, data in dagparser.parsedag(text):
1683 for type, data in dagparser.parsedag(text):
1681 if type == 'n':
1684 if type == 'n':
1682 total += 1
1685 total += 1
1683
1686
1684 if mergeable_file:
1687 if mergeable_file:
1685 linesperrev = 2
1688 linesperrev = 2
1686 # make a file with k lines per rev
1689 # make a file with k lines per rev
1687 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1690 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1688 initialmergedlines.append("")
1691 initialmergedlines.append("")
1689
1692
1690 tags = []
1693 tags = []
1691
1694
1692 lock = tr = None
1695 lock = tr = None
1693 try:
1696 try:
1694 lock = repo.lock()
1697 lock = repo.lock()
1695 tr = repo.transaction("builddag")
1698 tr = repo.transaction("builddag")
1696
1699
1697 at = -1
1700 at = -1
1698 atbranch = 'default'
1701 atbranch = 'default'
1699 nodeids = []
1702 nodeids = []
1700 id = 0
1703 id = 0
1701 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1704 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1702 for type, data in dagparser.parsedag(text):
1705 for type, data in dagparser.parsedag(text):
1703 if type == 'n':
1706 if type == 'n':
1704 ui.note(('node %s\n' % str(data)))
1707 ui.note(('node %s\n' % str(data)))
1705 id, ps = data
1708 id, ps = data
1706
1709
1707 files = []
1710 files = []
1708 fctxs = {}
1711 fctxs = {}
1709
1712
1710 p2 = None
1713 p2 = None
1711 if mergeable_file:
1714 if mergeable_file:
1712 fn = "mf"
1715 fn = "mf"
1713 p1 = repo[ps[0]]
1716 p1 = repo[ps[0]]
1714 if len(ps) > 1:
1717 if len(ps) > 1:
1715 p2 = repo[ps[1]]
1718 p2 = repo[ps[1]]
1716 pa = p1.ancestor(p2)
1719 pa = p1.ancestor(p2)
1717 base, local, other = [x[fn].data() for x in (pa, p1,
1720 base, local, other = [x[fn].data() for x in (pa, p1,
1718 p2)]
1721 p2)]
1719 m3 = simplemerge.Merge3Text(base, local, other)
1722 m3 = simplemerge.Merge3Text(base, local, other)
1720 ml = [l.strip() for l in m3.merge_lines()]
1723 ml = [l.strip() for l in m3.merge_lines()]
1721 ml.append("")
1724 ml.append("")
1722 elif at > 0:
1725 elif at > 0:
1723 ml = p1[fn].data().split("\n")
1726 ml = p1[fn].data().split("\n")
1724 else:
1727 else:
1725 ml = initialmergedlines
1728 ml = initialmergedlines
1726 ml[id * linesperrev] += " r%i" % id
1729 ml[id * linesperrev] += " r%i" % id
1727 mergedtext = "\n".join(ml)
1730 mergedtext = "\n".join(ml)
1728 files.append(fn)
1731 files.append(fn)
1729 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1732 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1730
1733
1731 if overwritten_file:
1734 if overwritten_file:
1732 fn = "of"
1735 fn = "of"
1733 files.append(fn)
1736 files.append(fn)
1734 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1737 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1735
1738
1736 if new_file:
1739 if new_file:
1737 fn = "nf%i" % id
1740 fn = "nf%i" % id
1738 files.append(fn)
1741 files.append(fn)
1739 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1742 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1740 if len(ps) > 1:
1743 if len(ps) > 1:
1741 if not p2:
1744 if not p2:
1742 p2 = repo[ps[1]]
1745 p2 = repo[ps[1]]
1743 for fn in p2:
1746 for fn in p2:
1744 if fn.startswith("nf"):
1747 if fn.startswith("nf"):
1745 files.append(fn)
1748 files.append(fn)
1746 fctxs[fn] = p2[fn]
1749 fctxs[fn] = p2[fn]
1747
1750
1748 def fctxfn(repo, cx, path):
1751 def fctxfn(repo, cx, path):
1749 return fctxs.get(path)
1752 return fctxs.get(path)
1750
1753
1751 if len(ps) == 0 or ps[0] < 0:
1754 if len(ps) == 0 or ps[0] < 0:
1752 pars = [None, None]
1755 pars = [None, None]
1753 elif len(ps) == 1:
1756 elif len(ps) == 1:
1754 pars = [nodeids[ps[0]], None]
1757 pars = [nodeids[ps[0]], None]
1755 else:
1758 else:
1756 pars = [nodeids[p] for p in ps]
1759 pars = [nodeids[p] for p in ps]
1757 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1760 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1758 date=(id, 0),
1761 date=(id, 0),
1759 user="debugbuilddag",
1762 user="debugbuilddag",
1760 extra={'branch': atbranch})
1763 extra={'branch': atbranch})
1761 nodeid = repo.commitctx(cx)
1764 nodeid = repo.commitctx(cx)
1762 nodeids.append(nodeid)
1765 nodeids.append(nodeid)
1763 at = id
1766 at = id
1764 elif type == 'l':
1767 elif type == 'l':
1765 id, name = data
1768 id, name = data
1766 ui.note(('tag %s\n' % name))
1769 ui.note(('tag %s\n' % name))
1767 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1770 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1768 elif type == 'a':
1771 elif type == 'a':
1769 ui.note(('branch %s\n' % data))
1772 ui.note(('branch %s\n' % data))
1770 atbranch = data
1773 atbranch = data
1771 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1774 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1772 tr.close()
1775 tr.close()
1773
1776
1774 if tags:
1777 if tags:
1775 repo.opener.write("localtags", "".join(tags))
1778 repo.opener.write("localtags", "".join(tags))
1776 finally:
1779 finally:
1777 ui.progress(_('building'), None)
1780 ui.progress(_('building'), None)
1778 release(tr, lock)
1781 release(tr, lock)
1779
1782
1780 @command('debugbundle',
1783 @command('debugbundle',
1781 [('a', 'all', None, _('show all details'))],
1784 [('a', 'all', None, _('show all details'))],
1782 _('FILE'),
1785 _('FILE'),
1783 norepo=True)
1786 norepo=True)
1784 def debugbundle(ui, bundlepath, all=None, **opts):
1787 def debugbundle(ui, bundlepath, all=None, **opts):
1785 """lists the contents of a bundle"""
1788 """lists the contents of a bundle"""
1786 f = hg.openpath(ui, bundlepath)
1789 f = hg.openpath(ui, bundlepath)
1787 try:
1790 try:
1788 gen = exchange.readbundle(ui, f, bundlepath)
1791 gen = exchange.readbundle(ui, f, bundlepath)
1789 if all:
1792 if all:
1790 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1793 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1791
1794
1792 def showchunks(named):
1795 def showchunks(named):
1793 ui.write("\n%s\n" % named)
1796 ui.write("\n%s\n" % named)
1794 chain = None
1797 chain = None
1795 while True:
1798 while True:
1796 chunkdata = gen.deltachunk(chain)
1799 chunkdata = gen.deltachunk(chain)
1797 if not chunkdata:
1800 if not chunkdata:
1798 break
1801 break
1799 node = chunkdata['node']
1802 node = chunkdata['node']
1800 p1 = chunkdata['p1']
1803 p1 = chunkdata['p1']
1801 p2 = chunkdata['p2']
1804 p2 = chunkdata['p2']
1802 cs = chunkdata['cs']
1805 cs = chunkdata['cs']
1803 deltabase = chunkdata['deltabase']
1806 deltabase = chunkdata['deltabase']
1804 delta = chunkdata['delta']
1807 delta = chunkdata['delta']
1805 ui.write("%s %s %s %s %s %s\n" %
1808 ui.write("%s %s %s %s %s %s\n" %
1806 (hex(node), hex(p1), hex(p2),
1809 (hex(node), hex(p1), hex(p2),
1807 hex(cs), hex(deltabase), len(delta)))
1810 hex(cs), hex(deltabase), len(delta)))
1808 chain = node
1811 chain = node
1809
1812
1810 chunkdata = gen.changelogheader()
1813 chunkdata = gen.changelogheader()
1811 showchunks("changelog")
1814 showchunks("changelog")
1812 chunkdata = gen.manifestheader()
1815 chunkdata = gen.manifestheader()
1813 showchunks("manifest")
1816 showchunks("manifest")
1814 while True:
1817 while True:
1815 chunkdata = gen.filelogheader()
1818 chunkdata = gen.filelogheader()
1816 if not chunkdata:
1819 if not chunkdata:
1817 break
1820 break
1818 fname = chunkdata['filename']
1821 fname = chunkdata['filename']
1819 showchunks(fname)
1822 showchunks(fname)
1820 else:
1823 else:
1821 chunkdata = gen.changelogheader()
1824 chunkdata = gen.changelogheader()
1822 chain = None
1825 chain = None
1823 while True:
1826 while True:
1824 chunkdata = gen.deltachunk(chain)
1827 chunkdata = gen.deltachunk(chain)
1825 if not chunkdata:
1828 if not chunkdata:
1826 break
1829 break
1827 node = chunkdata['node']
1830 node = chunkdata['node']
1828 ui.write("%s\n" % hex(node))
1831 ui.write("%s\n" % hex(node))
1829 chain = node
1832 chain = node
1830 finally:
1833 finally:
1831 f.close()
1834 f.close()
1832
1835
1833 @command('debugcheckstate', [], '')
1836 @command('debugcheckstate', [], '')
1834 def debugcheckstate(ui, repo):
1837 def debugcheckstate(ui, repo):
1835 """validate the correctness of the current dirstate"""
1838 """validate the correctness of the current dirstate"""
1836 parent1, parent2 = repo.dirstate.parents()
1839 parent1, parent2 = repo.dirstate.parents()
1837 m1 = repo[parent1].manifest()
1840 m1 = repo[parent1].manifest()
1838 m2 = repo[parent2].manifest()
1841 m2 = repo[parent2].manifest()
1839 errors = 0
1842 errors = 0
1840 for f in repo.dirstate:
1843 for f in repo.dirstate:
1841 state = repo.dirstate[f]
1844 state = repo.dirstate[f]
1842 if state in "nr" and f not in m1:
1845 if state in "nr" and f not in m1:
1843 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1846 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1844 errors += 1
1847 errors += 1
1845 if state in "a" and f in m1:
1848 if state in "a" and f in m1:
1846 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1849 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1847 errors += 1
1850 errors += 1
1848 if state in "m" and f not in m1 and f not in m2:
1851 if state in "m" and f not in m1 and f not in m2:
1849 ui.warn(_("%s in state %s, but not in either manifest\n") %
1852 ui.warn(_("%s in state %s, but not in either manifest\n") %
1850 (f, state))
1853 (f, state))
1851 errors += 1
1854 errors += 1
1852 for f in m1:
1855 for f in m1:
1853 state = repo.dirstate[f]
1856 state = repo.dirstate[f]
1854 if state not in "nrm":
1857 if state not in "nrm":
1855 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1858 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1856 errors += 1
1859 errors += 1
1857 if errors:
1860 if errors:
1858 error = _(".hg/dirstate inconsistent with current parent's manifest")
1861 error = _(".hg/dirstate inconsistent with current parent's manifest")
1859 raise util.Abort(error)
1862 raise util.Abort(error)
1860
1863
1861 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1864 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1862 def debugcommands(ui, cmd='', *args):
1865 def debugcommands(ui, cmd='', *args):
1863 """list all available commands and options"""
1866 """list all available commands and options"""
1864 for cmd, vals in sorted(table.iteritems()):
1867 for cmd, vals in sorted(table.iteritems()):
1865 cmd = cmd.split('|')[0].strip('^')
1868 cmd = cmd.split('|')[0].strip('^')
1866 opts = ', '.join([i[1] for i in vals[1]])
1869 opts = ', '.join([i[1] for i in vals[1]])
1867 ui.write('%s: %s\n' % (cmd, opts))
1870 ui.write('%s: %s\n' % (cmd, opts))
1868
1871
1869 @command('debugcomplete',
1872 @command('debugcomplete',
1870 [('o', 'options', None, _('show the command options'))],
1873 [('o', 'options', None, _('show the command options'))],
1871 _('[-o] CMD'),
1874 _('[-o] CMD'),
1872 norepo=True)
1875 norepo=True)
1873 def debugcomplete(ui, cmd='', **opts):
1876 def debugcomplete(ui, cmd='', **opts):
1874 """returns the completion list associated with the given command"""
1877 """returns the completion list associated with the given command"""
1875
1878
1876 if opts.get('options'):
1879 if opts.get('options'):
1877 options = []
1880 options = []
1878 otables = [globalopts]
1881 otables = [globalopts]
1879 if cmd:
1882 if cmd:
1880 aliases, entry = cmdutil.findcmd(cmd, table, False)
1883 aliases, entry = cmdutil.findcmd(cmd, table, False)
1881 otables.append(entry[1])
1884 otables.append(entry[1])
1882 for t in otables:
1885 for t in otables:
1883 for o in t:
1886 for o in t:
1884 if "(DEPRECATED)" in o[3]:
1887 if "(DEPRECATED)" in o[3]:
1885 continue
1888 continue
1886 if o[0]:
1889 if o[0]:
1887 options.append('-%s' % o[0])
1890 options.append('-%s' % o[0])
1888 options.append('--%s' % o[1])
1891 options.append('--%s' % o[1])
1889 ui.write("%s\n" % "\n".join(options))
1892 ui.write("%s\n" % "\n".join(options))
1890 return
1893 return
1891
1894
1892 cmdlist = cmdutil.findpossible(cmd, table)
1895 cmdlist = cmdutil.findpossible(cmd, table)
1893 if ui.verbose:
1896 if ui.verbose:
1894 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1897 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1895 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1898 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1896
1899
1897 @command('debugdag',
1900 @command('debugdag',
1898 [('t', 'tags', None, _('use tags as labels')),
1901 [('t', 'tags', None, _('use tags as labels')),
1899 ('b', 'branches', None, _('annotate with branch names')),
1902 ('b', 'branches', None, _('annotate with branch names')),
1900 ('', 'dots', None, _('use dots for runs')),
1903 ('', 'dots', None, _('use dots for runs')),
1901 ('s', 'spaces', None, _('separate elements by spaces'))],
1904 ('s', 'spaces', None, _('separate elements by spaces'))],
1902 _('[OPTION]... [FILE [REV]...]'),
1905 _('[OPTION]... [FILE [REV]...]'),
1903 optionalrepo=True)
1906 optionalrepo=True)
1904 def debugdag(ui, repo, file_=None, *revs, **opts):
1907 def debugdag(ui, repo, file_=None, *revs, **opts):
1905 """format the changelog or an index DAG as a concise textual description
1908 """format the changelog or an index DAG as a concise textual description
1906
1909
1907 If you pass a revlog index, the revlog's DAG is emitted. If you list
1910 If you pass a revlog index, the revlog's DAG is emitted. If you list
1908 revision numbers, they get labeled in the output as rN.
1911 revision numbers, they get labeled in the output as rN.
1909
1912
1910 Otherwise, the changelog DAG of the current repo is emitted.
1913 Otherwise, the changelog DAG of the current repo is emitted.
1911 """
1914 """
1912 spaces = opts.get('spaces')
1915 spaces = opts.get('spaces')
1913 dots = opts.get('dots')
1916 dots = opts.get('dots')
1914 if file_:
1917 if file_:
1915 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1918 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1916 revs = set((int(r) for r in revs))
1919 revs = set((int(r) for r in revs))
1917 def events():
1920 def events():
1918 for r in rlog:
1921 for r in rlog:
1919 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1922 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1920 if p != -1))
1923 if p != -1))
1921 if r in revs:
1924 if r in revs:
1922 yield 'l', (r, "r%i" % r)
1925 yield 'l', (r, "r%i" % r)
1923 elif repo:
1926 elif repo:
1924 cl = repo.changelog
1927 cl = repo.changelog
1925 tags = opts.get('tags')
1928 tags = opts.get('tags')
1926 branches = opts.get('branches')
1929 branches = opts.get('branches')
1927 if tags:
1930 if tags:
1928 labels = {}
1931 labels = {}
1929 for l, n in repo.tags().items():
1932 for l, n in repo.tags().items():
1930 labels.setdefault(cl.rev(n), []).append(l)
1933 labels.setdefault(cl.rev(n), []).append(l)
1931 def events():
1934 def events():
1932 b = "default"
1935 b = "default"
1933 for r in cl:
1936 for r in cl:
1934 if branches:
1937 if branches:
1935 newb = cl.read(cl.node(r))[5]['branch']
1938 newb = cl.read(cl.node(r))[5]['branch']
1936 if newb != b:
1939 if newb != b:
1937 yield 'a', newb
1940 yield 'a', newb
1938 b = newb
1941 b = newb
1939 yield 'n', (r, list(p for p in cl.parentrevs(r)
1942 yield 'n', (r, list(p for p in cl.parentrevs(r)
1940 if p != -1))
1943 if p != -1))
1941 if tags:
1944 if tags:
1942 ls = labels.get(r)
1945 ls = labels.get(r)
1943 if ls:
1946 if ls:
1944 for l in ls:
1947 for l in ls:
1945 yield 'l', (r, l)
1948 yield 'l', (r, l)
1946 else:
1949 else:
1947 raise util.Abort(_('need repo for changelog dag'))
1950 raise util.Abort(_('need repo for changelog dag'))
1948
1951
1949 for line in dagparser.dagtextlines(events(),
1952 for line in dagparser.dagtextlines(events(),
1950 addspaces=spaces,
1953 addspaces=spaces,
1951 wraplabels=True,
1954 wraplabels=True,
1952 wrapannotations=True,
1955 wrapannotations=True,
1953 wrapnonlinear=dots,
1956 wrapnonlinear=dots,
1954 usedots=dots,
1957 usedots=dots,
1955 maxlinewidth=70):
1958 maxlinewidth=70):
1956 ui.write(line)
1959 ui.write(line)
1957 ui.write("\n")
1960 ui.write("\n")
1958
1961
1959 @command('debugdata',
1962 @command('debugdata',
1960 [('c', 'changelog', False, _('open changelog')),
1963 [('c', 'changelog', False, _('open changelog')),
1961 ('m', 'manifest', False, _('open manifest'))],
1964 ('m', 'manifest', False, _('open manifest'))],
1962 _('-c|-m|FILE REV'))
1965 _('-c|-m|FILE REV'))
1963 def debugdata(ui, repo, file_, rev=None, **opts):
1966 def debugdata(ui, repo, file_, rev=None, **opts):
1964 """dump the contents of a data file revision"""
1967 """dump the contents of a data file revision"""
1965 if opts.get('changelog') or opts.get('manifest'):
1968 if opts.get('changelog') or opts.get('manifest'):
1966 file_, rev = None, file_
1969 file_, rev = None, file_
1967 elif rev is None:
1970 elif rev is None:
1968 raise error.CommandError('debugdata', _('invalid arguments'))
1971 raise error.CommandError('debugdata', _('invalid arguments'))
1969 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1972 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1970 try:
1973 try:
1971 ui.write(r.revision(r.lookup(rev)))
1974 ui.write(r.revision(r.lookup(rev)))
1972 except KeyError:
1975 except KeyError:
1973 raise util.Abort(_('invalid revision identifier %s') % rev)
1976 raise util.Abort(_('invalid revision identifier %s') % rev)
1974
1977
1975 @command('debugdate',
1978 @command('debugdate',
1976 [('e', 'extended', None, _('try extended date formats'))],
1979 [('e', 'extended', None, _('try extended date formats'))],
1977 _('[-e] DATE [RANGE]'),
1980 _('[-e] DATE [RANGE]'),
1978 norepo=True, optionalrepo=True)
1981 norepo=True, optionalrepo=True)
1979 def debugdate(ui, date, range=None, **opts):
1982 def debugdate(ui, date, range=None, **opts):
1980 """parse and display a date"""
1983 """parse and display a date"""
1981 if opts["extended"]:
1984 if opts["extended"]:
1982 d = util.parsedate(date, util.extendeddateformats)
1985 d = util.parsedate(date, util.extendeddateformats)
1983 else:
1986 else:
1984 d = util.parsedate(date)
1987 d = util.parsedate(date)
1985 ui.write(("internal: %s %s\n") % d)
1988 ui.write(("internal: %s %s\n") % d)
1986 ui.write(("standard: %s\n") % util.datestr(d))
1989 ui.write(("standard: %s\n") % util.datestr(d))
1987 if range:
1990 if range:
1988 m = util.matchdate(range)
1991 m = util.matchdate(range)
1989 ui.write(("match: %s\n") % m(d[0]))
1992 ui.write(("match: %s\n") % m(d[0]))
1990
1993
1991 @command('debugdiscovery',
1994 @command('debugdiscovery',
1992 [('', 'old', None, _('use old-style discovery')),
1995 [('', 'old', None, _('use old-style discovery')),
1993 ('', 'nonheads', None,
1996 ('', 'nonheads', None,
1994 _('use old-style discovery with non-heads included')),
1997 _('use old-style discovery with non-heads included')),
1995 ] + remoteopts,
1998 ] + remoteopts,
1996 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1999 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1997 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2000 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1998 """runs the changeset discovery protocol in isolation"""
2001 """runs the changeset discovery protocol in isolation"""
1999 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2002 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2000 opts.get('branch'))
2003 opts.get('branch'))
2001 remote = hg.peer(repo, opts, remoteurl)
2004 remote = hg.peer(repo, opts, remoteurl)
2002 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2005 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2003
2006
2004 # make sure tests are repeatable
2007 # make sure tests are repeatable
2005 random.seed(12323)
2008 random.seed(12323)
2006
2009
2007 def doit(localheads, remoteheads, remote=remote):
2010 def doit(localheads, remoteheads, remote=remote):
2008 if opts.get('old'):
2011 if opts.get('old'):
2009 if localheads:
2012 if localheads:
2010 raise util.Abort('cannot use localheads with old style '
2013 raise util.Abort('cannot use localheads with old style '
2011 'discovery')
2014 'discovery')
2012 if not util.safehasattr(remote, 'branches'):
2015 if not util.safehasattr(remote, 'branches'):
2013 # enable in-client legacy support
2016 # enable in-client legacy support
2014 remote = localrepo.locallegacypeer(remote.local())
2017 remote = localrepo.locallegacypeer(remote.local())
2015 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2018 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2016 force=True)
2019 force=True)
2017 common = set(common)
2020 common = set(common)
2018 if not opts.get('nonheads'):
2021 if not opts.get('nonheads'):
2019 ui.write(("unpruned common: %s\n") %
2022 ui.write(("unpruned common: %s\n") %
2020 " ".join(sorted(short(n) for n in common)))
2023 " ".join(sorted(short(n) for n in common)))
2021 dag = dagutil.revlogdag(repo.changelog)
2024 dag = dagutil.revlogdag(repo.changelog)
2022 all = dag.ancestorset(dag.internalizeall(common))
2025 all = dag.ancestorset(dag.internalizeall(common))
2023 common = dag.externalizeall(dag.headsetofconnecteds(all))
2026 common = dag.externalizeall(dag.headsetofconnecteds(all))
2024 else:
2027 else:
2025 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2028 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2026 common = set(common)
2029 common = set(common)
2027 rheads = set(hds)
2030 rheads = set(hds)
2028 lheads = set(repo.heads())
2031 lheads = set(repo.heads())
2029 ui.write(("common heads: %s\n") %
2032 ui.write(("common heads: %s\n") %
2030 " ".join(sorted(short(n) for n in common)))
2033 " ".join(sorted(short(n) for n in common)))
2031 if lheads <= common:
2034 if lheads <= common:
2032 ui.write(("local is subset\n"))
2035 ui.write(("local is subset\n"))
2033 elif rheads <= common:
2036 elif rheads <= common:
2034 ui.write(("remote is subset\n"))
2037 ui.write(("remote is subset\n"))
2035
2038
2036 serverlogs = opts.get('serverlog')
2039 serverlogs = opts.get('serverlog')
2037 if serverlogs:
2040 if serverlogs:
2038 for filename in serverlogs:
2041 for filename in serverlogs:
2039 logfile = open(filename, 'r')
2042 logfile = open(filename, 'r')
2040 try:
2043 try:
2041 line = logfile.readline()
2044 line = logfile.readline()
2042 while line:
2045 while line:
2043 parts = line.strip().split(';')
2046 parts = line.strip().split(';')
2044 op = parts[1]
2047 op = parts[1]
2045 if op == 'cg':
2048 if op == 'cg':
2046 pass
2049 pass
2047 elif op == 'cgss':
2050 elif op == 'cgss':
2048 doit(parts[2].split(' '), parts[3].split(' '))
2051 doit(parts[2].split(' '), parts[3].split(' '))
2049 elif op == 'unb':
2052 elif op == 'unb':
2050 doit(parts[3].split(' '), parts[2].split(' '))
2053 doit(parts[3].split(' '), parts[2].split(' '))
2051 line = logfile.readline()
2054 line = logfile.readline()
2052 finally:
2055 finally:
2053 logfile.close()
2056 logfile.close()
2054
2057
2055 else:
2058 else:
2056 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2059 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2057 opts.get('remote_head'))
2060 opts.get('remote_head'))
2058 localrevs = opts.get('local_head')
2061 localrevs = opts.get('local_head')
2059 doit(localrevs, remoterevs)
2062 doit(localrevs, remoterevs)
2060
2063
2061 @command('debugfileset',
2064 @command('debugfileset',
2062 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2065 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2063 _('[-r REV] FILESPEC'))
2066 _('[-r REV] FILESPEC'))
2064 def debugfileset(ui, repo, expr, **opts):
2067 def debugfileset(ui, repo, expr, **opts):
2065 '''parse and apply a fileset specification'''
2068 '''parse and apply a fileset specification'''
2066 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2069 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2067 if ui.verbose:
2070 if ui.verbose:
2068 tree = fileset.parse(expr)[0]
2071 tree = fileset.parse(expr)[0]
2069 ui.note(tree, "\n")
2072 ui.note(tree, "\n")
2070
2073
2071 for f in ctx.getfileset(expr):
2074 for f in ctx.getfileset(expr):
2072 ui.write("%s\n" % f)
2075 ui.write("%s\n" % f)
2073
2076
2074 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2077 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2075 def debugfsinfo(ui, path="."):
2078 def debugfsinfo(ui, path="."):
2076 """show information detected about current filesystem"""
2079 """show information detected about current filesystem"""
2077 util.writefile('.debugfsinfo', '')
2080 util.writefile('.debugfsinfo', '')
2078 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2081 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2079 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2082 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2080 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2083 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2081 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2084 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2082 and 'yes' or 'no'))
2085 and 'yes' or 'no'))
2083 os.unlink('.debugfsinfo')
2086 os.unlink('.debugfsinfo')
2084
2087
2085 @command('debuggetbundle',
2088 @command('debuggetbundle',
2086 [('H', 'head', [], _('id of head node'), _('ID')),
2089 [('H', 'head', [], _('id of head node'), _('ID')),
2087 ('C', 'common', [], _('id of common node'), _('ID')),
2090 ('C', 'common', [], _('id of common node'), _('ID')),
2088 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2091 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2089 _('REPO FILE [-H|-C ID]...'),
2092 _('REPO FILE [-H|-C ID]...'),
2090 norepo=True)
2093 norepo=True)
2091 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2094 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2092 """retrieves a bundle from a repo
2095 """retrieves a bundle from a repo
2093
2096
2094 Every ID must be a full-length hex node id string. Saves the bundle to the
2097 Every ID must be a full-length hex node id string. Saves the bundle to the
2095 given file.
2098 given file.
2096 """
2099 """
2097 repo = hg.peer(ui, opts, repopath)
2100 repo = hg.peer(ui, opts, repopath)
2098 if not repo.capable('getbundle'):
2101 if not repo.capable('getbundle'):
2099 raise util.Abort("getbundle() not supported by target repository")
2102 raise util.Abort("getbundle() not supported by target repository")
2100 args = {}
2103 args = {}
2101 if common:
2104 if common:
2102 args['common'] = [bin(s) for s in common]
2105 args['common'] = [bin(s) for s in common]
2103 if head:
2106 if head:
2104 args['heads'] = [bin(s) for s in head]
2107 args['heads'] = [bin(s) for s in head]
2105 # TODO: get desired bundlecaps from command line.
2108 # TODO: get desired bundlecaps from command line.
2106 args['bundlecaps'] = None
2109 args['bundlecaps'] = None
2107 bundle = repo.getbundle('debug', **args)
2110 bundle = repo.getbundle('debug', **args)
2108
2111
2109 bundletype = opts.get('type', 'bzip2').lower()
2112 bundletype = opts.get('type', 'bzip2').lower()
2110 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2113 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2111 bundletype = btypes.get(bundletype)
2114 bundletype = btypes.get(bundletype)
2112 if bundletype not in changegroup.bundletypes:
2115 if bundletype not in changegroup.bundletypes:
2113 raise util.Abort(_('unknown bundle type specified with --type'))
2116 raise util.Abort(_('unknown bundle type specified with --type'))
2114 changegroup.writebundle(bundle, bundlepath, bundletype)
2117 changegroup.writebundle(bundle, bundlepath, bundletype)
2115
2118
2116 @command('debugignore', [], '')
2119 @command('debugignore', [], '')
2117 def debugignore(ui, repo, *values, **opts):
2120 def debugignore(ui, repo, *values, **opts):
2118 """display the combined ignore pattern"""
2121 """display the combined ignore pattern"""
2119 ignore = repo.dirstate._ignore
2122 ignore = repo.dirstate._ignore
2120 includepat = getattr(ignore, 'includepat', None)
2123 includepat = getattr(ignore, 'includepat', None)
2121 if includepat is not None:
2124 if includepat is not None:
2122 ui.write("%s\n" % includepat)
2125 ui.write("%s\n" % includepat)
2123 else:
2126 else:
2124 raise util.Abort(_("no ignore patterns found"))
2127 raise util.Abort(_("no ignore patterns found"))
2125
2128
2126 @command('debugindex',
2129 @command('debugindex',
2127 [('c', 'changelog', False, _('open changelog')),
2130 [('c', 'changelog', False, _('open changelog')),
2128 ('m', 'manifest', False, _('open manifest')),
2131 ('m', 'manifest', False, _('open manifest')),
2129 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2132 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2130 _('[-f FORMAT] -c|-m|FILE'),
2133 _('[-f FORMAT] -c|-m|FILE'),
2131 optionalrepo=True)
2134 optionalrepo=True)
2132 def debugindex(ui, repo, file_=None, **opts):
2135 def debugindex(ui, repo, file_=None, **opts):
2133 """dump the contents of an index file"""
2136 """dump the contents of an index file"""
2134 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2137 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2135 format = opts.get('format', 0)
2138 format = opts.get('format', 0)
2136 if format not in (0, 1):
2139 if format not in (0, 1):
2137 raise util.Abort(_("unknown format %d") % format)
2140 raise util.Abort(_("unknown format %d") % format)
2138
2141
2139 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2142 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2140 if generaldelta:
2143 if generaldelta:
2141 basehdr = ' delta'
2144 basehdr = ' delta'
2142 else:
2145 else:
2143 basehdr = ' base'
2146 basehdr = ' base'
2144
2147
2145 if format == 0:
2148 if format == 0:
2146 ui.write(" rev offset length " + basehdr + " linkrev"
2149 ui.write(" rev offset length " + basehdr + " linkrev"
2147 " nodeid p1 p2\n")
2150 " nodeid p1 p2\n")
2148 elif format == 1:
2151 elif format == 1:
2149 ui.write(" rev flag offset length"
2152 ui.write(" rev flag offset length"
2150 " size " + basehdr + " link p1 p2"
2153 " size " + basehdr + " link p1 p2"
2151 " nodeid\n")
2154 " nodeid\n")
2152
2155
2153 for i in r:
2156 for i in r:
2154 node = r.node(i)
2157 node = r.node(i)
2155 if generaldelta:
2158 if generaldelta:
2156 base = r.deltaparent(i)
2159 base = r.deltaparent(i)
2157 else:
2160 else:
2158 base = r.chainbase(i)
2161 base = r.chainbase(i)
2159 if format == 0:
2162 if format == 0:
2160 try:
2163 try:
2161 pp = r.parents(node)
2164 pp = r.parents(node)
2162 except Exception:
2165 except Exception:
2163 pp = [nullid, nullid]
2166 pp = [nullid, nullid]
2164 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2167 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2165 i, r.start(i), r.length(i), base, r.linkrev(i),
2168 i, r.start(i), r.length(i), base, r.linkrev(i),
2166 short(node), short(pp[0]), short(pp[1])))
2169 short(node), short(pp[0]), short(pp[1])))
2167 elif format == 1:
2170 elif format == 1:
2168 pr = r.parentrevs(i)
2171 pr = r.parentrevs(i)
2169 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2172 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2170 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2173 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2171 base, r.linkrev(i), pr[0], pr[1], short(node)))
2174 base, r.linkrev(i), pr[0], pr[1], short(node)))
2172
2175
2173 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2176 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2174 def debugindexdot(ui, repo, file_):
2177 def debugindexdot(ui, repo, file_):
2175 """dump an index DAG as a graphviz dot file"""
2178 """dump an index DAG as a graphviz dot file"""
2176 r = None
2179 r = None
2177 if repo:
2180 if repo:
2178 filelog = repo.file(file_)
2181 filelog = repo.file(file_)
2179 if len(filelog):
2182 if len(filelog):
2180 r = filelog
2183 r = filelog
2181 if not r:
2184 if not r:
2182 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2185 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2183 ui.write(("digraph G {\n"))
2186 ui.write(("digraph G {\n"))
2184 for i in r:
2187 for i in r:
2185 node = r.node(i)
2188 node = r.node(i)
2186 pp = r.parents(node)
2189 pp = r.parents(node)
2187 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2190 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2188 if pp[1] != nullid:
2191 if pp[1] != nullid:
2189 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2192 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2190 ui.write("}\n")
2193 ui.write("}\n")
2191
2194
2192 @command('debuginstall', [], '', norepo=True)
2195 @command('debuginstall', [], '', norepo=True)
2193 def debuginstall(ui):
2196 def debuginstall(ui):
2194 '''test Mercurial installation
2197 '''test Mercurial installation
2195
2198
2196 Returns 0 on success.
2199 Returns 0 on success.
2197 '''
2200 '''
2198
2201
2199 def writetemp(contents):
2202 def writetemp(contents):
2200 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2203 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2201 f = os.fdopen(fd, "wb")
2204 f = os.fdopen(fd, "wb")
2202 f.write(contents)
2205 f.write(contents)
2203 f.close()
2206 f.close()
2204 return name
2207 return name
2205
2208
2206 problems = 0
2209 problems = 0
2207
2210
2208 # encoding
2211 # encoding
2209 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2212 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2210 try:
2213 try:
2211 encoding.fromlocal("test")
2214 encoding.fromlocal("test")
2212 except util.Abort, inst:
2215 except util.Abort, inst:
2213 ui.write(" %s\n" % inst)
2216 ui.write(" %s\n" % inst)
2214 ui.write(_(" (check that your locale is properly set)\n"))
2217 ui.write(_(" (check that your locale is properly set)\n"))
2215 problems += 1
2218 problems += 1
2216
2219
2217 # Python
2220 # Python
2218 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2221 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2219 ui.status(_("checking Python version (%s)\n")
2222 ui.status(_("checking Python version (%s)\n")
2220 % ("%s.%s.%s" % sys.version_info[:3]))
2223 % ("%s.%s.%s" % sys.version_info[:3]))
2221 ui.status(_("checking Python lib (%s)...\n")
2224 ui.status(_("checking Python lib (%s)...\n")
2222 % os.path.dirname(os.__file__))
2225 % os.path.dirname(os.__file__))
2223
2226
2224 # compiled modules
2227 # compiled modules
2225 ui.status(_("checking installed modules (%s)...\n")
2228 ui.status(_("checking installed modules (%s)...\n")
2226 % os.path.dirname(__file__))
2229 % os.path.dirname(__file__))
2227 try:
2230 try:
2228 import bdiff, mpatch, base85, osutil
2231 import bdiff, mpatch, base85, osutil
2229 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2232 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2230 except Exception, inst:
2233 except Exception, inst:
2231 ui.write(" %s\n" % inst)
2234 ui.write(" %s\n" % inst)
2232 ui.write(_(" One or more extensions could not be found"))
2235 ui.write(_(" One or more extensions could not be found"))
2233 ui.write(_(" (check that you compiled the extensions)\n"))
2236 ui.write(_(" (check that you compiled the extensions)\n"))
2234 problems += 1
2237 problems += 1
2235
2238
2236 # templates
2239 # templates
2237 import templater
2240 import templater
2238 p = templater.templatepath()
2241 p = templater.templatepath()
2239 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2242 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2240 if p:
2243 if p:
2241 m = templater.templatepath("map-cmdline.default")
2244 m = templater.templatepath("map-cmdline.default")
2242 if m:
2245 if m:
2243 # template found, check if it is working
2246 # template found, check if it is working
2244 try:
2247 try:
2245 templater.templater(m)
2248 templater.templater(m)
2246 except Exception, inst:
2249 except Exception, inst:
2247 ui.write(" %s\n" % inst)
2250 ui.write(" %s\n" % inst)
2248 p = None
2251 p = None
2249 else:
2252 else:
2250 ui.write(_(" template 'default' not found\n"))
2253 ui.write(_(" template 'default' not found\n"))
2251 p = None
2254 p = None
2252 else:
2255 else:
2253 ui.write(_(" no template directories found\n"))
2256 ui.write(_(" no template directories found\n"))
2254 if not p:
2257 if not p:
2255 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2258 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2256 problems += 1
2259 problems += 1
2257
2260
2258 # editor
2261 # editor
2259 ui.status(_("checking commit editor...\n"))
2262 ui.status(_("checking commit editor...\n"))
2260 editor = ui.geteditor()
2263 editor = ui.geteditor()
2261 cmdpath = util.findexe(shlex.split(editor)[0])
2264 cmdpath = util.findexe(shlex.split(editor)[0])
2262 if not cmdpath:
2265 if not cmdpath:
2263 if editor == 'vi':
2266 if editor == 'vi':
2264 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2267 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2265 ui.write(_(" (specify a commit editor in your configuration"
2268 ui.write(_(" (specify a commit editor in your configuration"
2266 " file)\n"))
2269 " file)\n"))
2267 else:
2270 else:
2268 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2271 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2269 ui.write(_(" (specify a commit editor in your configuration"
2272 ui.write(_(" (specify a commit editor in your configuration"
2270 " file)\n"))
2273 " file)\n"))
2271 problems += 1
2274 problems += 1
2272
2275
2273 # check username
2276 # check username
2274 ui.status(_("checking username...\n"))
2277 ui.status(_("checking username...\n"))
2275 try:
2278 try:
2276 ui.username()
2279 ui.username()
2277 except util.Abort, e:
2280 except util.Abort, e:
2278 ui.write(" %s\n" % e)
2281 ui.write(" %s\n" % e)
2279 ui.write(_(" (specify a username in your configuration file)\n"))
2282 ui.write(_(" (specify a username in your configuration file)\n"))
2280 problems += 1
2283 problems += 1
2281
2284
2282 if not problems:
2285 if not problems:
2283 ui.status(_("no problems detected\n"))
2286 ui.status(_("no problems detected\n"))
2284 else:
2287 else:
2285 ui.write(_("%s problems detected,"
2288 ui.write(_("%s problems detected,"
2286 " please check your install!\n") % problems)
2289 " please check your install!\n") % problems)
2287
2290
2288 return problems
2291 return problems
2289
2292
2290 @command('debugknown', [], _('REPO ID...'), norepo=True)
2293 @command('debugknown', [], _('REPO ID...'), norepo=True)
2291 def debugknown(ui, repopath, *ids, **opts):
2294 def debugknown(ui, repopath, *ids, **opts):
2292 """test whether node ids are known to a repo
2295 """test whether node ids are known to a repo
2293
2296
2294 Every ID must be a full-length hex node id string. Returns a list of 0s
2297 Every ID must be a full-length hex node id string. Returns a list of 0s
2295 and 1s indicating unknown/known.
2298 and 1s indicating unknown/known.
2296 """
2299 """
2297 repo = hg.peer(ui, opts, repopath)
2300 repo = hg.peer(ui, opts, repopath)
2298 if not repo.capable('known'):
2301 if not repo.capable('known'):
2299 raise util.Abort("known() not supported by target repository")
2302 raise util.Abort("known() not supported by target repository")
2300 flags = repo.known([bin(s) for s in ids])
2303 flags = repo.known([bin(s) for s in ids])
2301 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2304 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2302
2305
2303 @command('debuglabelcomplete', [], _('LABEL...'))
2306 @command('debuglabelcomplete', [], _('LABEL...'))
2304 def debuglabelcomplete(ui, repo, *args):
2307 def debuglabelcomplete(ui, repo, *args):
2305 '''complete "labels" - tags, open branch names, bookmark names'''
2308 '''complete "labels" - tags, open branch names, bookmark names'''
2306
2309
2307 labels = set()
2310 labels = set()
2308 labels.update(t[0] for t in repo.tagslist())
2311 labels.update(t[0] for t in repo.tagslist())
2309 labels.update(repo._bookmarks.keys())
2312 labels.update(repo._bookmarks.keys())
2310 labels.update(tag for (tag, heads, tip, closed)
2313 labels.update(tag for (tag, heads, tip, closed)
2311 in repo.branchmap().iterbranches() if not closed)
2314 in repo.branchmap().iterbranches() if not closed)
2312 completions = set()
2315 completions = set()
2313 if not args:
2316 if not args:
2314 args = ['']
2317 args = ['']
2315 for a in args:
2318 for a in args:
2316 completions.update(l for l in labels if l.startswith(a))
2319 completions.update(l for l in labels if l.startswith(a))
2317 ui.write('\n'.join(sorted(completions)))
2320 ui.write('\n'.join(sorted(completions)))
2318 ui.write('\n')
2321 ui.write('\n')
2319
2322
2320 @command('debugobsolete',
2323 @command('debugobsolete',
2321 [('', 'flags', 0, _('markers flag')),
2324 [('', 'flags', 0, _('markers flag')),
2322 ('', 'record-parents', False,
2325 ('', 'record-parents', False,
2323 _('record parent information for the precursor')),
2326 _('record parent information for the precursor')),
2324 ('r', 'rev', [], _('display markers relevant to REV')),
2327 ('r', 'rev', [], _('display markers relevant to REV')),
2325 ] + commitopts2,
2328 ] + commitopts2,
2326 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2329 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2327 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2330 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2328 """create arbitrary obsolete marker
2331 """create arbitrary obsolete marker
2329
2332
2330 With no arguments, displays the list of obsolescence markers."""
2333 With no arguments, displays the list of obsolescence markers."""
2331
2334
2332 def parsenodeid(s):
2335 def parsenodeid(s):
2333 try:
2336 try:
2334 # We do not use revsingle/revrange functions here to accept
2337 # We do not use revsingle/revrange functions here to accept
2335 # arbitrary node identifiers, possibly not present in the
2338 # arbitrary node identifiers, possibly not present in the
2336 # local repository.
2339 # local repository.
2337 n = bin(s)
2340 n = bin(s)
2338 if len(n) != len(nullid):
2341 if len(n) != len(nullid):
2339 raise TypeError()
2342 raise TypeError()
2340 return n
2343 return n
2341 except TypeError:
2344 except TypeError:
2342 raise util.Abort('changeset references must be full hexadecimal '
2345 raise util.Abort('changeset references must be full hexadecimal '
2343 'node identifiers')
2346 'node identifiers')
2344
2347
2345 if precursor is not None:
2348 if precursor is not None:
2346 if opts['rev']:
2349 if opts['rev']:
2347 raise util.Abort('cannot select revision when creating marker')
2350 raise util.Abort('cannot select revision when creating marker')
2348 metadata = {}
2351 metadata = {}
2349 metadata['user'] = opts['user'] or ui.username()
2352 metadata['user'] = opts['user'] or ui.username()
2350 succs = tuple(parsenodeid(succ) for succ in successors)
2353 succs = tuple(parsenodeid(succ) for succ in successors)
2351 l = repo.lock()
2354 l = repo.lock()
2352 try:
2355 try:
2353 tr = repo.transaction('debugobsolete')
2356 tr = repo.transaction('debugobsolete')
2354 try:
2357 try:
2355 try:
2358 try:
2356 date = opts.get('date')
2359 date = opts.get('date')
2357 if date:
2360 if date:
2358 date = util.parsedate(date)
2361 date = util.parsedate(date)
2359 else:
2362 else:
2360 date = None
2363 date = None
2361 prec = parsenodeid(precursor)
2364 prec = parsenodeid(precursor)
2362 parents = None
2365 parents = None
2363 if opts['record_parents']:
2366 if opts['record_parents']:
2364 if prec not in repo.unfiltered():
2367 if prec not in repo.unfiltered():
2365 raise util.Abort('cannot used --record-parents on '
2368 raise util.Abort('cannot used --record-parents on '
2366 'unknown changesets')
2369 'unknown changesets')
2367 parents = repo.unfiltered()[prec].parents()
2370 parents = repo.unfiltered()[prec].parents()
2368 parents = tuple(p.node() for p in parents)
2371 parents = tuple(p.node() for p in parents)
2369 repo.obsstore.create(tr, prec, succs, opts['flags'],
2372 repo.obsstore.create(tr, prec, succs, opts['flags'],
2370 parents=parents, date=date,
2373 parents=parents, date=date,
2371 metadata=metadata)
2374 metadata=metadata)
2372 tr.close()
2375 tr.close()
2373 except ValueError, exc:
2376 except ValueError, exc:
2374 raise util.Abort(_('bad obsmarker input: %s') % exc)
2377 raise util.Abort(_('bad obsmarker input: %s') % exc)
2375 finally:
2378 finally:
2376 tr.release()
2379 tr.release()
2377 finally:
2380 finally:
2378 l.release()
2381 l.release()
2379 else:
2382 else:
2380 if opts['rev']:
2383 if opts['rev']:
2381 revs = scmutil.revrange(repo, opts['rev'])
2384 revs = scmutil.revrange(repo, opts['rev'])
2382 nodes = [repo[r].node() for r in revs]
2385 nodes = [repo[r].node() for r in revs]
2383 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2386 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2384 markers.sort(key=lambda x: x._data)
2387 markers.sort(key=lambda x: x._data)
2385 else:
2388 else:
2386 markers = obsolete.getmarkers(repo)
2389 markers = obsolete.getmarkers(repo)
2387
2390
2388 for m in markers:
2391 for m in markers:
2389 cmdutil.showmarker(ui, m)
2392 cmdutil.showmarker(ui, m)
2390
2393
2391 @command('debugpathcomplete',
2394 @command('debugpathcomplete',
2392 [('f', 'full', None, _('complete an entire path')),
2395 [('f', 'full', None, _('complete an entire path')),
2393 ('n', 'normal', None, _('show only normal files')),
2396 ('n', 'normal', None, _('show only normal files')),
2394 ('a', 'added', None, _('show only added files')),
2397 ('a', 'added', None, _('show only added files')),
2395 ('r', 'removed', None, _('show only removed files'))],
2398 ('r', 'removed', None, _('show only removed files'))],
2396 _('FILESPEC...'))
2399 _('FILESPEC...'))
2397 def debugpathcomplete(ui, repo, *specs, **opts):
2400 def debugpathcomplete(ui, repo, *specs, **opts):
2398 '''complete part or all of a tracked path
2401 '''complete part or all of a tracked path
2399
2402
2400 This command supports shells that offer path name completion. It
2403 This command supports shells that offer path name completion. It
2401 currently completes only files already known to the dirstate.
2404 currently completes only files already known to the dirstate.
2402
2405
2403 Completion extends only to the next path segment unless
2406 Completion extends only to the next path segment unless
2404 --full is specified, in which case entire paths are used.'''
2407 --full is specified, in which case entire paths are used.'''
2405
2408
2406 def complete(path, acceptable):
2409 def complete(path, acceptable):
2407 dirstate = repo.dirstate
2410 dirstate = repo.dirstate
2408 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2411 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2409 rootdir = repo.root + os.sep
2412 rootdir = repo.root + os.sep
2410 if spec != repo.root and not spec.startswith(rootdir):
2413 if spec != repo.root and not spec.startswith(rootdir):
2411 return [], []
2414 return [], []
2412 if os.path.isdir(spec):
2415 if os.path.isdir(spec):
2413 spec += '/'
2416 spec += '/'
2414 spec = spec[len(rootdir):]
2417 spec = spec[len(rootdir):]
2415 fixpaths = os.sep != '/'
2418 fixpaths = os.sep != '/'
2416 if fixpaths:
2419 if fixpaths:
2417 spec = spec.replace(os.sep, '/')
2420 spec = spec.replace(os.sep, '/')
2418 speclen = len(spec)
2421 speclen = len(spec)
2419 fullpaths = opts['full']
2422 fullpaths = opts['full']
2420 files, dirs = set(), set()
2423 files, dirs = set(), set()
2421 adddir, addfile = dirs.add, files.add
2424 adddir, addfile = dirs.add, files.add
2422 for f, st in dirstate.iteritems():
2425 for f, st in dirstate.iteritems():
2423 if f.startswith(spec) and st[0] in acceptable:
2426 if f.startswith(spec) and st[0] in acceptable:
2424 if fixpaths:
2427 if fixpaths:
2425 f = f.replace('/', os.sep)
2428 f = f.replace('/', os.sep)
2426 if fullpaths:
2429 if fullpaths:
2427 addfile(f)
2430 addfile(f)
2428 continue
2431 continue
2429 s = f.find(os.sep, speclen)
2432 s = f.find(os.sep, speclen)
2430 if s >= 0:
2433 if s >= 0:
2431 adddir(f[:s])
2434 adddir(f[:s])
2432 else:
2435 else:
2433 addfile(f)
2436 addfile(f)
2434 return files, dirs
2437 return files, dirs
2435
2438
2436 acceptable = ''
2439 acceptable = ''
2437 if opts['normal']:
2440 if opts['normal']:
2438 acceptable += 'nm'
2441 acceptable += 'nm'
2439 if opts['added']:
2442 if opts['added']:
2440 acceptable += 'a'
2443 acceptable += 'a'
2441 if opts['removed']:
2444 if opts['removed']:
2442 acceptable += 'r'
2445 acceptable += 'r'
2443 cwd = repo.getcwd()
2446 cwd = repo.getcwd()
2444 if not specs:
2447 if not specs:
2445 specs = ['.']
2448 specs = ['.']
2446
2449
2447 files, dirs = set(), set()
2450 files, dirs = set(), set()
2448 for spec in specs:
2451 for spec in specs:
2449 f, d = complete(spec, acceptable or 'nmar')
2452 f, d = complete(spec, acceptable or 'nmar')
2450 files.update(f)
2453 files.update(f)
2451 dirs.update(d)
2454 dirs.update(d)
2452 files.update(dirs)
2455 files.update(dirs)
2453 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2456 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2454 ui.write('\n')
2457 ui.write('\n')
2455
2458
2456 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2459 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2457 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2460 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2458 '''access the pushkey key/value protocol
2461 '''access the pushkey key/value protocol
2459
2462
2460 With two args, list the keys in the given namespace.
2463 With two args, list the keys in the given namespace.
2461
2464
2462 With five args, set a key to new if it currently is set to old.
2465 With five args, set a key to new if it currently is set to old.
2463 Reports success or failure.
2466 Reports success or failure.
2464 '''
2467 '''
2465
2468
2466 target = hg.peer(ui, {}, repopath)
2469 target = hg.peer(ui, {}, repopath)
2467 if keyinfo:
2470 if keyinfo:
2468 key, old, new = keyinfo
2471 key, old, new = keyinfo
2469 r = target.pushkey(namespace, key, old, new)
2472 r = target.pushkey(namespace, key, old, new)
2470 ui.status(str(r) + '\n')
2473 ui.status(str(r) + '\n')
2471 return not r
2474 return not r
2472 else:
2475 else:
2473 for k, v in sorted(target.listkeys(namespace).iteritems()):
2476 for k, v in sorted(target.listkeys(namespace).iteritems()):
2474 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2477 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2475 v.encode('string-escape')))
2478 v.encode('string-escape')))
2476
2479
2477 @command('debugpvec', [], _('A B'))
2480 @command('debugpvec', [], _('A B'))
2478 def debugpvec(ui, repo, a, b=None):
2481 def debugpvec(ui, repo, a, b=None):
2479 ca = scmutil.revsingle(repo, a)
2482 ca = scmutil.revsingle(repo, a)
2480 cb = scmutil.revsingle(repo, b)
2483 cb = scmutil.revsingle(repo, b)
2481 pa = pvec.ctxpvec(ca)
2484 pa = pvec.ctxpvec(ca)
2482 pb = pvec.ctxpvec(cb)
2485 pb = pvec.ctxpvec(cb)
2483 if pa == pb:
2486 if pa == pb:
2484 rel = "="
2487 rel = "="
2485 elif pa > pb:
2488 elif pa > pb:
2486 rel = ">"
2489 rel = ">"
2487 elif pa < pb:
2490 elif pa < pb:
2488 rel = "<"
2491 rel = "<"
2489 elif pa | pb:
2492 elif pa | pb:
2490 rel = "|"
2493 rel = "|"
2491 ui.write(_("a: %s\n") % pa)
2494 ui.write(_("a: %s\n") % pa)
2492 ui.write(_("b: %s\n") % pb)
2495 ui.write(_("b: %s\n") % pb)
2493 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2496 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2494 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2497 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2495 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2498 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2496 pa.distance(pb), rel))
2499 pa.distance(pb), rel))
2497
2500
2498 @command('debugrebuilddirstate|debugrebuildstate',
2501 @command('debugrebuilddirstate|debugrebuildstate',
2499 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2502 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2500 _('[-r REV]'))
2503 _('[-r REV]'))
2501 def debugrebuilddirstate(ui, repo, rev):
2504 def debugrebuilddirstate(ui, repo, rev):
2502 """rebuild the dirstate as it would look like for the given revision
2505 """rebuild the dirstate as it would look like for the given revision
2503
2506
2504 If no revision is specified the first current parent will be used.
2507 If no revision is specified the first current parent will be used.
2505
2508
2506 The dirstate will be set to the files of the given revision.
2509 The dirstate will be set to the files of the given revision.
2507 The actual working directory content or existing dirstate
2510 The actual working directory content or existing dirstate
2508 information such as adds or removes is not considered.
2511 information such as adds or removes is not considered.
2509
2512
2510 One use of this command is to make the next :hg:`status` invocation
2513 One use of this command is to make the next :hg:`status` invocation
2511 check the actual file content.
2514 check the actual file content.
2512 """
2515 """
2513 ctx = scmutil.revsingle(repo, rev)
2516 ctx = scmutil.revsingle(repo, rev)
2514 wlock = repo.wlock()
2517 wlock = repo.wlock()
2515 try:
2518 try:
2516 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2519 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2517 finally:
2520 finally:
2518 wlock.release()
2521 wlock.release()
2519
2522
2520 @command('debugrename',
2523 @command('debugrename',
2521 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2524 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2522 _('[-r REV] FILE'))
2525 _('[-r REV] FILE'))
2523 def debugrename(ui, repo, file1, *pats, **opts):
2526 def debugrename(ui, repo, file1, *pats, **opts):
2524 """dump rename information"""
2527 """dump rename information"""
2525
2528
2526 ctx = scmutil.revsingle(repo, opts.get('rev'))
2529 ctx = scmutil.revsingle(repo, opts.get('rev'))
2527 m = scmutil.match(ctx, (file1,) + pats, opts)
2530 m = scmutil.match(ctx, (file1,) + pats, opts)
2528 for abs in ctx.walk(m):
2531 for abs in ctx.walk(m):
2529 fctx = ctx[abs]
2532 fctx = ctx[abs]
2530 o = fctx.filelog().renamed(fctx.filenode())
2533 o = fctx.filelog().renamed(fctx.filenode())
2531 rel = m.rel(abs)
2534 rel = m.rel(abs)
2532 if o:
2535 if o:
2533 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2536 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2534 else:
2537 else:
2535 ui.write(_("%s not renamed\n") % rel)
2538 ui.write(_("%s not renamed\n") % rel)
2536
2539
2537 @command('debugrevlog',
2540 @command('debugrevlog',
2538 [('c', 'changelog', False, _('open changelog')),
2541 [('c', 'changelog', False, _('open changelog')),
2539 ('m', 'manifest', False, _('open manifest')),
2542 ('m', 'manifest', False, _('open manifest')),
2540 ('d', 'dump', False, _('dump index data'))],
2543 ('d', 'dump', False, _('dump index data'))],
2541 _('-c|-m|FILE'),
2544 _('-c|-m|FILE'),
2542 optionalrepo=True)
2545 optionalrepo=True)
2543 def debugrevlog(ui, repo, file_=None, **opts):
2546 def debugrevlog(ui, repo, file_=None, **opts):
2544 """show data and statistics about a revlog"""
2547 """show data and statistics about a revlog"""
2545 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2548 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2546
2549
2547 if opts.get("dump"):
2550 if opts.get("dump"):
2548 numrevs = len(r)
2551 numrevs = len(r)
2549 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2552 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2550 " rawsize totalsize compression heads chainlen\n")
2553 " rawsize totalsize compression heads chainlen\n")
2551 ts = 0
2554 ts = 0
2552 heads = set()
2555 heads = set()
2553 rindex = r.index
2556 rindex = r.index
2554
2557
2555 def chainbaseandlen(rev):
2558 def chainbaseandlen(rev):
2556 clen = 0
2559 clen = 0
2557 base = rindex[rev][3]
2560 base = rindex[rev][3]
2558 while base != rev:
2561 while base != rev:
2559 clen += 1
2562 clen += 1
2560 rev = base
2563 rev = base
2561 base = rindex[rev][3]
2564 base = rindex[rev][3]
2562 return base, clen
2565 return base, clen
2563
2566
2564 for rev in xrange(numrevs):
2567 for rev in xrange(numrevs):
2565 dbase = r.deltaparent(rev)
2568 dbase = r.deltaparent(rev)
2566 if dbase == -1:
2569 if dbase == -1:
2567 dbase = rev
2570 dbase = rev
2568 cbase, clen = chainbaseandlen(rev)
2571 cbase, clen = chainbaseandlen(rev)
2569 p1, p2 = r.parentrevs(rev)
2572 p1, p2 = r.parentrevs(rev)
2570 rs = r.rawsize(rev)
2573 rs = r.rawsize(rev)
2571 ts = ts + rs
2574 ts = ts + rs
2572 heads -= set(r.parentrevs(rev))
2575 heads -= set(r.parentrevs(rev))
2573 heads.add(rev)
2576 heads.add(rev)
2574 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2577 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2575 "%11d %5d %8d\n" %
2578 "%11d %5d %8d\n" %
2576 (rev, p1, p2, r.start(rev), r.end(rev),
2579 (rev, p1, p2, r.start(rev), r.end(rev),
2577 r.start(dbase), r.start(cbase),
2580 r.start(dbase), r.start(cbase),
2578 r.start(p1), r.start(p2),
2581 r.start(p1), r.start(p2),
2579 rs, ts, ts / r.end(rev), len(heads), clen))
2582 rs, ts, ts / r.end(rev), len(heads), clen))
2580 return 0
2583 return 0
2581
2584
2582 v = r.version
2585 v = r.version
2583 format = v & 0xFFFF
2586 format = v & 0xFFFF
2584 flags = []
2587 flags = []
2585 gdelta = False
2588 gdelta = False
2586 if v & revlog.REVLOGNGINLINEDATA:
2589 if v & revlog.REVLOGNGINLINEDATA:
2587 flags.append('inline')
2590 flags.append('inline')
2588 if v & revlog.REVLOGGENERALDELTA:
2591 if v & revlog.REVLOGGENERALDELTA:
2589 gdelta = True
2592 gdelta = True
2590 flags.append('generaldelta')
2593 flags.append('generaldelta')
2591 if not flags:
2594 if not flags:
2592 flags = ['(none)']
2595 flags = ['(none)']
2593
2596
2594 nummerges = 0
2597 nummerges = 0
2595 numfull = 0
2598 numfull = 0
2596 numprev = 0
2599 numprev = 0
2597 nump1 = 0
2600 nump1 = 0
2598 nump2 = 0
2601 nump2 = 0
2599 numother = 0
2602 numother = 0
2600 nump1prev = 0
2603 nump1prev = 0
2601 nump2prev = 0
2604 nump2prev = 0
2602 chainlengths = []
2605 chainlengths = []
2603
2606
2604 datasize = [None, 0, 0L]
2607 datasize = [None, 0, 0L]
2605 fullsize = [None, 0, 0L]
2608 fullsize = [None, 0, 0L]
2606 deltasize = [None, 0, 0L]
2609 deltasize = [None, 0, 0L]
2607
2610
2608 def addsize(size, l):
2611 def addsize(size, l):
2609 if l[0] is None or size < l[0]:
2612 if l[0] is None or size < l[0]:
2610 l[0] = size
2613 l[0] = size
2611 if size > l[1]:
2614 if size > l[1]:
2612 l[1] = size
2615 l[1] = size
2613 l[2] += size
2616 l[2] += size
2614
2617
2615 numrevs = len(r)
2618 numrevs = len(r)
2616 for rev in xrange(numrevs):
2619 for rev in xrange(numrevs):
2617 p1, p2 = r.parentrevs(rev)
2620 p1, p2 = r.parentrevs(rev)
2618 delta = r.deltaparent(rev)
2621 delta = r.deltaparent(rev)
2619 if format > 0:
2622 if format > 0:
2620 addsize(r.rawsize(rev), datasize)
2623 addsize(r.rawsize(rev), datasize)
2621 if p2 != nullrev:
2624 if p2 != nullrev:
2622 nummerges += 1
2625 nummerges += 1
2623 size = r.length(rev)
2626 size = r.length(rev)
2624 if delta == nullrev:
2627 if delta == nullrev:
2625 chainlengths.append(0)
2628 chainlengths.append(0)
2626 numfull += 1
2629 numfull += 1
2627 addsize(size, fullsize)
2630 addsize(size, fullsize)
2628 else:
2631 else:
2629 chainlengths.append(chainlengths[delta] + 1)
2632 chainlengths.append(chainlengths[delta] + 1)
2630 addsize(size, deltasize)
2633 addsize(size, deltasize)
2631 if delta == rev - 1:
2634 if delta == rev - 1:
2632 numprev += 1
2635 numprev += 1
2633 if delta == p1:
2636 if delta == p1:
2634 nump1prev += 1
2637 nump1prev += 1
2635 elif delta == p2:
2638 elif delta == p2:
2636 nump2prev += 1
2639 nump2prev += 1
2637 elif delta == p1:
2640 elif delta == p1:
2638 nump1 += 1
2641 nump1 += 1
2639 elif delta == p2:
2642 elif delta == p2:
2640 nump2 += 1
2643 nump2 += 1
2641 elif delta != nullrev:
2644 elif delta != nullrev:
2642 numother += 1
2645 numother += 1
2643
2646
2644 # Adjust size min value for empty cases
2647 # Adjust size min value for empty cases
2645 for size in (datasize, fullsize, deltasize):
2648 for size in (datasize, fullsize, deltasize):
2646 if size[0] is None:
2649 if size[0] is None:
2647 size[0] = 0
2650 size[0] = 0
2648
2651
2649 numdeltas = numrevs - numfull
2652 numdeltas = numrevs - numfull
2650 numoprev = numprev - nump1prev - nump2prev
2653 numoprev = numprev - nump1prev - nump2prev
2651 totalrawsize = datasize[2]
2654 totalrawsize = datasize[2]
2652 datasize[2] /= numrevs
2655 datasize[2] /= numrevs
2653 fulltotal = fullsize[2]
2656 fulltotal = fullsize[2]
2654 fullsize[2] /= numfull
2657 fullsize[2] /= numfull
2655 deltatotal = deltasize[2]
2658 deltatotal = deltasize[2]
2656 if numrevs - numfull > 0:
2659 if numrevs - numfull > 0:
2657 deltasize[2] /= numrevs - numfull
2660 deltasize[2] /= numrevs - numfull
2658 totalsize = fulltotal + deltatotal
2661 totalsize = fulltotal + deltatotal
2659 avgchainlen = sum(chainlengths) / numrevs
2662 avgchainlen = sum(chainlengths) / numrevs
2660 compratio = totalrawsize / totalsize
2663 compratio = totalrawsize / totalsize
2661
2664
2662 basedfmtstr = '%%%dd\n'
2665 basedfmtstr = '%%%dd\n'
2663 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2666 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2664
2667
2665 def dfmtstr(max):
2668 def dfmtstr(max):
2666 return basedfmtstr % len(str(max))
2669 return basedfmtstr % len(str(max))
2667 def pcfmtstr(max, padding=0):
2670 def pcfmtstr(max, padding=0):
2668 return basepcfmtstr % (len(str(max)), ' ' * padding)
2671 return basepcfmtstr % (len(str(max)), ' ' * padding)
2669
2672
2670 def pcfmt(value, total):
2673 def pcfmt(value, total):
2671 return (value, 100 * float(value) / total)
2674 return (value, 100 * float(value) / total)
2672
2675
2673 ui.write(('format : %d\n') % format)
2676 ui.write(('format : %d\n') % format)
2674 ui.write(('flags : %s\n') % ', '.join(flags))
2677 ui.write(('flags : %s\n') % ', '.join(flags))
2675
2678
2676 ui.write('\n')
2679 ui.write('\n')
2677 fmt = pcfmtstr(totalsize)
2680 fmt = pcfmtstr(totalsize)
2678 fmt2 = dfmtstr(totalsize)
2681 fmt2 = dfmtstr(totalsize)
2679 ui.write(('revisions : ') + fmt2 % numrevs)
2682 ui.write(('revisions : ') + fmt2 % numrevs)
2680 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2683 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2681 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2684 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2682 ui.write(('revisions : ') + fmt2 % numrevs)
2685 ui.write(('revisions : ') + fmt2 % numrevs)
2683 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2686 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2684 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2687 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2685 ui.write(('revision size : ') + fmt2 % totalsize)
2688 ui.write(('revision size : ') + fmt2 % totalsize)
2686 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2689 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2687 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2690 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2688
2691
2689 ui.write('\n')
2692 ui.write('\n')
2690 fmt = dfmtstr(max(avgchainlen, compratio))
2693 fmt = dfmtstr(max(avgchainlen, compratio))
2691 ui.write(('avg chain length : ') + fmt % avgchainlen)
2694 ui.write(('avg chain length : ') + fmt % avgchainlen)
2692 ui.write(('compression ratio : ') + fmt % compratio)
2695 ui.write(('compression ratio : ') + fmt % compratio)
2693
2696
2694 if format > 0:
2697 if format > 0:
2695 ui.write('\n')
2698 ui.write('\n')
2696 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2699 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2697 % tuple(datasize))
2700 % tuple(datasize))
2698 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2701 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2699 % tuple(fullsize))
2702 % tuple(fullsize))
2700 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2703 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2701 % tuple(deltasize))
2704 % tuple(deltasize))
2702
2705
2703 if numdeltas > 0:
2706 if numdeltas > 0:
2704 ui.write('\n')
2707 ui.write('\n')
2705 fmt = pcfmtstr(numdeltas)
2708 fmt = pcfmtstr(numdeltas)
2706 fmt2 = pcfmtstr(numdeltas, 4)
2709 fmt2 = pcfmtstr(numdeltas, 4)
2707 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2710 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2708 if numprev > 0:
2711 if numprev > 0:
2709 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2712 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2710 numprev))
2713 numprev))
2711 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2714 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2712 numprev))
2715 numprev))
2713 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2716 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2714 numprev))
2717 numprev))
2715 if gdelta:
2718 if gdelta:
2716 ui.write(('deltas against p1 : ')
2719 ui.write(('deltas against p1 : ')
2717 + fmt % pcfmt(nump1, numdeltas))
2720 + fmt % pcfmt(nump1, numdeltas))
2718 ui.write(('deltas against p2 : ')
2721 ui.write(('deltas against p2 : ')
2719 + fmt % pcfmt(nump2, numdeltas))
2722 + fmt % pcfmt(nump2, numdeltas))
2720 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2723 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2721 numdeltas))
2724 numdeltas))
2722
2725
2723 @command('debugrevspec',
2726 @command('debugrevspec',
2724 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2727 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2725 ('REVSPEC'))
2728 ('REVSPEC'))
2726 def debugrevspec(ui, repo, expr, **opts):
2729 def debugrevspec(ui, repo, expr, **opts):
2727 """parse and apply a revision specification
2730 """parse and apply a revision specification
2728
2731
2729 Use --verbose to print the parsed tree before and after aliases
2732 Use --verbose to print the parsed tree before and after aliases
2730 expansion.
2733 expansion.
2731 """
2734 """
2732 if ui.verbose:
2735 if ui.verbose:
2733 tree = revset.parse(expr)[0]
2736 tree = revset.parse(expr)[0]
2734 ui.note(revset.prettyformat(tree), "\n")
2737 ui.note(revset.prettyformat(tree), "\n")
2735 newtree = revset.findaliases(ui, tree)
2738 newtree = revset.findaliases(ui, tree)
2736 if newtree != tree:
2739 if newtree != tree:
2737 ui.note(revset.prettyformat(newtree), "\n")
2740 ui.note(revset.prettyformat(newtree), "\n")
2738 if opts["optimize"]:
2741 if opts["optimize"]:
2739 weight, optimizedtree = revset.optimize(newtree, True)
2742 weight, optimizedtree = revset.optimize(newtree, True)
2740 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2743 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2741 func = revset.match(ui, expr)
2744 func = revset.match(ui, expr)
2742 for c in func(repo, revset.spanset(repo)):
2745 for c in func(repo, revset.spanset(repo)):
2743 ui.write("%s\n" % c)
2746 ui.write("%s\n" % c)
2744
2747
2745 @command('debugsetparents', [], _('REV1 [REV2]'))
2748 @command('debugsetparents', [], _('REV1 [REV2]'))
2746 def debugsetparents(ui, repo, rev1, rev2=None):
2749 def debugsetparents(ui, repo, rev1, rev2=None):
2747 """manually set the parents of the current working directory
2750 """manually set the parents of the current working directory
2748
2751
2749 This is useful for writing repository conversion tools, but should
2752 This is useful for writing repository conversion tools, but should
2750 be used with care.
2753 be used with care.
2751
2754
2752 Returns 0 on success.
2755 Returns 0 on success.
2753 """
2756 """
2754
2757
2755 r1 = scmutil.revsingle(repo, rev1).node()
2758 r1 = scmutil.revsingle(repo, rev1).node()
2756 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2759 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2757
2760
2758 wlock = repo.wlock()
2761 wlock = repo.wlock()
2759 try:
2762 try:
2760 repo.dirstate.beginparentchange()
2763 repo.dirstate.beginparentchange()
2761 repo.setparents(r1, r2)
2764 repo.setparents(r1, r2)
2762 repo.dirstate.endparentchange()
2765 repo.dirstate.endparentchange()
2763 finally:
2766 finally:
2764 wlock.release()
2767 wlock.release()
2765
2768
2766 @command('debugdirstate|debugstate',
2769 @command('debugdirstate|debugstate',
2767 [('', 'nodates', None, _('do not display the saved mtime')),
2770 [('', 'nodates', None, _('do not display the saved mtime')),
2768 ('', 'datesort', None, _('sort by saved mtime'))],
2771 ('', 'datesort', None, _('sort by saved mtime'))],
2769 _('[OPTION]...'))
2772 _('[OPTION]...'))
2770 def debugstate(ui, repo, nodates=None, datesort=None):
2773 def debugstate(ui, repo, nodates=None, datesort=None):
2771 """show the contents of the current dirstate"""
2774 """show the contents of the current dirstate"""
2772 timestr = ""
2775 timestr = ""
2773 showdate = not nodates
2776 showdate = not nodates
2774 if datesort:
2777 if datesort:
2775 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2778 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2776 else:
2779 else:
2777 keyfunc = None # sort by filename
2780 keyfunc = None # sort by filename
2778 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2781 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2779 if showdate:
2782 if showdate:
2780 if ent[3] == -1:
2783 if ent[3] == -1:
2781 # Pad or slice to locale representation
2784 # Pad or slice to locale representation
2782 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2785 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2783 time.localtime(0)))
2786 time.localtime(0)))
2784 timestr = 'unset'
2787 timestr = 'unset'
2785 timestr = (timestr[:locale_len] +
2788 timestr = (timestr[:locale_len] +
2786 ' ' * (locale_len - len(timestr)))
2789 ' ' * (locale_len - len(timestr)))
2787 else:
2790 else:
2788 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2791 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2789 time.localtime(ent[3]))
2792 time.localtime(ent[3]))
2790 if ent[1] & 020000:
2793 if ent[1] & 020000:
2791 mode = 'lnk'
2794 mode = 'lnk'
2792 else:
2795 else:
2793 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2796 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2794 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2797 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2795 for f in repo.dirstate.copies():
2798 for f in repo.dirstate.copies():
2796 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2799 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2797
2800
2798 @command('debugsub',
2801 @command('debugsub',
2799 [('r', 'rev', '',
2802 [('r', 'rev', '',
2800 _('revision to check'), _('REV'))],
2803 _('revision to check'), _('REV'))],
2801 _('[-r REV] [REV]'))
2804 _('[-r REV] [REV]'))
2802 def debugsub(ui, repo, rev=None):
2805 def debugsub(ui, repo, rev=None):
2803 ctx = scmutil.revsingle(repo, rev, None)
2806 ctx = scmutil.revsingle(repo, rev, None)
2804 for k, v in sorted(ctx.substate.items()):
2807 for k, v in sorted(ctx.substate.items()):
2805 ui.write(('path %s\n') % k)
2808 ui.write(('path %s\n') % k)
2806 ui.write((' source %s\n') % v[0])
2809 ui.write((' source %s\n') % v[0])
2807 ui.write((' revision %s\n') % v[1])
2810 ui.write((' revision %s\n') % v[1])
2808
2811
2809 @command('debugsuccessorssets',
2812 @command('debugsuccessorssets',
2810 [],
2813 [],
2811 _('[REV]'))
2814 _('[REV]'))
2812 def debugsuccessorssets(ui, repo, *revs):
2815 def debugsuccessorssets(ui, repo, *revs):
2813 """show set of successors for revision
2816 """show set of successors for revision
2814
2817
2815 A successors set of changeset A is a consistent group of revisions that
2818 A successors set of changeset A is a consistent group of revisions that
2816 succeed A. It contains non-obsolete changesets only.
2819 succeed A. It contains non-obsolete changesets only.
2817
2820
2818 In most cases a changeset A has a single successors set containing a single
2821 In most cases a changeset A has a single successors set containing a single
2819 successor (changeset A replaced by A').
2822 successor (changeset A replaced by A').
2820
2823
2821 A changeset that is made obsolete with no successors are called "pruned".
2824 A changeset that is made obsolete with no successors are called "pruned".
2822 Such changesets have no successors sets at all.
2825 Such changesets have no successors sets at all.
2823
2826
2824 A changeset that has been "split" will have a successors set containing
2827 A changeset that has been "split" will have a successors set containing
2825 more than one successor.
2828 more than one successor.
2826
2829
2827 A changeset that has been rewritten in multiple different ways is called
2830 A changeset that has been rewritten in multiple different ways is called
2828 "divergent". Such changesets have multiple successor sets (each of which
2831 "divergent". Such changesets have multiple successor sets (each of which
2829 may also be split, i.e. have multiple successors).
2832 may also be split, i.e. have multiple successors).
2830
2833
2831 Results are displayed as follows::
2834 Results are displayed as follows::
2832
2835
2833 <rev1>
2836 <rev1>
2834 <successors-1A>
2837 <successors-1A>
2835 <rev2>
2838 <rev2>
2836 <successors-2A>
2839 <successors-2A>
2837 <successors-2B1> <successors-2B2> <successors-2B3>
2840 <successors-2B1> <successors-2B2> <successors-2B3>
2838
2841
2839 Here rev2 has two possible (i.e. divergent) successors sets. The first
2842 Here rev2 has two possible (i.e. divergent) successors sets. The first
2840 holds one element, whereas the second holds three (i.e. the changeset has
2843 holds one element, whereas the second holds three (i.e. the changeset has
2841 been split).
2844 been split).
2842 """
2845 """
2843 # passed to successorssets caching computation from one call to another
2846 # passed to successorssets caching computation from one call to another
2844 cache = {}
2847 cache = {}
2845 ctx2str = str
2848 ctx2str = str
2846 node2str = short
2849 node2str = short
2847 if ui.debug():
2850 if ui.debug():
2848 def ctx2str(ctx):
2851 def ctx2str(ctx):
2849 return ctx.hex()
2852 return ctx.hex()
2850 node2str = hex
2853 node2str = hex
2851 for rev in scmutil.revrange(repo, revs):
2854 for rev in scmutil.revrange(repo, revs):
2852 ctx = repo[rev]
2855 ctx = repo[rev]
2853 ui.write('%s\n'% ctx2str(ctx))
2856 ui.write('%s\n'% ctx2str(ctx))
2854 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2857 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2855 if succsset:
2858 if succsset:
2856 ui.write(' ')
2859 ui.write(' ')
2857 ui.write(node2str(succsset[0]))
2860 ui.write(node2str(succsset[0]))
2858 for node in succsset[1:]:
2861 for node in succsset[1:]:
2859 ui.write(' ')
2862 ui.write(' ')
2860 ui.write(node2str(node))
2863 ui.write(node2str(node))
2861 ui.write('\n')
2864 ui.write('\n')
2862
2865
2863 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2866 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2864 def debugwalk(ui, repo, *pats, **opts):
2867 def debugwalk(ui, repo, *pats, **opts):
2865 """show how files match on given patterns"""
2868 """show how files match on given patterns"""
2866 m = scmutil.match(repo[None], pats, opts)
2869 m = scmutil.match(repo[None], pats, opts)
2867 items = list(repo.walk(m))
2870 items = list(repo.walk(m))
2868 if not items:
2871 if not items:
2869 return
2872 return
2870 f = lambda fn: fn
2873 f = lambda fn: fn
2871 if ui.configbool('ui', 'slash') and os.sep != '/':
2874 if ui.configbool('ui', 'slash') and os.sep != '/':
2872 f = lambda fn: util.normpath(fn)
2875 f = lambda fn: util.normpath(fn)
2873 fmt = 'f %%-%ds %%-%ds %%s' % (
2876 fmt = 'f %%-%ds %%-%ds %%s' % (
2874 max([len(abs) for abs in items]),
2877 max([len(abs) for abs in items]),
2875 max([len(m.rel(abs)) for abs in items]))
2878 max([len(m.rel(abs)) for abs in items]))
2876 for abs in items:
2879 for abs in items:
2877 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2880 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2878 ui.write("%s\n" % line.rstrip())
2881 ui.write("%s\n" % line.rstrip())
2879
2882
2880 @command('debugwireargs',
2883 @command('debugwireargs',
2881 [('', 'three', '', 'three'),
2884 [('', 'three', '', 'three'),
2882 ('', 'four', '', 'four'),
2885 ('', 'four', '', 'four'),
2883 ('', 'five', '', 'five'),
2886 ('', 'five', '', 'five'),
2884 ] + remoteopts,
2887 ] + remoteopts,
2885 _('REPO [OPTIONS]... [ONE [TWO]]'),
2888 _('REPO [OPTIONS]... [ONE [TWO]]'),
2886 norepo=True)
2889 norepo=True)
2887 def debugwireargs(ui, repopath, *vals, **opts):
2890 def debugwireargs(ui, repopath, *vals, **opts):
2888 repo = hg.peer(ui, opts, repopath)
2891 repo = hg.peer(ui, opts, repopath)
2889 for opt in remoteopts:
2892 for opt in remoteopts:
2890 del opts[opt[1]]
2893 del opts[opt[1]]
2891 args = {}
2894 args = {}
2892 for k, v in opts.iteritems():
2895 for k, v in opts.iteritems():
2893 if v:
2896 if v:
2894 args[k] = v
2897 args[k] = v
2895 # run twice to check that we don't mess up the stream for the next command
2898 # run twice to check that we don't mess up the stream for the next command
2896 res1 = repo.debugwireargs(*vals, **args)
2899 res1 = repo.debugwireargs(*vals, **args)
2897 res2 = repo.debugwireargs(*vals, **args)
2900 res2 = repo.debugwireargs(*vals, **args)
2898 ui.write("%s\n" % res1)
2901 ui.write("%s\n" % res1)
2899 if res1 != res2:
2902 if res1 != res2:
2900 ui.warn("%s\n" % res2)
2903 ui.warn("%s\n" % res2)
2901
2904
2902 @command('^diff',
2905 @command('^diff',
2903 [('r', 'rev', [], _('revision'), _('REV')),
2906 [('r', 'rev', [], _('revision'), _('REV')),
2904 ('c', 'change', '', _('change made by revision'), _('REV'))
2907 ('c', 'change', '', _('change made by revision'), _('REV'))
2905 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2908 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2906 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2909 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2907 inferrepo=True)
2910 inferrepo=True)
2908 def diff(ui, repo, *pats, **opts):
2911 def diff(ui, repo, *pats, **opts):
2909 """diff repository (or selected files)
2912 """diff repository (or selected files)
2910
2913
2911 Show differences between revisions for the specified files.
2914 Show differences between revisions for the specified files.
2912
2915
2913 Differences between files are shown using the unified diff format.
2916 Differences between files are shown using the unified diff format.
2914
2917
2915 .. note::
2918 .. note::
2916
2919
2917 diff may generate unexpected results for merges, as it will
2920 diff may generate unexpected results for merges, as it will
2918 default to comparing against the working directory's first
2921 default to comparing against the working directory's first
2919 parent changeset if no revisions are specified.
2922 parent changeset if no revisions are specified.
2920
2923
2921 When two revision arguments are given, then changes are shown
2924 When two revision arguments are given, then changes are shown
2922 between those revisions. If only one revision is specified then
2925 between those revisions. If only one revision is specified then
2923 that revision is compared to the working directory, and, when no
2926 that revision is compared to the working directory, and, when no
2924 revisions are specified, the working directory files are compared
2927 revisions are specified, the working directory files are compared
2925 to its parent.
2928 to its parent.
2926
2929
2927 Alternatively you can specify -c/--change with a revision to see
2930 Alternatively you can specify -c/--change with a revision to see
2928 the changes in that changeset relative to its first parent.
2931 the changes in that changeset relative to its first parent.
2929
2932
2930 Without the -a/--text option, diff will avoid generating diffs of
2933 Without the -a/--text option, diff will avoid generating diffs of
2931 files it detects as binary. With -a, diff will generate a diff
2934 files it detects as binary. With -a, diff will generate a diff
2932 anyway, probably with undesirable results.
2935 anyway, probably with undesirable results.
2933
2936
2934 Use the -g/--git option to generate diffs in the git extended diff
2937 Use the -g/--git option to generate diffs in the git extended diff
2935 format. For more information, read :hg:`help diffs`.
2938 format. For more information, read :hg:`help diffs`.
2936
2939
2937 .. container:: verbose
2940 .. container:: verbose
2938
2941
2939 Examples:
2942 Examples:
2940
2943
2941 - compare a file in the current working directory to its parent::
2944 - compare a file in the current working directory to its parent::
2942
2945
2943 hg diff foo.c
2946 hg diff foo.c
2944
2947
2945 - compare two historical versions of a directory, with rename info::
2948 - compare two historical versions of a directory, with rename info::
2946
2949
2947 hg diff --git -r 1.0:1.2 lib/
2950 hg diff --git -r 1.0:1.2 lib/
2948
2951
2949 - get change stats relative to the last change on some date::
2952 - get change stats relative to the last change on some date::
2950
2953
2951 hg diff --stat -r "date('may 2')"
2954 hg diff --stat -r "date('may 2')"
2952
2955
2953 - diff all newly-added files that contain a keyword::
2956 - diff all newly-added files that contain a keyword::
2954
2957
2955 hg diff "set:added() and grep(GNU)"
2958 hg diff "set:added() and grep(GNU)"
2956
2959
2957 - compare a revision and its parents::
2960 - compare a revision and its parents::
2958
2961
2959 hg diff -c 9353 # compare against first parent
2962 hg diff -c 9353 # compare against first parent
2960 hg diff -r 9353^:9353 # same using revset syntax
2963 hg diff -r 9353^:9353 # same using revset syntax
2961 hg diff -r 9353^2:9353 # compare against the second parent
2964 hg diff -r 9353^2:9353 # compare against the second parent
2962
2965
2963 Returns 0 on success.
2966 Returns 0 on success.
2964 """
2967 """
2965
2968
2966 revs = opts.get('rev')
2969 revs = opts.get('rev')
2967 change = opts.get('change')
2970 change = opts.get('change')
2968 stat = opts.get('stat')
2971 stat = opts.get('stat')
2969 reverse = opts.get('reverse')
2972 reverse = opts.get('reverse')
2970
2973
2971 if revs and change:
2974 if revs and change:
2972 msg = _('cannot specify --rev and --change at the same time')
2975 msg = _('cannot specify --rev and --change at the same time')
2973 raise util.Abort(msg)
2976 raise util.Abort(msg)
2974 elif change:
2977 elif change:
2975 node2 = scmutil.revsingle(repo, change, None).node()
2978 node2 = scmutil.revsingle(repo, change, None).node()
2976 node1 = repo[node2].p1().node()
2979 node1 = repo[node2].p1().node()
2977 else:
2980 else:
2978 node1, node2 = scmutil.revpair(repo, revs)
2981 node1, node2 = scmutil.revpair(repo, revs)
2979
2982
2980 if reverse:
2983 if reverse:
2981 node1, node2 = node2, node1
2984 node1, node2 = node2, node1
2982
2985
2983 diffopts = patch.diffopts(ui, opts)
2986 diffopts = patch.diffopts(ui, opts)
2984 m = scmutil.match(repo[node2], pats, opts)
2987 m = scmutil.match(repo[node2], pats, opts)
2985 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2988 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2986 listsubrepos=opts.get('subrepos'))
2989 listsubrepos=opts.get('subrepos'))
2987
2990
2988 @command('^export',
2991 @command('^export',
2989 [('o', 'output', '',
2992 [('o', 'output', '',
2990 _('print output to file with formatted name'), _('FORMAT')),
2993 _('print output to file with formatted name'), _('FORMAT')),
2991 ('', 'switch-parent', None, _('diff against the second parent')),
2994 ('', 'switch-parent', None, _('diff against the second parent')),
2992 ('r', 'rev', [], _('revisions to export'), _('REV')),
2995 ('r', 'rev', [], _('revisions to export'), _('REV')),
2993 ] + diffopts,
2996 ] + diffopts,
2994 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2997 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2995 def export(ui, repo, *changesets, **opts):
2998 def export(ui, repo, *changesets, **opts):
2996 """dump the header and diffs for one or more changesets
2999 """dump the header and diffs for one or more changesets
2997
3000
2998 Print the changeset header and diffs for one or more revisions.
3001 Print the changeset header and diffs for one or more revisions.
2999 If no revision is given, the parent of the working directory is used.
3002 If no revision is given, the parent of the working directory is used.
3000
3003
3001 The information shown in the changeset header is: author, date,
3004 The information shown in the changeset header is: author, date,
3002 branch name (if non-default), changeset hash, parent(s) and commit
3005 branch name (if non-default), changeset hash, parent(s) and commit
3003 comment.
3006 comment.
3004
3007
3005 .. note::
3008 .. note::
3006
3009
3007 export may generate unexpected diff output for merge
3010 export may generate unexpected diff output for merge
3008 changesets, as it will compare the merge changeset against its
3011 changesets, as it will compare the merge changeset against its
3009 first parent only.
3012 first parent only.
3010
3013
3011 Output may be to a file, in which case the name of the file is
3014 Output may be to a file, in which case the name of the file is
3012 given using a format string. The formatting rules are as follows:
3015 given using a format string. The formatting rules are as follows:
3013
3016
3014 :``%%``: literal "%" character
3017 :``%%``: literal "%" character
3015 :``%H``: changeset hash (40 hexadecimal digits)
3018 :``%H``: changeset hash (40 hexadecimal digits)
3016 :``%N``: number of patches being generated
3019 :``%N``: number of patches being generated
3017 :``%R``: changeset revision number
3020 :``%R``: changeset revision number
3018 :``%b``: basename of the exporting repository
3021 :``%b``: basename of the exporting repository
3019 :``%h``: short-form changeset hash (12 hexadecimal digits)
3022 :``%h``: short-form changeset hash (12 hexadecimal digits)
3020 :``%m``: first line of the commit message (only alphanumeric characters)
3023 :``%m``: first line of the commit message (only alphanumeric characters)
3021 :``%n``: zero-padded sequence number, starting at 1
3024 :``%n``: zero-padded sequence number, starting at 1
3022 :``%r``: zero-padded changeset revision number
3025 :``%r``: zero-padded changeset revision number
3023
3026
3024 Without the -a/--text option, export will avoid generating diffs
3027 Without the -a/--text option, export will avoid generating diffs
3025 of files it detects as binary. With -a, export will generate a
3028 of files it detects as binary. With -a, export will generate a
3026 diff anyway, probably with undesirable results.
3029 diff anyway, probably with undesirable results.
3027
3030
3028 Use the -g/--git option to generate diffs in the git extended diff
3031 Use the -g/--git option to generate diffs in the git extended diff
3029 format. See :hg:`help diffs` for more information.
3032 format. See :hg:`help diffs` for more information.
3030
3033
3031 With the --switch-parent option, the diff will be against the
3034 With the --switch-parent option, the diff will be against the
3032 second parent. It can be useful to review a merge.
3035 second parent. It can be useful to review a merge.
3033
3036
3034 .. container:: verbose
3037 .. container:: verbose
3035
3038
3036 Examples:
3039 Examples:
3037
3040
3038 - use export and import to transplant a bugfix to the current
3041 - use export and import to transplant a bugfix to the current
3039 branch::
3042 branch::
3040
3043
3041 hg export -r 9353 | hg import -
3044 hg export -r 9353 | hg import -
3042
3045
3043 - export all the changesets between two revisions to a file with
3046 - export all the changesets between two revisions to a file with
3044 rename information::
3047 rename information::
3045
3048
3046 hg export --git -r 123:150 > changes.txt
3049 hg export --git -r 123:150 > changes.txt
3047
3050
3048 - split outgoing changes into a series of patches with
3051 - split outgoing changes into a series of patches with
3049 descriptive names::
3052 descriptive names::
3050
3053
3051 hg export -r "outgoing()" -o "%n-%m.patch"
3054 hg export -r "outgoing()" -o "%n-%m.patch"
3052
3055
3053 Returns 0 on success.
3056 Returns 0 on success.
3054 """
3057 """
3055 changesets += tuple(opts.get('rev', []))
3058 changesets += tuple(opts.get('rev', []))
3056 if not changesets:
3059 if not changesets:
3057 changesets = ['.']
3060 changesets = ['.']
3058 revs = scmutil.revrange(repo, changesets)
3061 revs = scmutil.revrange(repo, changesets)
3059 if not revs:
3062 if not revs:
3060 raise util.Abort(_("export requires at least one changeset"))
3063 raise util.Abort(_("export requires at least one changeset"))
3061 if len(revs) > 1:
3064 if len(revs) > 1:
3062 ui.note(_('exporting patches:\n'))
3065 ui.note(_('exporting patches:\n'))
3063 else:
3066 else:
3064 ui.note(_('exporting patch:\n'))
3067 ui.note(_('exporting patch:\n'))
3065 cmdutil.export(repo, revs, template=opts.get('output'),
3068 cmdutil.export(repo, revs, template=opts.get('output'),
3066 switch_parent=opts.get('switch_parent'),
3069 switch_parent=opts.get('switch_parent'),
3067 opts=patch.diffopts(ui, opts))
3070 opts=patch.diffopts(ui, opts))
3068
3071
3069 @command('files',
3072 @command('files',
3070 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3073 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3071 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3074 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3072 ] + walkopts + formatteropts,
3075 ] + walkopts + formatteropts,
3073 _('[OPTION]... [PATTERN]...'))
3076 _('[OPTION]... [PATTERN]...'))
3074 def files(ui, repo, *pats, **opts):
3077 def files(ui, repo, *pats, **opts):
3075 """list tracked files
3078 """list tracked files
3076
3079
3077 Print files under Mercurial control in the working directory or
3080 Print files under Mercurial control in the working directory or
3078 specified revision whose names match the given patterns (excluding
3081 specified revision whose names match the given patterns (excluding
3079 removed files).
3082 removed files).
3080
3083
3081 If no patterns are given to match, this command prints the names
3084 If no patterns are given to match, this command prints the names
3082 of all files under Mercurial control in the working copy.
3085 of all files under Mercurial control in the working copy.
3083
3086
3084 .. container:: verbose
3087 .. container:: verbose
3085
3088
3086 Examples:
3089 Examples:
3087
3090
3088 - list all files under the current directory::
3091 - list all files under the current directory::
3089
3092
3090 hg files .
3093 hg files .
3091
3094
3092 - shows sizes and flags for current revision::
3095 - shows sizes and flags for current revision::
3093
3096
3094 hg files -vr .
3097 hg files -vr .
3095
3098
3096 - list all files named README::
3099 - list all files named README::
3097
3100
3098 hg files -I "**/README"
3101 hg files -I "**/README"
3099
3102
3100 - list all binary files::
3103 - list all binary files::
3101
3104
3102 hg files "set:binary()"
3105 hg files "set:binary()"
3103
3106
3104 - find files containing a regular expression:
3107 - find files containing a regular expression:
3105
3108
3106 hg files "set:grep('bob')"
3109 hg files "set:grep('bob')"
3107
3110
3108 - search tracked file contents with xargs and grep::
3111 - search tracked file contents with xargs and grep::
3109
3112
3110 hg files -0 | xargs -0 grep foo
3113 hg files -0 | xargs -0 grep foo
3111
3114
3112 See :hg:'help pattern' and :hg:'help revsets' for more information
3115 See :hg:'help pattern' and :hg:'help revsets' for more information
3113 on specifying file patterns.
3116 on specifying file patterns.
3114
3117
3115 Returns 0 if a match is found, 1 otherwise.
3118 Returns 0 if a match is found, 1 otherwise.
3116
3119
3117 """
3120 """
3118 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3121 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3119 rev = ctx.rev()
3122 rev = ctx.rev()
3120 ret = 1
3123 ret = 1
3121
3124
3122 end = '\n'
3125 end = '\n'
3123 if opts.get('print0'):
3126 if opts.get('print0'):
3124 end = '\0'
3127 end = '\0'
3125 fm = ui.formatter('status', opts)
3128 fm = ui.formatter('status', opts)
3126 fmt = '%s' + end
3129 fmt = '%s' + end
3127
3130
3128 m = scmutil.match(ctx, pats, opts)
3131 m = scmutil.match(ctx, pats, opts)
3129 for f in ctx.walk(m):
3132 for f in ctx.walk(m):
3130 if rev is None and repo.dirstate[f] in 'R?!':
3133 if rev is None and repo.dirstate[f] in 'R?!':
3131 continue
3134 continue
3132 fm.startitem()
3135 fm.startitem()
3133 if ui.verbose:
3136 if ui.verbose:
3134 fc = ctx[f]
3137 fc = ctx[f]
3135 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3138 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3136 fm.data(abspath=f)
3139 fm.data(abspath=f)
3137 fm.write('path', fmt, m.rel(f))
3140 fm.write('path', fmt, m.rel(f))
3138 ret = 0
3141 ret = 0
3139
3142
3140 fm.end()
3143 fm.end()
3141
3144
3142 return ret
3145 return ret
3143
3146
3144 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3147 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3145 def forget(ui, repo, *pats, **opts):
3148 def forget(ui, repo, *pats, **opts):
3146 """forget the specified files on the next commit
3149 """forget the specified files on the next commit
3147
3150
3148 Mark the specified files so they will no longer be tracked
3151 Mark the specified files so they will no longer be tracked
3149 after the next commit.
3152 after the next commit.
3150
3153
3151 This only removes files from the current branch, not from the
3154 This only removes files from the current branch, not from the
3152 entire project history, and it does not delete them from the
3155 entire project history, and it does not delete them from the
3153 working directory.
3156 working directory.
3154
3157
3155 To undo a forget before the next commit, see :hg:`add`.
3158 To undo a forget before the next commit, see :hg:`add`.
3156
3159
3157 .. container:: verbose
3160 .. container:: verbose
3158
3161
3159 Examples:
3162 Examples:
3160
3163
3161 - forget newly-added binary files::
3164 - forget newly-added binary files::
3162
3165
3163 hg forget "set:added() and binary()"
3166 hg forget "set:added() and binary()"
3164
3167
3165 - forget files that would be excluded by .hgignore::
3168 - forget files that would be excluded by .hgignore::
3166
3169
3167 hg forget "set:hgignore()"
3170 hg forget "set:hgignore()"
3168
3171
3169 Returns 0 on success.
3172 Returns 0 on success.
3170 """
3173 """
3171
3174
3172 if not pats:
3175 if not pats:
3173 raise util.Abort(_('no files specified'))
3176 raise util.Abort(_('no files specified'))
3174
3177
3175 m = scmutil.match(repo[None], pats, opts)
3178 m = scmutil.match(repo[None], pats, opts)
3176 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3179 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3177 return rejected and 1 or 0
3180 return rejected and 1 or 0
3178
3181
3179 @command(
3182 @command(
3180 'graft',
3183 'graft',
3181 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3184 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3182 ('c', 'continue', False, _('resume interrupted graft')),
3185 ('c', 'continue', False, _('resume interrupted graft')),
3183 ('e', 'edit', False, _('invoke editor on commit messages')),
3186 ('e', 'edit', False, _('invoke editor on commit messages')),
3184 ('', 'log', None, _('append graft info to log message')),
3187 ('', 'log', None, _('append graft info to log message')),
3185 ('f', 'force', False, _('force graft')),
3188 ('f', 'force', False, _('force graft')),
3186 ('D', 'currentdate', False,
3189 ('D', 'currentdate', False,
3187 _('record the current date as commit date')),
3190 _('record the current date as commit date')),
3188 ('U', 'currentuser', False,
3191 ('U', 'currentuser', False,
3189 _('record the current user as committer'), _('DATE'))]
3192 _('record the current user as committer'), _('DATE'))]
3190 + commitopts2 + mergetoolopts + dryrunopts,
3193 + commitopts2 + mergetoolopts + dryrunopts,
3191 _('[OPTION]... [-r] REV...'))
3194 _('[OPTION]... [-r] REV...'))
3192 def graft(ui, repo, *revs, **opts):
3195 def graft(ui, repo, *revs, **opts):
3193 '''copy changes from other branches onto the current branch
3196 '''copy changes from other branches onto the current branch
3194
3197
3195 This command uses Mercurial's merge logic to copy individual
3198 This command uses Mercurial's merge logic to copy individual
3196 changes from other branches without merging branches in the
3199 changes from other branches without merging branches in the
3197 history graph. This is sometimes known as 'backporting' or
3200 history graph. This is sometimes known as 'backporting' or
3198 'cherry-picking'. By default, graft will copy user, date, and
3201 'cherry-picking'. By default, graft will copy user, date, and
3199 description from the source changesets.
3202 description from the source changesets.
3200
3203
3201 Changesets that are ancestors of the current revision, that have
3204 Changesets that are ancestors of the current revision, that have
3202 already been grafted, or that are merges will be skipped.
3205 already been grafted, or that are merges will be skipped.
3203
3206
3204 If --log is specified, log messages will have a comment appended
3207 If --log is specified, log messages will have a comment appended
3205 of the form::
3208 of the form::
3206
3209
3207 (grafted from CHANGESETHASH)
3210 (grafted from CHANGESETHASH)
3208
3211
3209 If --force is specified, revisions will be grafted even if they
3212 If --force is specified, revisions will be grafted even if they
3210 are already ancestors of or have been grafted to the destination.
3213 are already ancestors of or have been grafted to the destination.
3211 This is useful when the revisions have since been backed out.
3214 This is useful when the revisions have since been backed out.
3212
3215
3213 If a graft merge results in conflicts, the graft process is
3216 If a graft merge results in conflicts, the graft process is
3214 interrupted so that the current merge can be manually resolved.
3217 interrupted so that the current merge can be manually resolved.
3215 Once all conflicts are addressed, the graft process can be
3218 Once all conflicts are addressed, the graft process can be
3216 continued with the -c/--continue option.
3219 continued with the -c/--continue option.
3217
3220
3218 .. note::
3221 .. note::
3219
3222
3220 The -c/--continue option does not reapply earlier options, except
3223 The -c/--continue option does not reapply earlier options, except
3221 for --force.
3224 for --force.
3222
3225
3223 .. container:: verbose
3226 .. container:: verbose
3224
3227
3225 Examples:
3228 Examples:
3226
3229
3227 - copy a single change to the stable branch and edit its description::
3230 - copy a single change to the stable branch and edit its description::
3228
3231
3229 hg update stable
3232 hg update stable
3230 hg graft --edit 9393
3233 hg graft --edit 9393
3231
3234
3232 - graft a range of changesets with one exception, updating dates::
3235 - graft a range of changesets with one exception, updating dates::
3233
3236
3234 hg graft -D "2085::2093 and not 2091"
3237 hg graft -D "2085::2093 and not 2091"
3235
3238
3236 - continue a graft after resolving conflicts::
3239 - continue a graft after resolving conflicts::
3237
3240
3238 hg graft -c
3241 hg graft -c
3239
3242
3240 - show the source of a grafted changeset::
3243 - show the source of a grafted changeset::
3241
3244
3242 hg log --debug -r .
3245 hg log --debug -r .
3243
3246
3244 See :hg:`help revisions` and :hg:`help revsets` for more about
3247 See :hg:`help revisions` and :hg:`help revsets` for more about
3245 specifying revisions.
3248 specifying revisions.
3246
3249
3247 Returns 0 on successful completion.
3250 Returns 0 on successful completion.
3248 '''
3251 '''
3249
3252
3250 revs = list(revs)
3253 revs = list(revs)
3251 revs.extend(opts['rev'])
3254 revs.extend(opts['rev'])
3252
3255
3253 if not opts.get('user') and opts.get('currentuser'):
3256 if not opts.get('user') and opts.get('currentuser'):
3254 opts['user'] = ui.username()
3257 opts['user'] = ui.username()
3255 if not opts.get('date') and opts.get('currentdate'):
3258 if not opts.get('date') and opts.get('currentdate'):
3256 opts['date'] = "%d %d" % util.makedate()
3259 opts['date'] = "%d %d" % util.makedate()
3257
3260
3258 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3261 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3259
3262
3260 cont = False
3263 cont = False
3261 if opts['continue']:
3264 if opts['continue']:
3262 cont = True
3265 cont = True
3263 if revs:
3266 if revs:
3264 raise util.Abort(_("can't specify --continue and revisions"))
3267 raise util.Abort(_("can't specify --continue and revisions"))
3265 # read in unfinished revisions
3268 # read in unfinished revisions
3266 try:
3269 try:
3267 nodes = repo.opener.read('graftstate').splitlines()
3270 nodes = repo.opener.read('graftstate').splitlines()
3268 revs = [repo[node].rev() for node in nodes]
3271 revs = [repo[node].rev() for node in nodes]
3269 except IOError, inst:
3272 except IOError, inst:
3270 if inst.errno != errno.ENOENT:
3273 if inst.errno != errno.ENOENT:
3271 raise
3274 raise
3272 raise util.Abort(_("no graft state found, can't continue"))
3275 raise util.Abort(_("no graft state found, can't continue"))
3273 else:
3276 else:
3274 cmdutil.checkunfinished(repo)
3277 cmdutil.checkunfinished(repo)
3275 cmdutil.bailifchanged(repo)
3278 cmdutil.bailifchanged(repo)
3276 if not revs:
3279 if not revs:
3277 raise util.Abort(_('no revisions specified'))
3280 raise util.Abort(_('no revisions specified'))
3278 revs = scmutil.revrange(repo, revs)
3281 revs = scmutil.revrange(repo, revs)
3279
3282
3280 # check for merges
3283 # check for merges
3281 for rev in repo.revs('%ld and merge()', revs):
3284 for rev in repo.revs('%ld and merge()', revs):
3282 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3285 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3283 revs.remove(rev)
3286 revs.remove(rev)
3284 if not revs:
3287 if not revs:
3285 return -1
3288 return -1
3286
3289
3287 # Don't check in the --continue case, in effect retaining --force across
3290 # Don't check in the --continue case, in effect retaining --force across
3288 # --continues. That's because without --force, any revisions we decided to
3291 # --continues. That's because without --force, any revisions we decided to
3289 # skip would have been filtered out here, so they wouldn't have made their
3292 # skip would have been filtered out here, so they wouldn't have made their
3290 # way to the graftstate. With --force, any revisions we would have otherwise
3293 # way to the graftstate. With --force, any revisions we would have otherwise
3291 # skipped would not have been filtered out, and if they hadn't been applied
3294 # skipped would not have been filtered out, and if they hadn't been applied
3292 # already, they'd have been in the graftstate.
3295 # already, they'd have been in the graftstate.
3293 if not (cont or opts.get('force')):
3296 if not (cont or opts.get('force')):
3294 # check for ancestors of dest branch
3297 # check for ancestors of dest branch
3295 crev = repo['.'].rev()
3298 crev = repo['.'].rev()
3296 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3299 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3297 # Cannot use x.remove(y) on smart set, this has to be a list.
3300 # Cannot use x.remove(y) on smart set, this has to be a list.
3298 # XXX make this lazy in the future
3301 # XXX make this lazy in the future
3299 revs = list(revs)
3302 revs = list(revs)
3300 # don't mutate while iterating, create a copy
3303 # don't mutate while iterating, create a copy
3301 for rev in list(revs):
3304 for rev in list(revs):
3302 if rev in ancestors:
3305 if rev in ancestors:
3303 ui.warn(_('skipping ancestor revision %s\n') % rev)
3306 ui.warn(_('skipping ancestor revision %s\n') % rev)
3304 # XXX remove on list is slow
3307 # XXX remove on list is slow
3305 revs.remove(rev)
3308 revs.remove(rev)
3306 if not revs:
3309 if not revs:
3307 return -1
3310 return -1
3308
3311
3309 # analyze revs for earlier grafts
3312 # analyze revs for earlier grafts
3310 ids = {}
3313 ids = {}
3311 for ctx in repo.set("%ld", revs):
3314 for ctx in repo.set("%ld", revs):
3312 ids[ctx.hex()] = ctx.rev()
3315 ids[ctx.hex()] = ctx.rev()
3313 n = ctx.extra().get('source')
3316 n = ctx.extra().get('source')
3314 if n:
3317 if n:
3315 ids[n] = ctx.rev()
3318 ids[n] = ctx.rev()
3316
3319
3317 # check ancestors for earlier grafts
3320 # check ancestors for earlier grafts
3318 ui.debug('scanning for duplicate grafts\n')
3321 ui.debug('scanning for duplicate grafts\n')
3319
3322
3320 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3323 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3321 ctx = repo[rev]
3324 ctx = repo[rev]
3322 n = ctx.extra().get('source')
3325 n = ctx.extra().get('source')
3323 if n in ids:
3326 if n in ids:
3324 try:
3327 try:
3325 r = repo[n].rev()
3328 r = repo[n].rev()
3326 except error.RepoLookupError:
3329 except error.RepoLookupError:
3327 r = None
3330 r = None
3328 if r in revs:
3331 if r in revs:
3329 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3332 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3330 % (r, rev))
3333 % (r, rev))
3331 revs.remove(r)
3334 revs.remove(r)
3332 elif ids[n] in revs:
3335 elif ids[n] in revs:
3333 if r is None:
3336 if r is None:
3334 ui.warn(_('skipping already grafted revision %s '
3337 ui.warn(_('skipping already grafted revision %s '
3335 '(%s also has unknown origin %s)\n')
3338 '(%s also has unknown origin %s)\n')
3336 % (ids[n], rev, n))
3339 % (ids[n], rev, n))
3337 else:
3340 else:
3338 ui.warn(_('skipping already grafted revision %s '
3341 ui.warn(_('skipping already grafted revision %s '
3339 '(%s also has origin %d)\n')
3342 '(%s also has origin %d)\n')
3340 % (ids[n], rev, r))
3343 % (ids[n], rev, r))
3341 revs.remove(ids[n])
3344 revs.remove(ids[n])
3342 elif ctx.hex() in ids:
3345 elif ctx.hex() in ids:
3343 r = ids[ctx.hex()]
3346 r = ids[ctx.hex()]
3344 ui.warn(_('skipping already grafted revision %s '
3347 ui.warn(_('skipping already grafted revision %s '
3345 '(was grafted from %d)\n') % (r, rev))
3348 '(was grafted from %d)\n') % (r, rev))
3346 revs.remove(r)
3349 revs.remove(r)
3347 if not revs:
3350 if not revs:
3348 return -1
3351 return -1
3349
3352
3350 wlock = repo.wlock()
3353 wlock = repo.wlock()
3351 try:
3354 try:
3352 current = repo['.']
3355 current = repo['.']
3353 for pos, ctx in enumerate(repo.set("%ld", revs)):
3356 for pos, ctx in enumerate(repo.set("%ld", revs)):
3354
3357
3355 ui.status(_('grafting revision %s\n') % ctx.rev())
3358 ui.status(_('grafting revision %s\n') % ctx.rev())
3356 if opts.get('dry_run'):
3359 if opts.get('dry_run'):
3357 continue
3360 continue
3358
3361
3359 source = ctx.extra().get('source')
3362 source = ctx.extra().get('source')
3360 if not source:
3363 if not source:
3361 source = ctx.hex()
3364 source = ctx.hex()
3362 extra = {'source': source}
3365 extra = {'source': source}
3363 user = ctx.user()
3366 user = ctx.user()
3364 if opts.get('user'):
3367 if opts.get('user'):
3365 user = opts['user']
3368 user = opts['user']
3366 date = ctx.date()
3369 date = ctx.date()
3367 if opts.get('date'):
3370 if opts.get('date'):
3368 date = opts['date']
3371 date = opts['date']
3369 message = ctx.description()
3372 message = ctx.description()
3370 if opts.get('log'):
3373 if opts.get('log'):
3371 message += '\n(grafted from %s)' % ctx.hex()
3374 message += '\n(grafted from %s)' % ctx.hex()
3372
3375
3373 # we don't merge the first commit when continuing
3376 # we don't merge the first commit when continuing
3374 if not cont:
3377 if not cont:
3375 # perform the graft merge with p1(rev) as 'ancestor'
3378 # perform the graft merge with p1(rev) as 'ancestor'
3376 try:
3379 try:
3377 # ui.forcemerge is an internal variable, do not document
3380 # ui.forcemerge is an internal variable, do not document
3378 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3381 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3379 'graft')
3382 'graft')
3380 stats = mergemod.update(repo, ctx.node(), True, True, False,
3383 stats = mergemod.update(repo, ctx.node(), True, True, False,
3381 ctx.p1().node(),
3384 ctx.p1().node(),
3382 labels=['local', 'graft'])
3385 labels=['local', 'graft'])
3383 finally:
3386 finally:
3384 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3387 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3385 # report any conflicts
3388 # report any conflicts
3386 if stats and stats[3] > 0:
3389 if stats and stats[3] > 0:
3387 # write out state for --continue
3390 # write out state for --continue
3388 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3391 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3389 repo.opener.write('graftstate', ''.join(nodelines))
3392 repo.opener.write('graftstate', ''.join(nodelines))
3390 raise util.Abort(
3393 raise util.Abort(
3391 _("unresolved conflicts, can't continue"),
3394 _("unresolved conflicts, can't continue"),
3392 hint=_('use hg resolve and hg graft --continue'))
3395 hint=_('use hg resolve and hg graft --continue'))
3393 else:
3396 else:
3394 cont = False
3397 cont = False
3395
3398
3396 # drop the second merge parent
3399 # drop the second merge parent
3397 repo.dirstate.beginparentchange()
3400 repo.dirstate.beginparentchange()
3398 repo.setparents(current.node(), nullid)
3401 repo.setparents(current.node(), nullid)
3399 repo.dirstate.write()
3402 repo.dirstate.write()
3400 # fix up dirstate for copies and renames
3403 # fix up dirstate for copies and renames
3401 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3404 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3402 repo.dirstate.endparentchange()
3405 repo.dirstate.endparentchange()
3403
3406
3404 # commit
3407 # commit
3405 node = repo.commit(text=message, user=user,
3408 node = repo.commit(text=message, user=user,
3406 date=date, extra=extra, editor=editor)
3409 date=date, extra=extra, editor=editor)
3407 if node is None:
3410 if node is None:
3408 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3411 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3409 else:
3412 else:
3410 current = repo[node]
3413 current = repo[node]
3411 finally:
3414 finally:
3412 wlock.release()
3415 wlock.release()
3413
3416
3414 # remove state when we complete successfully
3417 # remove state when we complete successfully
3415 if not opts.get('dry_run'):
3418 if not opts.get('dry_run'):
3416 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3419 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3417
3420
3418 return 0
3421 return 0
3419
3422
3420 @command('grep',
3423 @command('grep',
3421 [('0', 'print0', None, _('end fields with NUL')),
3424 [('0', 'print0', None, _('end fields with NUL')),
3422 ('', 'all', None, _('print all revisions that match')),
3425 ('', 'all', None, _('print all revisions that match')),
3423 ('a', 'text', None, _('treat all files as text')),
3426 ('a', 'text', None, _('treat all files as text')),
3424 ('f', 'follow', None,
3427 ('f', 'follow', None,
3425 _('follow changeset history,'
3428 _('follow changeset history,'
3426 ' or file history across copies and renames')),
3429 ' or file history across copies and renames')),
3427 ('i', 'ignore-case', None, _('ignore case when matching')),
3430 ('i', 'ignore-case', None, _('ignore case when matching')),
3428 ('l', 'files-with-matches', None,
3431 ('l', 'files-with-matches', None,
3429 _('print only filenames and revisions that match')),
3432 _('print only filenames and revisions that match')),
3430 ('n', 'line-number', None, _('print matching line numbers')),
3433 ('n', 'line-number', None, _('print matching line numbers')),
3431 ('r', 'rev', [],
3434 ('r', 'rev', [],
3432 _('only search files changed within revision range'), _('REV')),
3435 _('only search files changed within revision range'), _('REV')),
3433 ('u', 'user', None, _('list the author (long with -v)')),
3436 ('u', 'user', None, _('list the author (long with -v)')),
3434 ('d', 'date', None, _('list the date (short with -q)')),
3437 ('d', 'date', None, _('list the date (short with -q)')),
3435 ] + walkopts,
3438 ] + walkopts,
3436 _('[OPTION]... PATTERN [FILE]...'),
3439 _('[OPTION]... PATTERN [FILE]...'),
3437 inferrepo=True)
3440 inferrepo=True)
3438 def grep(ui, repo, pattern, *pats, **opts):
3441 def grep(ui, repo, pattern, *pats, **opts):
3439 """search for a pattern in specified files and revisions
3442 """search for a pattern in specified files and revisions
3440
3443
3441 Search revisions of files for a regular expression.
3444 Search revisions of files for a regular expression.
3442
3445
3443 This command behaves differently than Unix grep. It only accepts
3446 This command behaves differently than Unix grep. It only accepts
3444 Python/Perl regexps. It searches repository history, not the
3447 Python/Perl regexps. It searches repository history, not the
3445 working directory. It always prints the revision number in which a
3448 working directory. It always prints the revision number in which a
3446 match appears.
3449 match appears.
3447
3450
3448 By default, grep only prints output for the first revision of a
3451 By default, grep only prints output for the first revision of a
3449 file in which it finds a match. To get it to print every revision
3452 file in which it finds a match. To get it to print every revision
3450 that contains a change in match status ("-" for a match that
3453 that contains a change in match status ("-" for a match that
3451 becomes a non-match, or "+" for a non-match that becomes a match),
3454 becomes a non-match, or "+" for a non-match that becomes a match),
3452 use the --all flag.
3455 use the --all flag.
3453
3456
3454 Returns 0 if a match is found, 1 otherwise.
3457 Returns 0 if a match is found, 1 otherwise.
3455 """
3458 """
3456 reflags = re.M
3459 reflags = re.M
3457 if opts.get('ignore_case'):
3460 if opts.get('ignore_case'):
3458 reflags |= re.I
3461 reflags |= re.I
3459 try:
3462 try:
3460 regexp = util.re.compile(pattern, reflags)
3463 regexp = util.re.compile(pattern, reflags)
3461 except re.error, inst:
3464 except re.error, inst:
3462 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3465 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3463 return 1
3466 return 1
3464 sep, eol = ':', '\n'
3467 sep, eol = ':', '\n'
3465 if opts.get('print0'):
3468 if opts.get('print0'):
3466 sep = eol = '\0'
3469 sep = eol = '\0'
3467
3470
3468 getfile = util.lrucachefunc(repo.file)
3471 getfile = util.lrucachefunc(repo.file)
3469
3472
3470 def matchlines(body):
3473 def matchlines(body):
3471 begin = 0
3474 begin = 0
3472 linenum = 0
3475 linenum = 0
3473 while begin < len(body):
3476 while begin < len(body):
3474 match = regexp.search(body, begin)
3477 match = regexp.search(body, begin)
3475 if not match:
3478 if not match:
3476 break
3479 break
3477 mstart, mend = match.span()
3480 mstart, mend = match.span()
3478 linenum += body.count('\n', begin, mstart) + 1
3481 linenum += body.count('\n', begin, mstart) + 1
3479 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3482 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3480 begin = body.find('\n', mend) + 1 or len(body) + 1
3483 begin = body.find('\n', mend) + 1 or len(body) + 1
3481 lend = begin - 1
3484 lend = begin - 1
3482 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3485 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3483
3486
3484 class linestate(object):
3487 class linestate(object):
3485 def __init__(self, line, linenum, colstart, colend):
3488 def __init__(self, line, linenum, colstart, colend):
3486 self.line = line
3489 self.line = line
3487 self.linenum = linenum
3490 self.linenum = linenum
3488 self.colstart = colstart
3491 self.colstart = colstart
3489 self.colend = colend
3492 self.colend = colend
3490
3493
3491 def __hash__(self):
3494 def __hash__(self):
3492 return hash((self.linenum, self.line))
3495 return hash((self.linenum, self.line))
3493
3496
3494 def __eq__(self, other):
3497 def __eq__(self, other):
3495 return self.line == other.line
3498 return self.line == other.line
3496
3499
3497 def __iter__(self):
3500 def __iter__(self):
3498 yield (self.line[:self.colstart], '')
3501 yield (self.line[:self.colstart], '')
3499 yield (self.line[self.colstart:self.colend], 'grep.match')
3502 yield (self.line[self.colstart:self.colend], 'grep.match')
3500 rest = self.line[self.colend:]
3503 rest = self.line[self.colend:]
3501 while rest != '':
3504 while rest != '':
3502 match = regexp.search(rest)
3505 match = regexp.search(rest)
3503 if not match:
3506 if not match:
3504 yield (rest, '')
3507 yield (rest, '')
3505 break
3508 break
3506 mstart, mend = match.span()
3509 mstart, mend = match.span()
3507 yield (rest[:mstart], '')
3510 yield (rest[:mstart], '')
3508 yield (rest[mstart:mend], 'grep.match')
3511 yield (rest[mstart:mend], 'grep.match')
3509 rest = rest[mend:]
3512 rest = rest[mend:]
3510
3513
3511 matches = {}
3514 matches = {}
3512 copies = {}
3515 copies = {}
3513 def grepbody(fn, rev, body):
3516 def grepbody(fn, rev, body):
3514 matches[rev].setdefault(fn, [])
3517 matches[rev].setdefault(fn, [])
3515 m = matches[rev][fn]
3518 m = matches[rev][fn]
3516 for lnum, cstart, cend, line in matchlines(body):
3519 for lnum, cstart, cend, line in matchlines(body):
3517 s = linestate(line, lnum, cstart, cend)
3520 s = linestate(line, lnum, cstart, cend)
3518 m.append(s)
3521 m.append(s)
3519
3522
3520 def difflinestates(a, b):
3523 def difflinestates(a, b):
3521 sm = difflib.SequenceMatcher(None, a, b)
3524 sm = difflib.SequenceMatcher(None, a, b)
3522 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3525 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3523 if tag == 'insert':
3526 if tag == 'insert':
3524 for i in xrange(blo, bhi):
3527 for i in xrange(blo, bhi):
3525 yield ('+', b[i])
3528 yield ('+', b[i])
3526 elif tag == 'delete':
3529 elif tag == 'delete':
3527 for i in xrange(alo, ahi):
3530 for i in xrange(alo, ahi):
3528 yield ('-', a[i])
3531 yield ('-', a[i])
3529 elif tag == 'replace':
3532 elif tag == 'replace':
3530 for i in xrange(alo, ahi):
3533 for i in xrange(alo, ahi):
3531 yield ('-', a[i])
3534 yield ('-', a[i])
3532 for i in xrange(blo, bhi):
3535 for i in xrange(blo, bhi):
3533 yield ('+', b[i])
3536 yield ('+', b[i])
3534
3537
3535 def display(fn, ctx, pstates, states):
3538 def display(fn, ctx, pstates, states):
3536 rev = ctx.rev()
3539 rev = ctx.rev()
3537 datefunc = ui.quiet and util.shortdate or util.datestr
3540 datefunc = ui.quiet and util.shortdate or util.datestr
3538 found = False
3541 found = False
3539 @util.cachefunc
3542 @util.cachefunc
3540 def binary():
3543 def binary():
3541 flog = getfile(fn)
3544 flog = getfile(fn)
3542 return util.binary(flog.read(ctx.filenode(fn)))
3545 return util.binary(flog.read(ctx.filenode(fn)))
3543
3546
3544 if opts.get('all'):
3547 if opts.get('all'):
3545 iter = difflinestates(pstates, states)
3548 iter = difflinestates(pstates, states)
3546 else:
3549 else:
3547 iter = [('', l) for l in states]
3550 iter = [('', l) for l in states]
3548 for change, l in iter:
3551 for change, l in iter:
3549 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3552 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3550
3553
3551 if opts.get('line_number'):
3554 if opts.get('line_number'):
3552 cols.append((str(l.linenum), 'grep.linenumber'))
3555 cols.append((str(l.linenum), 'grep.linenumber'))
3553 if opts.get('all'):
3556 if opts.get('all'):
3554 cols.append((change, 'grep.change'))
3557 cols.append((change, 'grep.change'))
3555 if opts.get('user'):
3558 if opts.get('user'):
3556 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3559 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3557 if opts.get('date'):
3560 if opts.get('date'):
3558 cols.append((datefunc(ctx.date()), 'grep.date'))
3561 cols.append((datefunc(ctx.date()), 'grep.date'))
3559 for col, label in cols[:-1]:
3562 for col, label in cols[:-1]:
3560 ui.write(col, label=label)
3563 ui.write(col, label=label)
3561 ui.write(sep, label='grep.sep')
3564 ui.write(sep, label='grep.sep')
3562 ui.write(cols[-1][0], label=cols[-1][1])
3565 ui.write(cols[-1][0], label=cols[-1][1])
3563 if not opts.get('files_with_matches'):
3566 if not opts.get('files_with_matches'):
3564 ui.write(sep, label='grep.sep')
3567 ui.write(sep, label='grep.sep')
3565 if not opts.get('text') and binary():
3568 if not opts.get('text') and binary():
3566 ui.write(" Binary file matches")
3569 ui.write(" Binary file matches")
3567 else:
3570 else:
3568 for s, label in l:
3571 for s, label in l:
3569 ui.write(s, label=label)
3572 ui.write(s, label=label)
3570 ui.write(eol)
3573 ui.write(eol)
3571 found = True
3574 found = True
3572 if opts.get('files_with_matches'):
3575 if opts.get('files_with_matches'):
3573 break
3576 break
3574 return found
3577 return found
3575
3578
3576 skip = {}
3579 skip = {}
3577 revfiles = {}
3580 revfiles = {}
3578 matchfn = scmutil.match(repo[None], pats, opts)
3581 matchfn = scmutil.match(repo[None], pats, opts)
3579 found = False
3582 found = False
3580 follow = opts.get('follow')
3583 follow = opts.get('follow')
3581
3584
3582 def prep(ctx, fns):
3585 def prep(ctx, fns):
3583 rev = ctx.rev()
3586 rev = ctx.rev()
3584 pctx = ctx.p1()
3587 pctx = ctx.p1()
3585 parent = pctx.rev()
3588 parent = pctx.rev()
3586 matches.setdefault(rev, {})
3589 matches.setdefault(rev, {})
3587 matches.setdefault(parent, {})
3590 matches.setdefault(parent, {})
3588 files = revfiles.setdefault(rev, [])
3591 files = revfiles.setdefault(rev, [])
3589 for fn in fns:
3592 for fn in fns:
3590 flog = getfile(fn)
3593 flog = getfile(fn)
3591 try:
3594 try:
3592 fnode = ctx.filenode(fn)
3595 fnode = ctx.filenode(fn)
3593 except error.LookupError:
3596 except error.LookupError:
3594 continue
3597 continue
3595
3598
3596 copied = flog.renamed(fnode)
3599 copied = flog.renamed(fnode)
3597 copy = follow and copied and copied[0]
3600 copy = follow and copied and copied[0]
3598 if copy:
3601 if copy:
3599 copies.setdefault(rev, {})[fn] = copy
3602 copies.setdefault(rev, {})[fn] = copy
3600 if fn in skip:
3603 if fn in skip:
3601 if copy:
3604 if copy:
3602 skip[copy] = True
3605 skip[copy] = True
3603 continue
3606 continue
3604 files.append(fn)
3607 files.append(fn)
3605
3608
3606 if fn not in matches[rev]:
3609 if fn not in matches[rev]:
3607 grepbody(fn, rev, flog.read(fnode))
3610 grepbody(fn, rev, flog.read(fnode))
3608
3611
3609 pfn = copy or fn
3612 pfn = copy or fn
3610 if pfn not in matches[parent]:
3613 if pfn not in matches[parent]:
3611 try:
3614 try:
3612 fnode = pctx.filenode(pfn)
3615 fnode = pctx.filenode(pfn)
3613 grepbody(pfn, parent, flog.read(fnode))
3616 grepbody(pfn, parent, flog.read(fnode))
3614 except error.LookupError:
3617 except error.LookupError:
3615 pass
3618 pass
3616
3619
3617 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3620 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3618 rev = ctx.rev()
3621 rev = ctx.rev()
3619 parent = ctx.p1().rev()
3622 parent = ctx.p1().rev()
3620 for fn in sorted(revfiles.get(rev, [])):
3623 for fn in sorted(revfiles.get(rev, [])):
3621 states = matches[rev][fn]
3624 states = matches[rev][fn]
3622 copy = copies.get(rev, {}).get(fn)
3625 copy = copies.get(rev, {}).get(fn)
3623 if fn in skip:
3626 if fn in skip:
3624 if copy:
3627 if copy:
3625 skip[copy] = True
3628 skip[copy] = True
3626 continue
3629 continue
3627 pstates = matches.get(parent, {}).get(copy or fn, [])
3630 pstates = matches.get(parent, {}).get(copy or fn, [])
3628 if pstates or states:
3631 if pstates or states:
3629 r = display(fn, ctx, pstates, states)
3632 r = display(fn, ctx, pstates, states)
3630 found = found or r
3633 found = found or r
3631 if r and not opts.get('all'):
3634 if r and not opts.get('all'):
3632 skip[fn] = True
3635 skip[fn] = True
3633 if copy:
3636 if copy:
3634 skip[copy] = True
3637 skip[copy] = True
3635 del matches[rev]
3638 del matches[rev]
3636 del revfiles[rev]
3639 del revfiles[rev]
3637
3640
3638 return not found
3641 return not found
3639
3642
3640 @command('heads',
3643 @command('heads',
3641 [('r', 'rev', '',
3644 [('r', 'rev', '',
3642 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3645 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3643 ('t', 'topo', False, _('show topological heads only')),
3646 ('t', 'topo', False, _('show topological heads only')),
3644 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3647 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3645 ('c', 'closed', False, _('show normal and closed branch heads')),
3648 ('c', 'closed', False, _('show normal and closed branch heads')),
3646 ] + templateopts,
3649 ] + templateopts,
3647 _('[-ct] [-r STARTREV] [REV]...'))
3650 _('[-ct] [-r STARTREV] [REV]...'))
3648 def heads(ui, repo, *branchrevs, **opts):
3651 def heads(ui, repo, *branchrevs, **opts):
3649 """show branch heads
3652 """show branch heads
3650
3653
3651 With no arguments, show all open branch heads in the repository.
3654 With no arguments, show all open branch heads in the repository.
3652 Branch heads are changesets that have no descendants on the
3655 Branch heads are changesets that have no descendants on the
3653 same branch. They are where development generally takes place and
3656 same branch. They are where development generally takes place and
3654 are the usual targets for update and merge operations.
3657 are the usual targets for update and merge operations.
3655
3658
3656 If one or more REVs are given, only open branch heads on the
3659 If one or more REVs are given, only open branch heads on the
3657 branches associated with the specified changesets are shown. This
3660 branches associated with the specified changesets are shown. This
3658 means that you can use :hg:`heads .` to see the heads on the
3661 means that you can use :hg:`heads .` to see the heads on the
3659 currently checked-out branch.
3662 currently checked-out branch.
3660
3663
3661 If -c/--closed is specified, also show branch heads marked closed
3664 If -c/--closed is specified, also show branch heads marked closed
3662 (see :hg:`commit --close-branch`).
3665 (see :hg:`commit --close-branch`).
3663
3666
3664 If STARTREV is specified, only those heads that are descendants of
3667 If STARTREV is specified, only those heads that are descendants of
3665 STARTREV will be displayed.
3668 STARTREV will be displayed.
3666
3669
3667 If -t/--topo is specified, named branch mechanics will be ignored and only
3670 If -t/--topo is specified, named branch mechanics will be ignored and only
3668 topological heads (changesets with no children) will be shown.
3671 topological heads (changesets with no children) will be shown.
3669
3672
3670 Returns 0 if matching heads are found, 1 if not.
3673 Returns 0 if matching heads are found, 1 if not.
3671 """
3674 """
3672
3675
3673 start = None
3676 start = None
3674 if 'rev' in opts:
3677 if 'rev' in opts:
3675 start = scmutil.revsingle(repo, opts['rev'], None).node()
3678 start = scmutil.revsingle(repo, opts['rev'], None).node()
3676
3679
3677 if opts.get('topo'):
3680 if opts.get('topo'):
3678 heads = [repo[h] for h in repo.heads(start)]
3681 heads = [repo[h] for h in repo.heads(start)]
3679 else:
3682 else:
3680 heads = []
3683 heads = []
3681 for branch in repo.branchmap():
3684 for branch in repo.branchmap():
3682 heads += repo.branchheads(branch, start, opts.get('closed'))
3685 heads += repo.branchheads(branch, start, opts.get('closed'))
3683 heads = [repo[h] for h in heads]
3686 heads = [repo[h] for h in heads]
3684
3687
3685 if branchrevs:
3688 if branchrevs:
3686 branches = set(repo[br].branch() for br in branchrevs)
3689 branches = set(repo[br].branch() for br in branchrevs)
3687 heads = [h for h in heads if h.branch() in branches]
3690 heads = [h for h in heads if h.branch() in branches]
3688
3691
3689 if opts.get('active') and branchrevs:
3692 if opts.get('active') and branchrevs:
3690 dagheads = repo.heads(start)
3693 dagheads = repo.heads(start)
3691 heads = [h for h in heads if h.node() in dagheads]
3694 heads = [h for h in heads if h.node() in dagheads]
3692
3695
3693 if branchrevs:
3696 if branchrevs:
3694 haveheads = set(h.branch() for h in heads)
3697 haveheads = set(h.branch() for h in heads)
3695 if branches - haveheads:
3698 if branches - haveheads:
3696 headless = ', '.join(b for b in branches - haveheads)
3699 headless = ', '.join(b for b in branches - haveheads)
3697 msg = _('no open branch heads found on branches %s')
3700 msg = _('no open branch heads found on branches %s')
3698 if opts.get('rev'):
3701 if opts.get('rev'):
3699 msg += _(' (started at %s)') % opts['rev']
3702 msg += _(' (started at %s)') % opts['rev']
3700 ui.warn((msg + '\n') % headless)
3703 ui.warn((msg + '\n') % headless)
3701
3704
3702 if not heads:
3705 if not heads:
3703 return 1
3706 return 1
3704
3707
3705 heads = sorted(heads, key=lambda x: -x.rev())
3708 heads = sorted(heads, key=lambda x: -x.rev())
3706 displayer = cmdutil.show_changeset(ui, repo, opts)
3709 displayer = cmdutil.show_changeset(ui, repo, opts)
3707 for ctx in heads:
3710 for ctx in heads:
3708 displayer.show(ctx)
3711 displayer.show(ctx)
3709 displayer.close()
3712 displayer.close()
3710
3713
3711 @command('help',
3714 @command('help',
3712 [('e', 'extension', None, _('show only help for extensions')),
3715 [('e', 'extension', None, _('show only help for extensions')),
3713 ('c', 'command', None, _('show only help for commands')),
3716 ('c', 'command', None, _('show only help for commands')),
3714 ('k', 'keyword', '', _('show topics matching keyword')),
3717 ('k', 'keyword', '', _('show topics matching keyword')),
3715 ],
3718 ],
3716 _('[-ec] [TOPIC]'),
3719 _('[-ec] [TOPIC]'),
3717 norepo=True)
3720 norepo=True)
3718 def help_(ui, name=None, **opts):
3721 def help_(ui, name=None, **opts):
3719 """show help for a given topic or a help overview
3722 """show help for a given topic or a help overview
3720
3723
3721 With no arguments, print a list of commands with short help messages.
3724 With no arguments, print a list of commands with short help messages.
3722
3725
3723 Given a topic, extension, or command name, print help for that
3726 Given a topic, extension, or command name, print help for that
3724 topic.
3727 topic.
3725
3728
3726 Returns 0 if successful.
3729 Returns 0 if successful.
3727 """
3730 """
3728
3731
3729 textwidth = min(ui.termwidth(), 80) - 2
3732 textwidth = min(ui.termwidth(), 80) - 2
3730
3733
3731 keep = ui.verbose and ['verbose'] or []
3734 keep = ui.verbose and ['verbose'] or []
3732 text = help.help_(ui, name, **opts)
3735 text = help.help_(ui, name, **opts)
3733
3736
3734 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3737 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3735 if 'verbose' in pruned:
3738 if 'verbose' in pruned:
3736 keep.append('omitted')
3739 keep.append('omitted')
3737 else:
3740 else:
3738 keep.append('notomitted')
3741 keep.append('notomitted')
3739 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3742 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3740 ui.write(formatted)
3743 ui.write(formatted)
3741
3744
3742
3745
3743 @command('identify|id',
3746 @command('identify|id',
3744 [('r', 'rev', '',
3747 [('r', 'rev', '',
3745 _('identify the specified revision'), _('REV')),
3748 _('identify the specified revision'), _('REV')),
3746 ('n', 'num', None, _('show local revision number')),
3749 ('n', 'num', None, _('show local revision number')),
3747 ('i', 'id', None, _('show global revision id')),
3750 ('i', 'id', None, _('show global revision id')),
3748 ('b', 'branch', None, _('show branch')),
3751 ('b', 'branch', None, _('show branch')),
3749 ('t', 'tags', None, _('show tags')),
3752 ('t', 'tags', None, _('show tags')),
3750 ('B', 'bookmarks', None, _('show bookmarks')),
3753 ('B', 'bookmarks', None, _('show bookmarks')),
3751 ] + remoteopts,
3754 ] + remoteopts,
3752 _('[-nibtB] [-r REV] [SOURCE]'),
3755 _('[-nibtB] [-r REV] [SOURCE]'),
3753 optionalrepo=True)
3756 optionalrepo=True)
3754 def identify(ui, repo, source=None, rev=None,
3757 def identify(ui, repo, source=None, rev=None,
3755 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3758 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3756 """identify the working copy or specified revision
3759 """identify the working copy or specified revision
3757
3760
3758 Print a summary identifying the repository state at REV using one or
3761 Print a summary identifying the repository state at REV using one or
3759 two parent hash identifiers, followed by a "+" if the working
3762 two parent hash identifiers, followed by a "+" if the working
3760 directory has uncommitted changes, the branch name (if not default),
3763 directory has uncommitted changes, the branch name (if not default),
3761 a list of tags, and a list of bookmarks.
3764 a list of tags, and a list of bookmarks.
3762
3765
3763 When REV is not given, print a summary of the current state of the
3766 When REV is not given, print a summary of the current state of the
3764 repository.
3767 repository.
3765
3768
3766 Specifying a path to a repository root or Mercurial bundle will
3769 Specifying a path to a repository root or Mercurial bundle will
3767 cause lookup to operate on that repository/bundle.
3770 cause lookup to operate on that repository/bundle.
3768
3771
3769 .. container:: verbose
3772 .. container:: verbose
3770
3773
3771 Examples:
3774 Examples:
3772
3775
3773 - generate a build identifier for the working directory::
3776 - generate a build identifier for the working directory::
3774
3777
3775 hg id --id > build-id.dat
3778 hg id --id > build-id.dat
3776
3779
3777 - find the revision corresponding to a tag::
3780 - find the revision corresponding to a tag::
3778
3781
3779 hg id -n -r 1.3
3782 hg id -n -r 1.3
3780
3783
3781 - check the most recent revision of a remote repository::
3784 - check the most recent revision of a remote repository::
3782
3785
3783 hg id -r tip http://selenic.com/hg/
3786 hg id -r tip http://selenic.com/hg/
3784
3787
3785 Returns 0 if successful.
3788 Returns 0 if successful.
3786 """
3789 """
3787
3790
3788 if not repo and not source:
3791 if not repo and not source:
3789 raise util.Abort(_("there is no Mercurial repository here "
3792 raise util.Abort(_("there is no Mercurial repository here "
3790 "(.hg not found)"))
3793 "(.hg not found)"))
3791
3794
3792 hexfunc = ui.debugflag and hex or short
3795 hexfunc = ui.debugflag and hex or short
3793 default = not (num or id or branch or tags or bookmarks)
3796 default = not (num or id or branch or tags or bookmarks)
3794 output = []
3797 output = []
3795 revs = []
3798 revs = []
3796
3799
3797 if source:
3800 if source:
3798 source, branches = hg.parseurl(ui.expandpath(source))
3801 source, branches = hg.parseurl(ui.expandpath(source))
3799 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3802 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3800 repo = peer.local()
3803 repo = peer.local()
3801 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3804 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3802
3805
3803 if not repo:
3806 if not repo:
3804 if num or branch or tags:
3807 if num or branch or tags:
3805 raise util.Abort(
3808 raise util.Abort(
3806 _("can't query remote revision number, branch, or tags"))
3809 _("can't query remote revision number, branch, or tags"))
3807 if not rev and revs:
3810 if not rev and revs:
3808 rev = revs[0]
3811 rev = revs[0]
3809 if not rev:
3812 if not rev:
3810 rev = "tip"
3813 rev = "tip"
3811
3814
3812 remoterev = peer.lookup(rev)
3815 remoterev = peer.lookup(rev)
3813 if default or id:
3816 if default or id:
3814 output = [hexfunc(remoterev)]
3817 output = [hexfunc(remoterev)]
3815
3818
3816 def getbms():
3819 def getbms():
3817 bms = []
3820 bms = []
3818
3821
3819 if 'bookmarks' in peer.listkeys('namespaces'):
3822 if 'bookmarks' in peer.listkeys('namespaces'):
3820 hexremoterev = hex(remoterev)
3823 hexremoterev = hex(remoterev)
3821 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3824 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3822 if bmr == hexremoterev]
3825 if bmr == hexremoterev]
3823
3826
3824 return sorted(bms)
3827 return sorted(bms)
3825
3828
3826 if bookmarks:
3829 if bookmarks:
3827 output.extend(getbms())
3830 output.extend(getbms())
3828 elif default and not ui.quiet:
3831 elif default and not ui.quiet:
3829 # multiple bookmarks for a single parent separated by '/'
3832 # multiple bookmarks for a single parent separated by '/'
3830 bm = '/'.join(getbms())
3833 bm = '/'.join(getbms())
3831 if bm:
3834 if bm:
3832 output.append(bm)
3835 output.append(bm)
3833 else:
3836 else:
3834 if not rev:
3837 if not rev:
3835 ctx = repo[None]
3838 ctx = repo[None]
3836 parents = ctx.parents()
3839 parents = ctx.parents()
3837 changed = ""
3840 changed = ""
3838 if default or id or num:
3841 if default or id or num:
3839 if (util.any(repo.status())
3842 if (util.any(repo.status())
3840 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3843 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3841 changed = '+'
3844 changed = '+'
3842 if default or id:
3845 if default or id:
3843 output = ["%s%s" %
3846 output = ["%s%s" %
3844 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3847 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3845 if num:
3848 if num:
3846 output.append("%s%s" %
3849 output.append("%s%s" %
3847 ('+'.join([str(p.rev()) for p in parents]), changed))
3850 ('+'.join([str(p.rev()) for p in parents]), changed))
3848 else:
3851 else:
3849 ctx = scmutil.revsingle(repo, rev)
3852 ctx = scmutil.revsingle(repo, rev)
3850 if default or id:
3853 if default or id:
3851 output = [hexfunc(ctx.node())]
3854 output = [hexfunc(ctx.node())]
3852 if num:
3855 if num:
3853 output.append(str(ctx.rev()))
3856 output.append(str(ctx.rev()))
3854
3857
3855 if default and not ui.quiet:
3858 if default and not ui.quiet:
3856 b = ctx.branch()
3859 b = ctx.branch()
3857 if b != 'default':
3860 if b != 'default':
3858 output.append("(%s)" % b)
3861 output.append("(%s)" % b)
3859
3862
3860 # multiple tags for a single parent separated by '/'
3863 # multiple tags for a single parent separated by '/'
3861 t = '/'.join(ctx.tags())
3864 t = '/'.join(ctx.tags())
3862 if t:
3865 if t:
3863 output.append(t)
3866 output.append(t)
3864
3867
3865 # multiple bookmarks for a single parent separated by '/'
3868 # multiple bookmarks for a single parent separated by '/'
3866 bm = '/'.join(ctx.bookmarks())
3869 bm = '/'.join(ctx.bookmarks())
3867 if bm:
3870 if bm:
3868 output.append(bm)
3871 output.append(bm)
3869 else:
3872 else:
3870 if branch:
3873 if branch:
3871 output.append(ctx.branch())
3874 output.append(ctx.branch())
3872
3875
3873 if tags:
3876 if tags:
3874 output.extend(ctx.tags())
3877 output.extend(ctx.tags())
3875
3878
3876 if bookmarks:
3879 if bookmarks:
3877 output.extend(ctx.bookmarks())
3880 output.extend(ctx.bookmarks())
3878
3881
3879 ui.write("%s\n" % ' '.join(output))
3882 ui.write("%s\n" % ' '.join(output))
3880
3883
3881 @command('import|patch',
3884 @command('import|patch',
3882 [('p', 'strip', 1,
3885 [('p', 'strip', 1,
3883 _('directory strip option for patch. This has the same '
3886 _('directory strip option for patch. This has the same '
3884 'meaning as the corresponding patch option'), _('NUM')),
3887 'meaning as the corresponding patch option'), _('NUM')),
3885 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3888 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3886 ('e', 'edit', False, _('invoke editor on commit messages')),
3889 ('e', 'edit', False, _('invoke editor on commit messages')),
3887 ('f', 'force', None,
3890 ('f', 'force', None,
3888 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3891 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3889 ('', 'no-commit', None,
3892 ('', 'no-commit', None,
3890 _("don't commit, just update the working directory")),
3893 _("don't commit, just update the working directory")),
3891 ('', 'bypass', None,
3894 ('', 'bypass', None,
3892 _("apply patch without touching the working directory")),
3895 _("apply patch without touching the working directory")),
3893 ('', 'partial', None,
3896 ('', 'partial', None,
3894 _('commit even if some hunks fail')),
3897 _('commit even if some hunks fail')),
3895 ('', 'exact', None,
3898 ('', 'exact', None,
3896 _('apply patch to the nodes from which it was generated')),
3899 _('apply patch to the nodes from which it was generated')),
3897 ('', 'import-branch', None,
3900 ('', 'import-branch', None,
3898 _('use any branch information in patch (implied by --exact)'))] +
3901 _('use any branch information in patch (implied by --exact)'))] +
3899 commitopts + commitopts2 + similarityopts,
3902 commitopts + commitopts2 + similarityopts,
3900 _('[OPTION]... PATCH...'))
3903 _('[OPTION]... PATCH...'))
3901 def import_(ui, repo, patch1=None, *patches, **opts):
3904 def import_(ui, repo, patch1=None, *patches, **opts):
3902 """import an ordered set of patches
3905 """import an ordered set of patches
3903
3906
3904 Import a list of patches and commit them individually (unless
3907 Import a list of patches and commit them individually (unless
3905 --no-commit is specified).
3908 --no-commit is specified).
3906
3909
3907 Because import first applies changes to the working directory,
3910 Because import first applies changes to the working directory,
3908 import will abort if there are outstanding changes.
3911 import will abort if there are outstanding changes.
3909
3912
3910 You can import a patch straight from a mail message. Even patches
3913 You can import a patch straight from a mail message. Even patches
3911 as attachments work (to use the body part, it must have type
3914 as attachments work (to use the body part, it must have type
3912 text/plain or text/x-patch). From and Subject headers of email
3915 text/plain or text/x-patch). From and Subject headers of email
3913 message are used as default committer and commit message. All
3916 message are used as default committer and commit message. All
3914 text/plain body parts before first diff are added to commit
3917 text/plain body parts before first diff are added to commit
3915 message.
3918 message.
3916
3919
3917 If the imported patch was generated by :hg:`export`, user and
3920 If the imported patch was generated by :hg:`export`, user and
3918 description from patch override values from message headers and
3921 description from patch override values from message headers and
3919 body. Values given on command line with -m/--message and -u/--user
3922 body. Values given on command line with -m/--message and -u/--user
3920 override these.
3923 override these.
3921
3924
3922 If --exact is specified, import will set the working directory to
3925 If --exact is specified, import will set the working directory to
3923 the parent of each patch before applying it, and will abort if the
3926 the parent of each patch before applying it, and will abort if the
3924 resulting changeset has a different ID than the one recorded in
3927 resulting changeset has a different ID than the one recorded in
3925 the patch. This may happen due to character set problems or other
3928 the patch. This may happen due to character set problems or other
3926 deficiencies in the text patch format.
3929 deficiencies in the text patch format.
3927
3930
3928 Use --bypass to apply and commit patches directly to the
3931 Use --bypass to apply and commit patches directly to the
3929 repository, not touching the working directory. Without --exact,
3932 repository, not touching the working directory. Without --exact,
3930 patches will be applied on top of the working directory parent
3933 patches will be applied on top of the working directory parent
3931 revision.
3934 revision.
3932
3935
3933 With -s/--similarity, hg will attempt to discover renames and
3936 With -s/--similarity, hg will attempt to discover renames and
3934 copies in the patch in the same way as :hg:`addremove`.
3937 copies in the patch in the same way as :hg:`addremove`.
3935
3938
3936 Use --partial to ensure a changeset will be created from the patch
3939 Use --partial to ensure a changeset will be created from the patch
3937 even if some hunks fail to apply. Hunks that fail to apply will be
3940 even if some hunks fail to apply. Hunks that fail to apply will be
3938 written to a <target-file>.rej file. Conflicts can then be resolved
3941 written to a <target-file>.rej file. Conflicts can then be resolved
3939 by hand before :hg:`commit --amend` is run to update the created
3942 by hand before :hg:`commit --amend` is run to update the created
3940 changeset. This flag exists to let people import patches that
3943 changeset. This flag exists to let people import patches that
3941 partially apply without losing the associated metadata (author,
3944 partially apply without losing the associated metadata (author,
3942 date, description, ...). Note that when none of the hunk applies
3945 date, description, ...). Note that when none of the hunk applies
3943 cleanly, :hg:`import --partial` will create an empty changeset,
3946 cleanly, :hg:`import --partial` will create an empty changeset,
3944 importing only the patch metadata.
3947 importing only the patch metadata.
3945
3948
3946 To read a patch from standard input, use "-" as the patch name. If
3949 To read a patch from standard input, use "-" as the patch name. If
3947 a URL is specified, the patch will be downloaded from it.
3950 a URL is specified, the patch will be downloaded from it.
3948 See :hg:`help dates` for a list of formats valid for -d/--date.
3951 See :hg:`help dates` for a list of formats valid for -d/--date.
3949
3952
3950 .. container:: verbose
3953 .. container:: verbose
3951
3954
3952 Examples:
3955 Examples:
3953
3956
3954 - import a traditional patch from a website and detect renames::
3957 - import a traditional patch from a website and detect renames::
3955
3958
3956 hg import -s 80 http://example.com/bugfix.patch
3959 hg import -s 80 http://example.com/bugfix.patch
3957
3960
3958 - import a changeset from an hgweb server::
3961 - import a changeset from an hgweb server::
3959
3962
3960 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3963 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3961
3964
3962 - import all the patches in an Unix-style mbox::
3965 - import all the patches in an Unix-style mbox::
3963
3966
3964 hg import incoming-patches.mbox
3967 hg import incoming-patches.mbox
3965
3968
3966 - attempt to exactly restore an exported changeset (not always
3969 - attempt to exactly restore an exported changeset (not always
3967 possible)::
3970 possible)::
3968
3971
3969 hg import --exact proposed-fix.patch
3972 hg import --exact proposed-fix.patch
3970
3973
3971 Returns 0 on success, 1 on partial success (see --partial).
3974 Returns 0 on success, 1 on partial success (see --partial).
3972 """
3975 """
3973
3976
3974 if not patch1:
3977 if not patch1:
3975 raise util.Abort(_('need at least one patch to import'))
3978 raise util.Abort(_('need at least one patch to import'))
3976
3979
3977 patches = (patch1,) + patches
3980 patches = (patch1,) + patches
3978
3981
3979 date = opts.get('date')
3982 date = opts.get('date')
3980 if date:
3983 if date:
3981 opts['date'] = util.parsedate(date)
3984 opts['date'] = util.parsedate(date)
3982
3985
3983 update = not opts.get('bypass')
3986 update = not opts.get('bypass')
3984 if not update and opts.get('no_commit'):
3987 if not update and opts.get('no_commit'):
3985 raise util.Abort(_('cannot use --no-commit with --bypass'))
3988 raise util.Abort(_('cannot use --no-commit with --bypass'))
3986 try:
3989 try:
3987 sim = float(opts.get('similarity') or 0)
3990 sim = float(opts.get('similarity') or 0)
3988 except ValueError:
3991 except ValueError:
3989 raise util.Abort(_('similarity must be a number'))
3992 raise util.Abort(_('similarity must be a number'))
3990 if sim < 0 or sim > 100:
3993 if sim < 0 or sim > 100:
3991 raise util.Abort(_('similarity must be between 0 and 100'))
3994 raise util.Abort(_('similarity must be between 0 and 100'))
3992 if sim and not update:
3995 if sim and not update:
3993 raise util.Abort(_('cannot use --similarity with --bypass'))
3996 raise util.Abort(_('cannot use --similarity with --bypass'))
3994 if opts.get('exact') and opts.get('edit'):
3997 if opts.get('exact') and opts.get('edit'):
3995 raise util.Abort(_('cannot use --exact with --edit'))
3998 raise util.Abort(_('cannot use --exact with --edit'))
3996
3999
3997 if update:
4000 if update:
3998 cmdutil.checkunfinished(repo)
4001 cmdutil.checkunfinished(repo)
3999 if (opts.get('exact') or not opts.get('force')) and update:
4002 if (opts.get('exact') or not opts.get('force')) and update:
4000 cmdutil.bailifchanged(repo)
4003 cmdutil.bailifchanged(repo)
4001
4004
4002 base = opts["base"]
4005 base = opts["base"]
4003 wlock = lock = tr = None
4006 wlock = lock = tr = None
4004 msgs = []
4007 msgs = []
4005 ret = 0
4008 ret = 0
4006
4009
4007
4010
4008 try:
4011 try:
4009 try:
4012 try:
4010 wlock = repo.wlock()
4013 wlock = repo.wlock()
4011 repo.dirstate.beginparentchange()
4014 repo.dirstate.beginparentchange()
4012 if not opts.get('no_commit'):
4015 if not opts.get('no_commit'):
4013 lock = repo.lock()
4016 lock = repo.lock()
4014 tr = repo.transaction('import')
4017 tr = repo.transaction('import')
4015 parents = repo.parents()
4018 parents = repo.parents()
4016 for patchurl in patches:
4019 for patchurl in patches:
4017 if patchurl == '-':
4020 if patchurl == '-':
4018 ui.status(_('applying patch from stdin\n'))
4021 ui.status(_('applying patch from stdin\n'))
4019 patchfile = ui.fin
4022 patchfile = ui.fin
4020 patchurl = 'stdin' # for error message
4023 patchurl = 'stdin' # for error message
4021 else:
4024 else:
4022 patchurl = os.path.join(base, patchurl)
4025 patchurl = os.path.join(base, patchurl)
4023 ui.status(_('applying %s\n') % patchurl)
4026 ui.status(_('applying %s\n') % patchurl)
4024 patchfile = hg.openpath(ui, patchurl)
4027 patchfile = hg.openpath(ui, patchurl)
4025
4028
4026 haspatch = False
4029 haspatch = False
4027 for hunk in patch.split(patchfile):
4030 for hunk in patch.split(patchfile):
4028 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4031 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4029 parents, opts,
4032 parents, opts,
4030 msgs, hg.clean)
4033 msgs, hg.clean)
4031 if msg:
4034 if msg:
4032 haspatch = True
4035 haspatch = True
4033 ui.note(msg + '\n')
4036 ui.note(msg + '\n')
4034 if update or opts.get('exact'):
4037 if update or opts.get('exact'):
4035 parents = repo.parents()
4038 parents = repo.parents()
4036 else:
4039 else:
4037 parents = [repo[node]]
4040 parents = [repo[node]]
4038 if rej:
4041 if rej:
4039 ui.write_err(_("patch applied partially\n"))
4042 ui.write_err(_("patch applied partially\n"))
4040 ui.write_err(_("(fix the .rej files and run "
4043 ui.write_err(_("(fix the .rej files and run "
4041 "`hg commit --amend`)\n"))
4044 "`hg commit --amend`)\n"))
4042 ret = 1
4045 ret = 1
4043 break
4046 break
4044
4047
4045 if not haspatch:
4048 if not haspatch:
4046 raise util.Abort(_('%s: no diffs found') % patchurl)
4049 raise util.Abort(_('%s: no diffs found') % patchurl)
4047
4050
4048 if tr:
4051 if tr:
4049 tr.close()
4052 tr.close()
4050 if msgs:
4053 if msgs:
4051 repo.savecommitmessage('\n* * *\n'.join(msgs))
4054 repo.savecommitmessage('\n* * *\n'.join(msgs))
4052 repo.dirstate.endparentchange()
4055 repo.dirstate.endparentchange()
4053 return ret
4056 return ret
4054 except: # re-raises
4057 except: # re-raises
4055 # wlock.release() indirectly calls dirstate.write(): since
4058 # wlock.release() indirectly calls dirstate.write(): since
4056 # we're crashing, we do not want to change the working dir
4059 # we're crashing, we do not want to change the working dir
4057 # parent after all, so make sure it writes nothing
4060 # parent after all, so make sure it writes nothing
4058 repo.dirstate.invalidate()
4061 repo.dirstate.invalidate()
4059 raise
4062 raise
4060 finally:
4063 finally:
4061 if tr:
4064 if tr:
4062 tr.release()
4065 tr.release()
4063 release(lock, wlock)
4066 release(lock, wlock)
4064
4067
4065 @command('incoming|in',
4068 @command('incoming|in',
4066 [('f', 'force', None,
4069 [('f', 'force', None,
4067 _('run even if remote repository is unrelated')),
4070 _('run even if remote repository is unrelated')),
4068 ('n', 'newest-first', None, _('show newest record first')),
4071 ('n', 'newest-first', None, _('show newest record first')),
4069 ('', 'bundle', '',
4072 ('', 'bundle', '',
4070 _('file to store the bundles into'), _('FILE')),
4073 _('file to store the bundles into'), _('FILE')),
4071 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4074 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4072 ('B', 'bookmarks', False, _("compare bookmarks")),
4075 ('B', 'bookmarks', False, _("compare bookmarks")),
4073 ('b', 'branch', [],
4076 ('b', 'branch', [],
4074 _('a specific branch you would like to pull'), _('BRANCH')),
4077 _('a specific branch you would like to pull'), _('BRANCH')),
4075 ] + logopts + remoteopts + subrepoopts,
4078 ] + logopts + remoteopts + subrepoopts,
4076 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4079 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4077 def incoming(ui, repo, source="default", **opts):
4080 def incoming(ui, repo, source="default", **opts):
4078 """show new changesets found in source
4081 """show new changesets found in source
4079
4082
4080 Show new changesets found in the specified path/URL or the default
4083 Show new changesets found in the specified path/URL or the default
4081 pull location. These are the changesets that would have been pulled
4084 pull location. These are the changesets that would have been pulled
4082 if a pull at the time you issued this command.
4085 if a pull at the time you issued this command.
4083
4086
4084 For remote repository, using --bundle avoids downloading the
4087 For remote repository, using --bundle avoids downloading the
4085 changesets twice if the incoming is followed by a pull.
4088 changesets twice if the incoming is followed by a pull.
4086
4089
4087 See pull for valid source format details.
4090 See pull for valid source format details.
4088
4091
4089 .. container:: verbose
4092 .. container:: verbose
4090
4093
4091 Examples:
4094 Examples:
4092
4095
4093 - show incoming changes with patches and full description::
4096 - show incoming changes with patches and full description::
4094
4097
4095 hg incoming -vp
4098 hg incoming -vp
4096
4099
4097 - show incoming changes excluding merges, store a bundle::
4100 - show incoming changes excluding merges, store a bundle::
4098
4101
4099 hg in -vpM --bundle incoming.hg
4102 hg in -vpM --bundle incoming.hg
4100 hg pull incoming.hg
4103 hg pull incoming.hg
4101
4104
4102 - briefly list changes inside a bundle::
4105 - briefly list changes inside a bundle::
4103
4106
4104 hg in changes.hg -T "{desc|firstline}\\n"
4107 hg in changes.hg -T "{desc|firstline}\\n"
4105
4108
4106 Returns 0 if there are incoming changes, 1 otherwise.
4109 Returns 0 if there are incoming changes, 1 otherwise.
4107 """
4110 """
4108 if opts.get('graph'):
4111 if opts.get('graph'):
4109 cmdutil.checkunsupportedgraphflags([], opts)
4112 cmdutil.checkunsupportedgraphflags([], opts)
4110 def display(other, chlist, displayer):
4113 def display(other, chlist, displayer):
4111 revdag = cmdutil.graphrevs(other, chlist, opts)
4114 revdag = cmdutil.graphrevs(other, chlist, opts)
4112 showparents = [ctx.node() for ctx in repo[None].parents()]
4115 showparents = [ctx.node() for ctx in repo[None].parents()]
4113 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4116 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4114 graphmod.asciiedges)
4117 graphmod.asciiedges)
4115
4118
4116 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4119 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4117 return 0
4120 return 0
4118
4121
4119 if opts.get('bundle') and opts.get('subrepos'):
4122 if opts.get('bundle') and opts.get('subrepos'):
4120 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4123 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4121
4124
4122 if opts.get('bookmarks'):
4125 if opts.get('bookmarks'):
4123 source, branches = hg.parseurl(ui.expandpath(source),
4126 source, branches = hg.parseurl(ui.expandpath(source),
4124 opts.get('branch'))
4127 opts.get('branch'))
4125 other = hg.peer(repo, opts, source)
4128 other = hg.peer(repo, opts, source)
4126 if 'bookmarks' not in other.listkeys('namespaces'):
4129 if 'bookmarks' not in other.listkeys('namespaces'):
4127 ui.warn(_("remote doesn't support bookmarks\n"))
4130 ui.warn(_("remote doesn't support bookmarks\n"))
4128 return 0
4131 return 0
4129 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4132 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4130 return bookmarks.diff(ui, repo, other)
4133 return bookmarks.diff(ui, repo, other)
4131
4134
4132 repo._subtoppath = ui.expandpath(source)
4135 repo._subtoppath = ui.expandpath(source)
4133 try:
4136 try:
4134 return hg.incoming(ui, repo, source, opts)
4137 return hg.incoming(ui, repo, source, opts)
4135 finally:
4138 finally:
4136 del repo._subtoppath
4139 del repo._subtoppath
4137
4140
4138
4141
4139 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4142 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4140 norepo=True)
4143 norepo=True)
4141 def init(ui, dest=".", **opts):
4144 def init(ui, dest=".", **opts):
4142 """create a new repository in the given directory
4145 """create a new repository in the given directory
4143
4146
4144 Initialize a new repository in the given directory. If the given
4147 Initialize a new repository in the given directory. If the given
4145 directory does not exist, it will be created.
4148 directory does not exist, it will be created.
4146
4149
4147 If no directory is given, the current directory is used.
4150 If no directory is given, the current directory is used.
4148
4151
4149 It is possible to specify an ``ssh://`` URL as the destination.
4152 It is possible to specify an ``ssh://`` URL as the destination.
4150 See :hg:`help urls` for more information.
4153 See :hg:`help urls` for more information.
4151
4154
4152 Returns 0 on success.
4155 Returns 0 on success.
4153 """
4156 """
4154 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4157 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4155
4158
4156 @command('locate',
4159 @command('locate',
4157 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4160 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4158 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4161 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4159 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4162 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4160 ] + walkopts,
4163 ] + walkopts,
4161 _('[OPTION]... [PATTERN]...'))
4164 _('[OPTION]... [PATTERN]...'))
4162 def locate(ui, repo, *pats, **opts):
4165 def locate(ui, repo, *pats, **opts):
4163 """locate files matching specific patterns (DEPRECATED)
4166 """locate files matching specific patterns (DEPRECATED)
4164
4167
4165 Print files under Mercurial control in the working directory whose
4168 Print files under Mercurial control in the working directory whose
4166 names match the given patterns.
4169 names match the given patterns.
4167
4170
4168 By default, this command searches all directories in the working
4171 By default, this command searches all directories in the working
4169 directory. To search just the current directory and its
4172 directory. To search just the current directory and its
4170 subdirectories, use "--include .".
4173 subdirectories, use "--include .".
4171
4174
4172 If no patterns are given to match, this command prints the names
4175 If no patterns are given to match, this command prints the names
4173 of all files under Mercurial control in the working directory.
4176 of all files under Mercurial control in the working directory.
4174
4177
4175 If you want to feed the output of this command into the "xargs"
4178 If you want to feed the output of this command into the "xargs"
4176 command, use the -0 option to both this command and "xargs". This
4179 command, use the -0 option to both this command and "xargs". This
4177 will avoid the problem of "xargs" treating single filenames that
4180 will avoid the problem of "xargs" treating single filenames that
4178 contain whitespace as multiple filenames.
4181 contain whitespace as multiple filenames.
4179
4182
4180 See :hg:`help files` for a more versatile command.
4183 See :hg:`help files` for a more versatile command.
4181
4184
4182 Returns 0 if a match is found, 1 otherwise.
4185 Returns 0 if a match is found, 1 otherwise.
4183 """
4186 """
4184 end = opts.get('print0') and '\0' or '\n'
4187 end = opts.get('print0') and '\0' or '\n'
4185 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4188 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4186
4189
4187 ret = 1
4190 ret = 1
4188 ctx = repo[rev]
4191 ctx = repo[rev]
4189 m = scmutil.match(ctx, pats, opts, default='relglob')
4192 m = scmutil.match(ctx, pats, opts, default='relglob')
4190 m.bad = lambda x, y: False
4193 m.bad = lambda x, y: False
4191
4194
4192 for abs in ctx.matches(m):
4195 for abs in ctx.matches(m):
4193 if opts.get('fullpath'):
4196 if opts.get('fullpath'):
4194 ui.write(repo.wjoin(abs), end)
4197 ui.write(repo.wjoin(abs), end)
4195 else:
4198 else:
4196 ui.write(((pats and m.rel(abs)) or abs), end)
4199 ui.write(((pats and m.rel(abs)) or abs), end)
4197 ret = 0
4200 ret = 0
4198
4201
4199 return ret
4202 return ret
4200
4203
4201 @command('^log|history',
4204 @command('^log|history',
4202 [('f', 'follow', None,
4205 [('f', 'follow', None,
4203 _('follow changeset history, or file history across copies and renames')),
4206 _('follow changeset history, or file history across copies and renames')),
4204 ('', 'follow-first', None,
4207 ('', 'follow-first', None,
4205 _('only follow the first parent of merge changesets (DEPRECATED)')),
4208 _('only follow the first parent of merge changesets (DEPRECATED)')),
4206 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4209 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4207 ('C', 'copies', None, _('show copied files')),
4210 ('C', 'copies', None, _('show copied files')),
4208 ('k', 'keyword', [],
4211 ('k', 'keyword', [],
4209 _('do case-insensitive search for a given text'), _('TEXT')),
4212 _('do case-insensitive search for a given text'), _('TEXT')),
4210 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4213 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4211 ('', 'removed', None, _('include revisions where files were removed')),
4214 ('', 'removed', None, _('include revisions where files were removed')),
4212 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4215 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4213 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4216 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4214 ('', 'only-branch', [],
4217 ('', 'only-branch', [],
4215 _('show only changesets within the given named branch (DEPRECATED)'),
4218 _('show only changesets within the given named branch (DEPRECATED)'),
4216 _('BRANCH')),
4219 _('BRANCH')),
4217 ('b', 'branch', [],
4220 ('b', 'branch', [],
4218 _('show changesets within the given named branch'), _('BRANCH')),
4221 _('show changesets within the given named branch'), _('BRANCH')),
4219 ('P', 'prune', [],
4222 ('P', 'prune', [],
4220 _('do not display revision or any of its ancestors'), _('REV')),
4223 _('do not display revision or any of its ancestors'), _('REV')),
4221 ] + logopts + walkopts,
4224 ] + logopts + walkopts,
4222 _('[OPTION]... [FILE]'),
4225 _('[OPTION]... [FILE]'),
4223 inferrepo=True)
4226 inferrepo=True)
4224 def log(ui, repo, *pats, **opts):
4227 def log(ui, repo, *pats, **opts):
4225 """show revision history of entire repository or files
4228 """show revision history of entire repository or files
4226
4229
4227 Print the revision history of the specified files or the entire
4230 Print the revision history of the specified files or the entire
4228 project.
4231 project.
4229
4232
4230 If no revision range is specified, the default is ``tip:0`` unless
4233 If no revision range is specified, the default is ``tip:0`` unless
4231 --follow is set, in which case the working directory parent is
4234 --follow is set, in which case the working directory parent is
4232 used as the starting revision.
4235 used as the starting revision.
4233
4236
4234 File history is shown without following rename or copy history of
4237 File history is shown without following rename or copy history of
4235 files. Use -f/--follow with a filename to follow history across
4238 files. Use -f/--follow with a filename to follow history across
4236 renames and copies. --follow without a filename will only show
4239 renames and copies. --follow without a filename will only show
4237 ancestors or descendants of the starting revision.
4240 ancestors or descendants of the starting revision.
4238
4241
4239 By default this command prints revision number and changeset id,
4242 By default this command prints revision number and changeset id,
4240 tags, non-trivial parents, user, date and time, and a summary for
4243 tags, non-trivial parents, user, date and time, and a summary for
4241 each commit. When the -v/--verbose switch is used, the list of
4244 each commit. When the -v/--verbose switch is used, the list of
4242 changed files and full commit message are shown.
4245 changed files and full commit message are shown.
4243
4246
4244 With --graph the revisions are shown as an ASCII art DAG with the most
4247 With --graph the revisions are shown as an ASCII art DAG with the most
4245 recent changeset at the top.
4248 recent changeset at the top.
4246 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4249 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4247 and '+' represents a fork where the changeset from the lines below is a
4250 and '+' represents a fork where the changeset from the lines below is a
4248 parent of the 'o' merge on the same line.
4251 parent of the 'o' merge on the same line.
4249
4252
4250 .. note::
4253 .. note::
4251
4254
4252 log -p/--patch may generate unexpected diff output for merge
4255 log -p/--patch may generate unexpected diff output for merge
4253 changesets, as it will only compare the merge changeset against
4256 changesets, as it will only compare the merge changeset against
4254 its first parent. Also, only files different from BOTH parents
4257 its first parent. Also, only files different from BOTH parents
4255 will appear in files:.
4258 will appear in files:.
4256
4259
4257 .. note::
4260 .. note::
4258
4261
4259 for performance reasons, log FILE may omit duplicate changes
4262 for performance reasons, log FILE may omit duplicate changes
4260 made on branches and will not show deletions. To see all
4263 made on branches and will not show deletions. To see all
4261 changes including duplicates and deletions, use the --removed
4264 changes including duplicates and deletions, use the --removed
4262 switch.
4265 switch.
4263
4266
4264 .. container:: verbose
4267 .. container:: verbose
4265
4268
4266 Some examples:
4269 Some examples:
4267
4270
4268 - changesets with full descriptions and file lists::
4271 - changesets with full descriptions and file lists::
4269
4272
4270 hg log -v
4273 hg log -v
4271
4274
4272 - changesets ancestral to the working directory::
4275 - changesets ancestral to the working directory::
4273
4276
4274 hg log -f
4277 hg log -f
4275
4278
4276 - last 10 commits on the current branch::
4279 - last 10 commits on the current branch::
4277
4280
4278 hg log -l 10 -b .
4281 hg log -l 10 -b .
4279
4282
4280 - changesets showing all modifications of a file, including removals::
4283 - changesets showing all modifications of a file, including removals::
4281
4284
4282 hg log --removed file.c
4285 hg log --removed file.c
4283
4286
4284 - all changesets that touch a directory, with diffs, excluding merges::
4287 - all changesets that touch a directory, with diffs, excluding merges::
4285
4288
4286 hg log -Mp lib/
4289 hg log -Mp lib/
4287
4290
4288 - all revision numbers that match a keyword::
4291 - all revision numbers that match a keyword::
4289
4292
4290 hg log -k bug --template "{rev}\\n"
4293 hg log -k bug --template "{rev}\\n"
4291
4294
4292 - list available log templates::
4295 - list available log templates::
4293
4296
4294 hg log -T list
4297 hg log -T list
4295
4298
4296 - check if a given changeset is included is a tagged release::
4299 - check if a given changeset is included is a tagged release::
4297
4300
4298 hg log -r "a21ccf and ancestor(1.9)"
4301 hg log -r "a21ccf and ancestor(1.9)"
4299
4302
4300 - find all changesets by some user in a date range::
4303 - find all changesets by some user in a date range::
4301
4304
4302 hg log -k alice -d "may 2008 to jul 2008"
4305 hg log -k alice -d "may 2008 to jul 2008"
4303
4306
4304 - summary of all changesets after the last tag::
4307 - summary of all changesets after the last tag::
4305
4308
4306 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4309 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4307
4310
4308 See :hg:`help dates` for a list of formats valid for -d/--date.
4311 See :hg:`help dates` for a list of formats valid for -d/--date.
4309
4312
4310 See :hg:`help revisions` and :hg:`help revsets` for more about
4313 See :hg:`help revisions` and :hg:`help revsets` for more about
4311 specifying revisions.
4314 specifying revisions.
4312
4315
4313 See :hg:`help templates` for more about pre-packaged styles and
4316 See :hg:`help templates` for more about pre-packaged styles and
4314 specifying custom templates.
4317 specifying custom templates.
4315
4318
4316 Returns 0 on success.
4319 Returns 0 on success.
4317 """
4320 """
4318 if opts.get('graph'):
4321 if opts.get('graph'):
4319 return cmdutil.graphlog(ui, repo, *pats, **opts)
4322 return cmdutil.graphlog(ui, repo, *pats, **opts)
4320
4323
4321 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4324 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4322 limit = cmdutil.loglimit(opts)
4325 limit = cmdutil.loglimit(opts)
4323 count = 0
4326 count = 0
4324
4327
4325 getrenamed = None
4328 getrenamed = None
4326 if opts.get('copies'):
4329 if opts.get('copies'):
4327 endrev = None
4330 endrev = None
4328 if opts.get('rev'):
4331 if opts.get('rev'):
4329 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4332 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4330 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4333 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4331
4334
4332 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4335 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4333 for rev in revs:
4336 for rev in revs:
4334 if count == limit:
4337 if count == limit:
4335 break
4338 break
4336 ctx = repo[rev]
4339 ctx = repo[rev]
4337 copies = None
4340 copies = None
4338 if getrenamed is not None and rev:
4341 if getrenamed is not None and rev:
4339 copies = []
4342 copies = []
4340 for fn in ctx.files():
4343 for fn in ctx.files():
4341 rename = getrenamed(fn, rev)
4344 rename = getrenamed(fn, rev)
4342 if rename:
4345 if rename:
4343 copies.append((fn, rename[0]))
4346 copies.append((fn, rename[0]))
4344 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4347 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4345 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4348 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4346 if displayer.flush(rev):
4349 if displayer.flush(rev):
4347 count += 1
4350 count += 1
4348
4351
4349 displayer.close()
4352 displayer.close()
4350
4353
4351 @command('manifest',
4354 @command('manifest',
4352 [('r', 'rev', '', _('revision to display'), _('REV')),
4355 [('r', 'rev', '', _('revision to display'), _('REV')),
4353 ('', 'all', False, _("list files from all revisions"))]
4356 ('', 'all', False, _("list files from all revisions"))]
4354 + formatteropts,
4357 + formatteropts,
4355 _('[-r REV]'))
4358 _('[-r REV]'))
4356 def manifest(ui, repo, node=None, rev=None, **opts):
4359 def manifest(ui, repo, node=None, rev=None, **opts):
4357 """output the current or given revision of the project manifest
4360 """output the current or given revision of the project manifest
4358
4361
4359 Print a list of version controlled files for the given revision.
4362 Print a list of version controlled files for the given revision.
4360 If no revision is given, the first parent of the working directory
4363 If no revision is given, the first parent of the working directory
4361 is used, or the null revision if no revision is checked out.
4364 is used, or the null revision if no revision is checked out.
4362
4365
4363 With -v, print file permissions, symlink and executable bits.
4366 With -v, print file permissions, symlink and executable bits.
4364 With --debug, print file revision hashes.
4367 With --debug, print file revision hashes.
4365
4368
4366 If option --all is specified, the list of all files from all revisions
4369 If option --all is specified, the list of all files from all revisions
4367 is printed. This includes deleted and renamed files.
4370 is printed. This includes deleted and renamed files.
4368
4371
4369 Returns 0 on success.
4372 Returns 0 on success.
4370 """
4373 """
4371
4374
4372 fm = ui.formatter('manifest', opts)
4375 fm = ui.formatter('manifest', opts)
4373
4376
4374 if opts.get('all'):
4377 if opts.get('all'):
4375 if rev or node:
4378 if rev or node:
4376 raise util.Abort(_("can't specify a revision with --all"))
4379 raise util.Abort(_("can't specify a revision with --all"))
4377
4380
4378 res = []
4381 res = []
4379 prefix = "data/"
4382 prefix = "data/"
4380 suffix = ".i"
4383 suffix = ".i"
4381 plen = len(prefix)
4384 plen = len(prefix)
4382 slen = len(suffix)
4385 slen = len(suffix)
4383 lock = repo.lock()
4386 lock = repo.lock()
4384 try:
4387 try:
4385 for fn, b, size in repo.store.datafiles():
4388 for fn, b, size in repo.store.datafiles():
4386 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4389 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4387 res.append(fn[plen:-slen])
4390 res.append(fn[plen:-slen])
4388 finally:
4391 finally:
4389 lock.release()
4392 lock.release()
4390 for f in res:
4393 for f in res:
4391 fm.startitem()
4394 fm.startitem()
4392 fm.write("path", '%s\n', f)
4395 fm.write("path", '%s\n', f)
4393 fm.end()
4396 fm.end()
4394 return
4397 return
4395
4398
4396 if rev and node:
4399 if rev and node:
4397 raise util.Abort(_("please specify just one revision"))
4400 raise util.Abort(_("please specify just one revision"))
4398
4401
4399 if not node:
4402 if not node:
4400 node = rev
4403 node = rev
4401
4404
4402 char = {'l': '@', 'x': '*', '': ''}
4405 char = {'l': '@', 'x': '*', '': ''}
4403 mode = {'l': '644', 'x': '755', '': '644'}
4406 mode = {'l': '644', 'x': '755', '': '644'}
4404 ctx = scmutil.revsingle(repo, node)
4407 ctx = scmutil.revsingle(repo, node)
4405 mf = ctx.manifest()
4408 mf = ctx.manifest()
4406 for f in ctx:
4409 for f in ctx:
4407 fm.startitem()
4410 fm.startitem()
4408 fl = ctx[f].flags()
4411 fl = ctx[f].flags()
4409 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4412 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4410 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4413 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4411 fm.write('path', '%s\n', f)
4414 fm.write('path', '%s\n', f)
4412 fm.end()
4415 fm.end()
4413
4416
4414 @command('^merge',
4417 @command('^merge',
4415 [('f', 'force', None,
4418 [('f', 'force', None,
4416 _('force a merge including outstanding changes (DEPRECATED)')),
4419 _('force a merge including outstanding changes (DEPRECATED)')),
4417 ('r', 'rev', '', _('revision to merge'), _('REV')),
4420 ('r', 'rev', '', _('revision to merge'), _('REV')),
4418 ('P', 'preview', None,
4421 ('P', 'preview', None,
4419 _('review revisions to merge (no merge is performed)'))
4422 _('review revisions to merge (no merge is performed)'))
4420 ] + mergetoolopts,
4423 ] + mergetoolopts,
4421 _('[-P] [-f] [[-r] REV]'))
4424 _('[-P] [-f] [[-r] REV]'))
4422 def merge(ui, repo, node=None, **opts):
4425 def merge(ui, repo, node=None, **opts):
4423 """merge working directory with another revision
4426 """merge working directory with another revision
4424
4427
4425 The current working directory is updated with all changes made in
4428 The current working directory is updated with all changes made in
4426 the requested revision since the last common predecessor revision.
4429 the requested revision since the last common predecessor revision.
4427
4430
4428 Files that changed between either parent are marked as changed for
4431 Files that changed between either parent are marked as changed for
4429 the next commit and a commit must be performed before any further
4432 the next commit and a commit must be performed before any further
4430 updates to the repository are allowed. The next commit will have
4433 updates to the repository are allowed. The next commit will have
4431 two parents.
4434 two parents.
4432
4435
4433 ``--tool`` can be used to specify the merge tool used for file
4436 ``--tool`` can be used to specify the merge tool used for file
4434 merges. It overrides the HGMERGE environment variable and your
4437 merges. It overrides the HGMERGE environment variable and your
4435 configuration files. See :hg:`help merge-tools` for options.
4438 configuration files. See :hg:`help merge-tools` for options.
4436
4439
4437 If no revision is specified, the working directory's parent is a
4440 If no revision is specified, the working directory's parent is a
4438 head revision, and the current branch contains exactly one other
4441 head revision, and the current branch contains exactly one other
4439 head, the other head is merged with by default. Otherwise, an
4442 head, the other head is merged with by default. Otherwise, an
4440 explicit revision with which to merge with must be provided.
4443 explicit revision with which to merge with must be provided.
4441
4444
4442 :hg:`resolve` must be used to resolve unresolved files.
4445 :hg:`resolve` must be used to resolve unresolved files.
4443
4446
4444 To undo an uncommitted merge, use :hg:`update --clean .` which
4447 To undo an uncommitted merge, use :hg:`update --clean .` which
4445 will check out a clean copy of the original merge parent, losing
4448 will check out a clean copy of the original merge parent, losing
4446 all changes.
4449 all changes.
4447
4450
4448 Returns 0 on success, 1 if there are unresolved files.
4451 Returns 0 on success, 1 if there are unresolved files.
4449 """
4452 """
4450
4453
4451 if opts.get('rev') and node:
4454 if opts.get('rev') and node:
4452 raise util.Abort(_("please specify just one revision"))
4455 raise util.Abort(_("please specify just one revision"))
4453 if not node:
4456 if not node:
4454 node = opts.get('rev')
4457 node = opts.get('rev')
4455
4458
4456 if node:
4459 if node:
4457 node = scmutil.revsingle(repo, node).node()
4460 node = scmutil.revsingle(repo, node).node()
4458
4461
4459 if not node and repo._bookmarkcurrent:
4462 if not node and repo._bookmarkcurrent:
4460 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4463 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4461 curhead = repo[repo._bookmarkcurrent].node()
4464 curhead = repo[repo._bookmarkcurrent].node()
4462 if len(bmheads) == 2:
4465 if len(bmheads) == 2:
4463 if curhead == bmheads[0]:
4466 if curhead == bmheads[0]:
4464 node = bmheads[1]
4467 node = bmheads[1]
4465 else:
4468 else:
4466 node = bmheads[0]
4469 node = bmheads[0]
4467 elif len(bmheads) > 2:
4470 elif len(bmheads) > 2:
4468 raise util.Abort(_("multiple matching bookmarks to merge - "
4471 raise util.Abort(_("multiple matching bookmarks to merge - "
4469 "please merge with an explicit rev or bookmark"),
4472 "please merge with an explicit rev or bookmark"),
4470 hint=_("run 'hg heads' to see all heads"))
4473 hint=_("run 'hg heads' to see all heads"))
4471 elif len(bmheads) <= 1:
4474 elif len(bmheads) <= 1:
4472 raise util.Abort(_("no matching bookmark to merge - "
4475 raise util.Abort(_("no matching bookmark to merge - "
4473 "please merge with an explicit rev or bookmark"),
4476 "please merge with an explicit rev or bookmark"),
4474 hint=_("run 'hg heads' to see all heads"))
4477 hint=_("run 'hg heads' to see all heads"))
4475
4478
4476 if not node and not repo._bookmarkcurrent:
4479 if not node and not repo._bookmarkcurrent:
4477 branch = repo[None].branch()
4480 branch = repo[None].branch()
4478 bheads = repo.branchheads(branch)
4481 bheads = repo.branchheads(branch)
4479 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4482 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4480
4483
4481 if len(nbhs) > 2:
4484 if len(nbhs) > 2:
4482 raise util.Abort(_("branch '%s' has %d heads - "
4485 raise util.Abort(_("branch '%s' has %d heads - "
4483 "please merge with an explicit rev")
4486 "please merge with an explicit rev")
4484 % (branch, len(bheads)),
4487 % (branch, len(bheads)),
4485 hint=_("run 'hg heads .' to see heads"))
4488 hint=_("run 'hg heads .' to see heads"))
4486
4489
4487 parent = repo.dirstate.p1()
4490 parent = repo.dirstate.p1()
4488 if len(nbhs) <= 1:
4491 if len(nbhs) <= 1:
4489 if len(bheads) > 1:
4492 if len(bheads) > 1:
4490 raise util.Abort(_("heads are bookmarked - "
4493 raise util.Abort(_("heads are bookmarked - "
4491 "please merge with an explicit rev"),
4494 "please merge with an explicit rev"),
4492 hint=_("run 'hg heads' to see all heads"))
4495 hint=_("run 'hg heads' to see all heads"))
4493 if len(repo.heads()) > 1:
4496 if len(repo.heads()) > 1:
4494 raise util.Abort(_("branch '%s' has one head - "
4497 raise util.Abort(_("branch '%s' has one head - "
4495 "please merge with an explicit rev")
4498 "please merge with an explicit rev")
4496 % branch,
4499 % branch,
4497 hint=_("run 'hg heads' to see all heads"))
4500 hint=_("run 'hg heads' to see all heads"))
4498 msg, hint = _('nothing to merge'), None
4501 msg, hint = _('nothing to merge'), None
4499 if parent != repo.lookup(branch):
4502 if parent != repo.lookup(branch):
4500 hint = _("use 'hg update' instead")
4503 hint = _("use 'hg update' instead")
4501 raise util.Abort(msg, hint=hint)
4504 raise util.Abort(msg, hint=hint)
4502
4505
4503 if parent not in bheads:
4506 if parent not in bheads:
4504 raise util.Abort(_('working directory not at a head revision'),
4507 raise util.Abort(_('working directory not at a head revision'),
4505 hint=_("use 'hg update' or merge with an "
4508 hint=_("use 'hg update' or merge with an "
4506 "explicit revision"))
4509 "explicit revision"))
4507 if parent == nbhs[0]:
4510 if parent == nbhs[0]:
4508 node = nbhs[-1]
4511 node = nbhs[-1]
4509 else:
4512 else:
4510 node = nbhs[0]
4513 node = nbhs[0]
4511
4514
4512 if opts.get('preview'):
4515 if opts.get('preview'):
4513 # find nodes that are ancestors of p2 but not of p1
4516 # find nodes that are ancestors of p2 but not of p1
4514 p1 = repo.lookup('.')
4517 p1 = repo.lookup('.')
4515 p2 = repo.lookup(node)
4518 p2 = repo.lookup(node)
4516 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4519 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4517
4520
4518 displayer = cmdutil.show_changeset(ui, repo, opts)
4521 displayer = cmdutil.show_changeset(ui, repo, opts)
4519 for node in nodes:
4522 for node in nodes:
4520 displayer.show(repo[node])
4523 displayer.show(repo[node])
4521 displayer.close()
4524 displayer.close()
4522 return 0
4525 return 0
4523
4526
4524 try:
4527 try:
4525 # ui.forcemerge is an internal variable, do not document
4528 # ui.forcemerge is an internal variable, do not document
4526 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4529 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4527 return hg.merge(repo, node, force=opts.get('force'))
4530 return hg.merge(repo, node, force=opts.get('force'))
4528 finally:
4531 finally:
4529 ui.setconfig('ui', 'forcemerge', '', 'merge')
4532 ui.setconfig('ui', 'forcemerge', '', 'merge')
4530
4533
4531 @command('outgoing|out',
4534 @command('outgoing|out',
4532 [('f', 'force', None, _('run even when the destination is unrelated')),
4535 [('f', 'force', None, _('run even when the destination is unrelated')),
4533 ('r', 'rev', [],
4536 ('r', 'rev', [],
4534 _('a changeset intended to be included in the destination'), _('REV')),
4537 _('a changeset intended to be included in the destination'), _('REV')),
4535 ('n', 'newest-first', None, _('show newest record first')),
4538 ('n', 'newest-first', None, _('show newest record first')),
4536 ('B', 'bookmarks', False, _('compare bookmarks')),
4539 ('B', 'bookmarks', False, _('compare bookmarks')),
4537 ('b', 'branch', [], _('a specific branch you would like to push'),
4540 ('b', 'branch', [], _('a specific branch you would like to push'),
4538 _('BRANCH')),
4541 _('BRANCH')),
4539 ] + logopts + remoteopts + subrepoopts,
4542 ] + logopts + remoteopts + subrepoopts,
4540 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4543 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4541 def outgoing(ui, repo, dest=None, **opts):
4544 def outgoing(ui, repo, dest=None, **opts):
4542 """show changesets not found in the destination
4545 """show changesets not found in the destination
4543
4546
4544 Show changesets not found in the specified destination repository
4547 Show changesets not found in the specified destination repository
4545 or the default push location. These are the changesets that would
4548 or the default push location. These are the changesets that would
4546 be pushed if a push was requested.
4549 be pushed if a push was requested.
4547
4550
4548 See pull for details of valid destination formats.
4551 See pull for details of valid destination formats.
4549
4552
4550 Returns 0 if there are outgoing changes, 1 otherwise.
4553 Returns 0 if there are outgoing changes, 1 otherwise.
4551 """
4554 """
4552 if opts.get('graph'):
4555 if opts.get('graph'):
4553 cmdutil.checkunsupportedgraphflags([], opts)
4556 cmdutil.checkunsupportedgraphflags([], opts)
4554 o, other = hg._outgoing(ui, repo, dest, opts)
4557 o, other = hg._outgoing(ui, repo, dest, opts)
4555 if not o:
4558 if not o:
4556 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4559 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4557 return
4560 return
4558
4561
4559 revdag = cmdutil.graphrevs(repo, o, opts)
4562 revdag = cmdutil.graphrevs(repo, o, opts)
4560 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4563 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4561 showparents = [ctx.node() for ctx in repo[None].parents()]
4564 showparents = [ctx.node() for ctx in repo[None].parents()]
4562 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4565 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4563 graphmod.asciiedges)
4566 graphmod.asciiedges)
4564 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4567 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4565 return 0
4568 return 0
4566
4569
4567 if opts.get('bookmarks'):
4570 if opts.get('bookmarks'):
4568 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4571 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4569 dest, branches = hg.parseurl(dest, opts.get('branch'))
4572 dest, branches = hg.parseurl(dest, opts.get('branch'))
4570 other = hg.peer(repo, opts, dest)
4573 other = hg.peer(repo, opts, dest)
4571 if 'bookmarks' not in other.listkeys('namespaces'):
4574 if 'bookmarks' not in other.listkeys('namespaces'):
4572 ui.warn(_("remote doesn't support bookmarks\n"))
4575 ui.warn(_("remote doesn't support bookmarks\n"))
4573 return 0
4576 return 0
4574 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4577 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4575 return bookmarks.diff(ui, other, repo)
4578 return bookmarks.diff(ui, other, repo)
4576
4579
4577 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4580 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4578 try:
4581 try:
4579 return hg.outgoing(ui, repo, dest, opts)
4582 return hg.outgoing(ui, repo, dest, opts)
4580 finally:
4583 finally:
4581 del repo._subtoppath
4584 del repo._subtoppath
4582
4585
4583 @command('parents',
4586 @command('parents',
4584 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4587 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4585 ] + templateopts,
4588 ] + templateopts,
4586 _('[-r REV] [FILE]'),
4589 _('[-r REV] [FILE]'),
4587 inferrepo=True)
4590 inferrepo=True)
4588 def parents(ui, repo, file_=None, **opts):
4591 def parents(ui, repo, file_=None, **opts):
4589 """show the parents of the working directory or revision
4592 """show the parents of the working directory or revision
4590
4593
4591 Print the working directory's parent revisions. If a revision is
4594 Print the working directory's parent revisions. If a revision is
4592 given via -r/--rev, the parent of that revision will be printed.
4595 given via -r/--rev, the parent of that revision will be printed.
4593 If a file argument is given, the revision in which the file was
4596 If a file argument is given, the revision in which the file was
4594 last changed (before the working directory revision or the
4597 last changed (before the working directory revision or the
4595 argument to --rev if given) is printed.
4598 argument to --rev if given) is printed.
4596
4599
4597 Returns 0 on success.
4600 Returns 0 on success.
4598 """
4601 """
4599
4602
4600 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4603 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4601
4604
4602 if file_:
4605 if file_:
4603 m = scmutil.match(ctx, (file_,), opts)
4606 m = scmutil.match(ctx, (file_,), opts)
4604 if m.anypats() or len(m.files()) != 1:
4607 if m.anypats() or len(m.files()) != 1:
4605 raise util.Abort(_('can only specify an explicit filename'))
4608 raise util.Abort(_('can only specify an explicit filename'))
4606 file_ = m.files()[0]
4609 file_ = m.files()[0]
4607 filenodes = []
4610 filenodes = []
4608 for cp in ctx.parents():
4611 for cp in ctx.parents():
4609 if not cp:
4612 if not cp:
4610 continue
4613 continue
4611 try:
4614 try:
4612 filenodes.append(cp.filenode(file_))
4615 filenodes.append(cp.filenode(file_))
4613 except error.LookupError:
4616 except error.LookupError:
4614 pass
4617 pass
4615 if not filenodes:
4618 if not filenodes:
4616 raise util.Abort(_("'%s' not found in manifest!") % file_)
4619 raise util.Abort(_("'%s' not found in manifest!") % file_)
4617 p = []
4620 p = []
4618 for fn in filenodes:
4621 for fn in filenodes:
4619 fctx = repo.filectx(file_, fileid=fn)
4622 fctx = repo.filectx(file_, fileid=fn)
4620 p.append(fctx.node())
4623 p.append(fctx.node())
4621 else:
4624 else:
4622 p = [cp.node() for cp in ctx.parents()]
4625 p = [cp.node() for cp in ctx.parents()]
4623
4626
4624 displayer = cmdutil.show_changeset(ui, repo, opts)
4627 displayer = cmdutil.show_changeset(ui, repo, opts)
4625 for n in p:
4628 for n in p:
4626 if n != nullid:
4629 if n != nullid:
4627 displayer.show(repo[n])
4630 displayer.show(repo[n])
4628 displayer.close()
4631 displayer.close()
4629
4632
4630 @command('paths', [], _('[NAME]'), optionalrepo=True)
4633 @command('paths', [], _('[NAME]'), optionalrepo=True)
4631 def paths(ui, repo, search=None):
4634 def paths(ui, repo, search=None):
4632 """show aliases for remote repositories
4635 """show aliases for remote repositories
4633
4636
4634 Show definition of symbolic path name NAME. If no name is given,
4637 Show definition of symbolic path name NAME. If no name is given,
4635 show definition of all available names.
4638 show definition of all available names.
4636
4639
4637 Option -q/--quiet suppresses all output when searching for NAME
4640 Option -q/--quiet suppresses all output when searching for NAME
4638 and shows only the path names when listing all definitions.
4641 and shows only the path names when listing all definitions.
4639
4642
4640 Path names are defined in the [paths] section of your
4643 Path names are defined in the [paths] section of your
4641 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4644 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4642 repository, ``.hg/hgrc`` is used, too.
4645 repository, ``.hg/hgrc`` is used, too.
4643
4646
4644 The path names ``default`` and ``default-push`` have a special
4647 The path names ``default`` and ``default-push`` have a special
4645 meaning. When performing a push or pull operation, they are used
4648 meaning. When performing a push or pull operation, they are used
4646 as fallbacks if no location is specified on the command-line.
4649 as fallbacks if no location is specified on the command-line.
4647 When ``default-push`` is set, it will be used for push and
4650 When ``default-push`` is set, it will be used for push and
4648 ``default`` will be used for pull; otherwise ``default`` is used
4651 ``default`` will be used for pull; otherwise ``default`` is used
4649 as the fallback for both. When cloning a repository, the clone
4652 as the fallback for both. When cloning a repository, the clone
4650 source is written as ``default`` in ``.hg/hgrc``. Note that
4653 source is written as ``default`` in ``.hg/hgrc``. Note that
4651 ``default`` and ``default-push`` apply to all inbound (e.g.
4654 ``default`` and ``default-push`` apply to all inbound (e.g.
4652 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4655 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4653 :hg:`bundle`) operations.
4656 :hg:`bundle`) operations.
4654
4657
4655 See :hg:`help urls` for more information.
4658 See :hg:`help urls` for more information.
4656
4659
4657 Returns 0 on success.
4660 Returns 0 on success.
4658 """
4661 """
4659 if search:
4662 if search:
4660 for name, path in ui.configitems("paths"):
4663 for name, path in ui.configitems("paths"):
4661 if name == search:
4664 if name == search:
4662 ui.status("%s\n" % util.hidepassword(path))
4665 ui.status("%s\n" % util.hidepassword(path))
4663 return
4666 return
4664 if not ui.quiet:
4667 if not ui.quiet:
4665 ui.warn(_("not found!\n"))
4668 ui.warn(_("not found!\n"))
4666 return 1
4669 return 1
4667 else:
4670 else:
4668 for name, path in ui.configitems("paths"):
4671 for name, path in ui.configitems("paths"):
4669 if ui.quiet:
4672 if ui.quiet:
4670 ui.write("%s\n" % name)
4673 ui.write("%s\n" % name)
4671 else:
4674 else:
4672 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4675 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4673
4676
4674 @command('phase',
4677 @command('phase',
4675 [('p', 'public', False, _('set changeset phase to public')),
4678 [('p', 'public', False, _('set changeset phase to public')),
4676 ('d', 'draft', False, _('set changeset phase to draft')),
4679 ('d', 'draft', False, _('set changeset phase to draft')),
4677 ('s', 'secret', False, _('set changeset phase to secret')),
4680 ('s', 'secret', False, _('set changeset phase to secret')),
4678 ('f', 'force', False, _('allow to move boundary backward')),
4681 ('f', 'force', False, _('allow to move boundary backward')),
4679 ('r', 'rev', [], _('target revision'), _('REV')),
4682 ('r', 'rev', [], _('target revision'), _('REV')),
4680 ],
4683 ],
4681 _('[-p|-d|-s] [-f] [-r] REV...'))
4684 _('[-p|-d|-s] [-f] [-r] REV...'))
4682 def phase(ui, repo, *revs, **opts):
4685 def phase(ui, repo, *revs, **opts):
4683 """set or show the current phase name
4686 """set or show the current phase name
4684
4687
4685 With no argument, show the phase name of specified revisions.
4688 With no argument, show the phase name of specified revisions.
4686
4689
4687 With one of -p/--public, -d/--draft or -s/--secret, change the
4690 With one of -p/--public, -d/--draft or -s/--secret, change the
4688 phase value of the specified revisions.
4691 phase value of the specified revisions.
4689
4692
4690 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4693 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4691 lower phase to an higher phase. Phases are ordered as follows::
4694 lower phase to an higher phase. Phases are ordered as follows::
4692
4695
4693 public < draft < secret
4696 public < draft < secret
4694
4697
4695 Returns 0 on success, 1 if no phases were changed or some could not
4698 Returns 0 on success, 1 if no phases were changed or some could not
4696 be changed.
4699 be changed.
4697 """
4700 """
4698 # search for a unique phase argument
4701 # search for a unique phase argument
4699 targetphase = None
4702 targetphase = None
4700 for idx, name in enumerate(phases.phasenames):
4703 for idx, name in enumerate(phases.phasenames):
4701 if opts[name]:
4704 if opts[name]:
4702 if targetphase is not None:
4705 if targetphase is not None:
4703 raise util.Abort(_('only one phase can be specified'))
4706 raise util.Abort(_('only one phase can be specified'))
4704 targetphase = idx
4707 targetphase = idx
4705
4708
4706 # look for specified revision
4709 # look for specified revision
4707 revs = list(revs)
4710 revs = list(revs)
4708 revs.extend(opts['rev'])
4711 revs.extend(opts['rev'])
4709 if not revs:
4712 if not revs:
4710 raise util.Abort(_('no revisions specified'))
4713 raise util.Abort(_('no revisions specified'))
4711
4714
4712 revs = scmutil.revrange(repo, revs)
4715 revs = scmutil.revrange(repo, revs)
4713
4716
4714 lock = None
4717 lock = None
4715 ret = 0
4718 ret = 0
4716 if targetphase is None:
4719 if targetphase is None:
4717 # display
4720 # display
4718 for r in revs:
4721 for r in revs:
4719 ctx = repo[r]
4722 ctx = repo[r]
4720 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4723 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4721 else:
4724 else:
4722 tr = None
4725 tr = None
4723 lock = repo.lock()
4726 lock = repo.lock()
4724 try:
4727 try:
4725 tr = repo.transaction("phase")
4728 tr = repo.transaction("phase")
4726 # set phase
4729 # set phase
4727 if not revs:
4730 if not revs:
4728 raise util.Abort(_('empty revision set'))
4731 raise util.Abort(_('empty revision set'))
4729 nodes = [repo[r].node() for r in revs]
4732 nodes = [repo[r].node() for r in revs]
4730 olddata = repo._phasecache.getphaserevs(repo)[:]
4733 olddata = repo._phasecache.getphaserevs(repo)[:]
4731 phases.advanceboundary(repo, tr, targetphase, nodes)
4734 phases.advanceboundary(repo, tr, targetphase, nodes)
4732 if opts['force']:
4735 if opts['force']:
4733 phases.retractboundary(repo, tr, targetphase, nodes)
4736 phases.retractboundary(repo, tr, targetphase, nodes)
4734 tr.close()
4737 tr.close()
4735 finally:
4738 finally:
4736 if tr is not None:
4739 if tr is not None:
4737 tr.release()
4740 tr.release()
4738 lock.release()
4741 lock.release()
4739 # moving revision from public to draft may hide them
4742 # moving revision from public to draft may hide them
4740 # We have to check result on an unfiltered repository
4743 # We have to check result on an unfiltered repository
4741 unfi = repo.unfiltered()
4744 unfi = repo.unfiltered()
4742 newdata = repo._phasecache.getphaserevs(unfi)
4745 newdata = repo._phasecache.getphaserevs(unfi)
4743 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4746 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4744 cl = unfi.changelog
4747 cl = unfi.changelog
4745 rejected = [n for n in nodes
4748 rejected = [n for n in nodes
4746 if newdata[cl.rev(n)] < targetphase]
4749 if newdata[cl.rev(n)] < targetphase]
4747 if rejected:
4750 if rejected:
4748 ui.warn(_('cannot move %i changesets to a higher '
4751 ui.warn(_('cannot move %i changesets to a higher '
4749 'phase, use --force\n') % len(rejected))
4752 'phase, use --force\n') % len(rejected))
4750 ret = 1
4753 ret = 1
4751 if changes:
4754 if changes:
4752 msg = _('phase changed for %i changesets\n') % changes
4755 msg = _('phase changed for %i changesets\n') % changes
4753 if ret:
4756 if ret:
4754 ui.status(msg)
4757 ui.status(msg)
4755 else:
4758 else:
4756 ui.note(msg)
4759 ui.note(msg)
4757 else:
4760 else:
4758 ui.warn(_('no phases changed\n'))
4761 ui.warn(_('no phases changed\n'))
4759 ret = 1
4762 ret = 1
4760 return ret
4763 return ret
4761
4764
4762 def postincoming(ui, repo, modheads, optupdate, checkout):
4765 def postincoming(ui, repo, modheads, optupdate, checkout):
4763 if modheads == 0:
4766 if modheads == 0:
4764 return
4767 return
4765 if optupdate:
4768 if optupdate:
4766 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4769 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4767 try:
4770 try:
4768 ret = hg.update(repo, checkout)
4771 ret = hg.update(repo, checkout)
4769 except util.Abort, inst:
4772 except util.Abort, inst:
4770 ui.warn(_("not updating: %s\n") % str(inst))
4773 ui.warn(_("not updating: %s\n") % str(inst))
4771 if inst.hint:
4774 if inst.hint:
4772 ui.warn(_("(%s)\n") % inst.hint)
4775 ui.warn(_("(%s)\n") % inst.hint)
4773 return 0
4776 return 0
4774 if not ret and not checkout:
4777 if not ret and not checkout:
4775 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4778 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4776 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4779 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4777 return ret
4780 return ret
4778 if modheads > 1:
4781 if modheads > 1:
4779 currentbranchheads = len(repo.branchheads())
4782 currentbranchheads = len(repo.branchheads())
4780 if currentbranchheads == modheads:
4783 if currentbranchheads == modheads:
4781 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4784 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4782 elif currentbranchheads > 1:
4785 elif currentbranchheads > 1:
4783 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4786 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4784 "merge)\n"))
4787 "merge)\n"))
4785 else:
4788 else:
4786 ui.status(_("(run 'hg heads' to see heads)\n"))
4789 ui.status(_("(run 'hg heads' to see heads)\n"))
4787 else:
4790 else:
4788 ui.status(_("(run 'hg update' to get a working copy)\n"))
4791 ui.status(_("(run 'hg update' to get a working copy)\n"))
4789
4792
4790 @command('^pull',
4793 @command('^pull',
4791 [('u', 'update', None,
4794 [('u', 'update', None,
4792 _('update to new branch head if changesets were pulled')),
4795 _('update to new branch head if changesets were pulled')),
4793 ('f', 'force', None, _('run even when remote repository is unrelated')),
4796 ('f', 'force', None, _('run even when remote repository is unrelated')),
4794 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4797 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4795 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4798 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4796 ('b', 'branch', [], _('a specific branch you would like to pull'),
4799 ('b', 'branch', [], _('a specific branch you would like to pull'),
4797 _('BRANCH')),
4800 _('BRANCH')),
4798 ] + remoteopts,
4801 ] + remoteopts,
4799 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4802 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4800 def pull(ui, repo, source="default", **opts):
4803 def pull(ui, repo, source="default", **opts):
4801 """pull changes from the specified source
4804 """pull changes from the specified source
4802
4805
4803 Pull changes from a remote repository to a local one.
4806 Pull changes from a remote repository to a local one.
4804
4807
4805 This finds all changes from the repository at the specified path
4808 This finds all changes from the repository at the specified path
4806 or URL and adds them to a local repository (the current one unless
4809 or URL and adds them to a local repository (the current one unless
4807 -R is specified). By default, this does not update the copy of the
4810 -R is specified). By default, this does not update the copy of the
4808 project in the working directory.
4811 project in the working directory.
4809
4812
4810 Use :hg:`incoming` if you want to see what would have been added
4813 Use :hg:`incoming` if you want to see what would have been added
4811 by a pull at the time you issued this command. If you then decide
4814 by a pull at the time you issued this command. If you then decide
4812 to add those changes to the repository, you should use :hg:`pull
4815 to add those changes to the repository, you should use :hg:`pull
4813 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4816 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4814
4817
4815 If SOURCE is omitted, the 'default' path will be used.
4818 If SOURCE is omitted, the 'default' path will be used.
4816 See :hg:`help urls` for more information.
4819 See :hg:`help urls` for more information.
4817
4820
4818 Returns 0 on success, 1 if an update had unresolved files.
4821 Returns 0 on success, 1 if an update had unresolved files.
4819 """
4822 """
4820 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4823 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4821 other = hg.peer(repo, opts, source)
4824 other = hg.peer(repo, opts, source)
4822 try:
4825 try:
4823 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4826 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4824 revs, checkout = hg.addbranchrevs(repo, other, branches,
4827 revs, checkout = hg.addbranchrevs(repo, other, branches,
4825 opts.get('rev'))
4828 opts.get('rev'))
4826
4829
4827 remotebookmarks = other.listkeys('bookmarks')
4830 remotebookmarks = other.listkeys('bookmarks')
4828
4831
4829 if opts.get('bookmark'):
4832 if opts.get('bookmark'):
4830 if not revs:
4833 if not revs:
4831 revs = []
4834 revs = []
4832 for b in opts['bookmark']:
4835 for b in opts['bookmark']:
4833 if b not in remotebookmarks:
4836 if b not in remotebookmarks:
4834 raise util.Abort(_('remote bookmark %s not found!') % b)
4837 raise util.Abort(_('remote bookmark %s not found!') % b)
4835 revs.append(remotebookmarks[b])
4838 revs.append(remotebookmarks[b])
4836
4839
4837 if revs:
4840 if revs:
4838 try:
4841 try:
4839 revs = [other.lookup(rev) for rev in revs]
4842 revs = [other.lookup(rev) for rev in revs]
4840 except error.CapabilityError:
4843 except error.CapabilityError:
4841 err = _("other repository doesn't support revision lookup, "
4844 err = _("other repository doesn't support revision lookup, "
4842 "so a rev cannot be specified.")
4845 "so a rev cannot be specified.")
4843 raise util.Abort(err)
4846 raise util.Abort(err)
4844
4847
4845 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4848 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4846 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4849 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4847 if checkout:
4850 if checkout:
4848 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4851 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4849 repo._subtoppath = source
4852 repo._subtoppath = source
4850 try:
4853 try:
4851 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4854 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4852
4855
4853 finally:
4856 finally:
4854 del repo._subtoppath
4857 del repo._subtoppath
4855
4858
4856 # update specified bookmarks
4859 # update specified bookmarks
4857 if opts.get('bookmark'):
4860 if opts.get('bookmark'):
4858 marks = repo._bookmarks
4861 marks = repo._bookmarks
4859 for b in opts['bookmark']:
4862 for b in opts['bookmark']:
4860 # explicit pull overrides local bookmark if any
4863 # explicit pull overrides local bookmark if any
4861 ui.status(_("importing bookmark %s\n") % b)
4864 ui.status(_("importing bookmark %s\n") % b)
4862 marks[b] = repo[remotebookmarks[b]].node()
4865 marks[b] = repo[remotebookmarks[b]].node()
4863 marks.write()
4866 marks.write()
4864 finally:
4867 finally:
4865 other.close()
4868 other.close()
4866 return ret
4869 return ret
4867
4870
4868 @command('^push',
4871 @command('^push',
4869 [('f', 'force', None, _('force push')),
4872 [('f', 'force', None, _('force push')),
4870 ('r', 'rev', [],
4873 ('r', 'rev', [],
4871 _('a changeset intended to be included in the destination'),
4874 _('a changeset intended to be included in the destination'),
4872 _('REV')),
4875 _('REV')),
4873 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4876 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4874 ('b', 'branch', [],
4877 ('b', 'branch', [],
4875 _('a specific branch you would like to push'), _('BRANCH')),
4878 _('a specific branch you would like to push'), _('BRANCH')),
4876 ('', 'new-branch', False, _('allow pushing a new branch')),
4879 ('', 'new-branch', False, _('allow pushing a new branch')),
4877 ] + remoteopts,
4880 ] + remoteopts,
4878 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4881 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4879 def push(ui, repo, dest=None, **opts):
4882 def push(ui, repo, dest=None, **opts):
4880 """push changes to the specified destination
4883 """push changes to the specified destination
4881
4884
4882 Push changesets from the local repository to the specified
4885 Push changesets from the local repository to the specified
4883 destination.
4886 destination.
4884
4887
4885 This operation is symmetrical to pull: it is identical to a pull
4888 This operation is symmetrical to pull: it is identical to a pull
4886 in the destination repository from the current one.
4889 in the destination repository from the current one.
4887
4890
4888 By default, push will not allow creation of new heads at the
4891 By default, push will not allow creation of new heads at the
4889 destination, since multiple heads would make it unclear which head
4892 destination, since multiple heads would make it unclear which head
4890 to use. In this situation, it is recommended to pull and merge
4893 to use. In this situation, it is recommended to pull and merge
4891 before pushing.
4894 before pushing.
4892
4895
4893 Use --new-branch if you want to allow push to create a new named
4896 Use --new-branch if you want to allow push to create a new named
4894 branch that is not present at the destination. This allows you to
4897 branch that is not present at the destination. This allows you to
4895 only create a new branch without forcing other changes.
4898 only create a new branch without forcing other changes.
4896
4899
4897 .. note::
4900 .. note::
4898
4901
4899 Extra care should be taken with the -f/--force option,
4902 Extra care should be taken with the -f/--force option,
4900 which will push all new heads on all branches, an action which will
4903 which will push all new heads on all branches, an action which will
4901 almost always cause confusion for collaborators.
4904 almost always cause confusion for collaborators.
4902
4905
4903 If -r/--rev is used, the specified revision and all its ancestors
4906 If -r/--rev is used, the specified revision and all its ancestors
4904 will be pushed to the remote repository.
4907 will be pushed to the remote repository.
4905
4908
4906 If -B/--bookmark is used, the specified bookmarked revision, its
4909 If -B/--bookmark is used, the specified bookmarked revision, its
4907 ancestors, and the bookmark will be pushed to the remote
4910 ancestors, and the bookmark will be pushed to the remote
4908 repository.
4911 repository.
4909
4912
4910 Please see :hg:`help urls` for important details about ``ssh://``
4913 Please see :hg:`help urls` for important details about ``ssh://``
4911 URLs. If DESTINATION is omitted, a default path will be used.
4914 URLs. If DESTINATION is omitted, a default path will be used.
4912
4915
4913 Returns 0 if push was successful, 1 if nothing to push.
4916 Returns 0 if push was successful, 1 if nothing to push.
4914 """
4917 """
4915
4918
4916 if opts.get('bookmark'):
4919 if opts.get('bookmark'):
4917 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4920 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4918 for b in opts['bookmark']:
4921 for b in opts['bookmark']:
4919 # translate -B options to -r so changesets get pushed
4922 # translate -B options to -r so changesets get pushed
4920 if b in repo._bookmarks:
4923 if b in repo._bookmarks:
4921 opts.setdefault('rev', []).append(b)
4924 opts.setdefault('rev', []).append(b)
4922 else:
4925 else:
4923 # if we try to push a deleted bookmark, translate it to null
4926 # if we try to push a deleted bookmark, translate it to null
4924 # this lets simultaneous -r, -b options continue working
4927 # this lets simultaneous -r, -b options continue working
4925 opts.setdefault('rev', []).append("null")
4928 opts.setdefault('rev', []).append("null")
4926
4929
4927 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4930 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4928 dest, branches = hg.parseurl(dest, opts.get('branch'))
4931 dest, branches = hg.parseurl(dest, opts.get('branch'))
4929 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4932 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4930 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4933 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4931 try:
4934 try:
4932 other = hg.peer(repo, opts, dest)
4935 other = hg.peer(repo, opts, dest)
4933 except error.RepoError:
4936 except error.RepoError:
4934 if dest == "default-push":
4937 if dest == "default-push":
4935 raise util.Abort(_("default repository not configured!"),
4938 raise util.Abort(_("default repository not configured!"),
4936 hint=_('see the "path" section in "hg help config"'))
4939 hint=_('see the "path" section in "hg help config"'))
4937 else:
4940 else:
4938 raise
4941 raise
4939
4942
4940 if revs:
4943 if revs:
4941 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4944 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4942
4945
4943 repo._subtoppath = dest
4946 repo._subtoppath = dest
4944 try:
4947 try:
4945 # push subrepos depth-first for coherent ordering
4948 # push subrepos depth-first for coherent ordering
4946 c = repo['']
4949 c = repo['']
4947 subs = c.substate # only repos that are committed
4950 subs = c.substate # only repos that are committed
4948 for s in sorted(subs):
4951 for s in sorted(subs):
4949 result = c.sub(s).push(opts)
4952 result = c.sub(s).push(opts)
4950 if result == 0:
4953 if result == 0:
4951 return not result
4954 return not result
4952 finally:
4955 finally:
4953 del repo._subtoppath
4956 del repo._subtoppath
4954 result = repo.push(other, opts.get('force'), revs=revs,
4957 result = repo.push(other, opts.get('force'), revs=revs,
4955 newbranch=opts.get('new_branch'))
4958 newbranch=opts.get('new_branch'))
4956
4959
4957 result = not result
4960 result = not result
4958
4961
4959 if opts.get('bookmark'):
4962 if opts.get('bookmark'):
4960 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4963 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4961 if bresult == 2:
4964 if bresult == 2:
4962 return 2
4965 return 2
4963 if not result and bresult:
4966 if not result and bresult:
4964 result = 2
4967 result = 2
4965
4968
4966 return result
4969 return result
4967
4970
4968 @command('recover', [])
4971 @command('recover', [])
4969 def recover(ui, repo):
4972 def recover(ui, repo):
4970 """roll back an interrupted transaction
4973 """roll back an interrupted transaction
4971
4974
4972 Recover from an interrupted commit or pull.
4975 Recover from an interrupted commit or pull.
4973
4976
4974 This command tries to fix the repository status after an
4977 This command tries to fix the repository status after an
4975 interrupted operation. It should only be necessary when Mercurial
4978 interrupted operation. It should only be necessary when Mercurial
4976 suggests it.
4979 suggests it.
4977
4980
4978 Returns 0 if successful, 1 if nothing to recover or verify fails.
4981 Returns 0 if successful, 1 if nothing to recover or verify fails.
4979 """
4982 """
4980 if repo.recover():
4983 if repo.recover():
4981 return hg.verify(repo)
4984 return hg.verify(repo)
4982 return 1
4985 return 1
4983
4986
4984 @command('^remove|rm',
4987 @command('^remove|rm',
4985 [('A', 'after', None, _('record delete for missing files')),
4988 [('A', 'after', None, _('record delete for missing files')),
4986 ('f', 'force', None,
4989 ('f', 'force', None,
4987 _('remove (and delete) file even if added or modified')),
4990 _('remove (and delete) file even if added or modified')),
4988 ] + walkopts,
4991 ] + walkopts,
4989 _('[OPTION]... FILE...'),
4992 _('[OPTION]... FILE...'),
4990 inferrepo=True)
4993 inferrepo=True)
4991 def remove(ui, repo, *pats, **opts):
4994 def remove(ui, repo, *pats, **opts):
4992 """remove the specified files on the next commit
4995 """remove the specified files on the next commit
4993
4996
4994 Schedule the indicated files for removal from the current branch.
4997 Schedule the indicated files for removal from the current branch.
4995
4998
4996 This command schedules the files to be removed at the next commit.
4999 This command schedules the files to be removed at the next commit.
4997 To undo a remove before that, see :hg:`revert`. To undo added
5000 To undo a remove before that, see :hg:`revert`. To undo added
4998 files, see :hg:`forget`.
5001 files, see :hg:`forget`.
4999
5002
5000 .. container:: verbose
5003 .. container:: verbose
5001
5004
5002 -A/--after can be used to remove only files that have already
5005 -A/--after can be used to remove only files that have already
5003 been deleted, -f/--force can be used to force deletion, and -Af
5006 been deleted, -f/--force can be used to force deletion, and -Af
5004 can be used to remove files from the next revision without
5007 can be used to remove files from the next revision without
5005 deleting them from the working directory.
5008 deleting them from the working directory.
5006
5009
5007 The following table details the behavior of remove for different
5010 The following table details the behavior of remove for different
5008 file states (columns) and option combinations (rows). The file
5011 file states (columns) and option combinations (rows). The file
5009 states are Added [A], Clean [C], Modified [M] and Missing [!]
5012 states are Added [A], Clean [C], Modified [M] and Missing [!]
5010 (as reported by :hg:`status`). The actions are Warn, Remove
5013 (as reported by :hg:`status`). The actions are Warn, Remove
5011 (from branch) and Delete (from disk):
5014 (from branch) and Delete (from disk):
5012
5015
5013 ========= == == == ==
5016 ========= == == == ==
5014 opt/state A C M !
5017 opt/state A C M !
5015 ========= == == == ==
5018 ========= == == == ==
5016 none W RD W R
5019 none W RD W R
5017 -f R RD RD R
5020 -f R RD RD R
5018 -A W W W R
5021 -A W W W R
5019 -Af R R R R
5022 -Af R R R R
5020 ========= == == == ==
5023 ========= == == == ==
5021
5024
5022 Note that remove never deletes files in Added [A] state from the
5025 Note that remove never deletes files in Added [A] state from the
5023 working directory, not even if option --force is specified.
5026 working directory, not even if option --force is specified.
5024
5027
5025 Returns 0 on success, 1 if any warnings encountered.
5028 Returns 0 on success, 1 if any warnings encountered.
5026 """
5029 """
5027
5030
5028 ret = 0
5031 ret = 0
5029 after, force = opts.get('after'), opts.get('force')
5032 after, force = opts.get('after'), opts.get('force')
5030 if not pats and not after:
5033 if not pats and not after:
5031 raise util.Abort(_('no files specified'))
5034 raise util.Abort(_('no files specified'))
5032
5035
5033 m = scmutil.match(repo[None], pats, opts)
5036 m = scmutil.match(repo[None], pats, opts)
5034 s = repo.status(match=m, clean=True)
5037 s = repo.status(match=m, clean=True)
5035 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5038 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5036
5039
5037 # warn about failure to delete explicit files/dirs
5040 # warn about failure to delete explicit files/dirs
5038 wctx = repo[None]
5041 wctx = repo[None]
5039 for f in m.files():
5042 for f in m.files():
5040 if f in repo.dirstate or f in wctx.dirs():
5043 if f in repo.dirstate or f in wctx.dirs():
5041 continue
5044 continue
5042 if os.path.exists(m.rel(f)):
5045 if os.path.exists(m.rel(f)):
5043 if os.path.isdir(m.rel(f)):
5046 if os.path.isdir(m.rel(f)):
5044 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5047 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5045 else:
5048 else:
5046 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5049 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5047 # missing files will generate a warning elsewhere
5050 # missing files will generate a warning elsewhere
5048 ret = 1
5051 ret = 1
5049
5052
5050 if force:
5053 if force:
5051 list = modified + deleted + clean + added
5054 list = modified + deleted + clean + added
5052 elif after:
5055 elif after:
5053 list = deleted
5056 list = deleted
5054 for f in modified + added + clean:
5057 for f in modified + added + clean:
5055 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5058 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5056 ret = 1
5059 ret = 1
5057 else:
5060 else:
5058 list = deleted + clean
5061 list = deleted + clean
5059 for f in modified:
5062 for f in modified:
5060 ui.warn(_('not removing %s: file is modified (use -f'
5063 ui.warn(_('not removing %s: file is modified (use -f'
5061 ' to force removal)\n') % m.rel(f))
5064 ' to force removal)\n') % m.rel(f))
5062 ret = 1
5065 ret = 1
5063 for f in added:
5066 for f in added:
5064 ui.warn(_('not removing %s: file has been marked for add'
5067 ui.warn(_('not removing %s: file has been marked for add'
5065 ' (use forget to undo)\n') % m.rel(f))
5068 ' (use forget to undo)\n') % m.rel(f))
5066 ret = 1
5069 ret = 1
5067
5070
5068 for f in sorted(list):
5071 for f in sorted(list):
5069 if ui.verbose or not m.exact(f):
5072 if ui.verbose or not m.exact(f):
5070 ui.status(_('removing %s\n') % m.rel(f))
5073 ui.status(_('removing %s\n') % m.rel(f))
5071
5074
5072 wlock = repo.wlock()
5075 wlock = repo.wlock()
5073 try:
5076 try:
5074 if not after:
5077 if not after:
5075 for f in list:
5078 for f in list:
5076 if f in added:
5079 if f in added:
5077 continue # we never unlink added files on remove
5080 continue # we never unlink added files on remove
5078 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5081 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5079 repo[None].forget(list)
5082 repo[None].forget(list)
5080 finally:
5083 finally:
5081 wlock.release()
5084 wlock.release()
5082
5085
5083 return ret
5086 return ret
5084
5087
5085 @command('rename|move|mv',
5088 @command('rename|move|mv',
5086 [('A', 'after', None, _('record a rename that has already occurred')),
5089 [('A', 'after', None, _('record a rename that has already occurred')),
5087 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5090 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5088 ] + walkopts + dryrunopts,
5091 ] + walkopts + dryrunopts,
5089 _('[OPTION]... SOURCE... DEST'))
5092 _('[OPTION]... SOURCE... DEST'))
5090 def rename(ui, repo, *pats, **opts):
5093 def rename(ui, repo, *pats, **opts):
5091 """rename files; equivalent of copy + remove
5094 """rename files; equivalent of copy + remove
5092
5095
5093 Mark dest as copies of sources; mark sources for deletion. If dest
5096 Mark dest as copies of sources; mark sources for deletion. If dest
5094 is a directory, copies are put in that directory. If dest is a
5097 is a directory, copies are put in that directory. If dest is a
5095 file, there can only be one source.
5098 file, there can only be one source.
5096
5099
5097 By default, this command copies the contents of files as they
5100 By default, this command copies the contents of files as they
5098 exist in the working directory. If invoked with -A/--after, the
5101 exist in the working directory. If invoked with -A/--after, the
5099 operation is recorded, but no copying is performed.
5102 operation is recorded, but no copying is performed.
5100
5103
5101 This command takes effect at the next commit. To undo a rename
5104 This command takes effect at the next commit. To undo a rename
5102 before that, see :hg:`revert`.
5105 before that, see :hg:`revert`.
5103
5106
5104 Returns 0 on success, 1 if errors are encountered.
5107 Returns 0 on success, 1 if errors are encountered.
5105 """
5108 """
5106 wlock = repo.wlock(False)
5109 wlock = repo.wlock(False)
5107 try:
5110 try:
5108 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5111 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5109 finally:
5112 finally:
5110 wlock.release()
5113 wlock.release()
5111
5114
5112 @command('resolve',
5115 @command('resolve',
5113 [('a', 'all', None, _('select all unresolved files')),
5116 [('a', 'all', None, _('select all unresolved files')),
5114 ('l', 'list', None, _('list state of files needing merge')),
5117 ('l', 'list', None, _('list state of files needing merge')),
5115 ('m', 'mark', None, _('mark files as resolved')),
5118 ('m', 'mark', None, _('mark files as resolved')),
5116 ('u', 'unmark', None, _('mark files as unresolved')),
5119 ('u', 'unmark', None, _('mark files as unresolved')),
5117 ('n', 'no-status', None, _('hide status prefix'))]
5120 ('n', 'no-status', None, _('hide status prefix'))]
5118 + mergetoolopts + walkopts,
5121 + mergetoolopts + walkopts,
5119 _('[OPTION]... [FILE]...'),
5122 _('[OPTION]... [FILE]...'),
5120 inferrepo=True)
5123 inferrepo=True)
5121 def resolve(ui, repo, *pats, **opts):
5124 def resolve(ui, repo, *pats, **opts):
5122 """redo merges or set/view the merge status of files
5125 """redo merges or set/view the merge status of files
5123
5126
5124 Merges with unresolved conflicts are often the result of
5127 Merges with unresolved conflicts are often the result of
5125 non-interactive merging using the ``internal:merge`` configuration
5128 non-interactive merging using the ``internal:merge`` configuration
5126 setting, or a command-line merge tool like ``diff3``. The resolve
5129 setting, or a command-line merge tool like ``diff3``. The resolve
5127 command is used to manage the files involved in a merge, after
5130 command is used to manage the files involved in a merge, after
5128 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5131 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5129 working directory must have two parents). See :hg:`help
5132 working directory must have two parents). See :hg:`help
5130 merge-tools` for information on configuring merge tools.
5133 merge-tools` for information on configuring merge tools.
5131
5134
5132 The resolve command can be used in the following ways:
5135 The resolve command can be used in the following ways:
5133
5136
5134 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5137 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5135 files, discarding any previous merge attempts. Re-merging is not
5138 files, discarding any previous merge attempts. Re-merging is not
5136 performed for files already marked as resolved. Use ``--all/-a``
5139 performed for files already marked as resolved. Use ``--all/-a``
5137 to select all unresolved files. ``--tool`` can be used to specify
5140 to select all unresolved files. ``--tool`` can be used to specify
5138 the merge tool used for the given files. It overrides the HGMERGE
5141 the merge tool used for the given files. It overrides the HGMERGE
5139 environment variable and your configuration files. Previous file
5142 environment variable and your configuration files. Previous file
5140 contents are saved with a ``.orig`` suffix.
5143 contents are saved with a ``.orig`` suffix.
5141
5144
5142 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5145 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5143 (e.g. after having manually fixed-up the files). The default is
5146 (e.g. after having manually fixed-up the files). The default is
5144 to mark all unresolved files.
5147 to mark all unresolved files.
5145
5148
5146 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5149 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5147 default is to mark all resolved files.
5150 default is to mark all resolved files.
5148
5151
5149 - :hg:`resolve -l`: list files which had or still have conflicts.
5152 - :hg:`resolve -l`: list files which had or still have conflicts.
5150 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5153 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5151
5154
5152 Note that Mercurial will not let you commit files with unresolved
5155 Note that Mercurial will not let you commit files with unresolved
5153 merge conflicts. You must use :hg:`resolve -m ...` before you can
5156 merge conflicts. You must use :hg:`resolve -m ...` before you can
5154 commit after a conflicting merge.
5157 commit after a conflicting merge.
5155
5158
5156 Returns 0 on success, 1 if any files fail a resolve attempt.
5159 Returns 0 on success, 1 if any files fail a resolve attempt.
5157 """
5160 """
5158
5161
5159 all, mark, unmark, show, nostatus = \
5162 all, mark, unmark, show, nostatus = \
5160 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5163 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5161
5164
5162 if (show and (mark or unmark)) or (mark and unmark):
5165 if (show and (mark or unmark)) or (mark and unmark):
5163 raise util.Abort(_("too many options specified"))
5166 raise util.Abort(_("too many options specified"))
5164 if pats and all:
5167 if pats and all:
5165 raise util.Abort(_("can't specify --all and patterns"))
5168 raise util.Abort(_("can't specify --all and patterns"))
5166 if not (all or pats or show or mark or unmark):
5169 if not (all or pats or show or mark or unmark):
5167 raise util.Abort(_('no files or directories specified'),
5170 raise util.Abort(_('no files or directories specified'),
5168 hint=('use --all to remerge all files'))
5171 hint=('use --all to remerge all files'))
5169
5172
5170 wlock = repo.wlock()
5173 wlock = repo.wlock()
5171 try:
5174 try:
5172 ms = mergemod.mergestate(repo)
5175 ms = mergemod.mergestate(repo)
5173
5176
5174 if not ms.active() and not show:
5177 if not ms.active() and not show:
5175 raise util.Abort(
5178 raise util.Abort(
5176 _('resolve command not applicable when not merging'))
5179 _('resolve command not applicable when not merging'))
5177
5180
5178 m = scmutil.match(repo[None], pats, opts)
5181 m = scmutil.match(repo[None], pats, opts)
5179 ret = 0
5182 ret = 0
5180 didwork = False
5183 didwork = False
5181
5184
5182 for f in ms:
5185 for f in ms:
5183 if not m(f):
5186 if not m(f):
5184 continue
5187 continue
5185
5188
5186 didwork = True
5189 didwork = True
5187
5190
5188 if show:
5191 if show:
5189 if nostatus:
5192 if nostatus:
5190 ui.write("%s\n" % f)
5193 ui.write("%s\n" % f)
5191 else:
5194 else:
5192 ui.write("%s %s\n" % (ms[f].upper(), f),
5195 ui.write("%s %s\n" % (ms[f].upper(), f),
5193 label='resolve.' +
5196 label='resolve.' +
5194 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5197 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5195 elif mark:
5198 elif mark:
5196 ms.mark(f, "r")
5199 ms.mark(f, "r")
5197 elif unmark:
5200 elif unmark:
5198 ms.mark(f, "u")
5201 ms.mark(f, "u")
5199 else:
5202 else:
5200 wctx = repo[None]
5203 wctx = repo[None]
5201
5204
5202 # backup pre-resolve (merge uses .orig for its own purposes)
5205 # backup pre-resolve (merge uses .orig for its own purposes)
5203 a = repo.wjoin(f)
5206 a = repo.wjoin(f)
5204 util.copyfile(a, a + ".resolve")
5207 util.copyfile(a, a + ".resolve")
5205
5208
5206 try:
5209 try:
5207 # resolve file
5210 # resolve file
5208 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5211 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5209 'resolve')
5212 'resolve')
5210 if ms.resolve(f, wctx):
5213 if ms.resolve(f, wctx):
5211 ret = 1
5214 ret = 1
5212 finally:
5215 finally:
5213 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5216 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5214 ms.commit()
5217 ms.commit()
5215
5218
5216 # replace filemerge's .orig file with our resolve file
5219 # replace filemerge's .orig file with our resolve file
5217 util.rename(a + ".resolve", a + ".orig")
5220 util.rename(a + ".resolve", a + ".orig")
5218
5221
5219 ms.commit()
5222 ms.commit()
5220
5223
5221 if not didwork and pats:
5224 if not didwork and pats:
5222 ui.warn(_("arguments do not match paths that need resolving\n"))
5225 ui.warn(_("arguments do not match paths that need resolving\n"))
5223
5226
5224 finally:
5227 finally:
5225 wlock.release()
5228 wlock.release()
5226
5229
5227 # Nudge users into finishing an unfinished operation. We don't print
5230 # Nudge users into finishing an unfinished operation. We don't print
5228 # this with the list/show operation because we want list/show to remain
5231 # this with the list/show operation because we want list/show to remain
5229 # machine readable.
5232 # machine readable.
5230 if not list(ms.unresolved()) and not show:
5233 if not list(ms.unresolved()) and not show:
5231 ui.status(_('(no more unresolved files)\n'))
5234 ui.status(_('(no more unresolved files)\n'))
5232
5235
5233 return ret
5236 return ret
5234
5237
5235 @command('revert',
5238 @command('revert',
5236 [('a', 'all', None, _('revert all changes when no arguments given')),
5239 [('a', 'all', None, _('revert all changes when no arguments given')),
5237 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5240 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5238 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5241 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5239 ('C', 'no-backup', None, _('do not save backup copies of files')),
5242 ('C', 'no-backup', None, _('do not save backup copies of files')),
5240 ] + walkopts + dryrunopts,
5243 ] + walkopts + dryrunopts,
5241 _('[OPTION]... [-r REV] [NAME]...'))
5244 _('[OPTION]... [-r REV] [NAME]...'))
5242 def revert(ui, repo, *pats, **opts):
5245 def revert(ui, repo, *pats, **opts):
5243 """restore files to their checkout state
5246 """restore files to their checkout state
5244
5247
5245 .. note::
5248 .. note::
5246
5249
5247 To check out earlier revisions, you should use :hg:`update REV`.
5250 To check out earlier revisions, you should use :hg:`update REV`.
5248 To cancel an uncommitted merge (and lose your changes),
5251 To cancel an uncommitted merge (and lose your changes),
5249 use :hg:`update --clean .`.
5252 use :hg:`update --clean .`.
5250
5253
5251 With no revision specified, revert the specified files or directories
5254 With no revision specified, revert the specified files or directories
5252 to the contents they had in the parent of the working directory.
5255 to the contents they had in the parent of the working directory.
5253 This restores the contents of files to an unmodified
5256 This restores the contents of files to an unmodified
5254 state and unschedules adds, removes, copies, and renames. If the
5257 state and unschedules adds, removes, copies, and renames. If the
5255 working directory has two parents, you must explicitly specify a
5258 working directory has two parents, you must explicitly specify a
5256 revision.
5259 revision.
5257
5260
5258 Using the -r/--rev or -d/--date options, revert the given files or
5261 Using the -r/--rev or -d/--date options, revert the given files or
5259 directories to their states as of a specific revision. Because
5262 directories to their states as of a specific revision. Because
5260 revert does not change the working directory parents, this will
5263 revert does not change the working directory parents, this will
5261 cause these files to appear modified. This can be helpful to "back
5264 cause these files to appear modified. This can be helpful to "back
5262 out" some or all of an earlier change. See :hg:`backout` for a
5265 out" some or all of an earlier change. See :hg:`backout` for a
5263 related method.
5266 related method.
5264
5267
5265 Modified files are saved with a .orig suffix before reverting.
5268 Modified files are saved with a .orig suffix before reverting.
5266 To disable these backups, use --no-backup.
5269 To disable these backups, use --no-backup.
5267
5270
5268 See :hg:`help dates` for a list of formats valid for -d/--date.
5271 See :hg:`help dates` for a list of formats valid for -d/--date.
5269
5272
5270 Returns 0 on success.
5273 Returns 0 on success.
5271 """
5274 """
5272
5275
5273 if opts.get("date"):
5276 if opts.get("date"):
5274 if opts.get("rev"):
5277 if opts.get("rev"):
5275 raise util.Abort(_("you can't specify a revision and a date"))
5278 raise util.Abort(_("you can't specify a revision and a date"))
5276 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5279 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5277
5280
5278 parent, p2 = repo.dirstate.parents()
5281 parent, p2 = repo.dirstate.parents()
5279 if not opts.get('rev') and p2 != nullid:
5282 if not opts.get('rev') and p2 != nullid:
5280 # revert after merge is a trap for new users (issue2915)
5283 # revert after merge is a trap for new users (issue2915)
5281 raise util.Abort(_('uncommitted merge with no revision specified'),
5284 raise util.Abort(_('uncommitted merge with no revision specified'),
5282 hint=_('use "hg update" or see "hg help revert"'))
5285 hint=_('use "hg update" or see "hg help revert"'))
5283
5286
5284 ctx = scmutil.revsingle(repo, opts.get('rev'))
5287 ctx = scmutil.revsingle(repo, opts.get('rev'))
5285
5288
5286 if not pats and not opts.get('all'):
5289 if not pats and not opts.get('all'):
5287 msg = _("no files or directories specified")
5290 msg = _("no files or directories specified")
5288 if p2 != nullid:
5291 if p2 != nullid:
5289 hint = _("uncommitted merge, use --all to discard all changes,"
5292 hint = _("uncommitted merge, use --all to discard all changes,"
5290 " or 'hg update -C .' to abort the merge")
5293 " or 'hg update -C .' to abort the merge")
5291 raise util.Abort(msg, hint=hint)
5294 raise util.Abort(msg, hint=hint)
5292 dirty = util.any(repo.status())
5295 dirty = util.any(repo.status())
5293 node = ctx.node()
5296 node = ctx.node()
5294 if node != parent:
5297 if node != parent:
5295 if dirty:
5298 if dirty:
5296 hint = _("uncommitted changes, use --all to discard all"
5299 hint = _("uncommitted changes, use --all to discard all"
5297 " changes, or 'hg update %s' to update") % ctx.rev()
5300 " changes, or 'hg update %s' to update") % ctx.rev()
5298 else:
5301 else:
5299 hint = _("use --all to revert all files,"
5302 hint = _("use --all to revert all files,"
5300 " or 'hg update %s' to update") % ctx.rev()
5303 " or 'hg update %s' to update") % ctx.rev()
5301 elif dirty:
5304 elif dirty:
5302 hint = _("uncommitted changes, use --all to discard all changes")
5305 hint = _("uncommitted changes, use --all to discard all changes")
5303 else:
5306 else:
5304 hint = _("use --all to revert all files")
5307 hint = _("use --all to revert all files")
5305 raise util.Abort(msg, hint=hint)
5308 raise util.Abort(msg, hint=hint)
5306
5309
5307 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5310 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5308
5311
5309 @command('rollback', dryrunopts +
5312 @command('rollback', dryrunopts +
5310 [('f', 'force', False, _('ignore safety measures'))])
5313 [('f', 'force', False, _('ignore safety measures'))])
5311 def rollback(ui, repo, **opts):
5314 def rollback(ui, repo, **opts):
5312 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5315 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5313
5316
5314 Please use :hg:`commit --amend` instead of rollback to correct
5317 Please use :hg:`commit --amend` instead of rollback to correct
5315 mistakes in the last commit.
5318 mistakes in the last commit.
5316
5319
5317 This command should be used with care. There is only one level of
5320 This command should be used with care. There is only one level of
5318 rollback, and there is no way to undo a rollback. It will also
5321 rollback, and there is no way to undo a rollback. It will also
5319 restore the dirstate at the time of the last transaction, losing
5322 restore the dirstate at the time of the last transaction, losing
5320 any dirstate changes since that time. This command does not alter
5323 any dirstate changes since that time. This command does not alter
5321 the working directory.
5324 the working directory.
5322
5325
5323 Transactions are used to encapsulate the effects of all commands
5326 Transactions are used to encapsulate the effects of all commands
5324 that create new changesets or propagate existing changesets into a
5327 that create new changesets or propagate existing changesets into a
5325 repository.
5328 repository.
5326
5329
5327 .. container:: verbose
5330 .. container:: verbose
5328
5331
5329 For example, the following commands are transactional, and their
5332 For example, the following commands are transactional, and their
5330 effects can be rolled back:
5333 effects can be rolled back:
5331
5334
5332 - commit
5335 - commit
5333 - import
5336 - import
5334 - pull
5337 - pull
5335 - push (with this repository as the destination)
5338 - push (with this repository as the destination)
5336 - unbundle
5339 - unbundle
5337
5340
5338 To avoid permanent data loss, rollback will refuse to rollback a
5341 To avoid permanent data loss, rollback will refuse to rollback a
5339 commit transaction if it isn't checked out. Use --force to
5342 commit transaction if it isn't checked out. Use --force to
5340 override this protection.
5343 override this protection.
5341
5344
5342 This command is not intended for use on public repositories. Once
5345 This command is not intended for use on public repositories. Once
5343 changes are visible for pull by other users, rolling a transaction
5346 changes are visible for pull by other users, rolling a transaction
5344 back locally is ineffective (someone else may already have pulled
5347 back locally is ineffective (someone else may already have pulled
5345 the changes). Furthermore, a race is possible with readers of the
5348 the changes). Furthermore, a race is possible with readers of the
5346 repository; for example an in-progress pull from the repository
5349 repository; for example an in-progress pull from the repository
5347 may fail if a rollback is performed.
5350 may fail if a rollback is performed.
5348
5351
5349 Returns 0 on success, 1 if no rollback data is available.
5352 Returns 0 on success, 1 if no rollback data is available.
5350 """
5353 """
5351 return repo.rollback(dryrun=opts.get('dry_run'),
5354 return repo.rollback(dryrun=opts.get('dry_run'),
5352 force=opts.get('force'))
5355 force=opts.get('force'))
5353
5356
5354 @command('root', [])
5357 @command('root', [])
5355 def root(ui, repo):
5358 def root(ui, repo):
5356 """print the root (top) of the current working directory
5359 """print the root (top) of the current working directory
5357
5360
5358 Print the root directory of the current repository.
5361 Print the root directory of the current repository.
5359
5362
5360 Returns 0 on success.
5363 Returns 0 on success.
5361 """
5364 """
5362 ui.write(repo.root + "\n")
5365 ui.write(repo.root + "\n")
5363
5366
5364 @command('^serve',
5367 @command('^serve',
5365 [('A', 'accesslog', '', _('name of access log file to write to'),
5368 [('A', 'accesslog', '', _('name of access log file to write to'),
5366 _('FILE')),
5369 _('FILE')),
5367 ('d', 'daemon', None, _('run server in background')),
5370 ('d', 'daemon', None, _('run server in background')),
5368 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5371 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5369 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5372 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5370 # use string type, then we can check if something was passed
5373 # use string type, then we can check if something was passed
5371 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5374 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5372 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5375 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5373 _('ADDR')),
5376 _('ADDR')),
5374 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5377 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5375 _('PREFIX')),
5378 _('PREFIX')),
5376 ('n', 'name', '',
5379 ('n', 'name', '',
5377 _('name to show in web pages (default: working directory)'), _('NAME')),
5380 _('name to show in web pages (default: working directory)'), _('NAME')),
5378 ('', 'web-conf', '',
5381 ('', 'web-conf', '',
5379 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5382 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5380 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5383 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5381 _('FILE')),
5384 _('FILE')),
5382 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5385 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5383 ('', 'stdio', None, _('for remote clients')),
5386 ('', 'stdio', None, _('for remote clients')),
5384 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5387 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5385 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5388 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5386 ('', 'style', '', _('template style to use'), _('STYLE')),
5389 ('', 'style', '', _('template style to use'), _('STYLE')),
5387 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5390 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5388 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5391 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5389 _('[OPTION]...'),
5392 _('[OPTION]...'),
5390 optionalrepo=True)
5393 optionalrepo=True)
5391 def serve(ui, repo, **opts):
5394 def serve(ui, repo, **opts):
5392 """start stand-alone webserver
5395 """start stand-alone webserver
5393
5396
5394 Start a local HTTP repository browser and pull server. You can use
5397 Start a local HTTP repository browser and pull server. You can use
5395 this for ad-hoc sharing and browsing of repositories. It is
5398 this for ad-hoc sharing and browsing of repositories. It is
5396 recommended to use a real web server to serve a repository for
5399 recommended to use a real web server to serve a repository for
5397 longer periods of time.
5400 longer periods of time.
5398
5401
5399 Please note that the server does not implement access control.
5402 Please note that the server does not implement access control.
5400 This means that, by default, anybody can read from the server and
5403 This means that, by default, anybody can read from the server and
5401 nobody can write to it by default. Set the ``web.allow_push``
5404 nobody can write to it by default. Set the ``web.allow_push``
5402 option to ``*`` to allow everybody to push to the server. You
5405 option to ``*`` to allow everybody to push to the server. You
5403 should use a real web server if you need to authenticate users.
5406 should use a real web server if you need to authenticate users.
5404
5407
5405 By default, the server logs accesses to stdout and errors to
5408 By default, the server logs accesses to stdout and errors to
5406 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5409 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5407 files.
5410 files.
5408
5411
5409 To have the server choose a free port number to listen on, specify
5412 To have the server choose a free port number to listen on, specify
5410 a port number of 0; in this case, the server will print the port
5413 a port number of 0; in this case, the server will print the port
5411 number it uses.
5414 number it uses.
5412
5415
5413 Returns 0 on success.
5416 Returns 0 on success.
5414 """
5417 """
5415
5418
5416 if opts["stdio"] and opts["cmdserver"]:
5419 if opts["stdio"] and opts["cmdserver"]:
5417 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5420 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5418
5421
5419 if opts["stdio"]:
5422 if opts["stdio"]:
5420 if repo is None:
5423 if repo is None:
5421 raise error.RepoError(_("there is no Mercurial repository here"
5424 raise error.RepoError(_("there is no Mercurial repository here"
5422 " (.hg not found)"))
5425 " (.hg not found)"))
5423 s = sshserver.sshserver(ui, repo)
5426 s = sshserver.sshserver(ui, repo)
5424 s.serve_forever()
5427 s.serve_forever()
5425
5428
5426 if opts["cmdserver"]:
5429 if opts["cmdserver"]:
5427 s = commandserver.server(ui, repo, opts["cmdserver"])
5430 s = commandserver.server(ui, repo, opts["cmdserver"])
5428 return s.serve()
5431 return s.serve()
5429
5432
5430 # this way we can check if something was given in the command-line
5433 # this way we can check if something was given in the command-line
5431 if opts.get('port'):
5434 if opts.get('port'):
5432 opts['port'] = util.getport(opts.get('port'))
5435 opts['port'] = util.getport(opts.get('port'))
5433
5436
5434 baseui = repo and repo.baseui or ui
5437 baseui = repo and repo.baseui or ui
5435 optlist = ("name templates style address port prefix ipv6"
5438 optlist = ("name templates style address port prefix ipv6"
5436 " accesslog errorlog certificate encoding")
5439 " accesslog errorlog certificate encoding")
5437 for o in optlist.split():
5440 for o in optlist.split():
5438 val = opts.get(o, '')
5441 val = opts.get(o, '')
5439 if val in (None, ''): # should check against default options instead
5442 if val in (None, ''): # should check against default options instead
5440 continue
5443 continue
5441 baseui.setconfig("web", o, val, 'serve')
5444 baseui.setconfig("web", o, val, 'serve')
5442 if repo and repo.ui != baseui:
5445 if repo and repo.ui != baseui:
5443 repo.ui.setconfig("web", o, val, 'serve')
5446 repo.ui.setconfig("web", o, val, 'serve')
5444
5447
5445 o = opts.get('web_conf') or opts.get('webdir_conf')
5448 o = opts.get('web_conf') or opts.get('webdir_conf')
5446 if not o:
5449 if not o:
5447 if not repo:
5450 if not repo:
5448 raise error.RepoError(_("there is no Mercurial repository"
5451 raise error.RepoError(_("there is no Mercurial repository"
5449 " here (.hg not found)"))
5452 " here (.hg not found)"))
5450 o = repo
5453 o = repo
5451
5454
5452 app = hgweb.hgweb(o, baseui=baseui)
5455 app = hgweb.hgweb(o, baseui=baseui)
5453 service = httpservice(ui, app, opts)
5456 service = httpservice(ui, app, opts)
5454 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5457 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5455
5458
5456 class httpservice(object):
5459 class httpservice(object):
5457 def __init__(self, ui, app, opts):
5460 def __init__(self, ui, app, opts):
5458 self.ui = ui
5461 self.ui = ui
5459 self.app = app
5462 self.app = app
5460 self.opts = opts
5463 self.opts = opts
5461
5464
5462 def init(self):
5465 def init(self):
5463 util.setsignalhandler()
5466 util.setsignalhandler()
5464 self.httpd = hgweb_server.create_server(self.ui, self.app)
5467 self.httpd = hgweb_server.create_server(self.ui, self.app)
5465
5468
5466 if self.opts['port'] and not self.ui.verbose:
5469 if self.opts['port'] and not self.ui.verbose:
5467 return
5470 return
5468
5471
5469 if self.httpd.prefix:
5472 if self.httpd.prefix:
5470 prefix = self.httpd.prefix.strip('/') + '/'
5473 prefix = self.httpd.prefix.strip('/') + '/'
5471 else:
5474 else:
5472 prefix = ''
5475 prefix = ''
5473
5476
5474 port = ':%d' % self.httpd.port
5477 port = ':%d' % self.httpd.port
5475 if port == ':80':
5478 if port == ':80':
5476 port = ''
5479 port = ''
5477
5480
5478 bindaddr = self.httpd.addr
5481 bindaddr = self.httpd.addr
5479 if bindaddr == '0.0.0.0':
5482 if bindaddr == '0.0.0.0':
5480 bindaddr = '*'
5483 bindaddr = '*'
5481 elif ':' in bindaddr: # IPv6
5484 elif ':' in bindaddr: # IPv6
5482 bindaddr = '[%s]' % bindaddr
5485 bindaddr = '[%s]' % bindaddr
5483
5486
5484 fqaddr = self.httpd.fqaddr
5487 fqaddr = self.httpd.fqaddr
5485 if ':' in fqaddr:
5488 if ':' in fqaddr:
5486 fqaddr = '[%s]' % fqaddr
5489 fqaddr = '[%s]' % fqaddr
5487 if self.opts['port']:
5490 if self.opts['port']:
5488 write = self.ui.status
5491 write = self.ui.status
5489 else:
5492 else:
5490 write = self.ui.write
5493 write = self.ui.write
5491 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5494 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5492 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5495 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5493 self.ui.flush() # avoid buffering of status message
5496 self.ui.flush() # avoid buffering of status message
5494
5497
5495 def run(self):
5498 def run(self):
5496 self.httpd.serve_forever()
5499 self.httpd.serve_forever()
5497
5500
5498
5501
5499 @command('^status|st',
5502 @command('^status|st',
5500 [('A', 'all', None, _('show status of all files')),
5503 [('A', 'all', None, _('show status of all files')),
5501 ('m', 'modified', None, _('show only modified files')),
5504 ('m', 'modified', None, _('show only modified files')),
5502 ('a', 'added', None, _('show only added files')),
5505 ('a', 'added', None, _('show only added files')),
5503 ('r', 'removed', None, _('show only removed files')),
5506 ('r', 'removed', None, _('show only removed files')),
5504 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5507 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5505 ('c', 'clean', None, _('show only files without changes')),
5508 ('c', 'clean', None, _('show only files without changes')),
5506 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5509 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5507 ('i', 'ignored', None, _('show only ignored files')),
5510 ('i', 'ignored', None, _('show only ignored files')),
5508 ('n', 'no-status', None, _('hide status prefix')),
5511 ('n', 'no-status', None, _('hide status prefix')),
5509 ('C', 'copies', None, _('show source of copied files')),
5512 ('C', 'copies', None, _('show source of copied files')),
5510 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5513 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5511 ('', 'rev', [], _('show difference from revision'), _('REV')),
5514 ('', 'rev', [], _('show difference from revision'), _('REV')),
5512 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5515 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5513 ] + walkopts + subrepoopts + formatteropts,
5516 ] + walkopts + subrepoopts + formatteropts,
5514 _('[OPTION]... [FILE]...'),
5517 _('[OPTION]... [FILE]...'),
5515 inferrepo=True)
5518 inferrepo=True)
5516 def status(ui, repo, *pats, **opts):
5519 def status(ui, repo, *pats, **opts):
5517 """show changed files in the working directory
5520 """show changed files in the working directory
5518
5521
5519 Show status of files in the repository. If names are given, only
5522 Show status of files in the repository. If names are given, only
5520 files that match are shown. Files that are clean or ignored or
5523 files that match are shown. Files that are clean or ignored or
5521 the source of a copy/move operation, are not listed unless
5524 the source of a copy/move operation, are not listed unless
5522 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5525 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5523 Unless options described with "show only ..." are given, the
5526 Unless options described with "show only ..." are given, the
5524 options -mardu are used.
5527 options -mardu are used.
5525
5528
5526 Option -q/--quiet hides untracked (unknown and ignored) files
5529 Option -q/--quiet hides untracked (unknown and ignored) files
5527 unless explicitly requested with -u/--unknown or -i/--ignored.
5530 unless explicitly requested with -u/--unknown or -i/--ignored.
5528
5531
5529 .. note::
5532 .. note::
5530
5533
5531 status may appear to disagree with diff if permissions have
5534 status may appear to disagree with diff if permissions have
5532 changed or a merge has occurred. The standard diff format does
5535 changed or a merge has occurred. The standard diff format does
5533 not report permission changes and diff only reports changes
5536 not report permission changes and diff only reports changes
5534 relative to one merge parent.
5537 relative to one merge parent.
5535
5538
5536 If one revision is given, it is used as the base revision.
5539 If one revision is given, it is used as the base revision.
5537 If two revisions are given, the differences between them are
5540 If two revisions are given, the differences between them are
5538 shown. The --change option can also be used as a shortcut to list
5541 shown. The --change option can also be used as a shortcut to list
5539 the changed files of a revision from its first parent.
5542 the changed files of a revision from its first parent.
5540
5543
5541 The codes used to show the status of files are::
5544 The codes used to show the status of files are::
5542
5545
5543 M = modified
5546 M = modified
5544 A = added
5547 A = added
5545 R = removed
5548 R = removed
5546 C = clean
5549 C = clean
5547 ! = missing (deleted by non-hg command, but still tracked)
5550 ! = missing (deleted by non-hg command, but still tracked)
5548 ? = not tracked
5551 ? = not tracked
5549 I = ignored
5552 I = ignored
5550 = origin of the previous file (with --copies)
5553 = origin of the previous file (with --copies)
5551
5554
5552 .. container:: verbose
5555 .. container:: verbose
5553
5556
5554 Examples:
5557 Examples:
5555
5558
5556 - show changes in the working directory relative to a
5559 - show changes in the working directory relative to a
5557 changeset::
5560 changeset::
5558
5561
5559 hg status --rev 9353
5562 hg status --rev 9353
5560
5563
5561 - show all changes including copies in an existing changeset::
5564 - show all changes including copies in an existing changeset::
5562
5565
5563 hg status --copies --change 9353
5566 hg status --copies --change 9353
5564
5567
5565 - get a NUL separated list of added files, suitable for xargs::
5568 - get a NUL separated list of added files, suitable for xargs::
5566
5569
5567 hg status -an0
5570 hg status -an0
5568
5571
5569 Returns 0 on success.
5572 Returns 0 on success.
5570 """
5573 """
5571
5574
5572 revs = opts.get('rev')
5575 revs = opts.get('rev')
5573 change = opts.get('change')
5576 change = opts.get('change')
5574
5577
5575 if revs and change:
5578 if revs and change:
5576 msg = _('cannot specify --rev and --change at the same time')
5579 msg = _('cannot specify --rev and --change at the same time')
5577 raise util.Abort(msg)
5580 raise util.Abort(msg)
5578 elif change:
5581 elif change:
5579 node2 = scmutil.revsingle(repo, change, None).node()
5582 node2 = scmutil.revsingle(repo, change, None).node()
5580 node1 = repo[node2].p1().node()
5583 node1 = repo[node2].p1().node()
5581 else:
5584 else:
5582 node1, node2 = scmutil.revpair(repo, revs)
5585 node1, node2 = scmutil.revpair(repo, revs)
5583
5586
5584 cwd = (pats and repo.getcwd()) or ''
5587 cwd = (pats and repo.getcwd()) or ''
5585 end = opts.get('print0') and '\0' or '\n'
5588 end = opts.get('print0') and '\0' or '\n'
5586 copy = {}
5589 copy = {}
5587 states = 'modified added removed deleted unknown ignored clean'.split()
5590 states = 'modified added removed deleted unknown ignored clean'.split()
5588 show = [k for k in states if opts.get(k)]
5591 show = [k for k in states if opts.get(k)]
5589 if opts.get('all'):
5592 if opts.get('all'):
5590 show += ui.quiet and (states[:4] + ['clean']) or states
5593 show += ui.quiet and (states[:4] + ['clean']) or states
5591 if not show:
5594 if not show:
5592 show = ui.quiet and states[:4] or states[:5]
5595 show = ui.quiet and states[:4] or states[:5]
5593
5596
5594 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5597 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5595 'ignored' in show, 'clean' in show, 'unknown' in show,
5598 'ignored' in show, 'clean' in show, 'unknown' in show,
5596 opts.get('subrepos'))
5599 opts.get('subrepos'))
5597 changestates = zip(states, 'MAR!?IC', stat)
5600 changestates = zip(states, 'MAR!?IC', stat)
5598
5601
5599 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5602 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5600 copy = copies.pathcopies(repo[node1], repo[node2])
5603 copy = copies.pathcopies(repo[node1], repo[node2])
5601
5604
5602 fm = ui.formatter('status', opts)
5605 fm = ui.formatter('status', opts)
5603 fmt = '%s' + end
5606 fmt = '%s' + end
5604 showchar = not opts.get('no_status')
5607 showchar = not opts.get('no_status')
5605
5608
5606 for state, char, files in changestates:
5609 for state, char, files in changestates:
5607 if state in show:
5610 if state in show:
5608 label = 'status.' + state
5611 label = 'status.' + state
5609 for f in files:
5612 for f in files:
5610 fm.startitem()
5613 fm.startitem()
5611 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5614 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5612 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5615 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5613 if f in copy:
5616 if f in copy:
5614 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5617 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5615 label='status.copied')
5618 label='status.copied')
5616 fm.end()
5619 fm.end()
5617
5620
5618 @command('^summary|sum',
5621 @command('^summary|sum',
5619 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5622 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5620 def summary(ui, repo, **opts):
5623 def summary(ui, repo, **opts):
5621 """summarize working directory state
5624 """summarize working directory state
5622
5625
5623 This generates a brief summary of the working directory state,
5626 This generates a brief summary of the working directory state,
5624 including parents, branch, commit status, and available updates.
5627 including parents, branch, commit status, and available updates.
5625
5628
5626 With the --remote option, this will check the default paths for
5629 With the --remote option, this will check the default paths for
5627 incoming and outgoing changes. This can be time-consuming.
5630 incoming and outgoing changes. This can be time-consuming.
5628
5631
5629 Returns 0 on success.
5632 Returns 0 on success.
5630 """
5633 """
5631
5634
5632 ctx = repo[None]
5635 ctx = repo[None]
5633 parents = ctx.parents()
5636 parents = ctx.parents()
5634 pnode = parents[0].node()
5637 pnode = parents[0].node()
5635 marks = []
5638 marks = []
5636
5639
5637 for p in parents:
5640 for p in parents:
5638 # label with log.changeset (instead of log.parent) since this
5641 # label with log.changeset (instead of log.parent) since this
5639 # shows a working directory parent *changeset*:
5642 # shows a working directory parent *changeset*:
5640 # i18n: column positioning for "hg summary"
5643 # i18n: column positioning for "hg summary"
5641 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5644 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5642 label='log.changeset changeset.%s' % p.phasestr())
5645 label='log.changeset changeset.%s' % p.phasestr())
5643 ui.write(' '.join(p.tags()), label='log.tag')
5646 ui.write(' '.join(p.tags()), label='log.tag')
5644 if p.bookmarks():
5647 if p.bookmarks():
5645 marks.extend(p.bookmarks())
5648 marks.extend(p.bookmarks())
5646 if p.rev() == -1:
5649 if p.rev() == -1:
5647 if not len(repo):
5650 if not len(repo):
5648 ui.write(_(' (empty repository)'))
5651 ui.write(_(' (empty repository)'))
5649 else:
5652 else:
5650 ui.write(_(' (no revision checked out)'))
5653 ui.write(_(' (no revision checked out)'))
5651 ui.write('\n')
5654 ui.write('\n')
5652 if p.description():
5655 if p.description():
5653 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5656 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5654 label='log.summary')
5657 label='log.summary')
5655
5658
5656 branch = ctx.branch()
5659 branch = ctx.branch()
5657 bheads = repo.branchheads(branch)
5660 bheads = repo.branchheads(branch)
5658 # i18n: column positioning for "hg summary"
5661 # i18n: column positioning for "hg summary"
5659 m = _('branch: %s\n') % branch
5662 m = _('branch: %s\n') % branch
5660 if branch != 'default':
5663 if branch != 'default':
5661 ui.write(m, label='log.branch')
5664 ui.write(m, label='log.branch')
5662 else:
5665 else:
5663 ui.status(m, label='log.branch')
5666 ui.status(m, label='log.branch')
5664
5667
5665 if marks:
5668 if marks:
5666 current = repo._bookmarkcurrent
5669 current = repo._bookmarkcurrent
5667 # i18n: column positioning for "hg summary"
5670 # i18n: column positioning for "hg summary"
5668 ui.write(_('bookmarks:'), label='log.bookmark')
5671 ui.write(_('bookmarks:'), label='log.bookmark')
5669 if current is not None:
5672 if current is not None:
5670 if current in marks:
5673 if current in marks:
5671 ui.write(' *' + current, label='bookmarks.current')
5674 ui.write(' *' + current, label='bookmarks.current')
5672 marks.remove(current)
5675 marks.remove(current)
5673 else:
5676 else:
5674 ui.write(' [%s]' % current, label='bookmarks.current')
5677 ui.write(' [%s]' % current, label='bookmarks.current')
5675 for m in marks:
5678 for m in marks:
5676 ui.write(' ' + m, label='log.bookmark')
5679 ui.write(' ' + m, label='log.bookmark')
5677 ui.write('\n', label='log.bookmark')
5680 ui.write('\n', label='log.bookmark')
5678
5681
5679 st = list(repo.status(unknown=True))[:6]
5682 st = list(repo.status(unknown=True))[:6]
5680
5683
5681 c = repo.dirstate.copies()
5684 c = repo.dirstate.copies()
5682 copied, renamed = [], []
5685 copied, renamed = [], []
5683 for d, s in c.iteritems():
5686 for d, s in c.iteritems():
5684 if s in st[2]:
5687 if s in st[2]:
5685 st[2].remove(s)
5688 st[2].remove(s)
5686 renamed.append(d)
5689 renamed.append(d)
5687 else:
5690 else:
5688 copied.append(d)
5691 copied.append(d)
5689 if d in st[1]:
5692 if d in st[1]:
5690 st[1].remove(d)
5693 st[1].remove(d)
5691 st.insert(3, renamed)
5694 st.insert(3, renamed)
5692 st.insert(4, copied)
5695 st.insert(4, copied)
5693
5696
5694 ms = mergemod.mergestate(repo)
5697 ms = mergemod.mergestate(repo)
5695 st.append([f for f in ms if ms[f] == 'u'])
5698 st.append([f for f in ms if ms[f] == 'u'])
5696
5699
5697 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5700 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5698 st.append(subs)
5701 st.append(subs)
5699
5702
5700 labels = [ui.label(_('%d modified'), 'status.modified'),
5703 labels = [ui.label(_('%d modified'), 'status.modified'),
5701 ui.label(_('%d added'), 'status.added'),
5704 ui.label(_('%d added'), 'status.added'),
5702 ui.label(_('%d removed'), 'status.removed'),
5705 ui.label(_('%d removed'), 'status.removed'),
5703 ui.label(_('%d renamed'), 'status.copied'),
5706 ui.label(_('%d renamed'), 'status.copied'),
5704 ui.label(_('%d copied'), 'status.copied'),
5707 ui.label(_('%d copied'), 'status.copied'),
5705 ui.label(_('%d deleted'), 'status.deleted'),
5708 ui.label(_('%d deleted'), 'status.deleted'),
5706 ui.label(_('%d unknown'), 'status.unknown'),
5709 ui.label(_('%d unknown'), 'status.unknown'),
5707 ui.label(_('%d ignored'), 'status.ignored'),
5710 ui.label(_('%d ignored'), 'status.ignored'),
5708 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5711 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5709 ui.label(_('%d subrepos'), 'status.modified')]
5712 ui.label(_('%d subrepos'), 'status.modified')]
5710 t = []
5713 t = []
5711 for s, l in zip(st, labels):
5714 for s, l in zip(st, labels):
5712 if s:
5715 if s:
5713 t.append(l % len(s))
5716 t.append(l % len(s))
5714
5717
5715 t = ', '.join(t)
5718 t = ', '.join(t)
5716 cleanworkdir = False
5719 cleanworkdir = False
5717
5720
5718 if repo.vfs.exists('updatestate'):
5721 if repo.vfs.exists('updatestate'):
5719 t += _(' (interrupted update)')
5722 t += _(' (interrupted update)')
5720 elif len(parents) > 1:
5723 elif len(parents) > 1:
5721 t += _(' (merge)')
5724 t += _(' (merge)')
5722 elif branch != parents[0].branch():
5725 elif branch != parents[0].branch():
5723 t += _(' (new branch)')
5726 t += _(' (new branch)')
5724 elif (parents[0].closesbranch() and
5727 elif (parents[0].closesbranch() and
5725 pnode in repo.branchheads(branch, closed=True)):
5728 pnode in repo.branchheads(branch, closed=True)):
5726 t += _(' (head closed)')
5729 t += _(' (head closed)')
5727 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5730 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5728 t += _(' (clean)')
5731 t += _(' (clean)')
5729 cleanworkdir = True
5732 cleanworkdir = True
5730 elif pnode not in bheads:
5733 elif pnode not in bheads:
5731 t += _(' (new branch head)')
5734 t += _(' (new branch head)')
5732
5735
5733 if cleanworkdir:
5736 if cleanworkdir:
5734 # i18n: column positioning for "hg summary"
5737 # i18n: column positioning for "hg summary"
5735 ui.status(_('commit: %s\n') % t.strip())
5738 ui.status(_('commit: %s\n') % t.strip())
5736 else:
5739 else:
5737 # i18n: column positioning for "hg summary"
5740 # i18n: column positioning for "hg summary"
5738 ui.write(_('commit: %s\n') % t.strip())
5741 ui.write(_('commit: %s\n') % t.strip())
5739
5742
5740 # all ancestors of branch heads - all ancestors of parent = new csets
5743 # all ancestors of branch heads - all ancestors of parent = new csets
5741 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5744 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5742 bheads))
5745 bheads))
5743
5746
5744 if new == 0:
5747 if new == 0:
5745 # i18n: column positioning for "hg summary"
5748 # i18n: column positioning for "hg summary"
5746 ui.status(_('update: (current)\n'))
5749 ui.status(_('update: (current)\n'))
5747 elif pnode not in bheads:
5750 elif pnode not in bheads:
5748 # i18n: column positioning for "hg summary"
5751 # i18n: column positioning for "hg summary"
5749 ui.write(_('update: %d new changesets (update)\n') % new)
5752 ui.write(_('update: %d new changesets (update)\n') % new)
5750 else:
5753 else:
5751 # i18n: column positioning for "hg summary"
5754 # i18n: column positioning for "hg summary"
5752 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5755 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5753 (new, len(bheads)))
5756 (new, len(bheads)))
5754
5757
5755 cmdutil.summaryhooks(ui, repo)
5758 cmdutil.summaryhooks(ui, repo)
5756
5759
5757 if opts.get('remote'):
5760 if opts.get('remote'):
5758 needsincoming, needsoutgoing = True, True
5761 needsincoming, needsoutgoing = True, True
5759 else:
5762 else:
5760 needsincoming, needsoutgoing = False, False
5763 needsincoming, needsoutgoing = False, False
5761 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5764 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5762 if i:
5765 if i:
5763 needsincoming = True
5766 needsincoming = True
5764 if o:
5767 if o:
5765 needsoutgoing = True
5768 needsoutgoing = True
5766 if not needsincoming and not needsoutgoing:
5769 if not needsincoming and not needsoutgoing:
5767 return
5770 return
5768
5771
5769 def getincoming():
5772 def getincoming():
5770 source, branches = hg.parseurl(ui.expandpath('default'))
5773 source, branches = hg.parseurl(ui.expandpath('default'))
5771 sbranch = branches[0]
5774 sbranch = branches[0]
5772 try:
5775 try:
5773 other = hg.peer(repo, {}, source)
5776 other = hg.peer(repo, {}, source)
5774 except error.RepoError:
5777 except error.RepoError:
5775 if opts.get('remote'):
5778 if opts.get('remote'):
5776 raise
5779 raise
5777 return source, sbranch, None, None, None
5780 return source, sbranch, None, None, None
5778 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5781 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5779 if revs:
5782 if revs:
5780 revs = [other.lookup(rev) for rev in revs]
5783 revs = [other.lookup(rev) for rev in revs]
5781 ui.debug('comparing with %s\n' % util.hidepassword(source))
5784 ui.debug('comparing with %s\n' % util.hidepassword(source))
5782 repo.ui.pushbuffer()
5785 repo.ui.pushbuffer()
5783 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5786 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5784 repo.ui.popbuffer()
5787 repo.ui.popbuffer()
5785 return source, sbranch, other, commoninc, commoninc[1]
5788 return source, sbranch, other, commoninc, commoninc[1]
5786
5789
5787 if needsincoming:
5790 if needsincoming:
5788 source, sbranch, sother, commoninc, incoming = getincoming()
5791 source, sbranch, sother, commoninc, incoming = getincoming()
5789 else:
5792 else:
5790 source = sbranch = sother = commoninc = incoming = None
5793 source = sbranch = sother = commoninc = incoming = None
5791
5794
5792 def getoutgoing():
5795 def getoutgoing():
5793 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5796 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5794 dbranch = branches[0]
5797 dbranch = branches[0]
5795 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5798 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5796 if source != dest:
5799 if source != dest:
5797 try:
5800 try:
5798 dother = hg.peer(repo, {}, dest)
5801 dother = hg.peer(repo, {}, dest)
5799 except error.RepoError:
5802 except error.RepoError:
5800 if opts.get('remote'):
5803 if opts.get('remote'):
5801 raise
5804 raise
5802 return dest, dbranch, None, None
5805 return dest, dbranch, None, None
5803 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5806 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5804 elif sother is None:
5807 elif sother is None:
5805 # there is no explicit destination peer, but source one is invalid
5808 # there is no explicit destination peer, but source one is invalid
5806 return dest, dbranch, None, None
5809 return dest, dbranch, None, None
5807 else:
5810 else:
5808 dother = sother
5811 dother = sother
5809 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5812 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5810 common = None
5813 common = None
5811 else:
5814 else:
5812 common = commoninc
5815 common = commoninc
5813 if revs:
5816 if revs:
5814 revs = [repo.lookup(rev) for rev in revs]
5817 revs = [repo.lookup(rev) for rev in revs]
5815 repo.ui.pushbuffer()
5818 repo.ui.pushbuffer()
5816 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5819 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5817 commoninc=common)
5820 commoninc=common)
5818 repo.ui.popbuffer()
5821 repo.ui.popbuffer()
5819 return dest, dbranch, dother, outgoing
5822 return dest, dbranch, dother, outgoing
5820
5823
5821 if needsoutgoing:
5824 if needsoutgoing:
5822 dest, dbranch, dother, outgoing = getoutgoing()
5825 dest, dbranch, dother, outgoing = getoutgoing()
5823 else:
5826 else:
5824 dest = dbranch = dother = outgoing = None
5827 dest = dbranch = dother = outgoing = None
5825
5828
5826 if opts.get('remote'):
5829 if opts.get('remote'):
5827 t = []
5830 t = []
5828 if incoming:
5831 if incoming:
5829 t.append(_('1 or more incoming'))
5832 t.append(_('1 or more incoming'))
5830 o = outgoing.missing
5833 o = outgoing.missing
5831 if o:
5834 if o:
5832 t.append(_('%d outgoing') % len(o))
5835 t.append(_('%d outgoing') % len(o))
5833 other = dother or sother
5836 other = dother or sother
5834 if 'bookmarks' in other.listkeys('namespaces'):
5837 if 'bookmarks' in other.listkeys('namespaces'):
5835 lmarks = repo.listkeys('bookmarks')
5838 lmarks = repo.listkeys('bookmarks')
5836 rmarks = other.listkeys('bookmarks')
5839 rmarks = other.listkeys('bookmarks')
5837 diff = set(rmarks) - set(lmarks)
5840 diff = set(rmarks) - set(lmarks)
5838 if len(diff) > 0:
5841 if len(diff) > 0:
5839 t.append(_('%d incoming bookmarks') % len(diff))
5842 t.append(_('%d incoming bookmarks') % len(diff))
5840 diff = set(lmarks) - set(rmarks)
5843 diff = set(lmarks) - set(rmarks)
5841 if len(diff) > 0:
5844 if len(diff) > 0:
5842 t.append(_('%d outgoing bookmarks') % len(diff))
5845 t.append(_('%d outgoing bookmarks') % len(diff))
5843
5846
5844 if t:
5847 if t:
5845 # i18n: column positioning for "hg summary"
5848 # i18n: column positioning for "hg summary"
5846 ui.write(_('remote: %s\n') % (', '.join(t)))
5849 ui.write(_('remote: %s\n') % (', '.join(t)))
5847 else:
5850 else:
5848 # i18n: column positioning for "hg summary"
5851 # i18n: column positioning for "hg summary"
5849 ui.status(_('remote: (synced)\n'))
5852 ui.status(_('remote: (synced)\n'))
5850
5853
5851 cmdutil.summaryremotehooks(ui, repo, opts,
5854 cmdutil.summaryremotehooks(ui, repo, opts,
5852 ((source, sbranch, sother, commoninc),
5855 ((source, sbranch, sother, commoninc),
5853 (dest, dbranch, dother, outgoing)))
5856 (dest, dbranch, dother, outgoing)))
5854
5857
5855 @command('tag',
5858 @command('tag',
5856 [('f', 'force', None, _('force tag')),
5859 [('f', 'force', None, _('force tag')),
5857 ('l', 'local', None, _('make the tag local')),
5860 ('l', 'local', None, _('make the tag local')),
5858 ('r', 'rev', '', _('revision to tag'), _('REV')),
5861 ('r', 'rev', '', _('revision to tag'), _('REV')),
5859 ('', 'remove', None, _('remove a tag')),
5862 ('', 'remove', None, _('remove a tag')),
5860 # -l/--local is already there, commitopts cannot be used
5863 # -l/--local is already there, commitopts cannot be used
5861 ('e', 'edit', None, _('invoke editor on commit messages')),
5864 ('e', 'edit', None, _('invoke editor on commit messages')),
5862 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5865 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5863 ] + commitopts2,
5866 ] + commitopts2,
5864 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5867 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5865 def tag(ui, repo, name1, *names, **opts):
5868 def tag(ui, repo, name1, *names, **opts):
5866 """add one or more tags for the current or given revision
5869 """add one or more tags for the current or given revision
5867
5870
5868 Name a particular revision using <name>.
5871 Name a particular revision using <name>.
5869
5872
5870 Tags are used to name particular revisions of the repository and are
5873 Tags are used to name particular revisions of the repository and are
5871 very useful to compare different revisions, to go back to significant
5874 very useful to compare different revisions, to go back to significant
5872 earlier versions or to mark branch points as releases, etc. Changing
5875 earlier versions or to mark branch points as releases, etc. Changing
5873 an existing tag is normally disallowed; use -f/--force to override.
5876 an existing tag is normally disallowed; use -f/--force to override.
5874
5877
5875 If no revision is given, the parent of the working directory is
5878 If no revision is given, the parent of the working directory is
5876 used.
5879 used.
5877
5880
5878 To facilitate version control, distribution, and merging of tags,
5881 To facilitate version control, distribution, and merging of tags,
5879 they are stored as a file named ".hgtags" which is managed similarly
5882 they are stored as a file named ".hgtags" which is managed similarly
5880 to other project files and can be hand-edited if necessary. This
5883 to other project files and can be hand-edited if necessary. This
5881 also means that tagging creates a new commit. The file
5884 also means that tagging creates a new commit. The file
5882 ".hg/localtags" is used for local tags (not shared among
5885 ".hg/localtags" is used for local tags (not shared among
5883 repositories).
5886 repositories).
5884
5887
5885 Tag commits are usually made at the head of a branch. If the parent
5888 Tag commits are usually made at the head of a branch. If the parent
5886 of the working directory is not a branch head, :hg:`tag` aborts; use
5889 of the working directory is not a branch head, :hg:`tag` aborts; use
5887 -f/--force to force the tag commit to be based on a non-head
5890 -f/--force to force the tag commit to be based on a non-head
5888 changeset.
5891 changeset.
5889
5892
5890 See :hg:`help dates` for a list of formats valid for -d/--date.
5893 See :hg:`help dates` for a list of formats valid for -d/--date.
5891
5894
5892 Since tag names have priority over branch names during revision
5895 Since tag names have priority over branch names during revision
5893 lookup, using an existing branch name as a tag name is discouraged.
5896 lookup, using an existing branch name as a tag name is discouraged.
5894
5897
5895 Returns 0 on success.
5898 Returns 0 on success.
5896 """
5899 """
5897 wlock = lock = None
5900 wlock = lock = None
5898 try:
5901 try:
5899 wlock = repo.wlock()
5902 wlock = repo.wlock()
5900 lock = repo.lock()
5903 lock = repo.lock()
5901 rev_ = "."
5904 rev_ = "."
5902 names = [t.strip() for t in (name1,) + names]
5905 names = [t.strip() for t in (name1,) + names]
5903 if len(names) != len(set(names)):
5906 if len(names) != len(set(names)):
5904 raise util.Abort(_('tag names must be unique'))
5907 raise util.Abort(_('tag names must be unique'))
5905 for n in names:
5908 for n in names:
5906 scmutil.checknewlabel(repo, n, 'tag')
5909 scmutil.checknewlabel(repo, n, 'tag')
5907 if not n:
5910 if not n:
5908 raise util.Abort(_('tag names cannot consist entirely of '
5911 raise util.Abort(_('tag names cannot consist entirely of '
5909 'whitespace'))
5912 'whitespace'))
5910 if opts.get('rev') and opts.get('remove'):
5913 if opts.get('rev') and opts.get('remove'):
5911 raise util.Abort(_("--rev and --remove are incompatible"))
5914 raise util.Abort(_("--rev and --remove are incompatible"))
5912 if opts.get('rev'):
5915 if opts.get('rev'):
5913 rev_ = opts['rev']
5916 rev_ = opts['rev']
5914 message = opts.get('message')
5917 message = opts.get('message')
5915 if opts.get('remove'):
5918 if opts.get('remove'):
5916 expectedtype = opts.get('local') and 'local' or 'global'
5919 expectedtype = opts.get('local') and 'local' or 'global'
5917 for n in names:
5920 for n in names:
5918 if not repo.tagtype(n):
5921 if not repo.tagtype(n):
5919 raise util.Abort(_("tag '%s' does not exist") % n)
5922 raise util.Abort(_("tag '%s' does not exist") % n)
5920 if repo.tagtype(n) != expectedtype:
5923 if repo.tagtype(n) != expectedtype:
5921 if expectedtype == 'global':
5924 if expectedtype == 'global':
5922 raise util.Abort(_("tag '%s' is not a global tag") % n)
5925 raise util.Abort(_("tag '%s' is not a global tag") % n)
5923 else:
5926 else:
5924 raise util.Abort(_("tag '%s' is not a local tag") % n)
5927 raise util.Abort(_("tag '%s' is not a local tag") % n)
5925 rev_ = nullid
5928 rev_ = nullid
5926 if not message:
5929 if not message:
5927 # we don't translate commit messages
5930 # we don't translate commit messages
5928 message = 'Removed tag %s' % ', '.join(names)
5931 message = 'Removed tag %s' % ', '.join(names)
5929 elif not opts.get('force'):
5932 elif not opts.get('force'):
5930 for n in names:
5933 for n in names:
5931 if n in repo.tags():
5934 if n in repo.tags():
5932 raise util.Abort(_("tag '%s' already exists "
5935 raise util.Abort(_("tag '%s' already exists "
5933 "(use -f to force)") % n)
5936 "(use -f to force)") % n)
5934 if not opts.get('local'):
5937 if not opts.get('local'):
5935 p1, p2 = repo.dirstate.parents()
5938 p1, p2 = repo.dirstate.parents()
5936 if p2 != nullid:
5939 if p2 != nullid:
5937 raise util.Abort(_('uncommitted merge'))
5940 raise util.Abort(_('uncommitted merge'))
5938 bheads = repo.branchheads()
5941 bheads = repo.branchheads()
5939 if not opts.get('force') and bheads and p1 not in bheads:
5942 if not opts.get('force') and bheads and p1 not in bheads:
5940 raise util.Abort(_('not at a branch head (use -f to force)'))
5943 raise util.Abort(_('not at a branch head (use -f to force)'))
5941 r = scmutil.revsingle(repo, rev_).node()
5944 r = scmutil.revsingle(repo, rev_).node()
5942
5945
5943 if not message:
5946 if not message:
5944 # we don't translate commit messages
5947 # we don't translate commit messages
5945 message = ('Added tag %s for changeset %s' %
5948 message = ('Added tag %s for changeset %s' %
5946 (', '.join(names), short(r)))
5949 (', '.join(names), short(r)))
5947
5950
5948 date = opts.get('date')
5951 date = opts.get('date')
5949 if date:
5952 if date:
5950 date = util.parsedate(date)
5953 date = util.parsedate(date)
5951
5954
5952 if opts.get('remove'):
5955 if opts.get('remove'):
5953 editform = 'tag.remove'
5956 editform = 'tag.remove'
5954 else:
5957 else:
5955 editform = 'tag.add'
5958 editform = 'tag.add'
5956 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5959 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5957
5960
5958 # don't allow tagging the null rev
5961 # don't allow tagging the null rev
5959 if (not opts.get('remove') and
5962 if (not opts.get('remove') and
5960 scmutil.revsingle(repo, rev_).rev() == nullrev):
5963 scmutil.revsingle(repo, rev_).rev() == nullrev):
5961 raise util.Abort(_("cannot tag null revision"))
5964 raise util.Abort(_("cannot tag null revision"))
5962
5965
5963 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5966 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5964 editor=editor)
5967 editor=editor)
5965 finally:
5968 finally:
5966 release(lock, wlock)
5969 release(lock, wlock)
5967
5970
5968 @command('tags', formatteropts, '')
5971 @command('tags', formatteropts, '')
5969 def tags(ui, repo, **opts):
5972 def tags(ui, repo, **opts):
5970 """list repository tags
5973 """list repository tags
5971
5974
5972 This lists both regular and local tags. When the -v/--verbose
5975 This lists both regular and local tags. When the -v/--verbose
5973 switch is used, a third column "local" is printed for local tags.
5976 switch is used, a third column "local" is printed for local tags.
5974
5977
5975 Returns 0 on success.
5978 Returns 0 on success.
5976 """
5979 """
5977
5980
5978 fm = ui.formatter('tags', opts)
5981 fm = ui.formatter('tags', opts)
5979 hexfunc = ui.debugflag and hex or short
5982 hexfunc = ui.debugflag and hex or short
5980 tagtype = ""
5983 tagtype = ""
5981
5984
5982 for t, n in reversed(repo.tagslist()):
5985 for t, n in reversed(repo.tagslist()):
5983 hn = hexfunc(n)
5986 hn = hexfunc(n)
5984 label = 'tags.normal'
5987 label = 'tags.normal'
5985 tagtype = ''
5988 tagtype = ''
5986 if repo.tagtype(t) == 'local':
5989 if repo.tagtype(t) == 'local':
5987 label = 'tags.local'
5990 label = 'tags.local'
5988 tagtype = 'local'
5991 tagtype = 'local'
5989
5992
5990 fm.startitem()
5993 fm.startitem()
5991 fm.write('tag', '%s', t, label=label)
5994 fm.write('tag', '%s', t, label=label)
5992 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5995 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5993 fm.condwrite(not ui.quiet, 'rev id', fmt,
5996 fm.condwrite(not ui.quiet, 'rev id', fmt,
5994 repo.changelog.rev(n), hn, label=label)
5997 repo.changelog.rev(n), hn, label=label)
5995 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5998 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5996 tagtype, label=label)
5999 tagtype, label=label)
5997 fm.plain('\n')
6000 fm.plain('\n')
5998 fm.end()
6001 fm.end()
5999
6002
6000 @command('tip',
6003 @command('tip',
6001 [('p', 'patch', None, _('show patch')),
6004 [('p', 'patch', None, _('show patch')),
6002 ('g', 'git', None, _('use git extended diff format')),
6005 ('g', 'git', None, _('use git extended diff format')),
6003 ] + templateopts,
6006 ] + templateopts,
6004 _('[-p] [-g]'))
6007 _('[-p] [-g]'))
6005 def tip(ui, repo, **opts):
6008 def tip(ui, repo, **opts):
6006 """show the tip revision (DEPRECATED)
6009 """show the tip revision (DEPRECATED)
6007
6010
6008 The tip revision (usually just called the tip) is the changeset
6011 The tip revision (usually just called the tip) is the changeset
6009 most recently added to the repository (and therefore the most
6012 most recently added to the repository (and therefore the most
6010 recently changed head).
6013 recently changed head).
6011
6014
6012 If you have just made a commit, that commit will be the tip. If
6015 If you have just made a commit, that commit will be the tip. If
6013 you have just pulled changes from another repository, the tip of
6016 you have just pulled changes from another repository, the tip of
6014 that repository becomes the current tip. The "tip" tag is special
6017 that repository becomes the current tip. The "tip" tag is special
6015 and cannot be renamed or assigned to a different changeset.
6018 and cannot be renamed or assigned to a different changeset.
6016
6019
6017 This command is deprecated, please use :hg:`heads` instead.
6020 This command is deprecated, please use :hg:`heads` instead.
6018
6021
6019 Returns 0 on success.
6022 Returns 0 on success.
6020 """
6023 """
6021 displayer = cmdutil.show_changeset(ui, repo, opts)
6024 displayer = cmdutil.show_changeset(ui, repo, opts)
6022 displayer.show(repo['tip'])
6025 displayer.show(repo['tip'])
6023 displayer.close()
6026 displayer.close()
6024
6027
6025 @command('unbundle',
6028 @command('unbundle',
6026 [('u', 'update', None,
6029 [('u', 'update', None,
6027 _('update to new branch head if changesets were unbundled'))],
6030 _('update to new branch head if changesets were unbundled'))],
6028 _('[-u] FILE...'))
6031 _('[-u] FILE...'))
6029 def unbundle(ui, repo, fname1, *fnames, **opts):
6032 def unbundle(ui, repo, fname1, *fnames, **opts):
6030 """apply one or more changegroup files
6033 """apply one or more changegroup files
6031
6034
6032 Apply one or more compressed changegroup files generated by the
6035 Apply one or more compressed changegroup files generated by the
6033 bundle command.
6036 bundle command.
6034
6037
6035 Returns 0 on success, 1 if an update has unresolved files.
6038 Returns 0 on success, 1 if an update has unresolved files.
6036 """
6039 """
6037 fnames = (fname1,) + fnames
6040 fnames = (fname1,) + fnames
6038
6041
6039 lock = repo.lock()
6042 lock = repo.lock()
6040 try:
6043 try:
6041 for fname in fnames:
6044 for fname in fnames:
6042 f = hg.openpath(ui, fname)
6045 f = hg.openpath(ui, fname)
6043 gen = exchange.readbundle(ui, f, fname)
6046 gen = exchange.readbundle(ui, f, fname)
6044 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6047 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6045 'bundle:' + fname)
6048 'bundle:' + fname)
6046 finally:
6049 finally:
6047 lock.release()
6050 lock.release()
6048
6051
6049 return postincoming(ui, repo, modheads, opts.get('update'), None)
6052 return postincoming(ui, repo, modheads, opts.get('update'), None)
6050
6053
6051 @command('^update|up|checkout|co',
6054 @command('^update|up|checkout|co',
6052 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6055 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6053 ('c', 'check', None,
6056 ('c', 'check', None,
6054 _('update across branches if no uncommitted changes')),
6057 _('update across branches if no uncommitted changes')),
6055 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6058 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6056 ('r', 'rev', '', _('revision'), _('REV'))
6059 ('r', 'rev', '', _('revision'), _('REV'))
6057 ] + mergetoolopts,
6060 ] + mergetoolopts,
6058 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6061 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6059 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6062 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6060 tool=None):
6063 tool=None):
6061 """update working directory (or switch revisions)
6064 """update working directory (or switch revisions)
6062
6065
6063 Update the repository's working directory to the specified
6066 Update the repository's working directory to the specified
6064 changeset. If no changeset is specified, update to the tip of the
6067 changeset. If no changeset is specified, update to the tip of the
6065 current named branch and move the current bookmark (see :hg:`help
6068 current named branch and move the current bookmark (see :hg:`help
6066 bookmarks`).
6069 bookmarks`).
6067
6070
6068 Update sets the working directory's parent revision to the specified
6071 Update sets the working directory's parent revision to the specified
6069 changeset (see :hg:`help parents`).
6072 changeset (see :hg:`help parents`).
6070
6073
6071 If the changeset is not a descendant or ancestor of the working
6074 If the changeset is not a descendant or ancestor of the working
6072 directory's parent, the update is aborted. With the -c/--check
6075 directory's parent, the update is aborted. With the -c/--check
6073 option, the working directory is checked for uncommitted changes; if
6076 option, the working directory is checked for uncommitted changes; if
6074 none are found, the working directory is updated to the specified
6077 none are found, the working directory is updated to the specified
6075 changeset.
6078 changeset.
6076
6079
6077 .. container:: verbose
6080 .. container:: verbose
6078
6081
6079 The following rules apply when the working directory contains
6082 The following rules apply when the working directory contains
6080 uncommitted changes:
6083 uncommitted changes:
6081
6084
6082 1. If neither -c/--check nor -C/--clean is specified, and if
6085 1. If neither -c/--check nor -C/--clean is specified, and if
6083 the requested changeset is an ancestor or descendant of
6086 the requested changeset is an ancestor or descendant of
6084 the working directory's parent, the uncommitted changes
6087 the working directory's parent, the uncommitted changes
6085 are merged into the requested changeset and the merged
6088 are merged into the requested changeset and the merged
6086 result is left uncommitted. If the requested changeset is
6089 result is left uncommitted. If the requested changeset is
6087 not an ancestor or descendant (that is, it is on another
6090 not an ancestor or descendant (that is, it is on another
6088 branch), the update is aborted and the uncommitted changes
6091 branch), the update is aborted and the uncommitted changes
6089 are preserved.
6092 are preserved.
6090
6093
6091 2. With the -c/--check option, the update is aborted and the
6094 2. With the -c/--check option, the update is aborted and the
6092 uncommitted changes are preserved.
6095 uncommitted changes are preserved.
6093
6096
6094 3. With the -C/--clean option, uncommitted changes are discarded and
6097 3. With the -C/--clean option, uncommitted changes are discarded and
6095 the working directory is updated to the requested changeset.
6098 the working directory is updated to the requested changeset.
6096
6099
6097 To cancel an uncommitted merge (and lose your changes), use
6100 To cancel an uncommitted merge (and lose your changes), use
6098 :hg:`update --clean .`.
6101 :hg:`update --clean .`.
6099
6102
6100 Use null as the changeset to remove the working directory (like
6103 Use null as the changeset to remove the working directory (like
6101 :hg:`clone -U`).
6104 :hg:`clone -U`).
6102
6105
6103 If you want to revert just one file to an older revision, use
6106 If you want to revert just one file to an older revision, use
6104 :hg:`revert [-r REV] NAME`.
6107 :hg:`revert [-r REV] NAME`.
6105
6108
6106 See :hg:`help dates` for a list of formats valid for -d/--date.
6109 See :hg:`help dates` for a list of formats valid for -d/--date.
6107
6110
6108 Returns 0 on success, 1 if there are unresolved files.
6111 Returns 0 on success, 1 if there are unresolved files.
6109 """
6112 """
6110 if rev and node:
6113 if rev and node:
6111 raise util.Abort(_("please specify just one revision"))
6114 raise util.Abort(_("please specify just one revision"))
6112
6115
6113 if rev is None or rev == '':
6116 if rev is None or rev == '':
6114 rev = node
6117 rev = node
6115
6118
6116 cmdutil.clearunfinished(repo)
6119 cmdutil.clearunfinished(repo)
6117
6120
6118 # with no argument, we also move the current bookmark, if any
6121 # with no argument, we also move the current bookmark, if any
6119 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6122 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6120
6123
6121 # if we defined a bookmark, we have to remember the original bookmark name
6124 # if we defined a bookmark, we have to remember the original bookmark name
6122 brev = rev
6125 brev = rev
6123 rev = scmutil.revsingle(repo, rev, rev).rev()
6126 rev = scmutil.revsingle(repo, rev, rev).rev()
6124
6127
6125 if check and clean:
6128 if check and clean:
6126 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6129 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6127
6130
6128 if date:
6131 if date:
6129 if rev is not None:
6132 if rev is not None:
6130 raise util.Abort(_("you can't specify a revision and a date"))
6133 raise util.Abort(_("you can't specify a revision and a date"))
6131 rev = cmdutil.finddate(ui, repo, date)
6134 rev = cmdutil.finddate(ui, repo, date)
6132
6135
6133 if check:
6136 if check:
6134 c = repo[None]
6137 c = repo[None]
6135 if c.dirty(merge=False, branch=False, missing=True):
6138 if c.dirty(merge=False, branch=False, missing=True):
6136 raise util.Abort(_("uncommitted changes"))
6139 raise util.Abort(_("uncommitted changes"))
6137 if rev is None:
6140 if rev is None:
6138 rev = repo[repo[None].branch()].rev()
6141 rev = repo[repo[None].branch()].rev()
6139 mergemod._checkunknown(repo, repo[None], repo[rev])
6142 mergemod._checkunknown(repo, repo[None], repo[rev])
6140
6143
6141 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6144 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6142
6145
6143 if clean:
6146 if clean:
6144 ret = hg.clean(repo, rev)
6147 ret = hg.clean(repo, rev)
6145 else:
6148 else:
6146 ret = hg.update(repo, rev)
6149 ret = hg.update(repo, rev)
6147
6150
6148 if not ret and movemarkfrom:
6151 if not ret and movemarkfrom:
6149 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6152 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6150 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6153 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6151 elif brev in repo._bookmarks:
6154 elif brev in repo._bookmarks:
6152 bookmarks.setcurrent(repo, brev)
6155 bookmarks.setcurrent(repo, brev)
6153 ui.status(_("(activating bookmark %s)\n") % brev)
6156 ui.status(_("(activating bookmark %s)\n") % brev)
6154 elif brev:
6157 elif brev:
6155 if repo._bookmarkcurrent:
6158 if repo._bookmarkcurrent:
6156 ui.status(_("(leaving bookmark %s)\n") %
6159 ui.status(_("(leaving bookmark %s)\n") %
6157 repo._bookmarkcurrent)
6160 repo._bookmarkcurrent)
6158 bookmarks.unsetcurrent(repo)
6161 bookmarks.unsetcurrent(repo)
6159
6162
6160 return ret
6163 return ret
6161
6164
6162 @command('verify', [])
6165 @command('verify', [])
6163 def verify(ui, repo):
6166 def verify(ui, repo):
6164 """verify the integrity of the repository
6167 """verify the integrity of the repository
6165
6168
6166 Verify the integrity of the current repository.
6169 Verify the integrity of the current repository.
6167
6170
6168 This will perform an extensive check of the repository's
6171 This will perform an extensive check of the repository's
6169 integrity, validating the hashes and checksums of each entry in
6172 integrity, validating the hashes and checksums of each entry in
6170 the changelog, manifest, and tracked files, as well as the
6173 the changelog, manifest, and tracked files, as well as the
6171 integrity of their crosslinks and indices.
6174 integrity of their crosslinks and indices.
6172
6175
6173 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6176 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6174 for more information about recovery from corruption of the
6177 for more information about recovery from corruption of the
6175 repository.
6178 repository.
6176
6179
6177 Returns 0 on success, 1 if errors are encountered.
6180 Returns 0 on success, 1 if errors are encountered.
6178 """
6181 """
6179 return hg.verify(repo)
6182 return hg.verify(repo)
6180
6183
6181 @command('version', [], norepo=True)
6184 @command('version', [], norepo=True)
6182 def version_(ui):
6185 def version_(ui):
6183 """output version and copyright information"""
6186 """output version and copyright information"""
6184 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6187 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6185 % util.version())
6188 % util.version())
6186 ui.status(_(
6189 ui.status(_(
6187 "(see http://mercurial.selenic.com for more information)\n"
6190 "(see http://mercurial.selenic.com for more information)\n"
6188 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6191 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6189 "This is free software; see the source for copying conditions. "
6192 "This is free software; see the source for copying conditions. "
6190 "There is NO\nwarranty; "
6193 "There is NO\nwarranty; "
6191 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6194 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6192 ))
6195 ))
6193
6196
6194 ui.note(_("\nEnabled extensions:\n\n"))
6197 ui.note(_("\nEnabled extensions:\n\n"))
6195 if ui.verbose:
6198 if ui.verbose:
6196 # format names and versions into columns
6199 # format names and versions into columns
6197 names = []
6200 names = []
6198 vers = []
6201 vers = []
6199 for name, module in extensions.extensions():
6202 for name, module in extensions.extensions():
6200 names.append(name)
6203 names.append(name)
6201 vers.append(extensions.moduleversion(module))
6204 vers.append(extensions.moduleversion(module))
6202 if names:
6205 if names:
6203 maxnamelen = max(len(n) for n in names)
6206 maxnamelen = max(len(n) for n in names)
6204 for i, name in enumerate(names):
6207 for i, name in enumerate(names):
6205 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6208 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now