##// END OF EJS Templates
resolve: silence warning of unknown pats for -l/--list (BC)...
Yuya Nishihara -
r24125:18af6ebd default
parent child Browse files
Show More
@@ -1,6323 +1,6323 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, socket
12 import sys, socket
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, copies
21 import dagparser, context, simplemerge, graphmod, copies
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, bundle2
24 import phases, obsolete, exchange, bundle2
25 import ui as uimod
25 import ui as uimod
26
26
27 table = {}
27 table = {}
28
28
29 command = cmdutil.command(table)
29 command = cmdutil.command(table)
30
30
31 # Space delimited list of commands that don't require local repositories.
31 # Space delimited list of commands that don't require local repositories.
32 # This should be populated by passing norepo=True into the @command decorator.
32 # This should be populated by passing norepo=True into the @command decorator.
33 norepo = ''
33 norepo = ''
34 # Space delimited list of commands that optionally require local repositories.
34 # Space delimited list of commands that optionally require local repositories.
35 # This should be populated by passing optionalrepo=True into the @command
35 # This should be populated by passing optionalrepo=True into the @command
36 # decorator.
36 # decorator.
37 optionalrepo = ''
37 optionalrepo = ''
38 # Space delimited list of commands that will examine arguments looking for
38 # Space delimited list of commands that will examine arguments looking for
39 # a repository. This should be populated by passing inferrepo=True into the
39 # a repository. This should be populated by passing inferrepo=True into the
40 # @command decorator.
40 # @command decorator.
41 inferrepo = ''
41 inferrepo = ''
42
42
43 # common command options
43 # common command options
44
44
45 globalopts = [
45 globalopts = [
46 ('R', 'repository', '',
46 ('R', 'repository', '',
47 _('repository root directory or name of overlay bundle file'),
47 _('repository root directory or name of overlay bundle file'),
48 _('REPO')),
48 _('REPO')),
49 ('', 'cwd', '',
49 ('', 'cwd', '',
50 _('change working directory'), _('DIR')),
50 _('change working directory'), _('DIR')),
51 ('y', 'noninteractive', None,
51 ('y', 'noninteractive', None,
52 _('do not prompt, automatically pick the first choice for all prompts')),
52 _('do not prompt, automatically pick the first choice for all prompts')),
53 ('q', 'quiet', None, _('suppress output')),
53 ('q', 'quiet', None, _('suppress output')),
54 ('v', 'verbose', None, _('enable additional output')),
54 ('v', 'verbose', None, _('enable additional output')),
55 ('', 'config', [],
55 ('', 'config', [],
56 _('set/override config option (use \'section.name=value\')'),
56 _('set/override config option (use \'section.name=value\')'),
57 _('CONFIG')),
57 _('CONFIG')),
58 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debug', None, _('enable debugging output')),
59 ('', 'debugger', None, _('start debugger')),
59 ('', 'debugger', None, _('start debugger')),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
61 _('ENCODE')),
61 _('ENCODE')),
62 ('', 'encodingmode', encoding.encodingmode,
62 ('', 'encodingmode', encoding.encodingmode,
63 _('set the charset encoding mode'), _('MODE')),
63 _('set the charset encoding mode'), _('MODE')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
65 ('', 'time', None, _('time how long the command takes')),
65 ('', 'time', None, _('time how long the command takes')),
66 ('', 'profile', None, _('print command execution profile')),
66 ('', 'profile', None, _('print command execution profile')),
67 ('', 'version', None, _('output version information and exit')),
67 ('', 'version', None, _('output version information and exit')),
68 ('h', 'help', None, _('display help and exit')),
68 ('h', 'help', None, _('display help and exit')),
69 ('', 'hidden', False, _('consider hidden changesets')),
69 ('', 'hidden', False, _('consider hidden changesets')),
70 ]
70 ]
71
71
72 dryrunopts = [('n', 'dry-run', None,
72 dryrunopts = [('n', 'dry-run', None,
73 _('do not perform actions, just print output'))]
73 _('do not perform actions, just print output'))]
74
74
75 remoteopts = [
75 remoteopts = [
76 ('e', 'ssh', '',
76 ('e', 'ssh', '',
77 _('specify ssh command to use'), _('CMD')),
77 _('specify ssh command to use'), _('CMD')),
78 ('', 'remotecmd', '',
78 ('', 'remotecmd', '',
79 _('specify hg command to run on the remote side'), _('CMD')),
79 _('specify hg command to run on the remote side'), _('CMD')),
80 ('', 'insecure', None,
80 ('', 'insecure', None,
81 _('do not verify server certificate (ignoring web.cacerts config)')),
81 _('do not verify server certificate (ignoring web.cacerts config)')),
82 ]
82 ]
83
83
84 walkopts = [
84 walkopts = [
85 ('I', 'include', [],
85 ('I', 'include', [],
86 _('include names matching the given patterns'), _('PATTERN')),
86 _('include names matching the given patterns'), _('PATTERN')),
87 ('X', 'exclude', [],
87 ('X', 'exclude', [],
88 _('exclude names matching the given patterns'), _('PATTERN')),
88 _('exclude names matching the given patterns'), _('PATTERN')),
89 ]
89 ]
90
90
91 commitopts = [
91 commitopts = [
92 ('m', 'message', '',
92 ('m', 'message', '',
93 _('use text as commit message'), _('TEXT')),
93 _('use text as commit message'), _('TEXT')),
94 ('l', 'logfile', '',
94 ('l', 'logfile', '',
95 _('read commit message from file'), _('FILE')),
95 _('read commit message from file'), _('FILE')),
96 ]
96 ]
97
97
98 commitopts2 = [
98 commitopts2 = [
99 ('d', 'date', '',
99 ('d', 'date', '',
100 _('record the specified date as commit date'), _('DATE')),
100 _('record the specified date as commit date'), _('DATE')),
101 ('u', 'user', '',
101 ('u', 'user', '',
102 _('record the specified user as committer'), _('USER')),
102 _('record the specified user as committer'), _('USER')),
103 ]
103 ]
104
104
105 # hidden for now
105 # hidden for now
106 formatteropts = [
106 formatteropts = [
107 ('T', 'template', '',
107 ('T', 'template', '',
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
109 ]
109 ]
110
110
111 templateopts = [
111 templateopts = [
112 ('', 'style', '',
112 ('', 'style', '',
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template'), _('TEMPLATE')),
115 _('display with template'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 logopts = [
118 logopts = [
119 ('p', 'patch', None, _('show patch')),
119 ('p', 'patch', None, _('show patch')),
120 ('g', 'git', None, _('use git extended diff format')),
120 ('g', 'git', None, _('use git extended diff format')),
121 ('l', 'limit', '',
121 ('l', 'limit', '',
122 _('limit number of changes displayed'), _('NUM')),
122 _('limit number of changes displayed'), _('NUM')),
123 ('M', 'no-merges', None, _('do not show merges')),
123 ('M', 'no-merges', None, _('do not show merges')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('G', 'graph', None, _("show the revision DAG")),
125 ('G', 'graph', None, _("show the revision DAG")),
126 ] + templateopts
126 ] + templateopts
127
127
128 diffopts = [
128 diffopts = [
129 ('a', 'text', None, _('treat all files as text')),
129 ('a', 'text', None, _('treat all files as text')),
130 ('g', 'git', None, _('use git extended diff format')),
130 ('g', 'git', None, _('use git extended diff format')),
131 ('', 'nodates', None, _('omit dates from diff headers'))
131 ('', 'nodates', None, _('omit dates from diff headers'))
132 ]
132 ]
133
133
134 diffwsopts = [
134 diffwsopts = [
135 ('w', 'ignore-all-space', None,
135 ('w', 'ignore-all-space', None,
136 _('ignore white space when comparing lines')),
136 _('ignore white space when comparing lines')),
137 ('b', 'ignore-space-change', None,
137 ('b', 'ignore-space-change', None,
138 _('ignore changes in the amount of white space')),
138 _('ignore changes in the amount of white space')),
139 ('B', 'ignore-blank-lines', None,
139 ('B', 'ignore-blank-lines', None,
140 _('ignore changes whose lines are all blank')),
140 _('ignore changes whose lines are all blank')),
141 ]
141 ]
142
142
143 diffopts2 = [
143 diffopts2 = [
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
145 ('p', 'show-function', None, _('show which function each change is in')),
145 ('p', 'show-function', None, _('show which function each change is in')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
147 ] + diffwsopts + [
147 ] + diffwsopts + [
148 ('U', 'unified', '',
148 ('U', 'unified', '',
149 _('number of lines of context to show'), _('NUM')),
149 _('number of lines of context to show'), _('NUM')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
151 ]
151 ]
152
152
153 mergetoolopts = [
153 mergetoolopts = [
154 ('t', 'tool', '', _('specify merge tool')),
154 ('t', 'tool', '', _('specify merge tool')),
155 ]
155 ]
156
156
157 similarityopts = [
157 similarityopts = [
158 ('s', 'similarity', '',
158 ('s', 'similarity', '',
159 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
159 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
160 ]
160 ]
161
161
162 subrepoopts = [
162 subrepoopts = [
163 ('S', 'subrepos', None,
163 ('S', 'subrepos', None,
164 _('recurse into subrepositories'))
164 _('recurse into subrepositories'))
165 ]
165 ]
166
166
167 # Commands start here, listed alphabetically
167 # Commands start here, listed alphabetically
168
168
169 @command('^add',
169 @command('^add',
170 walkopts + subrepoopts + dryrunopts,
170 walkopts + subrepoopts + dryrunopts,
171 _('[OPTION]... [FILE]...'),
171 _('[OPTION]... [FILE]...'),
172 inferrepo=True)
172 inferrepo=True)
173 def add(ui, repo, *pats, **opts):
173 def add(ui, repo, *pats, **opts):
174 """add the specified files on the next commit
174 """add the specified files on the next commit
175
175
176 Schedule files to be version controlled and added to the
176 Schedule files to be version controlled and added to the
177 repository.
177 repository.
178
178
179 The files will be added to the repository at the next commit. To
179 The files will be added to the repository at the next commit. To
180 undo an add before that, see :hg:`forget`.
180 undo an add before that, see :hg:`forget`.
181
181
182 If no names are given, add all files to the repository.
182 If no names are given, add all files to the repository.
183
183
184 .. container:: verbose
184 .. container:: verbose
185
185
186 An example showing how new (unknown) files are added
186 An example showing how new (unknown) files are added
187 automatically by :hg:`add`::
187 automatically by :hg:`add`::
188
188
189 $ ls
189 $ ls
190 foo.c
190 foo.c
191 $ hg status
191 $ hg status
192 ? foo.c
192 ? foo.c
193 $ hg add
193 $ hg add
194 adding foo.c
194 adding foo.c
195 $ hg status
195 $ hg status
196 A foo.c
196 A foo.c
197
197
198 Returns 0 if all files are successfully added.
198 Returns 0 if all files are successfully added.
199 """
199 """
200
200
201 m = scmutil.match(repo[None], pats, opts)
201 m = scmutil.match(repo[None], pats, opts)
202 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
202 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
203 return rejected and 1 or 0
203 return rejected and 1 or 0
204
204
205 @command('addremove',
205 @command('addremove',
206 similarityopts + subrepoopts + walkopts + dryrunopts,
206 similarityopts + subrepoopts + walkopts + dryrunopts,
207 _('[OPTION]... [FILE]...'),
207 _('[OPTION]... [FILE]...'),
208 inferrepo=True)
208 inferrepo=True)
209 def addremove(ui, repo, *pats, **opts):
209 def addremove(ui, repo, *pats, **opts):
210 """add all new files, delete all missing files
210 """add all new files, delete all missing files
211
211
212 Add all new files and remove all missing files from the
212 Add all new files and remove all missing files from the
213 repository.
213 repository.
214
214
215 New files are ignored if they match any of the patterns in
215 New files are ignored if they match any of the patterns in
216 ``.hgignore``. As with add, these changes take effect at the next
216 ``.hgignore``. As with add, these changes take effect at the next
217 commit.
217 commit.
218
218
219 Use the -s/--similarity option to detect renamed files. This
219 Use the -s/--similarity option to detect renamed files. This
220 option takes a percentage between 0 (disabled) and 100 (files must
220 option takes a percentage between 0 (disabled) and 100 (files must
221 be identical) as its parameter. With a parameter greater than 0,
221 be identical) as its parameter. With a parameter greater than 0,
222 this compares every removed file with every added file and records
222 this compares every removed file with every added file and records
223 those similar enough as renames. Detecting renamed files this way
223 those similar enough as renames. Detecting renamed files this way
224 can be expensive. After using this option, :hg:`status -C` can be
224 can be expensive. After using this option, :hg:`status -C` can be
225 used to check which files were identified as moved or renamed. If
225 used to check which files were identified as moved or renamed. If
226 not specified, -s/--similarity defaults to 100 and only renames of
226 not specified, -s/--similarity defaults to 100 and only renames of
227 identical files are detected.
227 identical files are detected.
228
228
229 Returns 0 if all files are successfully added.
229 Returns 0 if all files are successfully added.
230 """
230 """
231 try:
231 try:
232 sim = float(opts.get('similarity') or 100)
232 sim = float(opts.get('similarity') or 100)
233 except ValueError:
233 except ValueError:
234 raise util.Abort(_('similarity must be a number'))
234 raise util.Abort(_('similarity must be a number'))
235 if sim < 0 or sim > 100:
235 if sim < 0 or sim > 100:
236 raise util.Abort(_('similarity must be between 0 and 100'))
236 raise util.Abort(_('similarity must be between 0 and 100'))
237 matcher = scmutil.match(repo[None], pats, opts)
237 matcher = scmutil.match(repo[None], pats, opts)
238 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
238 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
239
239
240 @command('^annotate|blame',
240 @command('^annotate|blame',
241 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
241 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
242 ('', 'follow', None,
242 ('', 'follow', None,
243 _('follow copies/renames and list the filename (DEPRECATED)')),
243 _('follow copies/renames and list the filename (DEPRECATED)')),
244 ('', 'no-follow', None, _("don't follow copies and renames")),
244 ('', 'no-follow', None, _("don't follow copies and renames")),
245 ('a', 'text', None, _('treat all files as text')),
245 ('a', 'text', None, _('treat all files as text')),
246 ('u', 'user', None, _('list the author (long with -v)')),
246 ('u', 'user', None, _('list the author (long with -v)')),
247 ('f', 'file', None, _('list the filename')),
247 ('f', 'file', None, _('list the filename')),
248 ('d', 'date', None, _('list the date (short with -q)')),
248 ('d', 'date', None, _('list the date (short with -q)')),
249 ('n', 'number', None, _('list the revision number (default)')),
249 ('n', 'number', None, _('list the revision number (default)')),
250 ('c', 'changeset', None, _('list the changeset')),
250 ('c', 'changeset', None, _('list the changeset')),
251 ('l', 'line-number', None, _('show line number at the first appearance'))
251 ('l', 'line-number', None, _('show line number at the first appearance'))
252 ] + diffwsopts + walkopts + formatteropts,
252 ] + diffwsopts + walkopts + formatteropts,
253 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
253 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
254 inferrepo=True)
254 inferrepo=True)
255 def annotate(ui, repo, *pats, **opts):
255 def annotate(ui, repo, *pats, **opts):
256 """show changeset information by line for each file
256 """show changeset information by line for each file
257
257
258 List changes in files, showing the revision id responsible for
258 List changes in files, showing the revision id responsible for
259 each line
259 each line
260
260
261 This command is useful for discovering when a change was made and
261 This command is useful for discovering when a change was made and
262 by whom.
262 by whom.
263
263
264 Without the -a/--text option, annotate will avoid processing files
264 Without the -a/--text option, annotate will avoid processing files
265 it detects as binary. With -a, annotate will annotate the file
265 it detects as binary. With -a, annotate will annotate the file
266 anyway, although the results will probably be neither useful
266 anyway, although the results will probably be neither useful
267 nor desirable.
267 nor desirable.
268
268
269 Returns 0 on success.
269 Returns 0 on success.
270 """
270 """
271 if not pats:
271 if not pats:
272 raise util.Abort(_('at least one filename or pattern is required'))
272 raise util.Abort(_('at least one filename or pattern is required'))
273
273
274 if opts.get('follow'):
274 if opts.get('follow'):
275 # --follow is deprecated and now just an alias for -f/--file
275 # --follow is deprecated and now just an alias for -f/--file
276 # to mimic the behavior of Mercurial before version 1.5
276 # to mimic the behavior of Mercurial before version 1.5
277 opts['file'] = True
277 opts['file'] = True
278
278
279 fm = ui.formatter('annotate', opts)
279 fm = ui.formatter('annotate', opts)
280 datefunc = ui.quiet and util.shortdate or util.datestr
280 datefunc = ui.quiet and util.shortdate or util.datestr
281 hexfn = fm.hexfunc
281 hexfn = fm.hexfunc
282
282
283 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
283 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
284 ('number', ' ', lambda x: x[0].rev(), str),
284 ('number', ' ', lambda x: x[0].rev(), str),
285 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
285 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
286 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
286 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
287 ('file', ' ', lambda x: x[0].path(), str),
287 ('file', ' ', lambda x: x[0].path(), str),
288 ('line_number', ':', lambda x: x[1], str),
288 ('line_number', ':', lambda x: x[1], str),
289 ]
289 ]
290 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
290 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
291
291
292 if (not opts.get('user') and not opts.get('changeset')
292 if (not opts.get('user') and not opts.get('changeset')
293 and not opts.get('date') and not opts.get('file')):
293 and not opts.get('date') and not opts.get('file')):
294 opts['number'] = True
294 opts['number'] = True
295
295
296 linenumber = opts.get('line_number') is not None
296 linenumber = opts.get('line_number') is not None
297 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
297 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
298 raise util.Abort(_('at least one of -n/-c is required for -l'))
298 raise util.Abort(_('at least one of -n/-c is required for -l'))
299
299
300 if fm:
300 if fm:
301 def makefunc(get, fmt):
301 def makefunc(get, fmt):
302 return get
302 return get
303 else:
303 else:
304 def makefunc(get, fmt):
304 def makefunc(get, fmt):
305 return lambda x: fmt(get(x))
305 return lambda x: fmt(get(x))
306 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
306 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
307 if opts.get(op)]
307 if opts.get(op)]
308 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
308 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
309 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
309 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
310 if opts.get(op))
310 if opts.get(op))
311
311
312 def bad(x, y):
312 def bad(x, y):
313 raise util.Abort("%s: %s" % (x, y))
313 raise util.Abort("%s: %s" % (x, y))
314
314
315 ctx = scmutil.revsingle(repo, opts.get('rev'))
315 ctx = scmutil.revsingle(repo, opts.get('rev'))
316 m = scmutil.match(ctx, pats, opts)
316 m = scmutil.match(ctx, pats, opts)
317 m.bad = bad
317 m.bad = bad
318 follow = not opts.get('no_follow')
318 follow = not opts.get('no_follow')
319 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
319 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
320 whitespace=True)
320 whitespace=True)
321 for abs in ctx.walk(m):
321 for abs in ctx.walk(m):
322 fctx = ctx[abs]
322 fctx = ctx[abs]
323 if not opts.get('text') and util.binary(fctx.data()):
323 if not opts.get('text') and util.binary(fctx.data()):
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
325 continue
325 continue
326
326
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
328 diffopts=diffopts)
328 diffopts=diffopts)
329 formats = []
329 formats = []
330 pieces = []
330 pieces = []
331
331
332 for f, sep in funcmap:
332 for f, sep in funcmap:
333 l = [f(n) for n, dummy in lines]
333 l = [f(n) for n, dummy in lines]
334 if l:
334 if l:
335 if fm:
335 if fm:
336 formats.append(['%s' for x in l])
336 formats.append(['%s' for x in l])
337 else:
337 else:
338 sizes = [encoding.colwidth(x) for x in l]
338 sizes = [encoding.colwidth(x) for x in l]
339 ml = max(sizes)
339 ml = max(sizes)
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
341 pieces.append(l)
341 pieces.append(l)
342
342
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
344 fm.startitem()
344 fm.startitem()
345 fm.write(fields, "".join(f), *p)
345 fm.write(fields, "".join(f), *p)
346 fm.write('line', ": %s", l[1])
346 fm.write('line', ": %s", l[1])
347
347
348 if lines and not lines[-1][1].endswith('\n'):
348 if lines and not lines[-1][1].endswith('\n'):
349 fm.plain('\n')
349 fm.plain('\n')
350
350
351 fm.end()
351 fm.end()
352
352
353 @command('archive',
353 @command('archive',
354 [('', 'no-decode', None, _('do not pass files through decoders')),
354 [('', 'no-decode', None, _('do not pass files through decoders')),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
356 _('PREFIX')),
356 _('PREFIX')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
359 ] + subrepoopts + walkopts,
359 ] + subrepoopts + walkopts,
360 _('[OPTION]... DEST'))
360 _('[OPTION]... DEST'))
361 def archive(ui, repo, dest, **opts):
361 def archive(ui, repo, dest, **opts):
362 '''create an unversioned archive of a repository revision
362 '''create an unversioned archive of a repository revision
363
363
364 By default, the revision used is the parent of the working
364 By default, the revision used is the parent of the working
365 directory; use -r/--rev to specify a different revision.
365 directory; use -r/--rev to specify a different revision.
366
366
367 The archive type is automatically detected based on file
367 The archive type is automatically detected based on file
368 extension (or override using -t/--type).
368 extension (or override using -t/--type).
369
369
370 .. container:: verbose
370 .. container:: verbose
371
371
372 Examples:
372 Examples:
373
373
374 - create a zip file containing the 1.0 release::
374 - create a zip file containing the 1.0 release::
375
375
376 hg archive -r 1.0 project-1.0.zip
376 hg archive -r 1.0 project-1.0.zip
377
377
378 - create a tarball excluding .hg files::
378 - create a tarball excluding .hg files::
379
379
380 hg archive project.tar.gz -X ".hg*"
380 hg archive project.tar.gz -X ".hg*"
381
381
382 Valid types are:
382 Valid types are:
383
383
384 :``files``: a directory full of files (default)
384 :``files``: a directory full of files (default)
385 :``tar``: tar archive, uncompressed
385 :``tar``: tar archive, uncompressed
386 :``tbz2``: tar archive, compressed using bzip2
386 :``tbz2``: tar archive, compressed using bzip2
387 :``tgz``: tar archive, compressed using gzip
387 :``tgz``: tar archive, compressed using gzip
388 :``uzip``: zip archive, uncompressed
388 :``uzip``: zip archive, uncompressed
389 :``zip``: zip archive, compressed using deflate
389 :``zip``: zip archive, compressed using deflate
390
390
391 The exact name of the destination archive or directory is given
391 The exact name of the destination archive or directory is given
392 using a format string; see :hg:`help export` for details.
392 using a format string; see :hg:`help export` for details.
393
393
394 Each member added to an archive file has a directory prefix
394 Each member added to an archive file has a directory prefix
395 prepended. Use -p/--prefix to specify a format string for the
395 prepended. Use -p/--prefix to specify a format string for the
396 prefix. The default is the basename of the archive, with suffixes
396 prefix. The default is the basename of the archive, with suffixes
397 removed.
397 removed.
398
398
399 Returns 0 on success.
399 Returns 0 on success.
400 '''
400 '''
401
401
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
403 if not ctx:
403 if not ctx:
404 raise util.Abort(_('no working directory: please specify a revision'))
404 raise util.Abort(_('no working directory: please specify a revision'))
405 node = ctx.node()
405 node = ctx.node()
406 dest = cmdutil.makefilename(repo, dest, node)
406 dest = cmdutil.makefilename(repo, dest, node)
407 if os.path.realpath(dest) == repo.root:
407 if os.path.realpath(dest) == repo.root:
408 raise util.Abort(_('repository root cannot be destination'))
408 raise util.Abort(_('repository root cannot be destination'))
409
409
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
411 prefix = opts.get('prefix')
411 prefix = opts.get('prefix')
412
412
413 if dest == '-':
413 if dest == '-':
414 if kind == 'files':
414 if kind == 'files':
415 raise util.Abort(_('cannot archive plain files to stdout'))
415 raise util.Abort(_('cannot archive plain files to stdout'))
416 dest = cmdutil.makefileobj(repo, dest)
416 dest = cmdutil.makefileobj(repo, dest)
417 if not prefix:
417 if not prefix:
418 prefix = os.path.basename(repo.root) + '-%h'
418 prefix = os.path.basename(repo.root) + '-%h'
419
419
420 prefix = cmdutil.makefilename(repo, prefix, node)
420 prefix = cmdutil.makefilename(repo, prefix, node)
421 matchfn = scmutil.match(ctx, [], opts)
421 matchfn = scmutil.match(ctx, [], opts)
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
423 matchfn, prefix, subrepos=opts.get('subrepos'))
423 matchfn, prefix, subrepos=opts.get('subrepos'))
424
424
425 @command('backout',
425 @command('backout',
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
427 ('', 'commit', None, _('commit if no conflicts were encountered')),
427 ('', 'commit', None, _('commit if no conflicts were encountered')),
428 ('', 'parent', '',
428 ('', 'parent', '',
429 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
429 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
430 ('r', 'rev', '', _('revision to backout'), _('REV')),
430 ('r', 'rev', '', _('revision to backout'), _('REV')),
431 ('e', 'edit', False, _('invoke editor on commit messages')),
431 ('e', 'edit', False, _('invoke editor on commit messages')),
432 ] + mergetoolopts + walkopts + commitopts + commitopts2,
432 ] + mergetoolopts + walkopts + commitopts + commitopts2,
433 _('[OPTION]... [-r] REV'))
433 _('[OPTION]... [-r] REV'))
434 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
434 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
435 '''reverse effect of earlier changeset
435 '''reverse effect of earlier changeset
436
436
437 Prepare a new changeset with the effect of REV undone in the
437 Prepare a new changeset with the effect of REV undone in the
438 current working directory.
438 current working directory.
439
439
440 If REV is the parent of the working directory, then this new changeset
440 If REV is the parent of the working directory, then this new changeset
441 is committed automatically. Otherwise, hg needs to merge the
441 is committed automatically. Otherwise, hg needs to merge the
442 changes and the merged result is left uncommitted.
442 changes and the merged result is left uncommitted.
443
443
444 .. note::
444 .. note::
445
445
446 backout cannot be used to fix either an unwanted or
446 backout cannot be used to fix either an unwanted or
447 incorrect merge.
447 incorrect merge.
448
448
449 .. container:: verbose
449 .. container:: verbose
450
450
451 By default, the pending changeset will have one parent,
451 By default, the pending changeset will have one parent,
452 maintaining a linear history. With --merge, the pending
452 maintaining a linear history. With --merge, the pending
453 changeset will instead have two parents: the old parent of the
453 changeset will instead have two parents: the old parent of the
454 working directory and a new child of REV that simply undoes REV.
454 working directory and a new child of REV that simply undoes REV.
455
455
456 Before version 1.7, the behavior without --merge was equivalent
456 Before version 1.7, the behavior without --merge was equivalent
457 to specifying --merge followed by :hg:`update --clean .` to
457 to specifying --merge followed by :hg:`update --clean .` to
458 cancel the merge and leave the child of REV as a head to be
458 cancel the merge and leave the child of REV as a head to be
459 merged separately.
459 merged separately.
460
460
461 See :hg:`help dates` for a list of formats valid for -d/--date.
461 See :hg:`help dates` for a list of formats valid for -d/--date.
462
462
463 Returns 0 on success, 1 if nothing to backout or there are unresolved
463 Returns 0 on success, 1 if nothing to backout or there are unresolved
464 files.
464 files.
465 '''
465 '''
466 if rev and node:
466 if rev and node:
467 raise util.Abort(_("please specify just one revision"))
467 raise util.Abort(_("please specify just one revision"))
468
468
469 if not rev:
469 if not rev:
470 rev = node
470 rev = node
471
471
472 if not rev:
472 if not rev:
473 raise util.Abort(_("please specify a revision to backout"))
473 raise util.Abort(_("please specify a revision to backout"))
474
474
475 date = opts.get('date')
475 date = opts.get('date')
476 if date:
476 if date:
477 opts['date'] = util.parsedate(date)
477 opts['date'] = util.parsedate(date)
478
478
479 cmdutil.checkunfinished(repo)
479 cmdutil.checkunfinished(repo)
480 cmdutil.bailifchanged(repo)
480 cmdutil.bailifchanged(repo)
481 node = scmutil.revsingle(repo, rev).node()
481 node = scmutil.revsingle(repo, rev).node()
482
482
483 op1, op2 = repo.dirstate.parents()
483 op1, op2 = repo.dirstate.parents()
484 if not repo.changelog.isancestor(node, op1):
484 if not repo.changelog.isancestor(node, op1):
485 raise util.Abort(_('cannot backout change that is not an ancestor'))
485 raise util.Abort(_('cannot backout change that is not an ancestor'))
486
486
487 p1, p2 = repo.changelog.parents(node)
487 p1, p2 = repo.changelog.parents(node)
488 if p1 == nullid:
488 if p1 == nullid:
489 raise util.Abort(_('cannot backout a change with no parents'))
489 raise util.Abort(_('cannot backout a change with no parents'))
490 if p2 != nullid:
490 if p2 != nullid:
491 if not opts.get('parent'):
491 if not opts.get('parent'):
492 raise util.Abort(_('cannot backout a merge changeset'))
492 raise util.Abort(_('cannot backout a merge changeset'))
493 p = repo.lookup(opts['parent'])
493 p = repo.lookup(opts['parent'])
494 if p not in (p1, p2):
494 if p not in (p1, p2):
495 raise util.Abort(_('%s is not a parent of %s') %
495 raise util.Abort(_('%s is not a parent of %s') %
496 (short(p), short(node)))
496 (short(p), short(node)))
497 parent = p
497 parent = p
498 else:
498 else:
499 if opts.get('parent'):
499 if opts.get('parent'):
500 raise util.Abort(_('cannot use --parent on non-merge changeset'))
500 raise util.Abort(_('cannot use --parent on non-merge changeset'))
501 parent = p1
501 parent = p1
502
502
503 # the backout should appear on the same branch
503 # the backout should appear on the same branch
504 wlock = repo.wlock()
504 wlock = repo.wlock()
505 try:
505 try:
506 branch = repo.dirstate.branch()
506 branch = repo.dirstate.branch()
507 bheads = repo.branchheads(branch)
507 bheads = repo.branchheads(branch)
508 rctx = scmutil.revsingle(repo, hex(parent))
508 rctx = scmutil.revsingle(repo, hex(parent))
509 if not opts.get('merge') and op1 != node:
509 if not opts.get('merge') and op1 != node:
510 try:
510 try:
511 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
511 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
512 'backout')
512 'backout')
513 repo.dirstate.beginparentchange()
513 repo.dirstate.beginparentchange()
514 stats = mergemod.update(repo, parent, True, True, False,
514 stats = mergemod.update(repo, parent, True, True, False,
515 node, False)
515 node, False)
516 repo.setparents(op1, op2)
516 repo.setparents(op1, op2)
517 repo.dirstate.endparentchange()
517 repo.dirstate.endparentchange()
518 hg._showstats(repo, stats)
518 hg._showstats(repo, stats)
519 if stats[3]:
519 if stats[3]:
520 repo.ui.status(_("use 'hg resolve' to retry unresolved "
520 repo.ui.status(_("use 'hg resolve' to retry unresolved "
521 "file merges\n"))
521 "file merges\n"))
522 return 1
522 return 1
523 elif not commit:
523 elif not commit:
524 msg = _("changeset %s backed out, "
524 msg = _("changeset %s backed out, "
525 "don't forget to commit.\n")
525 "don't forget to commit.\n")
526 ui.status(msg % short(node))
526 ui.status(msg % short(node))
527 return 0
527 return 0
528 finally:
528 finally:
529 ui.setconfig('ui', 'forcemerge', '', '')
529 ui.setconfig('ui', 'forcemerge', '', '')
530 else:
530 else:
531 hg.clean(repo, node, show_stats=False)
531 hg.clean(repo, node, show_stats=False)
532 repo.dirstate.setbranch(branch)
532 repo.dirstate.setbranch(branch)
533 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
533 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
534
534
535
535
536 def commitfunc(ui, repo, message, match, opts):
536 def commitfunc(ui, repo, message, match, opts):
537 editform = 'backout'
537 editform = 'backout'
538 e = cmdutil.getcommiteditor(editform=editform, **opts)
538 e = cmdutil.getcommiteditor(editform=editform, **opts)
539 if not message:
539 if not message:
540 # we don't translate commit messages
540 # we don't translate commit messages
541 message = "Backed out changeset %s" % short(node)
541 message = "Backed out changeset %s" % short(node)
542 e = cmdutil.getcommiteditor(edit=True, editform=editform)
542 e = cmdutil.getcommiteditor(edit=True, editform=editform)
543 return repo.commit(message, opts.get('user'), opts.get('date'),
543 return repo.commit(message, opts.get('user'), opts.get('date'),
544 match, editor=e)
544 match, editor=e)
545 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
545 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
546 if not newnode:
546 if not newnode:
547 ui.status(_("nothing changed\n"))
547 ui.status(_("nothing changed\n"))
548 return 1
548 return 1
549 cmdutil.commitstatus(repo, newnode, branch, bheads)
549 cmdutil.commitstatus(repo, newnode, branch, bheads)
550
550
551 def nice(node):
551 def nice(node):
552 return '%d:%s' % (repo.changelog.rev(node), short(node))
552 return '%d:%s' % (repo.changelog.rev(node), short(node))
553 ui.status(_('changeset %s backs out changeset %s\n') %
553 ui.status(_('changeset %s backs out changeset %s\n') %
554 (nice(repo.changelog.tip()), nice(node)))
554 (nice(repo.changelog.tip()), nice(node)))
555 if opts.get('merge') and op1 != node:
555 if opts.get('merge') and op1 != node:
556 hg.clean(repo, op1, show_stats=False)
556 hg.clean(repo, op1, show_stats=False)
557 ui.status(_('merging with changeset %s\n')
557 ui.status(_('merging with changeset %s\n')
558 % nice(repo.changelog.tip()))
558 % nice(repo.changelog.tip()))
559 try:
559 try:
560 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
560 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
561 'backout')
561 'backout')
562 return hg.merge(repo, hex(repo.changelog.tip()))
562 return hg.merge(repo, hex(repo.changelog.tip()))
563 finally:
563 finally:
564 ui.setconfig('ui', 'forcemerge', '', '')
564 ui.setconfig('ui', 'forcemerge', '', '')
565 finally:
565 finally:
566 wlock.release()
566 wlock.release()
567 return 0
567 return 0
568
568
569 @command('bisect',
569 @command('bisect',
570 [('r', 'reset', False, _('reset bisect state')),
570 [('r', 'reset', False, _('reset bisect state')),
571 ('g', 'good', False, _('mark changeset good')),
571 ('g', 'good', False, _('mark changeset good')),
572 ('b', 'bad', False, _('mark changeset bad')),
572 ('b', 'bad', False, _('mark changeset bad')),
573 ('s', 'skip', False, _('skip testing changeset')),
573 ('s', 'skip', False, _('skip testing changeset')),
574 ('e', 'extend', False, _('extend the bisect range')),
574 ('e', 'extend', False, _('extend the bisect range')),
575 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
575 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
576 ('U', 'noupdate', False, _('do not update to target'))],
576 ('U', 'noupdate', False, _('do not update to target'))],
577 _("[-gbsr] [-U] [-c CMD] [REV]"))
577 _("[-gbsr] [-U] [-c CMD] [REV]"))
578 def bisect(ui, repo, rev=None, extra=None, command=None,
578 def bisect(ui, repo, rev=None, extra=None, command=None,
579 reset=None, good=None, bad=None, skip=None, extend=None,
579 reset=None, good=None, bad=None, skip=None, extend=None,
580 noupdate=None):
580 noupdate=None):
581 """subdivision search of changesets
581 """subdivision search of changesets
582
582
583 This command helps to find changesets which introduce problems. To
583 This command helps to find changesets which introduce problems. To
584 use, mark the earliest changeset you know exhibits the problem as
584 use, mark the earliest changeset you know exhibits the problem as
585 bad, then mark the latest changeset which is free from the problem
585 bad, then mark the latest changeset which is free from the problem
586 as good. Bisect will update your working directory to a revision
586 as good. Bisect will update your working directory to a revision
587 for testing (unless the -U/--noupdate option is specified). Once
587 for testing (unless the -U/--noupdate option is specified). Once
588 you have performed tests, mark the working directory as good or
588 you have performed tests, mark the working directory as good or
589 bad, and bisect will either update to another candidate changeset
589 bad, and bisect will either update to another candidate changeset
590 or announce that it has found the bad revision.
590 or announce that it has found the bad revision.
591
591
592 As a shortcut, you can also use the revision argument to mark a
592 As a shortcut, you can also use the revision argument to mark a
593 revision as good or bad without checking it out first.
593 revision as good or bad without checking it out first.
594
594
595 If you supply a command, it will be used for automatic bisection.
595 If you supply a command, it will be used for automatic bisection.
596 The environment variable HG_NODE will contain the ID of the
596 The environment variable HG_NODE will contain the ID of the
597 changeset being tested. The exit status of the command will be
597 changeset being tested. The exit status of the command will be
598 used to mark revisions as good or bad: status 0 means good, 125
598 used to mark revisions as good or bad: status 0 means good, 125
599 means to skip the revision, 127 (command not found) will abort the
599 means to skip the revision, 127 (command not found) will abort the
600 bisection, and any other non-zero exit status means the revision
600 bisection, and any other non-zero exit status means the revision
601 is bad.
601 is bad.
602
602
603 .. container:: verbose
603 .. container:: verbose
604
604
605 Some examples:
605 Some examples:
606
606
607 - start a bisection with known bad revision 34, and good revision 12::
607 - start a bisection with known bad revision 34, and good revision 12::
608
608
609 hg bisect --bad 34
609 hg bisect --bad 34
610 hg bisect --good 12
610 hg bisect --good 12
611
611
612 - advance the current bisection by marking current revision as good or
612 - advance the current bisection by marking current revision as good or
613 bad::
613 bad::
614
614
615 hg bisect --good
615 hg bisect --good
616 hg bisect --bad
616 hg bisect --bad
617
617
618 - mark the current revision, or a known revision, to be skipped (e.g. if
618 - mark the current revision, or a known revision, to be skipped (e.g. if
619 that revision is not usable because of another issue)::
619 that revision is not usable because of another issue)::
620
620
621 hg bisect --skip
621 hg bisect --skip
622 hg bisect --skip 23
622 hg bisect --skip 23
623
623
624 - skip all revisions that do not touch directories ``foo`` or ``bar``::
624 - skip all revisions that do not touch directories ``foo`` or ``bar``::
625
625
626 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
626 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
627
627
628 - forget the current bisection::
628 - forget the current bisection::
629
629
630 hg bisect --reset
630 hg bisect --reset
631
631
632 - use 'make && make tests' to automatically find the first broken
632 - use 'make && make tests' to automatically find the first broken
633 revision::
633 revision::
634
634
635 hg bisect --reset
635 hg bisect --reset
636 hg bisect --bad 34
636 hg bisect --bad 34
637 hg bisect --good 12
637 hg bisect --good 12
638 hg bisect --command "make && make tests"
638 hg bisect --command "make && make tests"
639
639
640 - see all changesets whose states are already known in the current
640 - see all changesets whose states are already known in the current
641 bisection::
641 bisection::
642
642
643 hg log -r "bisect(pruned)"
643 hg log -r "bisect(pruned)"
644
644
645 - see the changeset currently being bisected (especially useful
645 - see the changeset currently being bisected (especially useful
646 if running with -U/--noupdate)::
646 if running with -U/--noupdate)::
647
647
648 hg log -r "bisect(current)"
648 hg log -r "bisect(current)"
649
649
650 - see all changesets that took part in the current bisection::
650 - see all changesets that took part in the current bisection::
651
651
652 hg log -r "bisect(range)"
652 hg log -r "bisect(range)"
653
653
654 - you can even get a nice graph::
654 - you can even get a nice graph::
655
655
656 hg log --graph -r "bisect(range)"
656 hg log --graph -r "bisect(range)"
657
657
658 See :hg:`help revsets` for more about the `bisect()` keyword.
658 See :hg:`help revsets` for more about the `bisect()` keyword.
659
659
660 Returns 0 on success.
660 Returns 0 on success.
661 """
661 """
662 def extendbisectrange(nodes, good):
662 def extendbisectrange(nodes, good):
663 # bisect is incomplete when it ends on a merge node and
663 # bisect is incomplete when it ends on a merge node and
664 # one of the parent was not checked.
664 # one of the parent was not checked.
665 parents = repo[nodes[0]].parents()
665 parents = repo[nodes[0]].parents()
666 if len(parents) > 1:
666 if len(parents) > 1:
667 side = good and state['bad'] or state['good']
667 side = good and state['bad'] or state['good']
668 num = len(set(i.node() for i in parents) & set(side))
668 num = len(set(i.node() for i in parents) & set(side))
669 if num == 1:
669 if num == 1:
670 return parents[0].ancestor(parents[1])
670 return parents[0].ancestor(parents[1])
671 return None
671 return None
672
672
673 def print_result(nodes, good):
673 def print_result(nodes, good):
674 displayer = cmdutil.show_changeset(ui, repo, {})
674 displayer = cmdutil.show_changeset(ui, repo, {})
675 if len(nodes) == 1:
675 if len(nodes) == 1:
676 # narrowed it down to a single revision
676 # narrowed it down to a single revision
677 if good:
677 if good:
678 ui.write(_("The first good revision is:\n"))
678 ui.write(_("The first good revision is:\n"))
679 else:
679 else:
680 ui.write(_("The first bad revision is:\n"))
680 ui.write(_("The first bad revision is:\n"))
681 displayer.show(repo[nodes[0]])
681 displayer.show(repo[nodes[0]])
682 extendnode = extendbisectrange(nodes, good)
682 extendnode = extendbisectrange(nodes, good)
683 if extendnode is not None:
683 if extendnode is not None:
684 ui.write(_('Not all ancestors of this changeset have been'
684 ui.write(_('Not all ancestors of this changeset have been'
685 ' checked.\nUse bisect --extend to continue the '
685 ' checked.\nUse bisect --extend to continue the '
686 'bisection from\nthe common ancestor, %s.\n')
686 'bisection from\nthe common ancestor, %s.\n')
687 % extendnode)
687 % extendnode)
688 else:
688 else:
689 # multiple possible revisions
689 # multiple possible revisions
690 if good:
690 if good:
691 ui.write(_("Due to skipped revisions, the first "
691 ui.write(_("Due to skipped revisions, the first "
692 "good revision could be any of:\n"))
692 "good revision could be any of:\n"))
693 else:
693 else:
694 ui.write(_("Due to skipped revisions, the first "
694 ui.write(_("Due to skipped revisions, the first "
695 "bad revision could be any of:\n"))
695 "bad revision could be any of:\n"))
696 for n in nodes:
696 for n in nodes:
697 displayer.show(repo[n])
697 displayer.show(repo[n])
698 displayer.close()
698 displayer.close()
699
699
700 def check_state(state, interactive=True):
700 def check_state(state, interactive=True):
701 if not state['good'] or not state['bad']:
701 if not state['good'] or not state['bad']:
702 if (good or bad or skip or reset) and interactive:
702 if (good or bad or skip or reset) and interactive:
703 return
703 return
704 if not state['good']:
704 if not state['good']:
705 raise util.Abort(_('cannot bisect (no known good revisions)'))
705 raise util.Abort(_('cannot bisect (no known good revisions)'))
706 else:
706 else:
707 raise util.Abort(_('cannot bisect (no known bad revisions)'))
707 raise util.Abort(_('cannot bisect (no known bad revisions)'))
708 return True
708 return True
709
709
710 # backward compatibility
710 # backward compatibility
711 if rev in "good bad reset init".split():
711 if rev in "good bad reset init".split():
712 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
712 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
713 cmd, rev, extra = rev, extra, None
713 cmd, rev, extra = rev, extra, None
714 if cmd == "good":
714 if cmd == "good":
715 good = True
715 good = True
716 elif cmd == "bad":
716 elif cmd == "bad":
717 bad = True
717 bad = True
718 else:
718 else:
719 reset = True
719 reset = True
720 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
720 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
721 raise util.Abort(_('incompatible arguments'))
721 raise util.Abort(_('incompatible arguments'))
722
722
723 cmdutil.checkunfinished(repo)
723 cmdutil.checkunfinished(repo)
724
724
725 if reset:
725 if reset:
726 p = repo.join("bisect.state")
726 p = repo.join("bisect.state")
727 if os.path.exists(p):
727 if os.path.exists(p):
728 os.unlink(p)
728 os.unlink(p)
729 return
729 return
730
730
731 state = hbisect.load_state(repo)
731 state = hbisect.load_state(repo)
732
732
733 if command:
733 if command:
734 changesets = 1
734 changesets = 1
735 if noupdate:
735 if noupdate:
736 try:
736 try:
737 node = state['current'][0]
737 node = state['current'][0]
738 except LookupError:
738 except LookupError:
739 raise util.Abort(_('current bisect revision is unknown - '
739 raise util.Abort(_('current bisect revision is unknown - '
740 'start a new bisect to fix'))
740 'start a new bisect to fix'))
741 else:
741 else:
742 node, p2 = repo.dirstate.parents()
742 node, p2 = repo.dirstate.parents()
743 if p2 != nullid:
743 if p2 != nullid:
744 raise util.Abort(_('current bisect revision is a merge'))
744 raise util.Abort(_('current bisect revision is a merge'))
745 try:
745 try:
746 while changesets:
746 while changesets:
747 # update state
747 # update state
748 state['current'] = [node]
748 state['current'] = [node]
749 hbisect.save_state(repo, state)
749 hbisect.save_state(repo, state)
750 status = ui.system(command, environ={'HG_NODE': hex(node)})
750 status = ui.system(command, environ={'HG_NODE': hex(node)})
751 if status == 125:
751 if status == 125:
752 transition = "skip"
752 transition = "skip"
753 elif status == 0:
753 elif status == 0:
754 transition = "good"
754 transition = "good"
755 # status < 0 means process was killed
755 # status < 0 means process was killed
756 elif status == 127:
756 elif status == 127:
757 raise util.Abort(_("failed to execute %s") % command)
757 raise util.Abort(_("failed to execute %s") % command)
758 elif status < 0:
758 elif status < 0:
759 raise util.Abort(_("%s killed") % command)
759 raise util.Abort(_("%s killed") % command)
760 else:
760 else:
761 transition = "bad"
761 transition = "bad"
762 ctx = scmutil.revsingle(repo, rev, node)
762 ctx = scmutil.revsingle(repo, rev, node)
763 rev = None # clear for future iterations
763 rev = None # clear for future iterations
764 state[transition].append(ctx.node())
764 state[transition].append(ctx.node())
765 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
765 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
766 check_state(state, interactive=False)
766 check_state(state, interactive=False)
767 # bisect
767 # bisect
768 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
768 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
769 # update to next check
769 # update to next check
770 node = nodes[0]
770 node = nodes[0]
771 if not noupdate:
771 if not noupdate:
772 cmdutil.bailifchanged(repo)
772 cmdutil.bailifchanged(repo)
773 hg.clean(repo, node, show_stats=False)
773 hg.clean(repo, node, show_stats=False)
774 finally:
774 finally:
775 state['current'] = [node]
775 state['current'] = [node]
776 hbisect.save_state(repo, state)
776 hbisect.save_state(repo, state)
777 print_result(nodes, bgood)
777 print_result(nodes, bgood)
778 return
778 return
779
779
780 # update state
780 # update state
781
781
782 if rev:
782 if rev:
783 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
783 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
784 else:
784 else:
785 nodes = [repo.lookup('.')]
785 nodes = [repo.lookup('.')]
786
786
787 if good or bad or skip:
787 if good or bad or skip:
788 if good:
788 if good:
789 state['good'] += nodes
789 state['good'] += nodes
790 elif bad:
790 elif bad:
791 state['bad'] += nodes
791 state['bad'] += nodes
792 elif skip:
792 elif skip:
793 state['skip'] += nodes
793 state['skip'] += nodes
794 hbisect.save_state(repo, state)
794 hbisect.save_state(repo, state)
795
795
796 if not check_state(state):
796 if not check_state(state):
797 return
797 return
798
798
799 # actually bisect
799 # actually bisect
800 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
800 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
801 if extend:
801 if extend:
802 if not changesets:
802 if not changesets:
803 extendnode = extendbisectrange(nodes, good)
803 extendnode = extendbisectrange(nodes, good)
804 if extendnode is not None:
804 if extendnode is not None:
805 ui.write(_("Extending search to changeset %d:%s\n")
805 ui.write(_("Extending search to changeset %d:%s\n")
806 % (extendnode.rev(), extendnode))
806 % (extendnode.rev(), extendnode))
807 state['current'] = [extendnode.node()]
807 state['current'] = [extendnode.node()]
808 hbisect.save_state(repo, state)
808 hbisect.save_state(repo, state)
809 if noupdate:
809 if noupdate:
810 return
810 return
811 cmdutil.bailifchanged(repo)
811 cmdutil.bailifchanged(repo)
812 return hg.clean(repo, extendnode.node())
812 return hg.clean(repo, extendnode.node())
813 raise util.Abort(_("nothing to extend"))
813 raise util.Abort(_("nothing to extend"))
814
814
815 if changesets == 0:
815 if changesets == 0:
816 print_result(nodes, good)
816 print_result(nodes, good)
817 else:
817 else:
818 assert len(nodes) == 1 # only a single node can be tested next
818 assert len(nodes) == 1 # only a single node can be tested next
819 node = nodes[0]
819 node = nodes[0]
820 # compute the approximate number of remaining tests
820 # compute the approximate number of remaining tests
821 tests, size = 0, 2
821 tests, size = 0, 2
822 while size <= changesets:
822 while size <= changesets:
823 tests, size = tests + 1, size * 2
823 tests, size = tests + 1, size * 2
824 rev = repo.changelog.rev(node)
824 rev = repo.changelog.rev(node)
825 ui.write(_("Testing changeset %d:%s "
825 ui.write(_("Testing changeset %d:%s "
826 "(%d changesets remaining, ~%d tests)\n")
826 "(%d changesets remaining, ~%d tests)\n")
827 % (rev, short(node), changesets, tests))
827 % (rev, short(node), changesets, tests))
828 state['current'] = [node]
828 state['current'] = [node]
829 hbisect.save_state(repo, state)
829 hbisect.save_state(repo, state)
830 if not noupdate:
830 if not noupdate:
831 cmdutil.bailifchanged(repo)
831 cmdutil.bailifchanged(repo)
832 return hg.clean(repo, node)
832 return hg.clean(repo, node)
833
833
834 @command('bookmarks|bookmark',
834 @command('bookmarks|bookmark',
835 [('f', 'force', False, _('force')),
835 [('f', 'force', False, _('force')),
836 ('r', 'rev', '', _('revision'), _('REV')),
836 ('r', 'rev', '', _('revision'), _('REV')),
837 ('d', 'delete', False, _('delete a given bookmark')),
837 ('d', 'delete', False, _('delete a given bookmark')),
838 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
838 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
839 ('i', 'inactive', False, _('mark a bookmark inactive')),
839 ('i', 'inactive', False, _('mark a bookmark inactive')),
840 ] + formatteropts,
840 ] + formatteropts,
841 _('hg bookmarks [OPTIONS]... [NAME]...'))
841 _('hg bookmarks [OPTIONS]... [NAME]...'))
842 def bookmark(ui, repo, *names, **opts):
842 def bookmark(ui, repo, *names, **opts):
843 '''create a new bookmark or list existing bookmarks
843 '''create a new bookmark or list existing bookmarks
844
844
845 Bookmarks are labels on changesets to help track lines of development.
845 Bookmarks are labels on changesets to help track lines of development.
846 Bookmarks are unversioned and can be moved, renamed and deleted.
846 Bookmarks are unversioned and can be moved, renamed and deleted.
847 Deleting or moving a bookmark has no effect on the associated changesets.
847 Deleting or moving a bookmark has no effect on the associated changesets.
848
848
849 Creating or updating to a bookmark causes it to be marked as 'active'.
849 Creating or updating to a bookmark causes it to be marked as 'active'.
850 The active bookmark is indicated with a '*'.
850 The active bookmark is indicated with a '*'.
851 When a commit is made, the active bookmark will advance to the new commit.
851 When a commit is made, the active bookmark will advance to the new commit.
852 A plain :hg:`update` will also advance an active bookmark, if possible.
852 A plain :hg:`update` will also advance an active bookmark, if possible.
853 Updating away from a bookmark will cause it to be deactivated.
853 Updating away from a bookmark will cause it to be deactivated.
854
854
855 Bookmarks can be pushed and pulled between repositories (see
855 Bookmarks can be pushed and pulled between repositories (see
856 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
856 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
857 diverged, a new 'divergent bookmark' of the form 'name@path' will
857 diverged, a new 'divergent bookmark' of the form 'name@path' will
858 be created. Using :hg:`merge` will resolve the divergence.
858 be created. Using :hg:`merge` will resolve the divergence.
859
859
860 A bookmark named '@' has the special property that :hg:`clone` will
860 A bookmark named '@' has the special property that :hg:`clone` will
861 check it out by default if it exists.
861 check it out by default if it exists.
862
862
863 .. container:: verbose
863 .. container:: verbose
864
864
865 Examples:
865 Examples:
866
866
867 - create an active bookmark for a new line of development::
867 - create an active bookmark for a new line of development::
868
868
869 hg book new-feature
869 hg book new-feature
870
870
871 - create an inactive bookmark as a place marker::
871 - create an inactive bookmark as a place marker::
872
872
873 hg book -i reviewed
873 hg book -i reviewed
874
874
875 - create an inactive bookmark on another changeset::
875 - create an inactive bookmark on another changeset::
876
876
877 hg book -r .^ tested
877 hg book -r .^ tested
878
878
879 - move the '@' bookmark from another branch::
879 - move the '@' bookmark from another branch::
880
880
881 hg book -f @
881 hg book -f @
882 '''
882 '''
883 force = opts.get('force')
883 force = opts.get('force')
884 rev = opts.get('rev')
884 rev = opts.get('rev')
885 delete = opts.get('delete')
885 delete = opts.get('delete')
886 rename = opts.get('rename')
886 rename = opts.get('rename')
887 inactive = opts.get('inactive')
887 inactive = opts.get('inactive')
888
888
889 def checkformat(mark):
889 def checkformat(mark):
890 mark = mark.strip()
890 mark = mark.strip()
891 if not mark:
891 if not mark:
892 raise util.Abort(_("bookmark names cannot consist entirely of "
892 raise util.Abort(_("bookmark names cannot consist entirely of "
893 "whitespace"))
893 "whitespace"))
894 scmutil.checknewlabel(repo, mark, 'bookmark')
894 scmutil.checknewlabel(repo, mark, 'bookmark')
895 return mark
895 return mark
896
896
897 def checkconflict(repo, mark, cur, force=False, target=None):
897 def checkconflict(repo, mark, cur, force=False, target=None):
898 if mark in marks and not force:
898 if mark in marks and not force:
899 if target:
899 if target:
900 if marks[mark] == target and target == cur:
900 if marks[mark] == target and target == cur:
901 # re-activating a bookmark
901 # re-activating a bookmark
902 return
902 return
903 anc = repo.changelog.ancestors([repo[target].rev()])
903 anc = repo.changelog.ancestors([repo[target].rev()])
904 bmctx = repo[marks[mark]]
904 bmctx = repo[marks[mark]]
905 divs = [repo[b].node() for b in marks
905 divs = [repo[b].node() for b in marks
906 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
906 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
907
907
908 # allow resolving a single divergent bookmark even if moving
908 # allow resolving a single divergent bookmark even if moving
909 # the bookmark across branches when a revision is specified
909 # the bookmark across branches when a revision is specified
910 # that contains a divergent bookmark
910 # that contains a divergent bookmark
911 if bmctx.rev() not in anc and target in divs:
911 if bmctx.rev() not in anc and target in divs:
912 bookmarks.deletedivergent(repo, [target], mark)
912 bookmarks.deletedivergent(repo, [target], mark)
913 return
913 return
914
914
915 deletefrom = [b for b in divs
915 deletefrom = [b for b in divs
916 if repo[b].rev() in anc or b == target]
916 if repo[b].rev() in anc or b == target]
917 bookmarks.deletedivergent(repo, deletefrom, mark)
917 bookmarks.deletedivergent(repo, deletefrom, mark)
918 if bookmarks.validdest(repo, bmctx, repo[target]):
918 if bookmarks.validdest(repo, bmctx, repo[target]):
919 ui.status(_("moving bookmark '%s' forward from %s\n") %
919 ui.status(_("moving bookmark '%s' forward from %s\n") %
920 (mark, short(bmctx.node())))
920 (mark, short(bmctx.node())))
921 return
921 return
922 raise util.Abort(_("bookmark '%s' already exists "
922 raise util.Abort(_("bookmark '%s' already exists "
923 "(use -f to force)") % mark)
923 "(use -f to force)") % mark)
924 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
924 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
925 and not force):
925 and not force):
926 raise util.Abort(
926 raise util.Abort(
927 _("a bookmark cannot have the name of an existing branch"))
927 _("a bookmark cannot have the name of an existing branch"))
928
928
929 if delete and rename:
929 if delete and rename:
930 raise util.Abort(_("--delete and --rename are incompatible"))
930 raise util.Abort(_("--delete and --rename are incompatible"))
931 if delete and rev:
931 if delete and rev:
932 raise util.Abort(_("--rev is incompatible with --delete"))
932 raise util.Abort(_("--rev is incompatible with --delete"))
933 if rename and rev:
933 if rename and rev:
934 raise util.Abort(_("--rev is incompatible with --rename"))
934 raise util.Abort(_("--rev is incompatible with --rename"))
935 if not names and (delete or rev):
935 if not names and (delete or rev):
936 raise util.Abort(_("bookmark name required"))
936 raise util.Abort(_("bookmark name required"))
937
937
938 if delete or rename or names or inactive:
938 if delete or rename or names or inactive:
939 wlock = repo.wlock()
939 wlock = repo.wlock()
940 try:
940 try:
941 cur = repo.changectx('.').node()
941 cur = repo.changectx('.').node()
942 marks = repo._bookmarks
942 marks = repo._bookmarks
943 if delete:
943 if delete:
944 for mark in names:
944 for mark in names:
945 if mark not in marks:
945 if mark not in marks:
946 raise util.Abort(_("bookmark '%s' does not exist") %
946 raise util.Abort(_("bookmark '%s' does not exist") %
947 mark)
947 mark)
948 if mark == repo._bookmarkcurrent:
948 if mark == repo._bookmarkcurrent:
949 bookmarks.unsetcurrent(repo)
949 bookmarks.unsetcurrent(repo)
950 del marks[mark]
950 del marks[mark]
951 marks.write()
951 marks.write()
952
952
953 elif rename:
953 elif rename:
954 if not names:
954 if not names:
955 raise util.Abort(_("new bookmark name required"))
955 raise util.Abort(_("new bookmark name required"))
956 elif len(names) > 1:
956 elif len(names) > 1:
957 raise util.Abort(_("only one new bookmark name allowed"))
957 raise util.Abort(_("only one new bookmark name allowed"))
958 mark = checkformat(names[0])
958 mark = checkformat(names[0])
959 if rename not in marks:
959 if rename not in marks:
960 raise util.Abort(_("bookmark '%s' does not exist") % rename)
960 raise util.Abort(_("bookmark '%s' does not exist") % rename)
961 checkconflict(repo, mark, cur, force)
961 checkconflict(repo, mark, cur, force)
962 marks[mark] = marks[rename]
962 marks[mark] = marks[rename]
963 if repo._bookmarkcurrent == rename and not inactive:
963 if repo._bookmarkcurrent == rename and not inactive:
964 bookmarks.setcurrent(repo, mark)
964 bookmarks.setcurrent(repo, mark)
965 del marks[rename]
965 del marks[rename]
966 marks.write()
966 marks.write()
967
967
968 elif names:
968 elif names:
969 newact = None
969 newact = None
970 for mark in names:
970 for mark in names:
971 mark = checkformat(mark)
971 mark = checkformat(mark)
972 if newact is None:
972 if newact is None:
973 newact = mark
973 newact = mark
974 if inactive and mark == repo._bookmarkcurrent:
974 if inactive and mark == repo._bookmarkcurrent:
975 bookmarks.unsetcurrent(repo)
975 bookmarks.unsetcurrent(repo)
976 return
976 return
977 tgt = cur
977 tgt = cur
978 if rev:
978 if rev:
979 tgt = scmutil.revsingle(repo, rev).node()
979 tgt = scmutil.revsingle(repo, rev).node()
980 checkconflict(repo, mark, cur, force, tgt)
980 checkconflict(repo, mark, cur, force, tgt)
981 marks[mark] = tgt
981 marks[mark] = tgt
982 if not inactive and cur == marks[newact] and not rev:
982 if not inactive and cur == marks[newact] and not rev:
983 bookmarks.setcurrent(repo, newact)
983 bookmarks.setcurrent(repo, newact)
984 elif cur != tgt and newact == repo._bookmarkcurrent:
984 elif cur != tgt and newact == repo._bookmarkcurrent:
985 bookmarks.unsetcurrent(repo)
985 bookmarks.unsetcurrent(repo)
986 marks.write()
986 marks.write()
987
987
988 elif inactive:
988 elif inactive:
989 if len(marks) == 0:
989 if len(marks) == 0:
990 ui.status(_("no bookmarks set\n"))
990 ui.status(_("no bookmarks set\n"))
991 elif not repo._bookmarkcurrent:
991 elif not repo._bookmarkcurrent:
992 ui.status(_("no active bookmark\n"))
992 ui.status(_("no active bookmark\n"))
993 else:
993 else:
994 bookmarks.unsetcurrent(repo)
994 bookmarks.unsetcurrent(repo)
995 finally:
995 finally:
996 wlock.release()
996 wlock.release()
997 else: # show bookmarks
997 else: # show bookmarks
998 fm = ui.formatter('bookmarks', opts)
998 fm = ui.formatter('bookmarks', opts)
999 hexfn = fm.hexfunc
999 hexfn = fm.hexfunc
1000 marks = repo._bookmarks
1000 marks = repo._bookmarks
1001 if len(marks) == 0 and not fm:
1001 if len(marks) == 0 and not fm:
1002 ui.status(_("no bookmarks set\n"))
1002 ui.status(_("no bookmarks set\n"))
1003 for bmark, n in sorted(marks.iteritems()):
1003 for bmark, n in sorted(marks.iteritems()):
1004 current = repo._bookmarkcurrent
1004 current = repo._bookmarkcurrent
1005 if bmark == current:
1005 if bmark == current:
1006 prefix, label = '*', 'bookmarks.current'
1006 prefix, label = '*', 'bookmarks.current'
1007 else:
1007 else:
1008 prefix, label = ' ', ''
1008 prefix, label = ' ', ''
1009
1009
1010 fm.startitem()
1010 fm.startitem()
1011 if not ui.quiet:
1011 if not ui.quiet:
1012 fm.plain(' %s ' % prefix, label=label)
1012 fm.plain(' %s ' % prefix, label=label)
1013 fm.write('bookmark', '%s', bmark, label=label)
1013 fm.write('bookmark', '%s', bmark, label=label)
1014 pad = " " * (25 - encoding.colwidth(bmark))
1014 pad = " " * (25 - encoding.colwidth(bmark))
1015 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1015 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1016 repo.changelog.rev(n), hexfn(n), label=label)
1016 repo.changelog.rev(n), hexfn(n), label=label)
1017 fm.data(active=(bmark == current))
1017 fm.data(active=(bmark == current))
1018 fm.plain('\n')
1018 fm.plain('\n')
1019 fm.end()
1019 fm.end()
1020
1020
1021 @command('branch',
1021 @command('branch',
1022 [('f', 'force', None,
1022 [('f', 'force', None,
1023 _('set branch name even if it shadows an existing branch')),
1023 _('set branch name even if it shadows an existing branch')),
1024 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1024 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1025 _('[-fC] [NAME]'))
1025 _('[-fC] [NAME]'))
1026 def branch(ui, repo, label=None, **opts):
1026 def branch(ui, repo, label=None, **opts):
1027 """set or show the current branch name
1027 """set or show the current branch name
1028
1028
1029 .. note::
1029 .. note::
1030
1030
1031 Branch names are permanent and global. Use :hg:`bookmark` to create a
1031 Branch names are permanent and global. Use :hg:`bookmark` to create a
1032 light-weight bookmark instead. See :hg:`help glossary` for more
1032 light-weight bookmark instead. See :hg:`help glossary` for more
1033 information about named branches and bookmarks.
1033 information about named branches and bookmarks.
1034
1034
1035 With no argument, show the current branch name. With one argument,
1035 With no argument, show the current branch name. With one argument,
1036 set the working directory branch name (the branch will not exist
1036 set the working directory branch name (the branch will not exist
1037 in the repository until the next commit). Standard practice
1037 in the repository until the next commit). Standard practice
1038 recommends that primary development take place on the 'default'
1038 recommends that primary development take place on the 'default'
1039 branch.
1039 branch.
1040
1040
1041 Unless -f/--force is specified, branch will not let you set a
1041 Unless -f/--force is specified, branch will not let you set a
1042 branch name that already exists.
1042 branch name that already exists.
1043
1043
1044 Use -C/--clean to reset the working directory branch to that of
1044 Use -C/--clean to reset the working directory branch to that of
1045 the parent of the working directory, negating a previous branch
1045 the parent of the working directory, negating a previous branch
1046 change.
1046 change.
1047
1047
1048 Use the command :hg:`update` to switch to an existing branch. Use
1048 Use the command :hg:`update` to switch to an existing branch. Use
1049 :hg:`commit --close-branch` to mark this branch as closed.
1049 :hg:`commit --close-branch` to mark this branch as closed.
1050
1050
1051 Returns 0 on success.
1051 Returns 0 on success.
1052 """
1052 """
1053 if label:
1053 if label:
1054 label = label.strip()
1054 label = label.strip()
1055
1055
1056 if not opts.get('clean') and not label:
1056 if not opts.get('clean') and not label:
1057 ui.write("%s\n" % repo.dirstate.branch())
1057 ui.write("%s\n" % repo.dirstate.branch())
1058 return
1058 return
1059
1059
1060 wlock = repo.wlock()
1060 wlock = repo.wlock()
1061 try:
1061 try:
1062 if opts.get('clean'):
1062 if opts.get('clean'):
1063 label = repo[None].p1().branch()
1063 label = repo[None].p1().branch()
1064 repo.dirstate.setbranch(label)
1064 repo.dirstate.setbranch(label)
1065 ui.status(_('reset working directory to branch %s\n') % label)
1065 ui.status(_('reset working directory to branch %s\n') % label)
1066 elif label:
1066 elif label:
1067 if not opts.get('force') and label in repo.branchmap():
1067 if not opts.get('force') and label in repo.branchmap():
1068 if label not in [p.branch() for p in repo.parents()]:
1068 if label not in [p.branch() for p in repo.parents()]:
1069 raise util.Abort(_('a branch of the same name already'
1069 raise util.Abort(_('a branch of the same name already'
1070 ' exists'),
1070 ' exists'),
1071 # i18n: "it" refers to an existing branch
1071 # i18n: "it" refers to an existing branch
1072 hint=_("use 'hg update' to switch to it"))
1072 hint=_("use 'hg update' to switch to it"))
1073 scmutil.checknewlabel(repo, label, 'branch')
1073 scmutil.checknewlabel(repo, label, 'branch')
1074 repo.dirstate.setbranch(label)
1074 repo.dirstate.setbranch(label)
1075 ui.status(_('marked working directory as branch %s\n') % label)
1075 ui.status(_('marked working directory as branch %s\n') % label)
1076 ui.status(_('(branches are permanent and global, '
1076 ui.status(_('(branches are permanent and global, '
1077 'did you want a bookmark?)\n'))
1077 'did you want a bookmark?)\n'))
1078 finally:
1078 finally:
1079 wlock.release()
1079 wlock.release()
1080
1080
1081 @command('branches',
1081 @command('branches',
1082 [('a', 'active', False,
1082 [('a', 'active', False,
1083 _('show only branches that have unmerged heads (DEPRECATED)')),
1083 _('show only branches that have unmerged heads (DEPRECATED)')),
1084 ('c', 'closed', False, _('show normal and closed branches')),
1084 ('c', 'closed', False, _('show normal and closed branches')),
1085 ] + formatteropts,
1085 ] + formatteropts,
1086 _('[-ac]'))
1086 _('[-ac]'))
1087 def branches(ui, repo, active=False, closed=False, **opts):
1087 def branches(ui, repo, active=False, closed=False, **opts):
1088 """list repository named branches
1088 """list repository named branches
1089
1089
1090 List the repository's named branches, indicating which ones are
1090 List the repository's named branches, indicating which ones are
1091 inactive. If -c/--closed is specified, also list branches which have
1091 inactive. If -c/--closed is specified, also list branches which have
1092 been marked closed (see :hg:`commit --close-branch`).
1092 been marked closed (see :hg:`commit --close-branch`).
1093
1093
1094 Use the command :hg:`update` to switch to an existing branch.
1094 Use the command :hg:`update` to switch to an existing branch.
1095
1095
1096 Returns 0.
1096 Returns 0.
1097 """
1097 """
1098
1098
1099 fm = ui.formatter('branches', opts)
1099 fm = ui.formatter('branches', opts)
1100 hexfunc = fm.hexfunc
1100 hexfunc = fm.hexfunc
1101
1101
1102 allheads = set(repo.heads())
1102 allheads = set(repo.heads())
1103 branches = []
1103 branches = []
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1105 isactive = not isclosed and bool(set(heads) & allheads)
1105 isactive = not isclosed and bool(set(heads) & allheads)
1106 branches.append((tag, repo[tip], isactive, not isclosed))
1106 branches.append((tag, repo[tip], isactive, not isclosed))
1107 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1107 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1108 reverse=True)
1108 reverse=True)
1109
1109
1110 for tag, ctx, isactive, isopen in branches:
1110 for tag, ctx, isactive, isopen in branches:
1111 if active and not isactive:
1111 if active and not isactive:
1112 continue
1112 continue
1113 if isactive:
1113 if isactive:
1114 label = 'branches.active'
1114 label = 'branches.active'
1115 notice = ''
1115 notice = ''
1116 elif not isopen:
1116 elif not isopen:
1117 if not closed:
1117 if not closed:
1118 continue
1118 continue
1119 label = 'branches.closed'
1119 label = 'branches.closed'
1120 notice = _(' (closed)')
1120 notice = _(' (closed)')
1121 else:
1121 else:
1122 label = 'branches.inactive'
1122 label = 'branches.inactive'
1123 notice = _(' (inactive)')
1123 notice = _(' (inactive)')
1124 current = (tag == repo.dirstate.branch())
1124 current = (tag == repo.dirstate.branch())
1125 if current:
1125 if current:
1126 label = 'branches.current'
1126 label = 'branches.current'
1127
1127
1128 fm.startitem()
1128 fm.startitem()
1129 fm.write('branch', '%s', tag, label=label)
1129 fm.write('branch', '%s', tag, label=label)
1130 rev = ctx.rev()
1130 rev = ctx.rev()
1131 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1131 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1132 fmt = ' ' * padsize + ' %d:%s'
1132 fmt = ' ' * padsize + ' %d:%s'
1133 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1133 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1134 label='log.changeset changeset.%s' % ctx.phasestr())
1134 label='log.changeset changeset.%s' % ctx.phasestr())
1135 fm.data(active=isactive, closed=not isopen, current=current)
1135 fm.data(active=isactive, closed=not isopen, current=current)
1136 if not ui.quiet:
1136 if not ui.quiet:
1137 fm.plain(notice)
1137 fm.plain(notice)
1138 fm.plain('\n')
1138 fm.plain('\n')
1139 fm.end()
1139 fm.end()
1140
1140
1141 @command('bundle',
1141 @command('bundle',
1142 [('f', 'force', None, _('run even when the destination is unrelated')),
1142 [('f', 'force', None, _('run even when the destination is unrelated')),
1143 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1143 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1144 _('REV')),
1144 _('REV')),
1145 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1145 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1146 _('BRANCH')),
1146 _('BRANCH')),
1147 ('', 'base', [],
1147 ('', 'base', [],
1148 _('a base changeset assumed to be available at the destination'),
1148 _('a base changeset assumed to be available at the destination'),
1149 _('REV')),
1149 _('REV')),
1150 ('a', 'all', None, _('bundle all changesets in the repository')),
1150 ('a', 'all', None, _('bundle all changesets in the repository')),
1151 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1151 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1152 ] + remoteopts,
1152 ] + remoteopts,
1153 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1153 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1154 def bundle(ui, repo, fname, dest=None, **opts):
1154 def bundle(ui, repo, fname, dest=None, **opts):
1155 """create a changegroup file
1155 """create a changegroup file
1156
1156
1157 Generate a compressed changegroup file collecting changesets not
1157 Generate a compressed changegroup file collecting changesets not
1158 known to be in another repository.
1158 known to be in another repository.
1159
1159
1160 If you omit the destination repository, then hg assumes the
1160 If you omit the destination repository, then hg assumes the
1161 destination will have all the nodes you specify with --base
1161 destination will have all the nodes you specify with --base
1162 parameters. To create a bundle containing all changesets, use
1162 parameters. To create a bundle containing all changesets, use
1163 -a/--all (or --base null).
1163 -a/--all (or --base null).
1164
1164
1165 You can change compression method with the -t/--type option.
1165 You can change compression method with the -t/--type option.
1166 The available compression methods are: none, bzip2, and
1166 The available compression methods are: none, bzip2, and
1167 gzip (by default, bundles are compressed using bzip2).
1167 gzip (by default, bundles are compressed using bzip2).
1168
1168
1169 The bundle file can then be transferred using conventional means
1169 The bundle file can then be transferred using conventional means
1170 and applied to another repository with the unbundle or pull
1170 and applied to another repository with the unbundle or pull
1171 command. This is useful when direct push and pull are not
1171 command. This is useful when direct push and pull are not
1172 available or when exporting an entire repository is undesirable.
1172 available or when exporting an entire repository is undesirable.
1173
1173
1174 Applying bundles preserves all changeset contents including
1174 Applying bundles preserves all changeset contents including
1175 permissions, copy/rename information, and revision history.
1175 permissions, copy/rename information, and revision history.
1176
1176
1177 Returns 0 on success, 1 if no changes found.
1177 Returns 0 on success, 1 if no changes found.
1178 """
1178 """
1179 revs = None
1179 revs = None
1180 if 'rev' in opts:
1180 if 'rev' in opts:
1181 revs = scmutil.revrange(repo, opts['rev'])
1181 revs = scmutil.revrange(repo, opts['rev'])
1182
1182
1183 bundletype = opts.get('type', 'bzip2').lower()
1183 bundletype = opts.get('type', 'bzip2').lower()
1184 btypes = {'none': 'HG10UN',
1184 btypes = {'none': 'HG10UN',
1185 'bzip2': 'HG10BZ',
1185 'bzip2': 'HG10BZ',
1186 'gzip': 'HG10GZ',
1186 'gzip': 'HG10GZ',
1187 'bundle2': 'HG2Y'}
1187 'bundle2': 'HG2Y'}
1188 bundletype = btypes.get(bundletype)
1188 bundletype = btypes.get(bundletype)
1189 if bundletype not in changegroup.bundletypes:
1189 if bundletype not in changegroup.bundletypes:
1190 raise util.Abort(_('unknown bundle type specified with --type'))
1190 raise util.Abort(_('unknown bundle type specified with --type'))
1191
1191
1192 if opts.get('all'):
1192 if opts.get('all'):
1193 base = ['null']
1193 base = ['null']
1194 else:
1194 else:
1195 base = scmutil.revrange(repo, opts.get('base'))
1195 base = scmutil.revrange(repo, opts.get('base'))
1196 # TODO: get desired bundlecaps from command line.
1196 # TODO: get desired bundlecaps from command line.
1197 bundlecaps = None
1197 bundlecaps = None
1198 if base:
1198 if base:
1199 if dest:
1199 if dest:
1200 raise util.Abort(_("--base is incompatible with specifying "
1200 raise util.Abort(_("--base is incompatible with specifying "
1201 "a destination"))
1201 "a destination"))
1202 common = [repo.lookup(rev) for rev in base]
1202 common = [repo.lookup(rev) for rev in base]
1203 heads = revs and map(repo.lookup, revs) or revs
1203 heads = revs and map(repo.lookup, revs) or revs
1204 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1204 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1205 common=common, bundlecaps=bundlecaps)
1205 common=common, bundlecaps=bundlecaps)
1206 outgoing = None
1206 outgoing = None
1207 else:
1207 else:
1208 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1208 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1209 dest, branches = hg.parseurl(dest, opts.get('branch'))
1209 dest, branches = hg.parseurl(dest, opts.get('branch'))
1210 other = hg.peer(repo, opts, dest)
1210 other = hg.peer(repo, opts, dest)
1211 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1211 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1212 heads = revs and map(repo.lookup, revs) or revs
1212 heads = revs and map(repo.lookup, revs) or revs
1213 outgoing = discovery.findcommonoutgoing(repo, other,
1213 outgoing = discovery.findcommonoutgoing(repo, other,
1214 onlyheads=heads,
1214 onlyheads=heads,
1215 force=opts.get('force'),
1215 force=opts.get('force'),
1216 portable=True)
1216 portable=True)
1217 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1217 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1218 bundlecaps)
1218 bundlecaps)
1219 if not cg:
1219 if not cg:
1220 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1220 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1221 return 1
1221 return 1
1222
1222
1223 changegroup.writebundle(ui, cg, fname, bundletype)
1223 changegroup.writebundle(ui, cg, fname, bundletype)
1224
1224
1225 @command('cat',
1225 @command('cat',
1226 [('o', 'output', '',
1226 [('o', 'output', '',
1227 _('print output to file with formatted name'), _('FORMAT')),
1227 _('print output to file with formatted name'), _('FORMAT')),
1228 ('r', 'rev', '', _('print the given revision'), _('REV')),
1228 ('r', 'rev', '', _('print the given revision'), _('REV')),
1229 ('', 'decode', None, _('apply any matching decode filter')),
1229 ('', 'decode', None, _('apply any matching decode filter')),
1230 ] + walkopts,
1230 ] + walkopts,
1231 _('[OPTION]... FILE...'),
1231 _('[OPTION]... FILE...'),
1232 inferrepo=True)
1232 inferrepo=True)
1233 def cat(ui, repo, file1, *pats, **opts):
1233 def cat(ui, repo, file1, *pats, **opts):
1234 """output the current or given revision of files
1234 """output the current or given revision of files
1235
1235
1236 Print the specified files as they were at the given revision. If
1236 Print the specified files as they were at the given revision. If
1237 no revision is given, the parent of the working directory is used.
1237 no revision is given, the parent of the working directory is used.
1238
1238
1239 Output may be to a file, in which case the name of the file is
1239 Output may be to a file, in which case the name of the file is
1240 given using a format string. The formatting rules as follows:
1240 given using a format string. The formatting rules as follows:
1241
1241
1242 :``%%``: literal "%" character
1242 :``%%``: literal "%" character
1243 :``%s``: basename of file being printed
1243 :``%s``: basename of file being printed
1244 :``%d``: dirname of file being printed, or '.' if in repository root
1244 :``%d``: dirname of file being printed, or '.' if in repository root
1245 :``%p``: root-relative path name of file being printed
1245 :``%p``: root-relative path name of file being printed
1246 :``%H``: changeset hash (40 hexadecimal digits)
1246 :``%H``: changeset hash (40 hexadecimal digits)
1247 :``%R``: changeset revision number
1247 :``%R``: changeset revision number
1248 :``%h``: short-form changeset hash (12 hexadecimal digits)
1248 :``%h``: short-form changeset hash (12 hexadecimal digits)
1249 :``%r``: zero-padded changeset revision number
1249 :``%r``: zero-padded changeset revision number
1250 :``%b``: basename of the exporting repository
1250 :``%b``: basename of the exporting repository
1251
1251
1252 Returns 0 on success.
1252 Returns 0 on success.
1253 """
1253 """
1254 ctx = scmutil.revsingle(repo, opts.get('rev'))
1254 ctx = scmutil.revsingle(repo, opts.get('rev'))
1255 m = scmutil.match(ctx, (file1,) + pats, opts)
1255 m = scmutil.match(ctx, (file1,) + pats, opts)
1256
1256
1257 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1257 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1258
1258
1259 @command('^clone',
1259 @command('^clone',
1260 [('U', 'noupdate', None,
1260 [('U', 'noupdate', None,
1261 _('the clone will include an empty working copy (only a repository)')),
1261 _('the clone will include an empty working copy (only a repository)')),
1262 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1262 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1263 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1263 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1264 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1264 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1265 ('', 'pull', None, _('use pull protocol to copy metadata')),
1265 ('', 'pull', None, _('use pull protocol to copy metadata')),
1266 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1266 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1267 ] + remoteopts,
1267 ] + remoteopts,
1268 _('[OPTION]... SOURCE [DEST]'),
1268 _('[OPTION]... SOURCE [DEST]'),
1269 norepo=True)
1269 norepo=True)
1270 def clone(ui, source, dest=None, **opts):
1270 def clone(ui, source, dest=None, **opts):
1271 """make a copy of an existing repository
1271 """make a copy of an existing repository
1272
1272
1273 Create a copy of an existing repository in a new directory.
1273 Create a copy of an existing repository in a new directory.
1274
1274
1275 If no destination directory name is specified, it defaults to the
1275 If no destination directory name is specified, it defaults to the
1276 basename of the source.
1276 basename of the source.
1277
1277
1278 The location of the source is added to the new repository's
1278 The location of the source is added to the new repository's
1279 ``.hg/hgrc`` file, as the default to be used for future pulls.
1279 ``.hg/hgrc`` file, as the default to be used for future pulls.
1280
1280
1281 Only local paths and ``ssh://`` URLs are supported as
1281 Only local paths and ``ssh://`` URLs are supported as
1282 destinations. For ``ssh://`` destinations, no working directory or
1282 destinations. For ``ssh://`` destinations, no working directory or
1283 ``.hg/hgrc`` will be created on the remote side.
1283 ``.hg/hgrc`` will be created on the remote side.
1284
1284
1285 To pull only a subset of changesets, specify one or more revisions
1285 To pull only a subset of changesets, specify one or more revisions
1286 identifiers with -r/--rev or branches with -b/--branch. The
1286 identifiers with -r/--rev or branches with -b/--branch. The
1287 resulting clone will contain only the specified changesets and
1287 resulting clone will contain only the specified changesets and
1288 their ancestors. These options (or 'clone src#rev dest') imply
1288 their ancestors. These options (or 'clone src#rev dest') imply
1289 --pull, even for local source repositories. Note that specifying a
1289 --pull, even for local source repositories. Note that specifying a
1290 tag will include the tagged changeset but not the changeset
1290 tag will include the tagged changeset but not the changeset
1291 containing the tag.
1291 containing the tag.
1292
1292
1293 If the source repository has a bookmark called '@' set, that
1293 If the source repository has a bookmark called '@' set, that
1294 revision will be checked out in the new repository by default.
1294 revision will be checked out in the new repository by default.
1295
1295
1296 To check out a particular version, use -u/--update, or
1296 To check out a particular version, use -u/--update, or
1297 -U/--noupdate to create a clone with no working directory.
1297 -U/--noupdate to create a clone with no working directory.
1298
1298
1299 .. container:: verbose
1299 .. container:: verbose
1300
1300
1301 For efficiency, hardlinks are used for cloning whenever the
1301 For efficiency, hardlinks are used for cloning whenever the
1302 source and destination are on the same filesystem (note this
1302 source and destination are on the same filesystem (note this
1303 applies only to the repository data, not to the working
1303 applies only to the repository data, not to the working
1304 directory). Some filesystems, such as AFS, implement hardlinking
1304 directory). Some filesystems, such as AFS, implement hardlinking
1305 incorrectly, but do not report errors. In these cases, use the
1305 incorrectly, but do not report errors. In these cases, use the
1306 --pull option to avoid hardlinking.
1306 --pull option to avoid hardlinking.
1307
1307
1308 In some cases, you can clone repositories and the working
1308 In some cases, you can clone repositories and the working
1309 directory using full hardlinks with ::
1309 directory using full hardlinks with ::
1310
1310
1311 $ cp -al REPO REPOCLONE
1311 $ cp -al REPO REPOCLONE
1312
1312
1313 This is the fastest way to clone, but it is not always safe. The
1313 This is the fastest way to clone, but it is not always safe. The
1314 operation is not atomic (making sure REPO is not modified during
1314 operation is not atomic (making sure REPO is not modified during
1315 the operation is up to you) and you have to make sure your
1315 the operation is up to you) and you have to make sure your
1316 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1316 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1317 so). Also, this is not compatible with certain extensions that
1317 so). Also, this is not compatible with certain extensions that
1318 place their metadata under the .hg directory, such as mq.
1318 place their metadata under the .hg directory, such as mq.
1319
1319
1320 Mercurial will update the working directory to the first applicable
1320 Mercurial will update the working directory to the first applicable
1321 revision from this list:
1321 revision from this list:
1322
1322
1323 a) null if -U or the source repository has no changesets
1323 a) null if -U or the source repository has no changesets
1324 b) if -u . and the source repository is local, the first parent of
1324 b) if -u . and the source repository is local, the first parent of
1325 the source repository's working directory
1325 the source repository's working directory
1326 c) the changeset specified with -u (if a branch name, this means the
1326 c) the changeset specified with -u (if a branch name, this means the
1327 latest head of that branch)
1327 latest head of that branch)
1328 d) the changeset specified with -r
1328 d) the changeset specified with -r
1329 e) the tipmost head specified with -b
1329 e) the tipmost head specified with -b
1330 f) the tipmost head specified with the url#branch source syntax
1330 f) the tipmost head specified with the url#branch source syntax
1331 g) the revision marked with the '@' bookmark, if present
1331 g) the revision marked with the '@' bookmark, if present
1332 h) the tipmost head of the default branch
1332 h) the tipmost head of the default branch
1333 i) tip
1333 i) tip
1334
1334
1335 Examples:
1335 Examples:
1336
1336
1337 - clone a remote repository to a new directory named hg/::
1337 - clone a remote repository to a new directory named hg/::
1338
1338
1339 hg clone http://selenic.com/hg
1339 hg clone http://selenic.com/hg
1340
1340
1341 - create a lightweight local clone::
1341 - create a lightweight local clone::
1342
1342
1343 hg clone project/ project-feature/
1343 hg clone project/ project-feature/
1344
1344
1345 - clone from an absolute path on an ssh server (note double-slash)::
1345 - clone from an absolute path on an ssh server (note double-slash)::
1346
1346
1347 hg clone ssh://user@server//home/projects/alpha/
1347 hg clone ssh://user@server//home/projects/alpha/
1348
1348
1349 - do a high-speed clone over a LAN while checking out a
1349 - do a high-speed clone over a LAN while checking out a
1350 specified version::
1350 specified version::
1351
1351
1352 hg clone --uncompressed http://server/repo -u 1.5
1352 hg clone --uncompressed http://server/repo -u 1.5
1353
1353
1354 - create a repository without changesets after a particular revision::
1354 - create a repository without changesets after a particular revision::
1355
1355
1356 hg clone -r 04e544 experimental/ good/
1356 hg clone -r 04e544 experimental/ good/
1357
1357
1358 - clone (and track) a particular named branch::
1358 - clone (and track) a particular named branch::
1359
1359
1360 hg clone http://selenic.com/hg#stable
1360 hg clone http://selenic.com/hg#stable
1361
1361
1362 See :hg:`help urls` for details on specifying URLs.
1362 See :hg:`help urls` for details on specifying URLs.
1363
1363
1364 Returns 0 on success.
1364 Returns 0 on success.
1365 """
1365 """
1366 if opts.get('noupdate') and opts.get('updaterev'):
1366 if opts.get('noupdate') and opts.get('updaterev'):
1367 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1367 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1368
1368
1369 r = hg.clone(ui, opts, source, dest,
1369 r = hg.clone(ui, opts, source, dest,
1370 pull=opts.get('pull'),
1370 pull=opts.get('pull'),
1371 stream=opts.get('uncompressed'),
1371 stream=opts.get('uncompressed'),
1372 rev=opts.get('rev'),
1372 rev=opts.get('rev'),
1373 update=opts.get('updaterev') or not opts.get('noupdate'),
1373 update=opts.get('updaterev') or not opts.get('noupdate'),
1374 branch=opts.get('branch'))
1374 branch=opts.get('branch'))
1375
1375
1376 return r is None
1376 return r is None
1377
1377
1378 @command('^commit|ci',
1378 @command('^commit|ci',
1379 [('A', 'addremove', None,
1379 [('A', 'addremove', None,
1380 _('mark new/missing files as added/removed before committing')),
1380 _('mark new/missing files as added/removed before committing')),
1381 ('', 'close-branch', None,
1381 ('', 'close-branch', None,
1382 _('mark a branch as closed, hiding it from the branch list')),
1382 _('mark a branch as closed, hiding it from the branch list')),
1383 ('', 'amend', None, _('amend the parent of the working dir')),
1383 ('', 'amend', None, _('amend the parent of the working dir')),
1384 ('s', 'secret', None, _('use the secret phase for committing')),
1384 ('s', 'secret', None, _('use the secret phase for committing')),
1385 ('e', 'edit', None, _('invoke editor on commit messages')),
1385 ('e', 'edit', None, _('invoke editor on commit messages')),
1386 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1386 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1387 _('[OPTION]... [FILE]...'),
1387 _('[OPTION]... [FILE]...'),
1388 inferrepo=True)
1388 inferrepo=True)
1389 def commit(ui, repo, *pats, **opts):
1389 def commit(ui, repo, *pats, **opts):
1390 """commit the specified files or all outstanding changes
1390 """commit the specified files or all outstanding changes
1391
1391
1392 Commit changes to the given files into the repository. Unlike a
1392 Commit changes to the given files into the repository. Unlike a
1393 centralized SCM, this operation is a local operation. See
1393 centralized SCM, this operation is a local operation. See
1394 :hg:`push` for a way to actively distribute your changes.
1394 :hg:`push` for a way to actively distribute your changes.
1395
1395
1396 If a list of files is omitted, all changes reported by :hg:`status`
1396 If a list of files is omitted, all changes reported by :hg:`status`
1397 will be committed.
1397 will be committed.
1398
1398
1399 If you are committing the result of a merge, do not provide any
1399 If you are committing the result of a merge, do not provide any
1400 filenames or -I/-X filters.
1400 filenames or -I/-X filters.
1401
1401
1402 If no commit message is specified, Mercurial starts your
1402 If no commit message is specified, Mercurial starts your
1403 configured editor where you can enter a message. In case your
1403 configured editor where you can enter a message. In case your
1404 commit fails, you will find a backup of your message in
1404 commit fails, you will find a backup of your message in
1405 ``.hg/last-message.txt``.
1405 ``.hg/last-message.txt``.
1406
1406
1407 The --amend flag can be used to amend the parent of the
1407 The --amend flag can be used to amend the parent of the
1408 working directory with a new commit that contains the changes
1408 working directory with a new commit that contains the changes
1409 in the parent in addition to those currently reported by :hg:`status`,
1409 in the parent in addition to those currently reported by :hg:`status`,
1410 if there are any. The old commit is stored in a backup bundle in
1410 if there are any. The old commit is stored in a backup bundle in
1411 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1411 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1412 on how to restore it).
1412 on how to restore it).
1413
1413
1414 Message, user and date are taken from the amended commit unless
1414 Message, user and date are taken from the amended commit unless
1415 specified. When a message isn't specified on the command line,
1415 specified. When a message isn't specified on the command line,
1416 the editor will open with the message of the amended commit.
1416 the editor will open with the message of the amended commit.
1417
1417
1418 It is not possible to amend public changesets (see :hg:`help phases`)
1418 It is not possible to amend public changesets (see :hg:`help phases`)
1419 or changesets that have children.
1419 or changesets that have children.
1420
1420
1421 See :hg:`help dates` for a list of formats valid for -d/--date.
1421 See :hg:`help dates` for a list of formats valid for -d/--date.
1422
1422
1423 Returns 0 on success, 1 if nothing changed.
1423 Returns 0 on success, 1 if nothing changed.
1424 """
1424 """
1425 if opts.get('subrepos'):
1425 if opts.get('subrepos'):
1426 if opts.get('amend'):
1426 if opts.get('amend'):
1427 raise util.Abort(_('cannot amend with --subrepos'))
1427 raise util.Abort(_('cannot amend with --subrepos'))
1428 # Let --subrepos on the command line override config setting.
1428 # Let --subrepos on the command line override config setting.
1429 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1429 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1430
1430
1431 cmdutil.checkunfinished(repo, commit=True)
1431 cmdutil.checkunfinished(repo, commit=True)
1432
1432
1433 branch = repo[None].branch()
1433 branch = repo[None].branch()
1434 bheads = repo.branchheads(branch)
1434 bheads = repo.branchheads(branch)
1435
1435
1436 extra = {}
1436 extra = {}
1437 if opts.get('close_branch'):
1437 if opts.get('close_branch'):
1438 extra['close'] = 1
1438 extra['close'] = 1
1439
1439
1440 if not bheads:
1440 if not bheads:
1441 raise util.Abort(_('can only close branch heads'))
1441 raise util.Abort(_('can only close branch heads'))
1442 elif opts.get('amend'):
1442 elif opts.get('amend'):
1443 if repo.parents()[0].p1().branch() != branch and \
1443 if repo.parents()[0].p1().branch() != branch and \
1444 repo.parents()[0].p2().branch() != branch:
1444 repo.parents()[0].p2().branch() != branch:
1445 raise util.Abort(_('can only close branch heads'))
1445 raise util.Abort(_('can only close branch heads'))
1446
1446
1447 if opts.get('amend'):
1447 if opts.get('amend'):
1448 if ui.configbool('ui', 'commitsubrepos'):
1448 if ui.configbool('ui', 'commitsubrepos'):
1449 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1449 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1450
1450
1451 old = repo['.']
1451 old = repo['.']
1452 if not old.mutable():
1452 if not old.mutable():
1453 raise util.Abort(_('cannot amend public changesets'))
1453 raise util.Abort(_('cannot amend public changesets'))
1454 if len(repo[None].parents()) > 1:
1454 if len(repo[None].parents()) > 1:
1455 raise util.Abort(_('cannot amend while merging'))
1455 raise util.Abort(_('cannot amend while merging'))
1456 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1456 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1457 if not allowunstable and old.children():
1457 if not allowunstable and old.children():
1458 raise util.Abort(_('cannot amend changeset with children'))
1458 raise util.Abort(_('cannot amend changeset with children'))
1459
1459
1460 # commitfunc is used only for temporary amend commit by cmdutil.amend
1460 # commitfunc is used only for temporary amend commit by cmdutil.amend
1461 def commitfunc(ui, repo, message, match, opts):
1461 def commitfunc(ui, repo, message, match, opts):
1462 return repo.commit(message,
1462 return repo.commit(message,
1463 opts.get('user') or old.user(),
1463 opts.get('user') or old.user(),
1464 opts.get('date') or old.date(),
1464 opts.get('date') or old.date(),
1465 match,
1465 match,
1466 extra=extra)
1466 extra=extra)
1467
1467
1468 current = repo._bookmarkcurrent
1468 current = repo._bookmarkcurrent
1469 marks = old.bookmarks()
1469 marks = old.bookmarks()
1470 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1470 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1471 if node == old.node():
1471 if node == old.node():
1472 ui.status(_("nothing changed\n"))
1472 ui.status(_("nothing changed\n"))
1473 return 1
1473 return 1
1474 elif marks:
1474 elif marks:
1475 ui.debug('moving bookmarks %r from %s to %s\n' %
1475 ui.debug('moving bookmarks %r from %s to %s\n' %
1476 (marks, old.hex(), hex(node)))
1476 (marks, old.hex(), hex(node)))
1477 newmarks = repo._bookmarks
1477 newmarks = repo._bookmarks
1478 for bm in marks:
1478 for bm in marks:
1479 newmarks[bm] = node
1479 newmarks[bm] = node
1480 if bm == current:
1480 if bm == current:
1481 bookmarks.setcurrent(repo, bm)
1481 bookmarks.setcurrent(repo, bm)
1482 newmarks.write()
1482 newmarks.write()
1483 else:
1483 else:
1484 def commitfunc(ui, repo, message, match, opts):
1484 def commitfunc(ui, repo, message, match, opts):
1485 backup = ui.backupconfig('phases', 'new-commit')
1485 backup = ui.backupconfig('phases', 'new-commit')
1486 baseui = repo.baseui
1486 baseui = repo.baseui
1487 basebackup = baseui.backupconfig('phases', 'new-commit')
1487 basebackup = baseui.backupconfig('phases', 'new-commit')
1488 try:
1488 try:
1489 if opts.get('secret'):
1489 if opts.get('secret'):
1490 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1490 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1491 # Propagate to subrepos
1491 # Propagate to subrepos
1492 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1492 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1493
1493
1494 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1494 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1495 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1495 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1496 return repo.commit(message, opts.get('user'), opts.get('date'),
1496 return repo.commit(message, opts.get('user'), opts.get('date'),
1497 match,
1497 match,
1498 editor=editor,
1498 editor=editor,
1499 extra=extra)
1499 extra=extra)
1500 finally:
1500 finally:
1501 ui.restoreconfig(backup)
1501 ui.restoreconfig(backup)
1502 repo.baseui.restoreconfig(basebackup)
1502 repo.baseui.restoreconfig(basebackup)
1503
1503
1504
1504
1505 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1505 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1506
1506
1507 if not node:
1507 if not node:
1508 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1508 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1509 if stat[3]:
1509 if stat[3]:
1510 ui.status(_("nothing changed (%d missing files, see "
1510 ui.status(_("nothing changed (%d missing files, see "
1511 "'hg status')\n") % len(stat[3]))
1511 "'hg status')\n") % len(stat[3]))
1512 else:
1512 else:
1513 ui.status(_("nothing changed\n"))
1513 ui.status(_("nothing changed\n"))
1514 return 1
1514 return 1
1515
1515
1516 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1516 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1517
1517
1518 @command('config|showconfig|debugconfig',
1518 @command('config|showconfig|debugconfig',
1519 [('u', 'untrusted', None, _('show untrusted configuration options')),
1519 [('u', 'untrusted', None, _('show untrusted configuration options')),
1520 ('e', 'edit', None, _('edit user config')),
1520 ('e', 'edit', None, _('edit user config')),
1521 ('l', 'local', None, _('edit repository config')),
1521 ('l', 'local', None, _('edit repository config')),
1522 ('g', 'global', None, _('edit global config'))],
1522 ('g', 'global', None, _('edit global config'))],
1523 _('[-u] [NAME]...'),
1523 _('[-u] [NAME]...'),
1524 optionalrepo=True)
1524 optionalrepo=True)
1525 def config(ui, repo, *values, **opts):
1525 def config(ui, repo, *values, **opts):
1526 """show combined config settings from all hgrc files
1526 """show combined config settings from all hgrc files
1527
1527
1528 With no arguments, print names and values of all config items.
1528 With no arguments, print names and values of all config items.
1529
1529
1530 With one argument of the form section.name, print just the value
1530 With one argument of the form section.name, print just the value
1531 of that config item.
1531 of that config item.
1532
1532
1533 With multiple arguments, print names and values of all config
1533 With multiple arguments, print names and values of all config
1534 items with matching section names.
1534 items with matching section names.
1535
1535
1536 With --edit, start an editor on the user-level config file. With
1536 With --edit, start an editor on the user-level config file. With
1537 --global, edit the system-wide config file. With --local, edit the
1537 --global, edit the system-wide config file. With --local, edit the
1538 repository-level config file.
1538 repository-level config file.
1539
1539
1540 With --debug, the source (filename and line number) is printed
1540 With --debug, the source (filename and line number) is printed
1541 for each config item.
1541 for each config item.
1542
1542
1543 See :hg:`help config` for more information about config files.
1543 See :hg:`help config` for more information about config files.
1544
1544
1545 Returns 0 on success, 1 if NAME does not exist.
1545 Returns 0 on success, 1 if NAME does not exist.
1546
1546
1547 """
1547 """
1548
1548
1549 if opts.get('edit') or opts.get('local') or opts.get('global'):
1549 if opts.get('edit') or opts.get('local') or opts.get('global'):
1550 if opts.get('local') and opts.get('global'):
1550 if opts.get('local') and opts.get('global'):
1551 raise util.Abort(_("can't use --local and --global together"))
1551 raise util.Abort(_("can't use --local and --global together"))
1552
1552
1553 if opts.get('local'):
1553 if opts.get('local'):
1554 if not repo:
1554 if not repo:
1555 raise util.Abort(_("can't use --local outside a repository"))
1555 raise util.Abort(_("can't use --local outside a repository"))
1556 paths = [repo.join('hgrc')]
1556 paths = [repo.join('hgrc')]
1557 elif opts.get('global'):
1557 elif opts.get('global'):
1558 paths = scmutil.systemrcpath()
1558 paths = scmutil.systemrcpath()
1559 else:
1559 else:
1560 paths = scmutil.userrcpath()
1560 paths = scmutil.userrcpath()
1561
1561
1562 for f in paths:
1562 for f in paths:
1563 if os.path.exists(f):
1563 if os.path.exists(f):
1564 break
1564 break
1565 else:
1565 else:
1566 if opts.get('global'):
1566 if opts.get('global'):
1567 samplehgrc = uimod.samplehgrcs['global']
1567 samplehgrc = uimod.samplehgrcs['global']
1568 elif opts.get('local'):
1568 elif opts.get('local'):
1569 samplehgrc = uimod.samplehgrcs['local']
1569 samplehgrc = uimod.samplehgrcs['local']
1570 else:
1570 else:
1571 samplehgrc = uimod.samplehgrcs['user']
1571 samplehgrc = uimod.samplehgrcs['user']
1572
1572
1573 f = paths[0]
1573 f = paths[0]
1574 fp = open(f, "w")
1574 fp = open(f, "w")
1575 fp.write(samplehgrc)
1575 fp.write(samplehgrc)
1576 fp.close()
1576 fp.close()
1577
1577
1578 editor = ui.geteditor()
1578 editor = ui.geteditor()
1579 ui.system("%s \"%s\"" % (editor, f),
1579 ui.system("%s \"%s\"" % (editor, f),
1580 onerr=util.Abort, errprefix=_("edit failed"))
1580 onerr=util.Abort, errprefix=_("edit failed"))
1581 return
1581 return
1582
1582
1583 for f in scmutil.rcpath():
1583 for f in scmutil.rcpath():
1584 ui.debug('read config from: %s\n' % f)
1584 ui.debug('read config from: %s\n' % f)
1585 untrusted = bool(opts.get('untrusted'))
1585 untrusted = bool(opts.get('untrusted'))
1586 if values:
1586 if values:
1587 sections = [v for v in values if '.' not in v]
1587 sections = [v for v in values if '.' not in v]
1588 items = [v for v in values if '.' in v]
1588 items = [v for v in values if '.' in v]
1589 if len(items) > 1 or items and sections:
1589 if len(items) > 1 or items and sections:
1590 raise util.Abort(_('only one config item permitted'))
1590 raise util.Abort(_('only one config item permitted'))
1591 matched = False
1591 matched = False
1592 for section, name, value in ui.walkconfig(untrusted=untrusted):
1592 for section, name, value in ui.walkconfig(untrusted=untrusted):
1593 value = str(value).replace('\n', '\\n')
1593 value = str(value).replace('\n', '\\n')
1594 sectname = section + '.' + name
1594 sectname = section + '.' + name
1595 if values:
1595 if values:
1596 for v in values:
1596 for v in values:
1597 if v == section:
1597 if v == section:
1598 ui.debug('%s: ' %
1598 ui.debug('%s: ' %
1599 ui.configsource(section, name, untrusted))
1599 ui.configsource(section, name, untrusted))
1600 ui.write('%s=%s\n' % (sectname, value))
1600 ui.write('%s=%s\n' % (sectname, value))
1601 matched = True
1601 matched = True
1602 elif v == sectname:
1602 elif v == sectname:
1603 ui.debug('%s: ' %
1603 ui.debug('%s: ' %
1604 ui.configsource(section, name, untrusted))
1604 ui.configsource(section, name, untrusted))
1605 ui.write(value, '\n')
1605 ui.write(value, '\n')
1606 matched = True
1606 matched = True
1607 else:
1607 else:
1608 ui.debug('%s: ' %
1608 ui.debug('%s: ' %
1609 ui.configsource(section, name, untrusted))
1609 ui.configsource(section, name, untrusted))
1610 ui.write('%s=%s\n' % (sectname, value))
1610 ui.write('%s=%s\n' % (sectname, value))
1611 matched = True
1611 matched = True
1612 if matched:
1612 if matched:
1613 return 0
1613 return 0
1614 return 1
1614 return 1
1615
1615
1616 @command('copy|cp',
1616 @command('copy|cp',
1617 [('A', 'after', None, _('record a copy that has already occurred')),
1617 [('A', 'after', None, _('record a copy that has already occurred')),
1618 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1618 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1619 ] + walkopts + dryrunopts,
1619 ] + walkopts + dryrunopts,
1620 _('[OPTION]... [SOURCE]... DEST'))
1620 _('[OPTION]... [SOURCE]... DEST'))
1621 def copy(ui, repo, *pats, **opts):
1621 def copy(ui, repo, *pats, **opts):
1622 """mark files as copied for the next commit
1622 """mark files as copied for the next commit
1623
1623
1624 Mark dest as having copies of source files. If dest is a
1624 Mark dest as having copies of source files. If dest is a
1625 directory, copies are put in that directory. If dest is a file,
1625 directory, copies are put in that directory. If dest is a file,
1626 the source must be a single file.
1626 the source must be a single file.
1627
1627
1628 By default, this command copies the contents of files as they
1628 By default, this command copies the contents of files as they
1629 exist in the working directory. If invoked with -A/--after, the
1629 exist in the working directory. If invoked with -A/--after, the
1630 operation is recorded, but no copying is performed.
1630 operation is recorded, but no copying is performed.
1631
1631
1632 This command takes effect with the next commit. To undo a copy
1632 This command takes effect with the next commit. To undo a copy
1633 before that, see :hg:`revert`.
1633 before that, see :hg:`revert`.
1634
1634
1635 Returns 0 on success, 1 if errors are encountered.
1635 Returns 0 on success, 1 if errors are encountered.
1636 """
1636 """
1637 wlock = repo.wlock(False)
1637 wlock = repo.wlock(False)
1638 try:
1638 try:
1639 return cmdutil.copy(ui, repo, pats, opts)
1639 return cmdutil.copy(ui, repo, pats, opts)
1640 finally:
1640 finally:
1641 wlock.release()
1641 wlock.release()
1642
1642
1643 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1643 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1644 def debugancestor(ui, repo, *args):
1644 def debugancestor(ui, repo, *args):
1645 """find the ancestor revision of two revisions in a given index"""
1645 """find the ancestor revision of two revisions in a given index"""
1646 if len(args) == 3:
1646 if len(args) == 3:
1647 index, rev1, rev2 = args
1647 index, rev1, rev2 = args
1648 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1648 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1649 lookup = r.lookup
1649 lookup = r.lookup
1650 elif len(args) == 2:
1650 elif len(args) == 2:
1651 if not repo:
1651 if not repo:
1652 raise util.Abort(_("there is no Mercurial repository here "
1652 raise util.Abort(_("there is no Mercurial repository here "
1653 "(.hg not found)"))
1653 "(.hg not found)"))
1654 rev1, rev2 = args
1654 rev1, rev2 = args
1655 r = repo.changelog
1655 r = repo.changelog
1656 lookup = repo.lookup
1656 lookup = repo.lookup
1657 else:
1657 else:
1658 raise util.Abort(_('either two or three arguments required'))
1658 raise util.Abort(_('either two or three arguments required'))
1659 a = r.ancestor(lookup(rev1), lookup(rev2))
1659 a = r.ancestor(lookup(rev1), lookup(rev2))
1660 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1660 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1661
1661
1662 @command('debugbuilddag',
1662 @command('debugbuilddag',
1663 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1663 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1664 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1664 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1665 ('n', 'new-file', None, _('add new file at each rev'))],
1665 ('n', 'new-file', None, _('add new file at each rev'))],
1666 _('[OPTION]... [TEXT]'))
1666 _('[OPTION]... [TEXT]'))
1667 def debugbuilddag(ui, repo, text=None,
1667 def debugbuilddag(ui, repo, text=None,
1668 mergeable_file=False,
1668 mergeable_file=False,
1669 overwritten_file=False,
1669 overwritten_file=False,
1670 new_file=False):
1670 new_file=False):
1671 """builds a repo with a given DAG from scratch in the current empty repo
1671 """builds a repo with a given DAG from scratch in the current empty repo
1672
1672
1673 The description of the DAG is read from stdin if not given on the
1673 The description of the DAG is read from stdin if not given on the
1674 command line.
1674 command line.
1675
1675
1676 Elements:
1676 Elements:
1677
1677
1678 - "+n" is a linear run of n nodes based on the current default parent
1678 - "+n" is a linear run of n nodes based on the current default parent
1679 - "." is a single node based on the current default parent
1679 - "." is a single node based on the current default parent
1680 - "$" resets the default parent to null (implied at the start);
1680 - "$" resets the default parent to null (implied at the start);
1681 otherwise the default parent is always the last node created
1681 otherwise the default parent is always the last node created
1682 - "<p" sets the default parent to the backref p
1682 - "<p" sets the default parent to the backref p
1683 - "*p" is a fork at parent p, which is a backref
1683 - "*p" is a fork at parent p, which is a backref
1684 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1684 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1685 - "/p2" is a merge of the preceding node and p2
1685 - "/p2" is a merge of the preceding node and p2
1686 - ":tag" defines a local tag for the preceding node
1686 - ":tag" defines a local tag for the preceding node
1687 - "@branch" sets the named branch for subsequent nodes
1687 - "@branch" sets the named branch for subsequent nodes
1688 - "#...\\n" is a comment up to the end of the line
1688 - "#...\\n" is a comment up to the end of the line
1689
1689
1690 Whitespace between the above elements is ignored.
1690 Whitespace between the above elements is ignored.
1691
1691
1692 A backref is either
1692 A backref is either
1693
1693
1694 - a number n, which references the node curr-n, where curr is the current
1694 - a number n, which references the node curr-n, where curr is the current
1695 node, or
1695 node, or
1696 - the name of a local tag you placed earlier using ":tag", or
1696 - the name of a local tag you placed earlier using ":tag", or
1697 - empty to denote the default parent.
1697 - empty to denote the default parent.
1698
1698
1699 All string valued-elements are either strictly alphanumeric, or must
1699 All string valued-elements are either strictly alphanumeric, or must
1700 be enclosed in double quotes ("..."), with "\\" as escape character.
1700 be enclosed in double quotes ("..."), with "\\" as escape character.
1701 """
1701 """
1702
1702
1703 if text is None:
1703 if text is None:
1704 ui.status(_("reading DAG from stdin\n"))
1704 ui.status(_("reading DAG from stdin\n"))
1705 text = ui.fin.read()
1705 text = ui.fin.read()
1706
1706
1707 cl = repo.changelog
1707 cl = repo.changelog
1708 if len(cl) > 0:
1708 if len(cl) > 0:
1709 raise util.Abort(_('repository is not empty'))
1709 raise util.Abort(_('repository is not empty'))
1710
1710
1711 # determine number of revs in DAG
1711 # determine number of revs in DAG
1712 total = 0
1712 total = 0
1713 for type, data in dagparser.parsedag(text):
1713 for type, data in dagparser.parsedag(text):
1714 if type == 'n':
1714 if type == 'n':
1715 total += 1
1715 total += 1
1716
1716
1717 if mergeable_file:
1717 if mergeable_file:
1718 linesperrev = 2
1718 linesperrev = 2
1719 # make a file with k lines per rev
1719 # make a file with k lines per rev
1720 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1720 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1721 initialmergedlines.append("")
1721 initialmergedlines.append("")
1722
1722
1723 tags = []
1723 tags = []
1724
1724
1725 lock = tr = None
1725 lock = tr = None
1726 try:
1726 try:
1727 lock = repo.lock()
1727 lock = repo.lock()
1728 tr = repo.transaction("builddag")
1728 tr = repo.transaction("builddag")
1729
1729
1730 at = -1
1730 at = -1
1731 atbranch = 'default'
1731 atbranch = 'default'
1732 nodeids = []
1732 nodeids = []
1733 id = 0
1733 id = 0
1734 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1734 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1735 for type, data in dagparser.parsedag(text):
1735 for type, data in dagparser.parsedag(text):
1736 if type == 'n':
1736 if type == 'n':
1737 ui.note(('node %s\n' % str(data)))
1737 ui.note(('node %s\n' % str(data)))
1738 id, ps = data
1738 id, ps = data
1739
1739
1740 files = []
1740 files = []
1741 fctxs = {}
1741 fctxs = {}
1742
1742
1743 p2 = None
1743 p2 = None
1744 if mergeable_file:
1744 if mergeable_file:
1745 fn = "mf"
1745 fn = "mf"
1746 p1 = repo[ps[0]]
1746 p1 = repo[ps[0]]
1747 if len(ps) > 1:
1747 if len(ps) > 1:
1748 p2 = repo[ps[1]]
1748 p2 = repo[ps[1]]
1749 pa = p1.ancestor(p2)
1749 pa = p1.ancestor(p2)
1750 base, local, other = [x[fn].data() for x in (pa, p1,
1750 base, local, other = [x[fn].data() for x in (pa, p1,
1751 p2)]
1751 p2)]
1752 m3 = simplemerge.Merge3Text(base, local, other)
1752 m3 = simplemerge.Merge3Text(base, local, other)
1753 ml = [l.strip() for l in m3.merge_lines()]
1753 ml = [l.strip() for l in m3.merge_lines()]
1754 ml.append("")
1754 ml.append("")
1755 elif at > 0:
1755 elif at > 0:
1756 ml = p1[fn].data().split("\n")
1756 ml = p1[fn].data().split("\n")
1757 else:
1757 else:
1758 ml = initialmergedlines
1758 ml = initialmergedlines
1759 ml[id * linesperrev] += " r%i" % id
1759 ml[id * linesperrev] += " r%i" % id
1760 mergedtext = "\n".join(ml)
1760 mergedtext = "\n".join(ml)
1761 files.append(fn)
1761 files.append(fn)
1762 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1762 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1763
1763
1764 if overwritten_file:
1764 if overwritten_file:
1765 fn = "of"
1765 fn = "of"
1766 files.append(fn)
1766 files.append(fn)
1767 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1767 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1768
1768
1769 if new_file:
1769 if new_file:
1770 fn = "nf%i" % id
1770 fn = "nf%i" % id
1771 files.append(fn)
1771 files.append(fn)
1772 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1772 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1773 if len(ps) > 1:
1773 if len(ps) > 1:
1774 if not p2:
1774 if not p2:
1775 p2 = repo[ps[1]]
1775 p2 = repo[ps[1]]
1776 for fn in p2:
1776 for fn in p2:
1777 if fn.startswith("nf"):
1777 if fn.startswith("nf"):
1778 files.append(fn)
1778 files.append(fn)
1779 fctxs[fn] = p2[fn]
1779 fctxs[fn] = p2[fn]
1780
1780
1781 def fctxfn(repo, cx, path):
1781 def fctxfn(repo, cx, path):
1782 return fctxs.get(path)
1782 return fctxs.get(path)
1783
1783
1784 if len(ps) == 0 or ps[0] < 0:
1784 if len(ps) == 0 or ps[0] < 0:
1785 pars = [None, None]
1785 pars = [None, None]
1786 elif len(ps) == 1:
1786 elif len(ps) == 1:
1787 pars = [nodeids[ps[0]], None]
1787 pars = [nodeids[ps[0]], None]
1788 else:
1788 else:
1789 pars = [nodeids[p] for p in ps]
1789 pars = [nodeids[p] for p in ps]
1790 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1790 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1791 date=(id, 0),
1791 date=(id, 0),
1792 user="debugbuilddag",
1792 user="debugbuilddag",
1793 extra={'branch': atbranch})
1793 extra={'branch': atbranch})
1794 nodeid = repo.commitctx(cx)
1794 nodeid = repo.commitctx(cx)
1795 nodeids.append(nodeid)
1795 nodeids.append(nodeid)
1796 at = id
1796 at = id
1797 elif type == 'l':
1797 elif type == 'l':
1798 id, name = data
1798 id, name = data
1799 ui.note(('tag %s\n' % name))
1799 ui.note(('tag %s\n' % name))
1800 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1800 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1801 elif type == 'a':
1801 elif type == 'a':
1802 ui.note(('branch %s\n' % data))
1802 ui.note(('branch %s\n' % data))
1803 atbranch = data
1803 atbranch = data
1804 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1804 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1805 tr.close()
1805 tr.close()
1806
1806
1807 if tags:
1807 if tags:
1808 repo.vfs.write("localtags", "".join(tags))
1808 repo.vfs.write("localtags", "".join(tags))
1809 finally:
1809 finally:
1810 ui.progress(_('building'), None)
1810 ui.progress(_('building'), None)
1811 release(tr, lock)
1811 release(tr, lock)
1812
1812
1813 @command('debugbundle',
1813 @command('debugbundle',
1814 [('a', 'all', None, _('show all details'))],
1814 [('a', 'all', None, _('show all details'))],
1815 _('FILE'),
1815 _('FILE'),
1816 norepo=True)
1816 norepo=True)
1817 def debugbundle(ui, bundlepath, all=None, **opts):
1817 def debugbundle(ui, bundlepath, all=None, **opts):
1818 """lists the contents of a bundle"""
1818 """lists the contents of a bundle"""
1819 f = hg.openpath(ui, bundlepath)
1819 f = hg.openpath(ui, bundlepath)
1820 try:
1820 try:
1821 gen = exchange.readbundle(ui, f, bundlepath)
1821 gen = exchange.readbundle(ui, f, bundlepath)
1822 if isinstance(gen, bundle2.unbundle20):
1822 if isinstance(gen, bundle2.unbundle20):
1823 return _debugbundle2(ui, gen, all=all, **opts)
1823 return _debugbundle2(ui, gen, all=all, **opts)
1824 if all:
1824 if all:
1825 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1825 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1826
1826
1827 def showchunks(named):
1827 def showchunks(named):
1828 ui.write("\n%s\n" % named)
1828 ui.write("\n%s\n" % named)
1829 chain = None
1829 chain = None
1830 while True:
1830 while True:
1831 chunkdata = gen.deltachunk(chain)
1831 chunkdata = gen.deltachunk(chain)
1832 if not chunkdata:
1832 if not chunkdata:
1833 break
1833 break
1834 node = chunkdata['node']
1834 node = chunkdata['node']
1835 p1 = chunkdata['p1']
1835 p1 = chunkdata['p1']
1836 p2 = chunkdata['p2']
1836 p2 = chunkdata['p2']
1837 cs = chunkdata['cs']
1837 cs = chunkdata['cs']
1838 deltabase = chunkdata['deltabase']
1838 deltabase = chunkdata['deltabase']
1839 delta = chunkdata['delta']
1839 delta = chunkdata['delta']
1840 ui.write("%s %s %s %s %s %s\n" %
1840 ui.write("%s %s %s %s %s %s\n" %
1841 (hex(node), hex(p1), hex(p2),
1841 (hex(node), hex(p1), hex(p2),
1842 hex(cs), hex(deltabase), len(delta)))
1842 hex(cs), hex(deltabase), len(delta)))
1843 chain = node
1843 chain = node
1844
1844
1845 chunkdata = gen.changelogheader()
1845 chunkdata = gen.changelogheader()
1846 showchunks("changelog")
1846 showchunks("changelog")
1847 chunkdata = gen.manifestheader()
1847 chunkdata = gen.manifestheader()
1848 showchunks("manifest")
1848 showchunks("manifest")
1849 while True:
1849 while True:
1850 chunkdata = gen.filelogheader()
1850 chunkdata = gen.filelogheader()
1851 if not chunkdata:
1851 if not chunkdata:
1852 break
1852 break
1853 fname = chunkdata['filename']
1853 fname = chunkdata['filename']
1854 showchunks(fname)
1854 showchunks(fname)
1855 else:
1855 else:
1856 if isinstance(gen, bundle2.unbundle20):
1856 if isinstance(gen, bundle2.unbundle20):
1857 raise util.Abort(_('use debugbundle2 for this file'))
1857 raise util.Abort(_('use debugbundle2 for this file'))
1858 chunkdata = gen.changelogheader()
1858 chunkdata = gen.changelogheader()
1859 chain = None
1859 chain = None
1860 while True:
1860 while True:
1861 chunkdata = gen.deltachunk(chain)
1861 chunkdata = gen.deltachunk(chain)
1862 if not chunkdata:
1862 if not chunkdata:
1863 break
1863 break
1864 node = chunkdata['node']
1864 node = chunkdata['node']
1865 ui.write("%s\n" % hex(node))
1865 ui.write("%s\n" % hex(node))
1866 chain = node
1866 chain = node
1867 finally:
1867 finally:
1868 f.close()
1868 f.close()
1869
1869
1870 def _debugbundle2(ui, gen, **opts):
1870 def _debugbundle2(ui, gen, **opts):
1871 """lists the contents of a bundle2"""
1871 """lists the contents of a bundle2"""
1872 if not isinstance(gen, bundle2.unbundle20):
1872 if not isinstance(gen, bundle2.unbundle20):
1873 raise util.Abort(_('not a bundle2 file'))
1873 raise util.Abort(_('not a bundle2 file'))
1874 ui.write(('Stream params: %s\n' % repr(gen.params)))
1874 ui.write(('Stream params: %s\n' % repr(gen.params)))
1875 for part in gen.iterparts():
1875 for part in gen.iterparts():
1876 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1876 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1877 if part.type == 'b2x:changegroup':
1877 if part.type == 'b2x:changegroup':
1878 version = part.params.get('version', '01')
1878 version = part.params.get('version', '01')
1879 cg = changegroup.packermap[version][1](part, 'UN')
1879 cg = changegroup.packermap[version][1](part, 'UN')
1880 chunkdata = cg.changelogheader()
1880 chunkdata = cg.changelogheader()
1881 chain = None
1881 chain = None
1882 while True:
1882 while True:
1883 chunkdata = cg.deltachunk(chain)
1883 chunkdata = cg.deltachunk(chain)
1884 if not chunkdata:
1884 if not chunkdata:
1885 break
1885 break
1886 node = chunkdata['node']
1886 node = chunkdata['node']
1887 ui.write(" %s\n" % hex(node))
1887 ui.write(" %s\n" % hex(node))
1888 chain = node
1888 chain = node
1889
1889
1890 @command('debugcheckstate', [], '')
1890 @command('debugcheckstate', [], '')
1891 def debugcheckstate(ui, repo):
1891 def debugcheckstate(ui, repo):
1892 """validate the correctness of the current dirstate"""
1892 """validate the correctness of the current dirstate"""
1893 parent1, parent2 = repo.dirstate.parents()
1893 parent1, parent2 = repo.dirstate.parents()
1894 m1 = repo[parent1].manifest()
1894 m1 = repo[parent1].manifest()
1895 m2 = repo[parent2].manifest()
1895 m2 = repo[parent2].manifest()
1896 errors = 0
1896 errors = 0
1897 for f in repo.dirstate:
1897 for f in repo.dirstate:
1898 state = repo.dirstate[f]
1898 state = repo.dirstate[f]
1899 if state in "nr" and f not in m1:
1899 if state in "nr" and f not in m1:
1900 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1900 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1901 errors += 1
1901 errors += 1
1902 if state in "a" and f in m1:
1902 if state in "a" and f in m1:
1903 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1903 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1904 errors += 1
1904 errors += 1
1905 if state in "m" and f not in m1 and f not in m2:
1905 if state in "m" and f not in m1 and f not in m2:
1906 ui.warn(_("%s in state %s, but not in either manifest\n") %
1906 ui.warn(_("%s in state %s, but not in either manifest\n") %
1907 (f, state))
1907 (f, state))
1908 errors += 1
1908 errors += 1
1909 for f in m1:
1909 for f in m1:
1910 state = repo.dirstate[f]
1910 state = repo.dirstate[f]
1911 if state not in "nrm":
1911 if state not in "nrm":
1912 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1912 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1913 errors += 1
1913 errors += 1
1914 if errors:
1914 if errors:
1915 error = _(".hg/dirstate inconsistent with current parent's manifest")
1915 error = _(".hg/dirstate inconsistent with current parent's manifest")
1916 raise util.Abort(error)
1916 raise util.Abort(error)
1917
1917
1918 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1918 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1919 def debugcommands(ui, cmd='', *args):
1919 def debugcommands(ui, cmd='', *args):
1920 """list all available commands and options"""
1920 """list all available commands and options"""
1921 for cmd, vals in sorted(table.iteritems()):
1921 for cmd, vals in sorted(table.iteritems()):
1922 cmd = cmd.split('|')[0].strip('^')
1922 cmd = cmd.split('|')[0].strip('^')
1923 opts = ', '.join([i[1] for i in vals[1]])
1923 opts = ', '.join([i[1] for i in vals[1]])
1924 ui.write('%s: %s\n' % (cmd, opts))
1924 ui.write('%s: %s\n' % (cmd, opts))
1925
1925
1926 @command('debugcomplete',
1926 @command('debugcomplete',
1927 [('o', 'options', None, _('show the command options'))],
1927 [('o', 'options', None, _('show the command options'))],
1928 _('[-o] CMD'),
1928 _('[-o] CMD'),
1929 norepo=True)
1929 norepo=True)
1930 def debugcomplete(ui, cmd='', **opts):
1930 def debugcomplete(ui, cmd='', **opts):
1931 """returns the completion list associated with the given command"""
1931 """returns the completion list associated with the given command"""
1932
1932
1933 if opts.get('options'):
1933 if opts.get('options'):
1934 options = []
1934 options = []
1935 otables = [globalopts]
1935 otables = [globalopts]
1936 if cmd:
1936 if cmd:
1937 aliases, entry = cmdutil.findcmd(cmd, table, False)
1937 aliases, entry = cmdutil.findcmd(cmd, table, False)
1938 otables.append(entry[1])
1938 otables.append(entry[1])
1939 for t in otables:
1939 for t in otables:
1940 for o in t:
1940 for o in t:
1941 if "(DEPRECATED)" in o[3]:
1941 if "(DEPRECATED)" in o[3]:
1942 continue
1942 continue
1943 if o[0]:
1943 if o[0]:
1944 options.append('-%s' % o[0])
1944 options.append('-%s' % o[0])
1945 options.append('--%s' % o[1])
1945 options.append('--%s' % o[1])
1946 ui.write("%s\n" % "\n".join(options))
1946 ui.write("%s\n" % "\n".join(options))
1947 return
1947 return
1948
1948
1949 cmdlist = cmdutil.findpossible(cmd, table)
1949 cmdlist = cmdutil.findpossible(cmd, table)
1950 if ui.verbose:
1950 if ui.verbose:
1951 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1951 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1952 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1952 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1953
1953
1954 @command('debugdag',
1954 @command('debugdag',
1955 [('t', 'tags', None, _('use tags as labels')),
1955 [('t', 'tags', None, _('use tags as labels')),
1956 ('b', 'branches', None, _('annotate with branch names')),
1956 ('b', 'branches', None, _('annotate with branch names')),
1957 ('', 'dots', None, _('use dots for runs')),
1957 ('', 'dots', None, _('use dots for runs')),
1958 ('s', 'spaces', None, _('separate elements by spaces'))],
1958 ('s', 'spaces', None, _('separate elements by spaces'))],
1959 _('[OPTION]... [FILE [REV]...]'),
1959 _('[OPTION]... [FILE [REV]...]'),
1960 optionalrepo=True)
1960 optionalrepo=True)
1961 def debugdag(ui, repo, file_=None, *revs, **opts):
1961 def debugdag(ui, repo, file_=None, *revs, **opts):
1962 """format the changelog or an index DAG as a concise textual description
1962 """format the changelog or an index DAG as a concise textual description
1963
1963
1964 If you pass a revlog index, the revlog's DAG is emitted. If you list
1964 If you pass a revlog index, the revlog's DAG is emitted. If you list
1965 revision numbers, they get labeled in the output as rN.
1965 revision numbers, they get labeled in the output as rN.
1966
1966
1967 Otherwise, the changelog DAG of the current repo is emitted.
1967 Otherwise, the changelog DAG of the current repo is emitted.
1968 """
1968 """
1969 spaces = opts.get('spaces')
1969 spaces = opts.get('spaces')
1970 dots = opts.get('dots')
1970 dots = opts.get('dots')
1971 if file_:
1971 if file_:
1972 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1972 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1973 revs = set((int(r) for r in revs))
1973 revs = set((int(r) for r in revs))
1974 def events():
1974 def events():
1975 for r in rlog:
1975 for r in rlog:
1976 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1976 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1977 if p != -1))
1977 if p != -1))
1978 if r in revs:
1978 if r in revs:
1979 yield 'l', (r, "r%i" % r)
1979 yield 'l', (r, "r%i" % r)
1980 elif repo:
1980 elif repo:
1981 cl = repo.changelog
1981 cl = repo.changelog
1982 tags = opts.get('tags')
1982 tags = opts.get('tags')
1983 branches = opts.get('branches')
1983 branches = opts.get('branches')
1984 if tags:
1984 if tags:
1985 labels = {}
1985 labels = {}
1986 for l, n in repo.tags().items():
1986 for l, n in repo.tags().items():
1987 labels.setdefault(cl.rev(n), []).append(l)
1987 labels.setdefault(cl.rev(n), []).append(l)
1988 def events():
1988 def events():
1989 b = "default"
1989 b = "default"
1990 for r in cl:
1990 for r in cl:
1991 if branches:
1991 if branches:
1992 newb = cl.read(cl.node(r))[5]['branch']
1992 newb = cl.read(cl.node(r))[5]['branch']
1993 if newb != b:
1993 if newb != b:
1994 yield 'a', newb
1994 yield 'a', newb
1995 b = newb
1995 b = newb
1996 yield 'n', (r, list(p for p in cl.parentrevs(r)
1996 yield 'n', (r, list(p for p in cl.parentrevs(r)
1997 if p != -1))
1997 if p != -1))
1998 if tags:
1998 if tags:
1999 ls = labels.get(r)
1999 ls = labels.get(r)
2000 if ls:
2000 if ls:
2001 for l in ls:
2001 for l in ls:
2002 yield 'l', (r, l)
2002 yield 'l', (r, l)
2003 else:
2003 else:
2004 raise util.Abort(_('need repo for changelog dag'))
2004 raise util.Abort(_('need repo for changelog dag'))
2005
2005
2006 for line in dagparser.dagtextlines(events(),
2006 for line in dagparser.dagtextlines(events(),
2007 addspaces=spaces,
2007 addspaces=spaces,
2008 wraplabels=True,
2008 wraplabels=True,
2009 wrapannotations=True,
2009 wrapannotations=True,
2010 wrapnonlinear=dots,
2010 wrapnonlinear=dots,
2011 usedots=dots,
2011 usedots=dots,
2012 maxlinewidth=70):
2012 maxlinewidth=70):
2013 ui.write(line)
2013 ui.write(line)
2014 ui.write("\n")
2014 ui.write("\n")
2015
2015
2016 @command('debugdata',
2016 @command('debugdata',
2017 [('c', 'changelog', False, _('open changelog')),
2017 [('c', 'changelog', False, _('open changelog')),
2018 ('m', 'manifest', False, _('open manifest'))],
2018 ('m', 'manifest', False, _('open manifest'))],
2019 _('-c|-m|FILE REV'))
2019 _('-c|-m|FILE REV'))
2020 def debugdata(ui, repo, file_, rev=None, **opts):
2020 def debugdata(ui, repo, file_, rev=None, **opts):
2021 """dump the contents of a data file revision"""
2021 """dump the contents of a data file revision"""
2022 if opts.get('changelog') or opts.get('manifest'):
2022 if opts.get('changelog') or opts.get('manifest'):
2023 file_, rev = None, file_
2023 file_, rev = None, file_
2024 elif rev is None:
2024 elif rev is None:
2025 raise error.CommandError('debugdata', _('invalid arguments'))
2025 raise error.CommandError('debugdata', _('invalid arguments'))
2026 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2026 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2027 try:
2027 try:
2028 ui.write(r.revision(r.lookup(rev)))
2028 ui.write(r.revision(r.lookup(rev)))
2029 except KeyError:
2029 except KeyError:
2030 raise util.Abort(_('invalid revision identifier %s') % rev)
2030 raise util.Abort(_('invalid revision identifier %s') % rev)
2031
2031
2032 @command('debugdate',
2032 @command('debugdate',
2033 [('e', 'extended', None, _('try extended date formats'))],
2033 [('e', 'extended', None, _('try extended date formats'))],
2034 _('[-e] DATE [RANGE]'),
2034 _('[-e] DATE [RANGE]'),
2035 norepo=True, optionalrepo=True)
2035 norepo=True, optionalrepo=True)
2036 def debugdate(ui, date, range=None, **opts):
2036 def debugdate(ui, date, range=None, **opts):
2037 """parse and display a date"""
2037 """parse and display a date"""
2038 if opts["extended"]:
2038 if opts["extended"]:
2039 d = util.parsedate(date, util.extendeddateformats)
2039 d = util.parsedate(date, util.extendeddateformats)
2040 else:
2040 else:
2041 d = util.parsedate(date)
2041 d = util.parsedate(date)
2042 ui.write(("internal: %s %s\n") % d)
2042 ui.write(("internal: %s %s\n") % d)
2043 ui.write(("standard: %s\n") % util.datestr(d))
2043 ui.write(("standard: %s\n") % util.datestr(d))
2044 if range:
2044 if range:
2045 m = util.matchdate(range)
2045 m = util.matchdate(range)
2046 ui.write(("match: %s\n") % m(d[0]))
2046 ui.write(("match: %s\n") % m(d[0]))
2047
2047
2048 @command('debugdiscovery',
2048 @command('debugdiscovery',
2049 [('', 'old', None, _('use old-style discovery')),
2049 [('', 'old', None, _('use old-style discovery')),
2050 ('', 'nonheads', None,
2050 ('', 'nonheads', None,
2051 _('use old-style discovery with non-heads included')),
2051 _('use old-style discovery with non-heads included')),
2052 ] + remoteopts,
2052 ] + remoteopts,
2053 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2053 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2054 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2054 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2055 """runs the changeset discovery protocol in isolation"""
2055 """runs the changeset discovery protocol in isolation"""
2056 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2056 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2057 opts.get('branch'))
2057 opts.get('branch'))
2058 remote = hg.peer(repo, opts, remoteurl)
2058 remote = hg.peer(repo, opts, remoteurl)
2059 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2059 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2060
2060
2061 # make sure tests are repeatable
2061 # make sure tests are repeatable
2062 random.seed(12323)
2062 random.seed(12323)
2063
2063
2064 def doit(localheads, remoteheads, remote=remote):
2064 def doit(localheads, remoteheads, remote=remote):
2065 if opts.get('old'):
2065 if opts.get('old'):
2066 if localheads:
2066 if localheads:
2067 raise util.Abort('cannot use localheads with old style '
2067 raise util.Abort('cannot use localheads with old style '
2068 'discovery')
2068 'discovery')
2069 if not util.safehasattr(remote, 'branches'):
2069 if not util.safehasattr(remote, 'branches'):
2070 # enable in-client legacy support
2070 # enable in-client legacy support
2071 remote = localrepo.locallegacypeer(remote.local())
2071 remote = localrepo.locallegacypeer(remote.local())
2072 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2072 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2073 force=True)
2073 force=True)
2074 common = set(common)
2074 common = set(common)
2075 if not opts.get('nonheads'):
2075 if not opts.get('nonheads'):
2076 ui.write(("unpruned common: %s\n") %
2076 ui.write(("unpruned common: %s\n") %
2077 " ".join(sorted(short(n) for n in common)))
2077 " ".join(sorted(short(n) for n in common)))
2078 dag = dagutil.revlogdag(repo.changelog)
2078 dag = dagutil.revlogdag(repo.changelog)
2079 all = dag.ancestorset(dag.internalizeall(common))
2079 all = dag.ancestorset(dag.internalizeall(common))
2080 common = dag.externalizeall(dag.headsetofconnecteds(all))
2080 common = dag.externalizeall(dag.headsetofconnecteds(all))
2081 else:
2081 else:
2082 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2082 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2083 common = set(common)
2083 common = set(common)
2084 rheads = set(hds)
2084 rheads = set(hds)
2085 lheads = set(repo.heads())
2085 lheads = set(repo.heads())
2086 ui.write(("common heads: %s\n") %
2086 ui.write(("common heads: %s\n") %
2087 " ".join(sorted(short(n) for n in common)))
2087 " ".join(sorted(short(n) for n in common)))
2088 if lheads <= common:
2088 if lheads <= common:
2089 ui.write(("local is subset\n"))
2089 ui.write(("local is subset\n"))
2090 elif rheads <= common:
2090 elif rheads <= common:
2091 ui.write(("remote is subset\n"))
2091 ui.write(("remote is subset\n"))
2092
2092
2093 serverlogs = opts.get('serverlog')
2093 serverlogs = opts.get('serverlog')
2094 if serverlogs:
2094 if serverlogs:
2095 for filename in serverlogs:
2095 for filename in serverlogs:
2096 logfile = open(filename, 'r')
2096 logfile = open(filename, 'r')
2097 try:
2097 try:
2098 line = logfile.readline()
2098 line = logfile.readline()
2099 while line:
2099 while line:
2100 parts = line.strip().split(';')
2100 parts = line.strip().split(';')
2101 op = parts[1]
2101 op = parts[1]
2102 if op == 'cg':
2102 if op == 'cg':
2103 pass
2103 pass
2104 elif op == 'cgss':
2104 elif op == 'cgss':
2105 doit(parts[2].split(' '), parts[3].split(' '))
2105 doit(parts[2].split(' '), parts[3].split(' '))
2106 elif op == 'unb':
2106 elif op == 'unb':
2107 doit(parts[3].split(' '), parts[2].split(' '))
2107 doit(parts[3].split(' '), parts[2].split(' '))
2108 line = logfile.readline()
2108 line = logfile.readline()
2109 finally:
2109 finally:
2110 logfile.close()
2110 logfile.close()
2111
2111
2112 else:
2112 else:
2113 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2113 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2114 opts.get('remote_head'))
2114 opts.get('remote_head'))
2115 localrevs = opts.get('local_head')
2115 localrevs = opts.get('local_head')
2116 doit(localrevs, remoterevs)
2116 doit(localrevs, remoterevs)
2117
2117
2118 @command('debugfileset',
2118 @command('debugfileset',
2119 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2119 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2120 _('[-r REV] FILESPEC'))
2120 _('[-r REV] FILESPEC'))
2121 def debugfileset(ui, repo, expr, **opts):
2121 def debugfileset(ui, repo, expr, **opts):
2122 '''parse and apply a fileset specification'''
2122 '''parse and apply a fileset specification'''
2123 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2123 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2124 if ui.verbose:
2124 if ui.verbose:
2125 tree = fileset.parse(expr)[0]
2125 tree = fileset.parse(expr)[0]
2126 ui.note(tree, "\n")
2126 ui.note(tree, "\n")
2127
2127
2128 for f in ctx.getfileset(expr):
2128 for f in ctx.getfileset(expr):
2129 ui.write("%s\n" % f)
2129 ui.write("%s\n" % f)
2130
2130
2131 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2131 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2132 def debugfsinfo(ui, path="."):
2132 def debugfsinfo(ui, path="."):
2133 """show information detected about current filesystem"""
2133 """show information detected about current filesystem"""
2134 util.writefile('.debugfsinfo', '')
2134 util.writefile('.debugfsinfo', '')
2135 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2135 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2136 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2136 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2137 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2137 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2138 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2138 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2139 and 'yes' or 'no'))
2139 and 'yes' or 'no'))
2140 os.unlink('.debugfsinfo')
2140 os.unlink('.debugfsinfo')
2141
2141
2142 @command('debuggetbundle',
2142 @command('debuggetbundle',
2143 [('H', 'head', [], _('id of head node'), _('ID')),
2143 [('H', 'head', [], _('id of head node'), _('ID')),
2144 ('C', 'common', [], _('id of common node'), _('ID')),
2144 ('C', 'common', [], _('id of common node'), _('ID')),
2145 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2145 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2146 _('REPO FILE [-H|-C ID]...'),
2146 _('REPO FILE [-H|-C ID]...'),
2147 norepo=True)
2147 norepo=True)
2148 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2148 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2149 """retrieves a bundle from a repo
2149 """retrieves a bundle from a repo
2150
2150
2151 Every ID must be a full-length hex node id string. Saves the bundle to the
2151 Every ID must be a full-length hex node id string. Saves the bundle to the
2152 given file.
2152 given file.
2153 """
2153 """
2154 repo = hg.peer(ui, opts, repopath)
2154 repo = hg.peer(ui, opts, repopath)
2155 if not repo.capable('getbundle'):
2155 if not repo.capable('getbundle'):
2156 raise util.Abort("getbundle() not supported by target repository")
2156 raise util.Abort("getbundle() not supported by target repository")
2157 args = {}
2157 args = {}
2158 if common:
2158 if common:
2159 args['common'] = [bin(s) for s in common]
2159 args['common'] = [bin(s) for s in common]
2160 if head:
2160 if head:
2161 args['heads'] = [bin(s) for s in head]
2161 args['heads'] = [bin(s) for s in head]
2162 # TODO: get desired bundlecaps from command line.
2162 # TODO: get desired bundlecaps from command line.
2163 args['bundlecaps'] = None
2163 args['bundlecaps'] = None
2164 bundle = repo.getbundle('debug', **args)
2164 bundle = repo.getbundle('debug', **args)
2165
2165
2166 bundletype = opts.get('type', 'bzip2').lower()
2166 bundletype = opts.get('type', 'bzip2').lower()
2167 btypes = {'none': 'HG10UN',
2167 btypes = {'none': 'HG10UN',
2168 'bzip2': 'HG10BZ',
2168 'bzip2': 'HG10BZ',
2169 'gzip': 'HG10GZ',
2169 'gzip': 'HG10GZ',
2170 'bundle2': 'HG2Y'}
2170 'bundle2': 'HG2Y'}
2171 bundletype = btypes.get(bundletype)
2171 bundletype = btypes.get(bundletype)
2172 if bundletype not in changegroup.bundletypes:
2172 if bundletype not in changegroup.bundletypes:
2173 raise util.Abort(_('unknown bundle type specified with --type'))
2173 raise util.Abort(_('unknown bundle type specified with --type'))
2174 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2174 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2175
2175
2176 @command('debugignore', [], '')
2176 @command('debugignore', [], '')
2177 def debugignore(ui, repo, *values, **opts):
2177 def debugignore(ui, repo, *values, **opts):
2178 """display the combined ignore pattern"""
2178 """display the combined ignore pattern"""
2179 ignore = repo.dirstate._ignore
2179 ignore = repo.dirstate._ignore
2180 includepat = getattr(ignore, 'includepat', None)
2180 includepat = getattr(ignore, 'includepat', None)
2181 if includepat is not None:
2181 if includepat is not None:
2182 ui.write("%s\n" % includepat)
2182 ui.write("%s\n" % includepat)
2183 else:
2183 else:
2184 raise util.Abort(_("no ignore patterns found"))
2184 raise util.Abort(_("no ignore patterns found"))
2185
2185
2186 @command('debugindex',
2186 @command('debugindex',
2187 [('c', 'changelog', False, _('open changelog')),
2187 [('c', 'changelog', False, _('open changelog')),
2188 ('m', 'manifest', False, _('open manifest')),
2188 ('m', 'manifest', False, _('open manifest')),
2189 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2189 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2190 _('[-f FORMAT] -c|-m|FILE'),
2190 _('[-f FORMAT] -c|-m|FILE'),
2191 optionalrepo=True)
2191 optionalrepo=True)
2192 def debugindex(ui, repo, file_=None, **opts):
2192 def debugindex(ui, repo, file_=None, **opts):
2193 """dump the contents of an index file"""
2193 """dump the contents of an index file"""
2194 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2194 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2195 format = opts.get('format', 0)
2195 format = opts.get('format', 0)
2196 if format not in (0, 1):
2196 if format not in (0, 1):
2197 raise util.Abort(_("unknown format %d") % format)
2197 raise util.Abort(_("unknown format %d") % format)
2198
2198
2199 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2199 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2200 if generaldelta:
2200 if generaldelta:
2201 basehdr = ' delta'
2201 basehdr = ' delta'
2202 else:
2202 else:
2203 basehdr = ' base'
2203 basehdr = ' base'
2204
2204
2205 if ui.debugflag:
2205 if ui.debugflag:
2206 shortfn = hex
2206 shortfn = hex
2207 else:
2207 else:
2208 shortfn = short
2208 shortfn = short
2209
2209
2210 # There might not be anything in r, so have a sane default
2210 # There might not be anything in r, so have a sane default
2211 idlen = 12
2211 idlen = 12
2212 for i in r:
2212 for i in r:
2213 idlen = len(shortfn(r.node(i)))
2213 idlen = len(shortfn(r.node(i)))
2214 break
2214 break
2215
2215
2216 if format == 0:
2216 if format == 0:
2217 ui.write(" rev offset length " + basehdr + " linkrev"
2217 ui.write(" rev offset length " + basehdr + " linkrev"
2218 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2218 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2219 elif format == 1:
2219 elif format == 1:
2220 ui.write(" rev flag offset length"
2220 ui.write(" rev flag offset length"
2221 " size " + basehdr + " link p1 p2"
2221 " size " + basehdr + " link p1 p2"
2222 " %s\n" % "nodeid".rjust(idlen))
2222 " %s\n" % "nodeid".rjust(idlen))
2223
2223
2224 for i in r:
2224 for i in r:
2225 node = r.node(i)
2225 node = r.node(i)
2226 if generaldelta:
2226 if generaldelta:
2227 base = r.deltaparent(i)
2227 base = r.deltaparent(i)
2228 else:
2228 else:
2229 base = r.chainbase(i)
2229 base = r.chainbase(i)
2230 if format == 0:
2230 if format == 0:
2231 try:
2231 try:
2232 pp = r.parents(node)
2232 pp = r.parents(node)
2233 except Exception:
2233 except Exception:
2234 pp = [nullid, nullid]
2234 pp = [nullid, nullid]
2235 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2235 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2236 i, r.start(i), r.length(i), base, r.linkrev(i),
2236 i, r.start(i), r.length(i), base, r.linkrev(i),
2237 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2237 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2238 elif format == 1:
2238 elif format == 1:
2239 pr = r.parentrevs(i)
2239 pr = r.parentrevs(i)
2240 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2240 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2241 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2241 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2242 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2242 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2243
2243
2244 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2244 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2245 def debugindexdot(ui, repo, file_):
2245 def debugindexdot(ui, repo, file_):
2246 """dump an index DAG as a graphviz dot file"""
2246 """dump an index DAG as a graphviz dot file"""
2247 r = None
2247 r = None
2248 if repo:
2248 if repo:
2249 filelog = repo.file(file_)
2249 filelog = repo.file(file_)
2250 if len(filelog):
2250 if len(filelog):
2251 r = filelog
2251 r = filelog
2252 if not r:
2252 if not r:
2253 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2253 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2254 ui.write(("digraph G {\n"))
2254 ui.write(("digraph G {\n"))
2255 for i in r:
2255 for i in r:
2256 node = r.node(i)
2256 node = r.node(i)
2257 pp = r.parents(node)
2257 pp = r.parents(node)
2258 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2258 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2259 if pp[1] != nullid:
2259 if pp[1] != nullid:
2260 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2260 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2261 ui.write("}\n")
2261 ui.write("}\n")
2262
2262
2263 @command('debuginstall', [], '', norepo=True)
2263 @command('debuginstall', [], '', norepo=True)
2264 def debuginstall(ui):
2264 def debuginstall(ui):
2265 '''test Mercurial installation
2265 '''test Mercurial installation
2266
2266
2267 Returns 0 on success.
2267 Returns 0 on success.
2268 '''
2268 '''
2269
2269
2270 def writetemp(contents):
2270 def writetemp(contents):
2271 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2271 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2272 f = os.fdopen(fd, "wb")
2272 f = os.fdopen(fd, "wb")
2273 f.write(contents)
2273 f.write(contents)
2274 f.close()
2274 f.close()
2275 return name
2275 return name
2276
2276
2277 problems = 0
2277 problems = 0
2278
2278
2279 # encoding
2279 # encoding
2280 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2280 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2281 try:
2281 try:
2282 encoding.fromlocal("test")
2282 encoding.fromlocal("test")
2283 except util.Abort, inst:
2283 except util.Abort, inst:
2284 ui.write(" %s\n" % inst)
2284 ui.write(" %s\n" % inst)
2285 ui.write(_(" (check that your locale is properly set)\n"))
2285 ui.write(_(" (check that your locale is properly set)\n"))
2286 problems += 1
2286 problems += 1
2287
2287
2288 # Python
2288 # Python
2289 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2289 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2290 ui.status(_("checking Python version (%s)\n")
2290 ui.status(_("checking Python version (%s)\n")
2291 % ("%s.%s.%s" % sys.version_info[:3]))
2291 % ("%s.%s.%s" % sys.version_info[:3]))
2292 ui.status(_("checking Python lib (%s)...\n")
2292 ui.status(_("checking Python lib (%s)...\n")
2293 % os.path.dirname(os.__file__))
2293 % os.path.dirname(os.__file__))
2294
2294
2295 # compiled modules
2295 # compiled modules
2296 ui.status(_("checking installed modules (%s)...\n")
2296 ui.status(_("checking installed modules (%s)...\n")
2297 % os.path.dirname(__file__))
2297 % os.path.dirname(__file__))
2298 try:
2298 try:
2299 import bdiff, mpatch, base85, osutil
2299 import bdiff, mpatch, base85, osutil
2300 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2300 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2301 except Exception, inst:
2301 except Exception, inst:
2302 ui.write(" %s\n" % inst)
2302 ui.write(" %s\n" % inst)
2303 ui.write(_(" One or more extensions could not be found"))
2303 ui.write(_(" One or more extensions could not be found"))
2304 ui.write(_(" (check that you compiled the extensions)\n"))
2304 ui.write(_(" (check that you compiled the extensions)\n"))
2305 problems += 1
2305 problems += 1
2306
2306
2307 # templates
2307 # templates
2308 import templater
2308 import templater
2309 p = templater.templatepaths()
2309 p = templater.templatepaths()
2310 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2310 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2311 if p:
2311 if p:
2312 m = templater.templatepath("map-cmdline.default")
2312 m = templater.templatepath("map-cmdline.default")
2313 if m:
2313 if m:
2314 # template found, check if it is working
2314 # template found, check if it is working
2315 try:
2315 try:
2316 templater.templater(m)
2316 templater.templater(m)
2317 except Exception, inst:
2317 except Exception, inst:
2318 ui.write(" %s\n" % inst)
2318 ui.write(" %s\n" % inst)
2319 p = None
2319 p = None
2320 else:
2320 else:
2321 ui.write(_(" template 'default' not found\n"))
2321 ui.write(_(" template 'default' not found\n"))
2322 p = None
2322 p = None
2323 else:
2323 else:
2324 ui.write(_(" no template directories found\n"))
2324 ui.write(_(" no template directories found\n"))
2325 if not p:
2325 if not p:
2326 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2326 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2327 problems += 1
2327 problems += 1
2328
2328
2329 # editor
2329 # editor
2330 ui.status(_("checking commit editor...\n"))
2330 ui.status(_("checking commit editor...\n"))
2331 editor = ui.geteditor()
2331 editor = ui.geteditor()
2332 cmdpath = util.findexe(shlex.split(editor)[0])
2332 cmdpath = util.findexe(shlex.split(editor)[0])
2333 if not cmdpath:
2333 if not cmdpath:
2334 if editor == 'vi':
2334 if editor == 'vi':
2335 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2335 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2336 ui.write(_(" (specify a commit editor in your configuration"
2336 ui.write(_(" (specify a commit editor in your configuration"
2337 " file)\n"))
2337 " file)\n"))
2338 else:
2338 else:
2339 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2339 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2340 ui.write(_(" (specify a commit editor in your configuration"
2340 ui.write(_(" (specify a commit editor in your configuration"
2341 " file)\n"))
2341 " file)\n"))
2342 problems += 1
2342 problems += 1
2343
2343
2344 # check username
2344 # check username
2345 ui.status(_("checking username...\n"))
2345 ui.status(_("checking username...\n"))
2346 try:
2346 try:
2347 ui.username()
2347 ui.username()
2348 except util.Abort, e:
2348 except util.Abort, e:
2349 ui.write(" %s\n" % e)
2349 ui.write(" %s\n" % e)
2350 ui.write(_(" (specify a username in your configuration file)\n"))
2350 ui.write(_(" (specify a username in your configuration file)\n"))
2351 problems += 1
2351 problems += 1
2352
2352
2353 if not problems:
2353 if not problems:
2354 ui.status(_("no problems detected\n"))
2354 ui.status(_("no problems detected\n"))
2355 else:
2355 else:
2356 ui.write(_("%s problems detected,"
2356 ui.write(_("%s problems detected,"
2357 " please check your install!\n") % problems)
2357 " please check your install!\n") % problems)
2358
2358
2359 return problems
2359 return problems
2360
2360
2361 @command('debugknown', [], _('REPO ID...'), norepo=True)
2361 @command('debugknown', [], _('REPO ID...'), norepo=True)
2362 def debugknown(ui, repopath, *ids, **opts):
2362 def debugknown(ui, repopath, *ids, **opts):
2363 """test whether node ids are known to a repo
2363 """test whether node ids are known to a repo
2364
2364
2365 Every ID must be a full-length hex node id string. Returns a list of 0s
2365 Every ID must be a full-length hex node id string. Returns a list of 0s
2366 and 1s indicating unknown/known.
2366 and 1s indicating unknown/known.
2367 """
2367 """
2368 repo = hg.peer(ui, opts, repopath)
2368 repo = hg.peer(ui, opts, repopath)
2369 if not repo.capable('known'):
2369 if not repo.capable('known'):
2370 raise util.Abort("known() not supported by target repository")
2370 raise util.Abort("known() not supported by target repository")
2371 flags = repo.known([bin(s) for s in ids])
2371 flags = repo.known([bin(s) for s in ids])
2372 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2372 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2373
2373
2374 @command('debuglabelcomplete', [], _('LABEL...'))
2374 @command('debuglabelcomplete', [], _('LABEL...'))
2375 def debuglabelcomplete(ui, repo, *args):
2375 def debuglabelcomplete(ui, repo, *args):
2376 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2376 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2377 debugnamecomplete(ui, repo, *args)
2377 debugnamecomplete(ui, repo, *args)
2378
2378
2379 @command('debugnamecomplete', [], _('NAME...'))
2379 @command('debugnamecomplete', [], _('NAME...'))
2380 def debugnamecomplete(ui, repo, *args):
2380 def debugnamecomplete(ui, repo, *args):
2381 '''complete "names" - tags, open branch names, bookmark names'''
2381 '''complete "names" - tags, open branch names, bookmark names'''
2382
2382
2383 names = set()
2383 names = set()
2384 # since we previously only listed open branches, we will handle that
2384 # since we previously only listed open branches, we will handle that
2385 # specially (after this for loop)
2385 # specially (after this for loop)
2386 for name, ns in repo.names.iteritems():
2386 for name, ns in repo.names.iteritems():
2387 if name != 'branches':
2387 if name != 'branches':
2388 names.update(ns.listnames(repo))
2388 names.update(ns.listnames(repo))
2389 names.update(tag for (tag, heads, tip, closed)
2389 names.update(tag for (tag, heads, tip, closed)
2390 in repo.branchmap().iterbranches() if not closed)
2390 in repo.branchmap().iterbranches() if not closed)
2391 completions = set()
2391 completions = set()
2392 if not args:
2392 if not args:
2393 args = ['']
2393 args = ['']
2394 for a in args:
2394 for a in args:
2395 completions.update(n for n in names if n.startswith(a))
2395 completions.update(n for n in names if n.startswith(a))
2396 ui.write('\n'.join(sorted(completions)))
2396 ui.write('\n'.join(sorted(completions)))
2397 ui.write('\n')
2397 ui.write('\n')
2398
2398
2399 @command('debuglocks',
2399 @command('debuglocks',
2400 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2400 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2401 ('W', 'force-wlock', None,
2401 ('W', 'force-wlock', None,
2402 _('free the working state lock (DANGEROUS)'))],
2402 _('free the working state lock (DANGEROUS)'))],
2403 _('[OPTION]...'))
2403 _('[OPTION]...'))
2404 def debuglocks(ui, repo, **opts):
2404 def debuglocks(ui, repo, **opts):
2405 """show or modify state of locks
2405 """show or modify state of locks
2406
2406
2407 By default, this command will show which locks are held. This
2407 By default, this command will show which locks are held. This
2408 includes the user and process holding the lock, the amount of time
2408 includes the user and process holding the lock, the amount of time
2409 the lock has been held, and the machine name where the process is
2409 the lock has been held, and the machine name where the process is
2410 running if it's not local.
2410 running if it's not local.
2411
2411
2412 Locks protect the integrity of Mercurial's data, so should be
2412 Locks protect the integrity of Mercurial's data, so should be
2413 treated with care. System crashes or other interruptions may cause
2413 treated with care. System crashes or other interruptions may cause
2414 locks to not be properly released, though Mercurial will usually
2414 locks to not be properly released, though Mercurial will usually
2415 detect and remove such stale locks automatically.
2415 detect and remove such stale locks automatically.
2416
2416
2417 However, detecting stale locks may not always be possible (for
2417 However, detecting stale locks may not always be possible (for
2418 instance, on a shared filesystem). Removing locks may also be
2418 instance, on a shared filesystem). Removing locks may also be
2419 blocked by filesystem permissions.
2419 blocked by filesystem permissions.
2420
2420
2421 Returns 0 if no locks are held.
2421 Returns 0 if no locks are held.
2422
2422
2423 """
2423 """
2424
2424
2425 if opts.get('force_lock'):
2425 if opts.get('force_lock'):
2426 repo.svfs.unlink('lock')
2426 repo.svfs.unlink('lock')
2427 if opts.get('force_wlock'):
2427 if opts.get('force_wlock'):
2428 repo.vfs.unlink('wlock')
2428 repo.vfs.unlink('wlock')
2429 if opts.get('force_lock') or opts.get('force_lock'):
2429 if opts.get('force_lock') or opts.get('force_lock'):
2430 return 0
2430 return 0
2431
2431
2432 now = time.time()
2432 now = time.time()
2433 held = 0
2433 held = 0
2434
2434
2435 def report(vfs, name, method):
2435 def report(vfs, name, method):
2436 # this causes stale locks to get reaped for more accurate reporting
2436 # this causes stale locks to get reaped for more accurate reporting
2437 try:
2437 try:
2438 l = method(False)
2438 l = method(False)
2439 except error.LockHeld:
2439 except error.LockHeld:
2440 l = None
2440 l = None
2441
2441
2442 if l:
2442 if l:
2443 l.release()
2443 l.release()
2444 else:
2444 else:
2445 try:
2445 try:
2446 stat = repo.svfs.lstat(name)
2446 stat = repo.svfs.lstat(name)
2447 age = now - stat.st_mtime
2447 age = now - stat.st_mtime
2448 user = util.username(stat.st_uid)
2448 user = util.username(stat.st_uid)
2449 locker = vfs.readlock(name)
2449 locker = vfs.readlock(name)
2450 if ":" in locker:
2450 if ":" in locker:
2451 host, pid = locker.split(':')
2451 host, pid = locker.split(':')
2452 if host == socket.gethostname():
2452 if host == socket.gethostname():
2453 locker = 'user %s, process %s' % (user, pid)
2453 locker = 'user %s, process %s' % (user, pid)
2454 else:
2454 else:
2455 locker = 'user %s, process %s, host %s' \
2455 locker = 'user %s, process %s, host %s' \
2456 % (user, pid, host)
2456 % (user, pid, host)
2457 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2457 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2458 return 1
2458 return 1
2459 except OSError, e:
2459 except OSError, e:
2460 if e.errno != errno.ENOENT:
2460 if e.errno != errno.ENOENT:
2461 raise
2461 raise
2462
2462
2463 ui.write("%-6s free\n" % (name + ":"))
2463 ui.write("%-6s free\n" % (name + ":"))
2464 return 0
2464 return 0
2465
2465
2466 held += report(repo.svfs, "lock", repo.lock)
2466 held += report(repo.svfs, "lock", repo.lock)
2467 held += report(repo.vfs, "wlock", repo.wlock)
2467 held += report(repo.vfs, "wlock", repo.wlock)
2468
2468
2469 return held
2469 return held
2470
2470
2471 @command('debugobsolete',
2471 @command('debugobsolete',
2472 [('', 'flags', 0, _('markers flag')),
2472 [('', 'flags', 0, _('markers flag')),
2473 ('', 'record-parents', False,
2473 ('', 'record-parents', False,
2474 _('record parent information for the precursor')),
2474 _('record parent information for the precursor')),
2475 ('r', 'rev', [], _('display markers relevant to REV')),
2475 ('r', 'rev', [], _('display markers relevant to REV')),
2476 ] + commitopts2,
2476 ] + commitopts2,
2477 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2477 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2478 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2478 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2479 """create arbitrary obsolete marker
2479 """create arbitrary obsolete marker
2480
2480
2481 With no arguments, displays the list of obsolescence markers."""
2481 With no arguments, displays the list of obsolescence markers."""
2482
2482
2483 def parsenodeid(s):
2483 def parsenodeid(s):
2484 try:
2484 try:
2485 # We do not use revsingle/revrange functions here to accept
2485 # We do not use revsingle/revrange functions here to accept
2486 # arbitrary node identifiers, possibly not present in the
2486 # arbitrary node identifiers, possibly not present in the
2487 # local repository.
2487 # local repository.
2488 n = bin(s)
2488 n = bin(s)
2489 if len(n) != len(nullid):
2489 if len(n) != len(nullid):
2490 raise TypeError()
2490 raise TypeError()
2491 return n
2491 return n
2492 except TypeError:
2492 except TypeError:
2493 raise util.Abort('changeset references must be full hexadecimal '
2493 raise util.Abort('changeset references must be full hexadecimal '
2494 'node identifiers')
2494 'node identifiers')
2495
2495
2496 if precursor is not None:
2496 if precursor is not None:
2497 if opts['rev']:
2497 if opts['rev']:
2498 raise util.Abort('cannot select revision when creating marker')
2498 raise util.Abort('cannot select revision when creating marker')
2499 metadata = {}
2499 metadata = {}
2500 metadata['user'] = opts['user'] or ui.username()
2500 metadata['user'] = opts['user'] or ui.username()
2501 succs = tuple(parsenodeid(succ) for succ in successors)
2501 succs = tuple(parsenodeid(succ) for succ in successors)
2502 l = repo.lock()
2502 l = repo.lock()
2503 try:
2503 try:
2504 tr = repo.transaction('debugobsolete')
2504 tr = repo.transaction('debugobsolete')
2505 try:
2505 try:
2506 try:
2506 try:
2507 date = opts.get('date')
2507 date = opts.get('date')
2508 if date:
2508 if date:
2509 date = util.parsedate(date)
2509 date = util.parsedate(date)
2510 else:
2510 else:
2511 date = None
2511 date = None
2512 prec = parsenodeid(precursor)
2512 prec = parsenodeid(precursor)
2513 parents = None
2513 parents = None
2514 if opts['record_parents']:
2514 if opts['record_parents']:
2515 if prec not in repo.unfiltered():
2515 if prec not in repo.unfiltered():
2516 raise util.Abort('cannot used --record-parents on '
2516 raise util.Abort('cannot used --record-parents on '
2517 'unknown changesets')
2517 'unknown changesets')
2518 parents = repo.unfiltered()[prec].parents()
2518 parents = repo.unfiltered()[prec].parents()
2519 parents = tuple(p.node() for p in parents)
2519 parents = tuple(p.node() for p in parents)
2520 repo.obsstore.create(tr, prec, succs, opts['flags'],
2520 repo.obsstore.create(tr, prec, succs, opts['flags'],
2521 parents=parents, date=date,
2521 parents=parents, date=date,
2522 metadata=metadata)
2522 metadata=metadata)
2523 tr.close()
2523 tr.close()
2524 except ValueError, exc:
2524 except ValueError, exc:
2525 raise util.Abort(_('bad obsmarker input: %s') % exc)
2525 raise util.Abort(_('bad obsmarker input: %s') % exc)
2526 finally:
2526 finally:
2527 tr.release()
2527 tr.release()
2528 finally:
2528 finally:
2529 l.release()
2529 l.release()
2530 else:
2530 else:
2531 if opts['rev']:
2531 if opts['rev']:
2532 revs = scmutil.revrange(repo, opts['rev'])
2532 revs = scmutil.revrange(repo, opts['rev'])
2533 nodes = [repo[r].node() for r in revs]
2533 nodes = [repo[r].node() for r in revs]
2534 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2534 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2535 markers.sort(key=lambda x: x._data)
2535 markers.sort(key=lambda x: x._data)
2536 else:
2536 else:
2537 markers = obsolete.getmarkers(repo)
2537 markers = obsolete.getmarkers(repo)
2538
2538
2539 for m in markers:
2539 for m in markers:
2540 cmdutil.showmarker(ui, m)
2540 cmdutil.showmarker(ui, m)
2541
2541
2542 @command('debugpathcomplete',
2542 @command('debugpathcomplete',
2543 [('f', 'full', None, _('complete an entire path')),
2543 [('f', 'full', None, _('complete an entire path')),
2544 ('n', 'normal', None, _('show only normal files')),
2544 ('n', 'normal', None, _('show only normal files')),
2545 ('a', 'added', None, _('show only added files')),
2545 ('a', 'added', None, _('show only added files')),
2546 ('r', 'removed', None, _('show only removed files'))],
2546 ('r', 'removed', None, _('show only removed files'))],
2547 _('FILESPEC...'))
2547 _('FILESPEC...'))
2548 def debugpathcomplete(ui, repo, *specs, **opts):
2548 def debugpathcomplete(ui, repo, *specs, **opts):
2549 '''complete part or all of a tracked path
2549 '''complete part or all of a tracked path
2550
2550
2551 This command supports shells that offer path name completion. It
2551 This command supports shells that offer path name completion. It
2552 currently completes only files already known to the dirstate.
2552 currently completes only files already known to the dirstate.
2553
2553
2554 Completion extends only to the next path segment unless
2554 Completion extends only to the next path segment unless
2555 --full is specified, in which case entire paths are used.'''
2555 --full is specified, in which case entire paths are used.'''
2556
2556
2557 def complete(path, acceptable):
2557 def complete(path, acceptable):
2558 dirstate = repo.dirstate
2558 dirstate = repo.dirstate
2559 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2559 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2560 rootdir = repo.root + os.sep
2560 rootdir = repo.root + os.sep
2561 if spec != repo.root and not spec.startswith(rootdir):
2561 if spec != repo.root and not spec.startswith(rootdir):
2562 return [], []
2562 return [], []
2563 if os.path.isdir(spec):
2563 if os.path.isdir(spec):
2564 spec += '/'
2564 spec += '/'
2565 spec = spec[len(rootdir):]
2565 spec = spec[len(rootdir):]
2566 fixpaths = os.sep != '/'
2566 fixpaths = os.sep != '/'
2567 if fixpaths:
2567 if fixpaths:
2568 spec = spec.replace(os.sep, '/')
2568 spec = spec.replace(os.sep, '/')
2569 speclen = len(spec)
2569 speclen = len(spec)
2570 fullpaths = opts['full']
2570 fullpaths = opts['full']
2571 files, dirs = set(), set()
2571 files, dirs = set(), set()
2572 adddir, addfile = dirs.add, files.add
2572 adddir, addfile = dirs.add, files.add
2573 for f, st in dirstate.iteritems():
2573 for f, st in dirstate.iteritems():
2574 if f.startswith(spec) and st[0] in acceptable:
2574 if f.startswith(spec) and st[0] in acceptable:
2575 if fixpaths:
2575 if fixpaths:
2576 f = f.replace('/', os.sep)
2576 f = f.replace('/', os.sep)
2577 if fullpaths:
2577 if fullpaths:
2578 addfile(f)
2578 addfile(f)
2579 continue
2579 continue
2580 s = f.find(os.sep, speclen)
2580 s = f.find(os.sep, speclen)
2581 if s >= 0:
2581 if s >= 0:
2582 adddir(f[:s])
2582 adddir(f[:s])
2583 else:
2583 else:
2584 addfile(f)
2584 addfile(f)
2585 return files, dirs
2585 return files, dirs
2586
2586
2587 acceptable = ''
2587 acceptable = ''
2588 if opts['normal']:
2588 if opts['normal']:
2589 acceptable += 'nm'
2589 acceptable += 'nm'
2590 if opts['added']:
2590 if opts['added']:
2591 acceptable += 'a'
2591 acceptable += 'a'
2592 if opts['removed']:
2592 if opts['removed']:
2593 acceptable += 'r'
2593 acceptable += 'r'
2594 cwd = repo.getcwd()
2594 cwd = repo.getcwd()
2595 if not specs:
2595 if not specs:
2596 specs = ['.']
2596 specs = ['.']
2597
2597
2598 files, dirs = set(), set()
2598 files, dirs = set(), set()
2599 for spec in specs:
2599 for spec in specs:
2600 f, d = complete(spec, acceptable or 'nmar')
2600 f, d = complete(spec, acceptable or 'nmar')
2601 files.update(f)
2601 files.update(f)
2602 dirs.update(d)
2602 dirs.update(d)
2603 files.update(dirs)
2603 files.update(dirs)
2604 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2604 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2605 ui.write('\n')
2605 ui.write('\n')
2606
2606
2607 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2607 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2608 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2608 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2609 '''access the pushkey key/value protocol
2609 '''access the pushkey key/value protocol
2610
2610
2611 With two args, list the keys in the given namespace.
2611 With two args, list the keys in the given namespace.
2612
2612
2613 With five args, set a key to new if it currently is set to old.
2613 With five args, set a key to new if it currently is set to old.
2614 Reports success or failure.
2614 Reports success or failure.
2615 '''
2615 '''
2616
2616
2617 target = hg.peer(ui, {}, repopath)
2617 target = hg.peer(ui, {}, repopath)
2618 if keyinfo:
2618 if keyinfo:
2619 key, old, new = keyinfo
2619 key, old, new = keyinfo
2620 r = target.pushkey(namespace, key, old, new)
2620 r = target.pushkey(namespace, key, old, new)
2621 ui.status(str(r) + '\n')
2621 ui.status(str(r) + '\n')
2622 return not r
2622 return not r
2623 else:
2623 else:
2624 for k, v in sorted(target.listkeys(namespace).iteritems()):
2624 for k, v in sorted(target.listkeys(namespace).iteritems()):
2625 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2625 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2626 v.encode('string-escape')))
2626 v.encode('string-escape')))
2627
2627
2628 @command('debugpvec', [], _('A B'))
2628 @command('debugpvec', [], _('A B'))
2629 def debugpvec(ui, repo, a, b=None):
2629 def debugpvec(ui, repo, a, b=None):
2630 ca = scmutil.revsingle(repo, a)
2630 ca = scmutil.revsingle(repo, a)
2631 cb = scmutil.revsingle(repo, b)
2631 cb = scmutil.revsingle(repo, b)
2632 pa = pvec.ctxpvec(ca)
2632 pa = pvec.ctxpvec(ca)
2633 pb = pvec.ctxpvec(cb)
2633 pb = pvec.ctxpvec(cb)
2634 if pa == pb:
2634 if pa == pb:
2635 rel = "="
2635 rel = "="
2636 elif pa > pb:
2636 elif pa > pb:
2637 rel = ">"
2637 rel = ">"
2638 elif pa < pb:
2638 elif pa < pb:
2639 rel = "<"
2639 rel = "<"
2640 elif pa | pb:
2640 elif pa | pb:
2641 rel = "|"
2641 rel = "|"
2642 ui.write(_("a: %s\n") % pa)
2642 ui.write(_("a: %s\n") % pa)
2643 ui.write(_("b: %s\n") % pb)
2643 ui.write(_("b: %s\n") % pb)
2644 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2644 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2645 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2645 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2646 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2646 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2647 pa.distance(pb), rel))
2647 pa.distance(pb), rel))
2648
2648
2649 @command('debugrebuilddirstate|debugrebuildstate',
2649 @command('debugrebuilddirstate|debugrebuildstate',
2650 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2650 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2651 _('[-r REV]'))
2651 _('[-r REV]'))
2652 def debugrebuilddirstate(ui, repo, rev):
2652 def debugrebuilddirstate(ui, repo, rev):
2653 """rebuild the dirstate as it would look like for the given revision
2653 """rebuild the dirstate as it would look like for the given revision
2654
2654
2655 If no revision is specified the first current parent will be used.
2655 If no revision is specified the first current parent will be used.
2656
2656
2657 The dirstate will be set to the files of the given revision.
2657 The dirstate will be set to the files of the given revision.
2658 The actual working directory content or existing dirstate
2658 The actual working directory content or existing dirstate
2659 information such as adds or removes is not considered.
2659 information such as adds or removes is not considered.
2660
2660
2661 One use of this command is to make the next :hg:`status` invocation
2661 One use of this command is to make the next :hg:`status` invocation
2662 check the actual file content.
2662 check the actual file content.
2663 """
2663 """
2664 ctx = scmutil.revsingle(repo, rev)
2664 ctx = scmutil.revsingle(repo, rev)
2665 wlock = repo.wlock()
2665 wlock = repo.wlock()
2666 try:
2666 try:
2667 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2667 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2668 finally:
2668 finally:
2669 wlock.release()
2669 wlock.release()
2670
2670
2671 @command('debugrename',
2671 @command('debugrename',
2672 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2672 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2673 _('[-r REV] FILE'))
2673 _('[-r REV] FILE'))
2674 def debugrename(ui, repo, file1, *pats, **opts):
2674 def debugrename(ui, repo, file1, *pats, **opts):
2675 """dump rename information"""
2675 """dump rename information"""
2676
2676
2677 ctx = scmutil.revsingle(repo, opts.get('rev'))
2677 ctx = scmutil.revsingle(repo, opts.get('rev'))
2678 m = scmutil.match(ctx, (file1,) + pats, opts)
2678 m = scmutil.match(ctx, (file1,) + pats, opts)
2679 for abs in ctx.walk(m):
2679 for abs in ctx.walk(m):
2680 fctx = ctx[abs]
2680 fctx = ctx[abs]
2681 o = fctx.filelog().renamed(fctx.filenode())
2681 o = fctx.filelog().renamed(fctx.filenode())
2682 rel = m.rel(abs)
2682 rel = m.rel(abs)
2683 if o:
2683 if o:
2684 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2684 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2685 else:
2685 else:
2686 ui.write(_("%s not renamed\n") % rel)
2686 ui.write(_("%s not renamed\n") % rel)
2687
2687
2688 @command('debugrevlog',
2688 @command('debugrevlog',
2689 [('c', 'changelog', False, _('open changelog')),
2689 [('c', 'changelog', False, _('open changelog')),
2690 ('m', 'manifest', False, _('open manifest')),
2690 ('m', 'manifest', False, _('open manifest')),
2691 ('d', 'dump', False, _('dump index data'))],
2691 ('d', 'dump', False, _('dump index data'))],
2692 _('-c|-m|FILE'),
2692 _('-c|-m|FILE'),
2693 optionalrepo=True)
2693 optionalrepo=True)
2694 def debugrevlog(ui, repo, file_=None, **opts):
2694 def debugrevlog(ui, repo, file_=None, **opts):
2695 """show data and statistics about a revlog"""
2695 """show data and statistics about a revlog"""
2696 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2696 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2697
2697
2698 if opts.get("dump"):
2698 if opts.get("dump"):
2699 numrevs = len(r)
2699 numrevs = len(r)
2700 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2700 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2701 " rawsize totalsize compression heads chainlen\n")
2701 " rawsize totalsize compression heads chainlen\n")
2702 ts = 0
2702 ts = 0
2703 heads = set()
2703 heads = set()
2704
2704
2705 for rev in xrange(numrevs):
2705 for rev in xrange(numrevs):
2706 dbase = r.deltaparent(rev)
2706 dbase = r.deltaparent(rev)
2707 if dbase == -1:
2707 if dbase == -1:
2708 dbase = rev
2708 dbase = rev
2709 cbase = r.chainbase(rev)
2709 cbase = r.chainbase(rev)
2710 clen = r.chainlen(rev)
2710 clen = r.chainlen(rev)
2711 p1, p2 = r.parentrevs(rev)
2711 p1, p2 = r.parentrevs(rev)
2712 rs = r.rawsize(rev)
2712 rs = r.rawsize(rev)
2713 ts = ts + rs
2713 ts = ts + rs
2714 heads -= set(r.parentrevs(rev))
2714 heads -= set(r.parentrevs(rev))
2715 heads.add(rev)
2715 heads.add(rev)
2716 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2716 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2717 "%11d %5d %8d\n" %
2717 "%11d %5d %8d\n" %
2718 (rev, p1, p2, r.start(rev), r.end(rev),
2718 (rev, p1, p2, r.start(rev), r.end(rev),
2719 r.start(dbase), r.start(cbase),
2719 r.start(dbase), r.start(cbase),
2720 r.start(p1), r.start(p2),
2720 r.start(p1), r.start(p2),
2721 rs, ts, ts / r.end(rev), len(heads), clen))
2721 rs, ts, ts / r.end(rev), len(heads), clen))
2722 return 0
2722 return 0
2723
2723
2724 v = r.version
2724 v = r.version
2725 format = v & 0xFFFF
2725 format = v & 0xFFFF
2726 flags = []
2726 flags = []
2727 gdelta = False
2727 gdelta = False
2728 if v & revlog.REVLOGNGINLINEDATA:
2728 if v & revlog.REVLOGNGINLINEDATA:
2729 flags.append('inline')
2729 flags.append('inline')
2730 if v & revlog.REVLOGGENERALDELTA:
2730 if v & revlog.REVLOGGENERALDELTA:
2731 gdelta = True
2731 gdelta = True
2732 flags.append('generaldelta')
2732 flags.append('generaldelta')
2733 if not flags:
2733 if not flags:
2734 flags = ['(none)']
2734 flags = ['(none)']
2735
2735
2736 nummerges = 0
2736 nummerges = 0
2737 numfull = 0
2737 numfull = 0
2738 numprev = 0
2738 numprev = 0
2739 nump1 = 0
2739 nump1 = 0
2740 nump2 = 0
2740 nump2 = 0
2741 numother = 0
2741 numother = 0
2742 nump1prev = 0
2742 nump1prev = 0
2743 nump2prev = 0
2743 nump2prev = 0
2744 chainlengths = []
2744 chainlengths = []
2745
2745
2746 datasize = [None, 0, 0L]
2746 datasize = [None, 0, 0L]
2747 fullsize = [None, 0, 0L]
2747 fullsize = [None, 0, 0L]
2748 deltasize = [None, 0, 0L]
2748 deltasize = [None, 0, 0L]
2749
2749
2750 def addsize(size, l):
2750 def addsize(size, l):
2751 if l[0] is None or size < l[0]:
2751 if l[0] is None or size < l[0]:
2752 l[0] = size
2752 l[0] = size
2753 if size > l[1]:
2753 if size > l[1]:
2754 l[1] = size
2754 l[1] = size
2755 l[2] += size
2755 l[2] += size
2756
2756
2757 numrevs = len(r)
2757 numrevs = len(r)
2758 for rev in xrange(numrevs):
2758 for rev in xrange(numrevs):
2759 p1, p2 = r.parentrevs(rev)
2759 p1, p2 = r.parentrevs(rev)
2760 delta = r.deltaparent(rev)
2760 delta = r.deltaparent(rev)
2761 if format > 0:
2761 if format > 0:
2762 addsize(r.rawsize(rev), datasize)
2762 addsize(r.rawsize(rev), datasize)
2763 if p2 != nullrev:
2763 if p2 != nullrev:
2764 nummerges += 1
2764 nummerges += 1
2765 size = r.length(rev)
2765 size = r.length(rev)
2766 if delta == nullrev:
2766 if delta == nullrev:
2767 chainlengths.append(0)
2767 chainlengths.append(0)
2768 numfull += 1
2768 numfull += 1
2769 addsize(size, fullsize)
2769 addsize(size, fullsize)
2770 else:
2770 else:
2771 chainlengths.append(chainlengths[delta] + 1)
2771 chainlengths.append(chainlengths[delta] + 1)
2772 addsize(size, deltasize)
2772 addsize(size, deltasize)
2773 if delta == rev - 1:
2773 if delta == rev - 1:
2774 numprev += 1
2774 numprev += 1
2775 if delta == p1:
2775 if delta == p1:
2776 nump1prev += 1
2776 nump1prev += 1
2777 elif delta == p2:
2777 elif delta == p2:
2778 nump2prev += 1
2778 nump2prev += 1
2779 elif delta == p1:
2779 elif delta == p1:
2780 nump1 += 1
2780 nump1 += 1
2781 elif delta == p2:
2781 elif delta == p2:
2782 nump2 += 1
2782 nump2 += 1
2783 elif delta != nullrev:
2783 elif delta != nullrev:
2784 numother += 1
2784 numother += 1
2785
2785
2786 # Adjust size min value for empty cases
2786 # Adjust size min value for empty cases
2787 for size in (datasize, fullsize, deltasize):
2787 for size in (datasize, fullsize, deltasize):
2788 if size[0] is None:
2788 if size[0] is None:
2789 size[0] = 0
2789 size[0] = 0
2790
2790
2791 numdeltas = numrevs - numfull
2791 numdeltas = numrevs - numfull
2792 numoprev = numprev - nump1prev - nump2prev
2792 numoprev = numprev - nump1prev - nump2prev
2793 totalrawsize = datasize[2]
2793 totalrawsize = datasize[2]
2794 datasize[2] /= numrevs
2794 datasize[2] /= numrevs
2795 fulltotal = fullsize[2]
2795 fulltotal = fullsize[2]
2796 fullsize[2] /= numfull
2796 fullsize[2] /= numfull
2797 deltatotal = deltasize[2]
2797 deltatotal = deltasize[2]
2798 if numrevs - numfull > 0:
2798 if numrevs - numfull > 0:
2799 deltasize[2] /= numrevs - numfull
2799 deltasize[2] /= numrevs - numfull
2800 totalsize = fulltotal + deltatotal
2800 totalsize = fulltotal + deltatotal
2801 avgchainlen = sum(chainlengths) / numrevs
2801 avgchainlen = sum(chainlengths) / numrevs
2802 compratio = totalrawsize / totalsize
2802 compratio = totalrawsize / totalsize
2803
2803
2804 basedfmtstr = '%%%dd\n'
2804 basedfmtstr = '%%%dd\n'
2805 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2805 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2806
2806
2807 def dfmtstr(max):
2807 def dfmtstr(max):
2808 return basedfmtstr % len(str(max))
2808 return basedfmtstr % len(str(max))
2809 def pcfmtstr(max, padding=0):
2809 def pcfmtstr(max, padding=0):
2810 return basepcfmtstr % (len(str(max)), ' ' * padding)
2810 return basepcfmtstr % (len(str(max)), ' ' * padding)
2811
2811
2812 def pcfmt(value, total):
2812 def pcfmt(value, total):
2813 return (value, 100 * float(value) / total)
2813 return (value, 100 * float(value) / total)
2814
2814
2815 ui.write(('format : %d\n') % format)
2815 ui.write(('format : %d\n') % format)
2816 ui.write(('flags : %s\n') % ', '.join(flags))
2816 ui.write(('flags : %s\n') % ', '.join(flags))
2817
2817
2818 ui.write('\n')
2818 ui.write('\n')
2819 fmt = pcfmtstr(totalsize)
2819 fmt = pcfmtstr(totalsize)
2820 fmt2 = dfmtstr(totalsize)
2820 fmt2 = dfmtstr(totalsize)
2821 ui.write(('revisions : ') + fmt2 % numrevs)
2821 ui.write(('revisions : ') + fmt2 % numrevs)
2822 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2822 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2823 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2823 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2824 ui.write(('revisions : ') + fmt2 % numrevs)
2824 ui.write(('revisions : ') + fmt2 % numrevs)
2825 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2825 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2826 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2826 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2827 ui.write(('revision size : ') + fmt2 % totalsize)
2827 ui.write(('revision size : ') + fmt2 % totalsize)
2828 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2828 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2829 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2829 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2830
2830
2831 ui.write('\n')
2831 ui.write('\n')
2832 fmt = dfmtstr(max(avgchainlen, compratio))
2832 fmt = dfmtstr(max(avgchainlen, compratio))
2833 ui.write(('avg chain length : ') + fmt % avgchainlen)
2833 ui.write(('avg chain length : ') + fmt % avgchainlen)
2834 ui.write(('compression ratio : ') + fmt % compratio)
2834 ui.write(('compression ratio : ') + fmt % compratio)
2835
2835
2836 if format > 0:
2836 if format > 0:
2837 ui.write('\n')
2837 ui.write('\n')
2838 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2838 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2839 % tuple(datasize))
2839 % tuple(datasize))
2840 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2840 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2841 % tuple(fullsize))
2841 % tuple(fullsize))
2842 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2842 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2843 % tuple(deltasize))
2843 % tuple(deltasize))
2844
2844
2845 if numdeltas > 0:
2845 if numdeltas > 0:
2846 ui.write('\n')
2846 ui.write('\n')
2847 fmt = pcfmtstr(numdeltas)
2847 fmt = pcfmtstr(numdeltas)
2848 fmt2 = pcfmtstr(numdeltas, 4)
2848 fmt2 = pcfmtstr(numdeltas, 4)
2849 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2849 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2850 if numprev > 0:
2850 if numprev > 0:
2851 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2851 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2852 numprev))
2852 numprev))
2853 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2853 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2854 numprev))
2854 numprev))
2855 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2855 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2856 numprev))
2856 numprev))
2857 if gdelta:
2857 if gdelta:
2858 ui.write(('deltas against p1 : ')
2858 ui.write(('deltas against p1 : ')
2859 + fmt % pcfmt(nump1, numdeltas))
2859 + fmt % pcfmt(nump1, numdeltas))
2860 ui.write(('deltas against p2 : ')
2860 ui.write(('deltas against p2 : ')
2861 + fmt % pcfmt(nump2, numdeltas))
2861 + fmt % pcfmt(nump2, numdeltas))
2862 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2862 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2863 numdeltas))
2863 numdeltas))
2864
2864
2865 @command('debugrevspec',
2865 @command('debugrevspec',
2866 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2866 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2867 ('REVSPEC'))
2867 ('REVSPEC'))
2868 def debugrevspec(ui, repo, expr, **opts):
2868 def debugrevspec(ui, repo, expr, **opts):
2869 """parse and apply a revision specification
2869 """parse and apply a revision specification
2870
2870
2871 Use --verbose to print the parsed tree before and after aliases
2871 Use --verbose to print the parsed tree before and after aliases
2872 expansion.
2872 expansion.
2873 """
2873 """
2874 if ui.verbose:
2874 if ui.verbose:
2875 tree = revset.parse(expr)[0]
2875 tree = revset.parse(expr)[0]
2876 ui.note(revset.prettyformat(tree), "\n")
2876 ui.note(revset.prettyformat(tree), "\n")
2877 newtree = revset.findaliases(ui, tree)
2877 newtree = revset.findaliases(ui, tree)
2878 if newtree != tree:
2878 if newtree != tree:
2879 ui.note(revset.prettyformat(newtree), "\n")
2879 ui.note(revset.prettyformat(newtree), "\n")
2880 tree = newtree
2880 tree = newtree
2881 newtree = revset.foldconcat(tree)
2881 newtree = revset.foldconcat(tree)
2882 if newtree != tree:
2882 if newtree != tree:
2883 ui.note(revset.prettyformat(newtree), "\n")
2883 ui.note(revset.prettyformat(newtree), "\n")
2884 if opts["optimize"]:
2884 if opts["optimize"]:
2885 weight, optimizedtree = revset.optimize(newtree, True)
2885 weight, optimizedtree = revset.optimize(newtree, True)
2886 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2886 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2887 func = revset.match(ui, expr)
2887 func = revset.match(ui, expr)
2888 for c in func(repo):
2888 for c in func(repo):
2889 ui.write("%s\n" % c)
2889 ui.write("%s\n" % c)
2890
2890
2891 @command('debugsetparents', [], _('REV1 [REV2]'))
2891 @command('debugsetparents', [], _('REV1 [REV2]'))
2892 def debugsetparents(ui, repo, rev1, rev2=None):
2892 def debugsetparents(ui, repo, rev1, rev2=None):
2893 """manually set the parents of the current working directory
2893 """manually set the parents of the current working directory
2894
2894
2895 This is useful for writing repository conversion tools, but should
2895 This is useful for writing repository conversion tools, but should
2896 be used with care.
2896 be used with care.
2897
2897
2898 Returns 0 on success.
2898 Returns 0 on success.
2899 """
2899 """
2900
2900
2901 r1 = scmutil.revsingle(repo, rev1).node()
2901 r1 = scmutil.revsingle(repo, rev1).node()
2902 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2902 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2903
2903
2904 wlock = repo.wlock()
2904 wlock = repo.wlock()
2905 try:
2905 try:
2906 repo.dirstate.beginparentchange()
2906 repo.dirstate.beginparentchange()
2907 repo.setparents(r1, r2)
2907 repo.setparents(r1, r2)
2908 repo.dirstate.endparentchange()
2908 repo.dirstate.endparentchange()
2909 finally:
2909 finally:
2910 wlock.release()
2910 wlock.release()
2911
2911
2912 @command('debugdirstate|debugstate',
2912 @command('debugdirstate|debugstate',
2913 [('', 'nodates', None, _('do not display the saved mtime')),
2913 [('', 'nodates', None, _('do not display the saved mtime')),
2914 ('', 'datesort', None, _('sort by saved mtime'))],
2914 ('', 'datesort', None, _('sort by saved mtime'))],
2915 _('[OPTION]...'))
2915 _('[OPTION]...'))
2916 def debugstate(ui, repo, nodates=None, datesort=None):
2916 def debugstate(ui, repo, nodates=None, datesort=None):
2917 """show the contents of the current dirstate"""
2917 """show the contents of the current dirstate"""
2918 timestr = ""
2918 timestr = ""
2919 if datesort:
2919 if datesort:
2920 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2920 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2921 else:
2921 else:
2922 keyfunc = None # sort by filename
2922 keyfunc = None # sort by filename
2923 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2923 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2924 if ent[3] == -1:
2924 if ent[3] == -1:
2925 timestr = 'unset '
2925 timestr = 'unset '
2926 elif nodates:
2926 elif nodates:
2927 timestr = 'set '
2927 timestr = 'set '
2928 else:
2928 else:
2929 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2929 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2930 time.localtime(ent[3]))
2930 time.localtime(ent[3]))
2931 if ent[1] & 020000:
2931 if ent[1] & 020000:
2932 mode = 'lnk'
2932 mode = 'lnk'
2933 else:
2933 else:
2934 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2934 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2935 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2935 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2936 for f in repo.dirstate.copies():
2936 for f in repo.dirstate.copies():
2937 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2937 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2938
2938
2939 @command('debugsub',
2939 @command('debugsub',
2940 [('r', 'rev', '',
2940 [('r', 'rev', '',
2941 _('revision to check'), _('REV'))],
2941 _('revision to check'), _('REV'))],
2942 _('[-r REV] [REV]'))
2942 _('[-r REV] [REV]'))
2943 def debugsub(ui, repo, rev=None):
2943 def debugsub(ui, repo, rev=None):
2944 ctx = scmutil.revsingle(repo, rev, None)
2944 ctx = scmutil.revsingle(repo, rev, None)
2945 for k, v in sorted(ctx.substate.items()):
2945 for k, v in sorted(ctx.substate.items()):
2946 ui.write(('path %s\n') % k)
2946 ui.write(('path %s\n') % k)
2947 ui.write((' source %s\n') % v[0])
2947 ui.write((' source %s\n') % v[0])
2948 ui.write((' revision %s\n') % v[1])
2948 ui.write((' revision %s\n') % v[1])
2949
2949
2950 @command('debugsuccessorssets',
2950 @command('debugsuccessorssets',
2951 [],
2951 [],
2952 _('[REV]'))
2952 _('[REV]'))
2953 def debugsuccessorssets(ui, repo, *revs):
2953 def debugsuccessorssets(ui, repo, *revs):
2954 """show set of successors for revision
2954 """show set of successors for revision
2955
2955
2956 A successors set of changeset A is a consistent group of revisions that
2956 A successors set of changeset A is a consistent group of revisions that
2957 succeed A. It contains non-obsolete changesets only.
2957 succeed A. It contains non-obsolete changesets only.
2958
2958
2959 In most cases a changeset A has a single successors set containing a single
2959 In most cases a changeset A has a single successors set containing a single
2960 successor (changeset A replaced by A').
2960 successor (changeset A replaced by A').
2961
2961
2962 A changeset that is made obsolete with no successors are called "pruned".
2962 A changeset that is made obsolete with no successors are called "pruned".
2963 Such changesets have no successors sets at all.
2963 Such changesets have no successors sets at all.
2964
2964
2965 A changeset that has been "split" will have a successors set containing
2965 A changeset that has been "split" will have a successors set containing
2966 more than one successor.
2966 more than one successor.
2967
2967
2968 A changeset that has been rewritten in multiple different ways is called
2968 A changeset that has been rewritten in multiple different ways is called
2969 "divergent". Such changesets have multiple successor sets (each of which
2969 "divergent". Such changesets have multiple successor sets (each of which
2970 may also be split, i.e. have multiple successors).
2970 may also be split, i.e. have multiple successors).
2971
2971
2972 Results are displayed as follows::
2972 Results are displayed as follows::
2973
2973
2974 <rev1>
2974 <rev1>
2975 <successors-1A>
2975 <successors-1A>
2976 <rev2>
2976 <rev2>
2977 <successors-2A>
2977 <successors-2A>
2978 <successors-2B1> <successors-2B2> <successors-2B3>
2978 <successors-2B1> <successors-2B2> <successors-2B3>
2979
2979
2980 Here rev2 has two possible (i.e. divergent) successors sets. The first
2980 Here rev2 has two possible (i.e. divergent) successors sets. The first
2981 holds one element, whereas the second holds three (i.e. the changeset has
2981 holds one element, whereas the second holds three (i.e. the changeset has
2982 been split).
2982 been split).
2983 """
2983 """
2984 # passed to successorssets caching computation from one call to another
2984 # passed to successorssets caching computation from one call to another
2985 cache = {}
2985 cache = {}
2986 ctx2str = str
2986 ctx2str = str
2987 node2str = short
2987 node2str = short
2988 if ui.debug():
2988 if ui.debug():
2989 def ctx2str(ctx):
2989 def ctx2str(ctx):
2990 return ctx.hex()
2990 return ctx.hex()
2991 node2str = hex
2991 node2str = hex
2992 for rev in scmutil.revrange(repo, revs):
2992 for rev in scmutil.revrange(repo, revs):
2993 ctx = repo[rev]
2993 ctx = repo[rev]
2994 ui.write('%s\n'% ctx2str(ctx))
2994 ui.write('%s\n'% ctx2str(ctx))
2995 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2995 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2996 if succsset:
2996 if succsset:
2997 ui.write(' ')
2997 ui.write(' ')
2998 ui.write(node2str(succsset[0]))
2998 ui.write(node2str(succsset[0]))
2999 for node in succsset[1:]:
2999 for node in succsset[1:]:
3000 ui.write(' ')
3000 ui.write(' ')
3001 ui.write(node2str(node))
3001 ui.write(node2str(node))
3002 ui.write('\n')
3002 ui.write('\n')
3003
3003
3004 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3004 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3005 def debugwalk(ui, repo, *pats, **opts):
3005 def debugwalk(ui, repo, *pats, **opts):
3006 """show how files match on given patterns"""
3006 """show how files match on given patterns"""
3007 m = scmutil.match(repo[None], pats, opts)
3007 m = scmutil.match(repo[None], pats, opts)
3008 items = list(repo.walk(m))
3008 items = list(repo.walk(m))
3009 if not items:
3009 if not items:
3010 return
3010 return
3011 f = lambda fn: fn
3011 f = lambda fn: fn
3012 if ui.configbool('ui', 'slash') and os.sep != '/':
3012 if ui.configbool('ui', 'slash') and os.sep != '/':
3013 f = lambda fn: util.normpath(fn)
3013 f = lambda fn: util.normpath(fn)
3014 fmt = 'f %%-%ds %%-%ds %%s' % (
3014 fmt = 'f %%-%ds %%-%ds %%s' % (
3015 max([len(abs) for abs in items]),
3015 max([len(abs) for abs in items]),
3016 max([len(m.rel(abs)) for abs in items]))
3016 max([len(m.rel(abs)) for abs in items]))
3017 for abs in items:
3017 for abs in items:
3018 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3018 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3019 ui.write("%s\n" % line.rstrip())
3019 ui.write("%s\n" % line.rstrip())
3020
3020
3021 @command('debugwireargs',
3021 @command('debugwireargs',
3022 [('', 'three', '', 'three'),
3022 [('', 'three', '', 'three'),
3023 ('', 'four', '', 'four'),
3023 ('', 'four', '', 'four'),
3024 ('', 'five', '', 'five'),
3024 ('', 'five', '', 'five'),
3025 ] + remoteopts,
3025 ] + remoteopts,
3026 _('REPO [OPTIONS]... [ONE [TWO]]'),
3026 _('REPO [OPTIONS]... [ONE [TWO]]'),
3027 norepo=True)
3027 norepo=True)
3028 def debugwireargs(ui, repopath, *vals, **opts):
3028 def debugwireargs(ui, repopath, *vals, **opts):
3029 repo = hg.peer(ui, opts, repopath)
3029 repo = hg.peer(ui, opts, repopath)
3030 for opt in remoteopts:
3030 for opt in remoteopts:
3031 del opts[opt[1]]
3031 del opts[opt[1]]
3032 args = {}
3032 args = {}
3033 for k, v in opts.iteritems():
3033 for k, v in opts.iteritems():
3034 if v:
3034 if v:
3035 args[k] = v
3035 args[k] = v
3036 # run twice to check that we don't mess up the stream for the next command
3036 # run twice to check that we don't mess up the stream for the next command
3037 res1 = repo.debugwireargs(*vals, **args)
3037 res1 = repo.debugwireargs(*vals, **args)
3038 res2 = repo.debugwireargs(*vals, **args)
3038 res2 = repo.debugwireargs(*vals, **args)
3039 ui.write("%s\n" % res1)
3039 ui.write("%s\n" % res1)
3040 if res1 != res2:
3040 if res1 != res2:
3041 ui.warn("%s\n" % res2)
3041 ui.warn("%s\n" % res2)
3042
3042
3043 @command('^diff',
3043 @command('^diff',
3044 [('r', 'rev', [], _('revision'), _('REV')),
3044 [('r', 'rev', [], _('revision'), _('REV')),
3045 ('c', 'change', '', _('change made by revision'), _('REV'))
3045 ('c', 'change', '', _('change made by revision'), _('REV'))
3046 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3046 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3047 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3047 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3048 inferrepo=True)
3048 inferrepo=True)
3049 def diff(ui, repo, *pats, **opts):
3049 def diff(ui, repo, *pats, **opts):
3050 """diff repository (or selected files)
3050 """diff repository (or selected files)
3051
3051
3052 Show differences between revisions for the specified files.
3052 Show differences between revisions for the specified files.
3053
3053
3054 Differences between files are shown using the unified diff format.
3054 Differences between files are shown using the unified diff format.
3055
3055
3056 .. note::
3056 .. note::
3057
3057
3058 diff may generate unexpected results for merges, as it will
3058 diff may generate unexpected results for merges, as it will
3059 default to comparing against the working directory's first
3059 default to comparing against the working directory's first
3060 parent changeset if no revisions are specified.
3060 parent changeset if no revisions are specified.
3061
3061
3062 When two revision arguments are given, then changes are shown
3062 When two revision arguments are given, then changes are shown
3063 between those revisions. If only one revision is specified then
3063 between those revisions. If only one revision is specified then
3064 that revision is compared to the working directory, and, when no
3064 that revision is compared to the working directory, and, when no
3065 revisions are specified, the working directory files are compared
3065 revisions are specified, the working directory files are compared
3066 to its parent.
3066 to its parent.
3067
3067
3068 Alternatively you can specify -c/--change with a revision to see
3068 Alternatively you can specify -c/--change with a revision to see
3069 the changes in that changeset relative to its first parent.
3069 the changes in that changeset relative to its first parent.
3070
3070
3071 Without the -a/--text option, diff will avoid generating diffs of
3071 Without the -a/--text option, diff will avoid generating diffs of
3072 files it detects as binary. With -a, diff will generate a diff
3072 files it detects as binary. With -a, diff will generate a diff
3073 anyway, probably with undesirable results.
3073 anyway, probably with undesirable results.
3074
3074
3075 Use the -g/--git option to generate diffs in the git extended diff
3075 Use the -g/--git option to generate diffs in the git extended diff
3076 format. For more information, read :hg:`help diffs`.
3076 format. For more information, read :hg:`help diffs`.
3077
3077
3078 .. container:: verbose
3078 .. container:: verbose
3079
3079
3080 Examples:
3080 Examples:
3081
3081
3082 - compare a file in the current working directory to its parent::
3082 - compare a file in the current working directory to its parent::
3083
3083
3084 hg diff foo.c
3084 hg diff foo.c
3085
3085
3086 - compare two historical versions of a directory, with rename info::
3086 - compare two historical versions of a directory, with rename info::
3087
3087
3088 hg diff --git -r 1.0:1.2 lib/
3088 hg diff --git -r 1.0:1.2 lib/
3089
3089
3090 - get change stats relative to the last change on some date::
3090 - get change stats relative to the last change on some date::
3091
3091
3092 hg diff --stat -r "date('may 2')"
3092 hg diff --stat -r "date('may 2')"
3093
3093
3094 - diff all newly-added files that contain a keyword::
3094 - diff all newly-added files that contain a keyword::
3095
3095
3096 hg diff "set:added() and grep(GNU)"
3096 hg diff "set:added() and grep(GNU)"
3097
3097
3098 - compare a revision and its parents::
3098 - compare a revision and its parents::
3099
3099
3100 hg diff -c 9353 # compare against first parent
3100 hg diff -c 9353 # compare against first parent
3101 hg diff -r 9353^:9353 # same using revset syntax
3101 hg diff -r 9353^:9353 # same using revset syntax
3102 hg diff -r 9353^2:9353 # compare against the second parent
3102 hg diff -r 9353^2:9353 # compare against the second parent
3103
3103
3104 Returns 0 on success.
3104 Returns 0 on success.
3105 """
3105 """
3106
3106
3107 revs = opts.get('rev')
3107 revs = opts.get('rev')
3108 change = opts.get('change')
3108 change = opts.get('change')
3109 stat = opts.get('stat')
3109 stat = opts.get('stat')
3110 reverse = opts.get('reverse')
3110 reverse = opts.get('reverse')
3111
3111
3112 if revs and change:
3112 if revs and change:
3113 msg = _('cannot specify --rev and --change at the same time')
3113 msg = _('cannot specify --rev and --change at the same time')
3114 raise util.Abort(msg)
3114 raise util.Abort(msg)
3115 elif change:
3115 elif change:
3116 node2 = scmutil.revsingle(repo, change, None).node()
3116 node2 = scmutil.revsingle(repo, change, None).node()
3117 node1 = repo[node2].p1().node()
3117 node1 = repo[node2].p1().node()
3118 else:
3118 else:
3119 node1, node2 = scmutil.revpair(repo, revs)
3119 node1, node2 = scmutil.revpair(repo, revs)
3120
3120
3121 if reverse:
3121 if reverse:
3122 node1, node2 = node2, node1
3122 node1, node2 = node2, node1
3123
3123
3124 diffopts = patch.diffallopts(ui, opts)
3124 diffopts = patch.diffallopts(ui, opts)
3125 m = scmutil.match(repo[node2], pats, opts)
3125 m = scmutil.match(repo[node2], pats, opts)
3126 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3126 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3127 listsubrepos=opts.get('subrepos'))
3127 listsubrepos=opts.get('subrepos'))
3128
3128
3129 @command('^export',
3129 @command('^export',
3130 [('o', 'output', '',
3130 [('o', 'output', '',
3131 _('print output to file with formatted name'), _('FORMAT')),
3131 _('print output to file with formatted name'), _('FORMAT')),
3132 ('', 'switch-parent', None, _('diff against the second parent')),
3132 ('', 'switch-parent', None, _('diff against the second parent')),
3133 ('r', 'rev', [], _('revisions to export'), _('REV')),
3133 ('r', 'rev', [], _('revisions to export'), _('REV')),
3134 ] + diffopts,
3134 ] + diffopts,
3135 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3135 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3136 def export(ui, repo, *changesets, **opts):
3136 def export(ui, repo, *changesets, **opts):
3137 """dump the header and diffs for one or more changesets
3137 """dump the header and diffs for one or more changesets
3138
3138
3139 Print the changeset header and diffs for one or more revisions.
3139 Print the changeset header and diffs for one or more revisions.
3140 If no revision is given, the parent of the working directory is used.
3140 If no revision is given, the parent of the working directory is used.
3141
3141
3142 The information shown in the changeset header is: author, date,
3142 The information shown in the changeset header is: author, date,
3143 branch name (if non-default), changeset hash, parent(s) and commit
3143 branch name (if non-default), changeset hash, parent(s) and commit
3144 comment.
3144 comment.
3145
3145
3146 .. note::
3146 .. note::
3147
3147
3148 export may generate unexpected diff output for merge
3148 export may generate unexpected diff output for merge
3149 changesets, as it will compare the merge changeset against its
3149 changesets, as it will compare the merge changeset against its
3150 first parent only.
3150 first parent only.
3151
3151
3152 Output may be to a file, in which case the name of the file is
3152 Output may be to a file, in which case the name of the file is
3153 given using a format string. The formatting rules are as follows:
3153 given using a format string. The formatting rules are as follows:
3154
3154
3155 :``%%``: literal "%" character
3155 :``%%``: literal "%" character
3156 :``%H``: changeset hash (40 hexadecimal digits)
3156 :``%H``: changeset hash (40 hexadecimal digits)
3157 :``%N``: number of patches being generated
3157 :``%N``: number of patches being generated
3158 :``%R``: changeset revision number
3158 :``%R``: changeset revision number
3159 :``%b``: basename of the exporting repository
3159 :``%b``: basename of the exporting repository
3160 :``%h``: short-form changeset hash (12 hexadecimal digits)
3160 :``%h``: short-form changeset hash (12 hexadecimal digits)
3161 :``%m``: first line of the commit message (only alphanumeric characters)
3161 :``%m``: first line of the commit message (only alphanumeric characters)
3162 :``%n``: zero-padded sequence number, starting at 1
3162 :``%n``: zero-padded sequence number, starting at 1
3163 :``%r``: zero-padded changeset revision number
3163 :``%r``: zero-padded changeset revision number
3164
3164
3165 Without the -a/--text option, export will avoid generating diffs
3165 Without the -a/--text option, export will avoid generating diffs
3166 of files it detects as binary. With -a, export will generate a
3166 of files it detects as binary. With -a, export will generate a
3167 diff anyway, probably with undesirable results.
3167 diff anyway, probably with undesirable results.
3168
3168
3169 Use the -g/--git option to generate diffs in the git extended diff
3169 Use the -g/--git option to generate diffs in the git extended diff
3170 format. See :hg:`help diffs` for more information.
3170 format. See :hg:`help diffs` for more information.
3171
3171
3172 With the --switch-parent option, the diff will be against the
3172 With the --switch-parent option, the diff will be against the
3173 second parent. It can be useful to review a merge.
3173 second parent. It can be useful to review a merge.
3174
3174
3175 .. container:: verbose
3175 .. container:: verbose
3176
3176
3177 Examples:
3177 Examples:
3178
3178
3179 - use export and import to transplant a bugfix to the current
3179 - use export and import to transplant a bugfix to the current
3180 branch::
3180 branch::
3181
3181
3182 hg export -r 9353 | hg import -
3182 hg export -r 9353 | hg import -
3183
3183
3184 - export all the changesets between two revisions to a file with
3184 - export all the changesets between two revisions to a file with
3185 rename information::
3185 rename information::
3186
3186
3187 hg export --git -r 123:150 > changes.txt
3187 hg export --git -r 123:150 > changes.txt
3188
3188
3189 - split outgoing changes into a series of patches with
3189 - split outgoing changes into a series of patches with
3190 descriptive names::
3190 descriptive names::
3191
3191
3192 hg export -r "outgoing()" -o "%n-%m.patch"
3192 hg export -r "outgoing()" -o "%n-%m.patch"
3193
3193
3194 Returns 0 on success.
3194 Returns 0 on success.
3195 """
3195 """
3196 changesets += tuple(opts.get('rev', []))
3196 changesets += tuple(opts.get('rev', []))
3197 if not changesets:
3197 if not changesets:
3198 changesets = ['.']
3198 changesets = ['.']
3199 revs = scmutil.revrange(repo, changesets)
3199 revs = scmutil.revrange(repo, changesets)
3200 if not revs:
3200 if not revs:
3201 raise util.Abort(_("export requires at least one changeset"))
3201 raise util.Abort(_("export requires at least one changeset"))
3202 if len(revs) > 1:
3202 if len(revs) > 1:
3203 ui.note(_('exporting patches:\n'))
3203 ui.note(_('exporting patches:\n'))
3204 else:
3204 else:
3205 ui.note(_('exporting patch:\n'))
3205 ui.note(_('exporting patch:\n'))
3206 cmdutil.export(repo, revs, template=opts.get('output'),
3206 cmdutil.export(repo, revs, template=opts.get('output'),
3207 switch_parent=opts.get('switch_parent'),
3207 switch_parent=opts.get('switch_parent'),
3208 opts=patch.diffallopts(ui, opts))
3208 opts=patch.diffallopts(ui, opts))
3209
3209
3210 @command('files',
3210 @command('files',
3211 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3211 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3212 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3212 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3213 ] + walkopts + formatteropts,
3213 ] + walkopts + formatteropts,
3214 _('[OPTION]... [PATTERN]...'))
3214 _('[OPTION]... [PATTERN]...'))
3215 def files(ui, repo, *pats, **opts):
3215 def files(ui, repo, *pats, **opts):
3216 """list tracked files
3216 """list tracked files
3217
3217
3218 Print files under Mercurial control in the working directory or
3218 Print files under Mercurial control in the working directory or
3219 specified revision whose names match the given patterns (excluding
3219 specified revision whose names match the given patterns (excluding
3220 removed files).
3220 removed files).
3221
3221
3222 If no patterns are given to match, this command prints the names
3222 If no patterns are given to match, this command prints the names
3223 of all files under Mercurial control in the working copy.
3223 of all files under Mercurial control in the working copy.
3224
3224
3225 .. container:: verbose
3225 .. container:: verbose
3226
3226
3227 Examples:
3227 Examples:
3228
3228
3229 - list all files under the current directory::
3229 - list all files under the current directory::
3230
3230
3231 hg files .
3231 hg files .
3232
3232
3233 - shows sizes and flags for current revision::
3233 - shows sizes and flags for current revision::
3234
3234
3235 hg files -vr .
3235 hg files -vr .
3236
3236
3237 - list all files named README::
3237 - list all files named README::
3238
3238
3239 hg files -I "**/README"
3239 hg files -I "**/README"
3240
3240
3241 - list all binary files::
3241 - list all binary files::
3242
3242
3243 hg files "set:binary()"
3243 hg files "set:binary()"
3244
3244
3245 - find files containing a regular expression::
3245 - find files containing a regular expression::
3246
3246
3247 hg files "set:grep('bob')"
3247 hg files "set:grep('bob')"
3248
3248
3249 - search tracked file contents with xargs and grep::
3249 - search tracked file contents with xargs and grep::
3250
3250
3251 hg files -0 | xargs -0 grep foo
3251 hg files -0 | xargs -0 grep foo
3252
3252
3253 See :hg:`help patterns` and :hg:`help filesets` for more information
3253 See :hg:`help patterns` and :hg:`help filesets` for more information
3254 on specifying file patterns.
3254 on specifying file patterns.
3255
3255
3256 Returns 0 if a match is found, 1 otherwise.
3256 Returns 0 if a match is found, 1 otherwise.
3257
3257
3258 """
3258 """
3259 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3259 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3260 rev = ctx.rev()
3260 rev = ctx.rev()
3261 ret = 1
3261 ret = 1
3262
3262
3263 end = '\n'
3263 end = '\n'
3264 if opts.get('print0'):
3264 if opts.get('print0'):
3265 end = '\0'
3265 end = '\0'
3266 fm = ui.formatter('files', opts)
3266 fm = ui.formatter('files', opts)
3267 fmt = '%s' + end
3267 fmt = '%s' + end
3268
3268
3269 m = scmutil.match(ctx, pats, opts)
3269 m = scmutil.match(ctx, pats, opts)
3270 ds = repo.dirstate
3270 ds = repo.dirstate
3271 for f in ctx.matches(m):
3271 for f in ctx.matches(m):
3272 if rev is None and ds[f] == 'r':
3272 if rev is None and ds[f] == 'r':
3273 continue
3273 continue
3274 fm.startitem()
3274 fm.startitem()
3275 if ui.verbose:
3275 if ui.verbose:
3276 fc = ctx[f]
3276 fc = ctx[f]
3277 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3277 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3278 fm.data(abspath=f)
3278 fm.data(abspath=f)
3279 fm.write('path', fmt, m.rel(f))
3279 fm.write('path', fmt, m.rel(f))
3280 ret = 0
3280 ret = 0
3281
3281
3282 fm.end()
3282 fm.end()
3283
3283
3284 return ret
3284 return ret
3285
3285
3286 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3286 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3287 def forget(ui, repo, *pats, **opts):
3287 def forget(ui, repo, *pats, **opts):
3288 """forget the specified files on the next commit
3288 """forget the specified files on the next commit
3289
3289
3290 Mark the specified files so they will no longer be tracked
3290 Mark the specified files so they will no longer be tracked
3291 after the next commit.
3291 after the next commit.
3292
3292
3293 This only removes files from the current branch, not from the
3293 This only removes files from the current branch, not from the
3294 entire project history, and it does not delete them from the
3294 entire project history, and it does not delete them from the
3295 working directory.
3295 working directory.
3296
3296
3297 To undo a forget before the next commit, see :hg:`add`.
3297 To undo a forget before the next commit, see :hg:`add`.
3298
3298
3299 .. container:: verbose
3299 .. container:: verbose
3300
3300
3301 Examples:
3301 Examples:
3302
3302
3303 - forget newly-added binary files::
3303 - forget newly-added binary files::
3304
3304
3305 hg forget "set:added() and binary()"
3305 hg forget "set:added() and binary()"
3306
3306
3307 - forget files that would be excluded by .hgignore::
3307 - forget files that would be excluded by .hgignore::
3308
3308
3309 hg forget "set:hgignore()"
3309 hg forget "set:hgignore()"
3310
3310
3311 Returns 0 on success.
3311 Returns 0 on success.
3312 """
3312 """
3313
3313
3314 if not pats:
3314 if not pats:
3315 raise util.Abort(_('no files specified'))
3315 raise util.Abort(_('no files specified'))
3316
3316
3317 m = scmutil.match(repo[None], pats, opts)
3317 m = scmutil.match(repo[None], pats, opts)
3318 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3318 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3319 return rejected and 1 or 0
3319 return rejected and 1 or 0
3320
3320
3321 @command(
3321 @command(
3322 'graft',
3322 'graft',
3323 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3323 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3324 ('c', 'continue', False, _('resume interrupted graft')),
3324 ('c', 'continue', False, _('resume interrupted graft')),
3325 ('e', 'edit', False, _('invoke editor on commit messages')),
3325 ('e', 'edit', False, _('invoke editor on commit messages')),
3326 ('', 'log', None, _('append graft info to log message')),
3326 ('', 'log', None, _('append graft info to log message')),
3327 ('f', 'force', False, _('force graft')),
3327 ('f', 'force', False, _('force graft')),
3328 ('D', 'currentdate', False,
3328 ('D', 'currentdate', False,
3329 _('record the current date as commit date')),
3329 _('record the current date as commit date')),
3330 ('U', 'currentuser', False,
3330 ('U', 'currentuser', False,
3331 _('record the current user as committer'), _('DATE'))]
3331 _('record the current user as committer'), _('DATE'))]
3332 + commitopts2 + mergetoolopts + dryrunopts,
3332 + commitopts2 + mergetoolopts + dryrunopts,
3333 _('[OPTION]... [-r] REV...'))
3333 _('[OPTION]... [-r] REV...'))
3334 def graft(ui, repo, *revs, **opts):
3334 def graft(ui, repo, *revs, **opts):
3335 '''copy changes from other branches onto the current branch
3335 '''copy changes from other branches onto the current branch
3336
3336
3337 This command uses Mercurial's merge logic to copy individual
3337 This command uses Mercurial's merge logic to copy individual
3338 changes from other branches without merging branches in the
3338 changes from other branches without merging branches in the
3339 history graph. This is sometimes known as 'backporting' or
3339 history graph. This is sometimes known as 'backporting' or
3340 'cherry-picking'. By default, graft will copy user, date, and
3340 'cherry-picking'. By default, graft will copy user, date, and
3341 description from the source changesets.
3341 description from the source changesets.
3342
3342
3343 Changesets that are ancestors of the current revision, that have
3343 Changesets that are ancestors of the current revision, that have
3344 already been grafted, or that are merges will be skipped.
3344 already been grafted, or that are merges will be skipped.
3345
3345
3346 If --log is specified, log messages will have a comment appended
3346 If --log is specified, log messages will have a comment appended
3347 of the form::
3347 of the form::
3348
3348
3349 (grafted from CHANGESETHASH)
3349 (grafted from CHANGESETHASH)
3350
3350
3351 If --force is specified, revisions will be grafted even if they
3351 If --force is specified, revisions will be grafted even if they
3352 are already ancestors of or have been grafted to the destination.
3352 are already ancestors of or have been grafted to the destination.
3353 This is useful when the revisions have since been backed out.
3353 This is useful when the revisions have since been backed out.
3354
3354
3355 If a graft merge results in conflicts, the graft process is
3355 If a graft merge results in conflicts, the graft process is
3356 interrupted so that the current merge can be manually resolved.
3356 interrupted so that the current merge can be manually resolved.
3357 Once all conflicts are addressed, the graft process can be
3357 Once all conflicts are addressed, the graft process can be
3358 continued with the -c/--continue option.
3358 continued with the -c/--continue option.
3359
3359
3360 .. note::
3360 .. note::
3361
3361
3362 The -c/--continue option does not reapply earlier options, except
3362 The -c/--continue option does not reapply earlier options, except
3363 for --force.
3363 for --force.
3364
3364
3365 .. container:: verbose
3365 .. container:: verbose
3366
3366
3367 Examples:
3367 Examples:
3368
3368
3369 - copy a single change to the stable branch and edit its description::
3369 - copy a single change to the stable branch and edit its description::
3370
3370
3371 hg update stable
3371 hg update stable
3372 hg graft --edit 9393
3372 hg graft --edit 9393
3373
3373
3374 - graft a range of changesets with one exception, updating dates::
3374 - graft a range of changesets with one exception, updating dates::
3375
3375
3376 hg graft -D "2085::2093 and not 2091"
3376 hg graft -D "2085::2093 and not 2091"
3377
3377
3378 - continue a graft after resolving conflicts::
3378 - continue a graft after resolving conflicts::
3379
3379
3380 hg graft -c
3380 hg graft -c
3381
3381
3382 - show the source of a grafted changeset::
3382 - show the source of a grafted changeset::
3383
3383
3384 hg log --debug -r .
3384 hg log --debug -r .
3385
3385
3386 See :hg:`help revisions` and :hg:`help revsets` for more about
3386 See :hg:`help revisions` and :hg:`help revsets` for more about
3387 specifying revisions.
3387 specifying revisions.
3388
3388
3389 Returns 0 on successful completion.
3389 Returns 0 on successful completion.
3390 '''
3390 '''
3391
3391
3392 revs = list(revs)
3392 revs = list(revs)
3393 revs.extend(opts['rev'])
3393 revs.extend(opts['rev'])
3394
3394
3395 if not opts.get('user') and opts.get('currentuser'):
3395 if not opts.get('user') and opts.get('currentuser'):
3396 opts['user'] = ui.username()
3396 opts['user'] = ui.username()
3397 if not opts.get('date') and opts.get('currentdate'):
3397 if not opts.get('date') and opts.get('currentdate'):
3398 opts['date'] = "%d %d" % util.makedate()
3398 opts['date'] = "%d %d" % util.makedate()
3399
3399
3400 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3400 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3401
3401
3402 cont = False
3402 cont = False
3403 if opts['continue']:
3403 if opts['continue']:
3404 cont = True
3404 cont = True
3405 if revs:
3405 if revs:
3406 raise util.Abort(_("can't specify --continue and revisions"))
3406 raise util.Abort(_("can't specify --continue and revisions"))
3407 # read in unfinished revisions
3407 # read in unfinished revisions
3408 try:
3408 try:
3409 nodes = repo.vfs.read('graftstate').splitlines()
3409 nodes = repo.vfs.read('graftstate').splitlines()
3410 revs = [repo[node].rev() for node in nodes]
3410 revs = [repo[node].rev() for node in nodes]
3411 except IOError, inst:
3411 except IOError, inst:
3412 if inst.errno != errno.ENOENT:
3412 if inst.errno != errno.ENOENT:
3413 raise
3413 raise
3414 raise util.Abort(_("no graft state found, can't continue"))
3414 raise util.Abort(_("no graft state found, can't continue"))
3415 else:
3415 else:
3416 cmdutil.checkunfinished(repo)
3416 cmdutil.checkunfinished(repo)
3417 cmdutil.bailifchanged(repo)
3417 cmdutil.bailifchanged(repo)
3418 if not revs:
3418 if not revs:
3419 raise util.Abort(_('no revisions specified'))
3419 raise util.Abort(_('no revisions specified'))
3420 revs = scmutil.revrange(repo, revs)
3420 revs = scmutil.revrange(repo, revs)
3421
3421
3422 skipped = set()
3422 skipped = set()
3423 # check for merges
3423 # check for merges
3424 for rev in repo.revs('%ld and merge()', revs):
3424 for rev in repo.revs('%ld and merge()', revs):
3425 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3425 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3426 skipped.add(rev)
3426 skipped.add(rev)
3427 revs = [r for r in revs if r not in skipped]
3427 revs = [r for r in revs if r not in skipped]
3428 if not revs:
3428 if not revs:
3429 return -1
3429 return -1
3430
3430
3431 # Don't check in the --continue case, in effect retaining --force across
3431 # Don't check in the --continue case, in effect retaining --force across
3432 # --continues. That's because without --force, any revisions we decided to
3432 # --continues. That's because without --force, any revisions we decided to
3433 # skip would have been filtered out here, so they wouldn't have made their
3433 # skip would have been filtered out here, so they wouldn't have made their
3434 # way to the graftstate. With --force, any revisions we would have otherwise
3434 # way to the graftstate. With --force, any revisions we would have otherwise
3435 # skipped would not have been filtered out, and if they hadn't been applied
3435 # skipped would not have been filtered out, and if they hadn't been applied
3436 # already, they'd have been in the graftstate.
3436 # already, they'd have been in the graftstate.
3437 if not (cont or opts.get('force')):
3437 if not (cont or opts.get('force')):
3438 # check for ancestors of dest branch
3438 # check for ancestors of dest branch
3439 crev = repo['.'].rev()
3439 crev = repo['.'].rev()
3440 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3440 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3441 # Cannot use x.remove(y) on smart set, this has to be a list.
3441 # Cannot use x.remove(y) on smart set, this has to be a list.
3442 # XXX make this lazy in the future
3442 # XXX make this lazy in the future
3443 revs = list(revs)
3443 revs = list(revs)
3444 # don't mutate while iterating, create a copy
3444 # don't mutate while iterating, create a copy
3445 for rev in list(revs):
3445 for rev in list(revs):
3446 if rev in ancestors:
3446 if rev in ancestors:
3447 ui.warn(_('skipping ancestor revision %d:%s\n') %
3447 ui.warn(_('skipping ancestor revision %d:%s\n') %
3448 (rev, repo[rev]))
3448 (rev, repo[rev]))
3449 # XXX remove on list is slow
3449 # XXX remove on list is slow
3450 revs.remove(rev)
3450 revs.remove(rev)
3451 if not revs:
3451 if not revs:
3452 return -1
3452 return -1
3453
3453
3454 # analyze revs for earlier grafts
3454 # analyze revs for earlier grafts
3455 ids = {}
3455 ids = {}
3456 for ctx in repo.set("%ld", revs):
3456 for ctx in repo.set("%ld", revs):
3457 ids[ctx.hex()] = ctx.rev()
3457 ids[ctx.hex()] = ctx.rev()
3458 n = ctx.extra().get('source')
3458 n = ctx.extra().get('source')
3459 if n:
3459 if n:
3460 ids[n] = ctx.rev()
3460 ids[n] = ctx.rev()
3461
3461
3462 # check ancestors for earlier grafts
3462 # check ancestors for earlier grafts
3463 ui.debug('scanning for duplicate grafts\n')
3463 ui.debug('scanning for duplicate grafts\n')
3464
3464
3465 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3465 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3466 ctx = repo[rev]
3466 ctx = repo[rev]
3467 n = ctx.extra().get('source')
3467 n = ctx.extra().get('source')
3468 if n in ids:
3468 if n in ids:
3469 try:
3469 try:
3470 r = repo[n].rev()
3470 r = repo[n].rev()
3471 except error.RepoLookupError:
3471 except error.RepoLookupError:
3472 r = None
3472 r = None
3473 if r in revs:
3473 if r in revs:
3474 ui.warn(_('skipping revision %d:%s '
3474 ui.warn(_('skipping revision %d:%s '
3475 '(already grafted to %d:%s)\n')
3475 '(already grafted to %d:%s)\n')
3476 % (r, repo[r], rev, ctx))
3476 % (r, repo[r], rev, ctx))
3477 revs.remove(r)
3477 revs.remove(r)
3478 elif ids[n] in revs:
3478 elif ids[n] in revs:
3479 if r is None:
3479 if r is None:
3480 ui.warn(_('skipping already grafted revision %d:%s '
3480 ui.warn(_('skipping already grafted revision %d:%s '
3481 '(%d:%s also has unknown origin %s)\n')
3481 '(%d:%s also has unknown origin %s)\n')
3482 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3482 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3483 else:
3483 else:
3484 ui.warn(_('skipping already grafted revision %d:%s '
3484 ui.warn(_('skipping already grafted revision %d:%s '
3485 '(%d:%s also has origin %d:%s)\n')
3485 '(%d:%s also has origin %d:%s)\n')
3486 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3486 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3487 revs.remove(ids[n])
3487 revs.remove(ids[n])
3488 elif ctx.hex() in ids:
3488 elif ctx.hex() in ids:
3489 r = ids[ctx.hex()]
3489 r = ids[ctx.hex()]
3490 ui.warn(_('skipping already grafted revision %d:%s '
3490 ui.warn(_('skipping already grafted revision %d:%s '
3491 '(was grafted from %d:%s)\n') %
3491 '(was grafted from %d:%s)\n') %
3492 (r, repo[r], rev, ctx))
3492 (r, repo[r], rev, ctx))
3493 revs.remove(r)
3493 revs.remove(r)
3494 if not revs:
3494 if not revs:
3495 return -1
3495 return -1
3496
3496
3497 wlock = repo.wlock()
3497 wlock = repo.wlock()
3498 try:
3498 try:
3499 for pos, ctx in enumerate(repo.set("%ld", revs)):
3499 for pos, ctx in enumerate(repo.set("%ld", revs)):
3500 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3500 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3501 ctx.description().split('\n', 1)[0])
3501 ctx.description().split('\n', 1)[0])
3502 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3502 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3503 if names:
3503 if names:
3504 desc += ' (%s)' % ' '.join(names)
3504 desc += ' (%s)' % ' '.join(names)
3505 ui.status(_('grafting %s\n') % desc)
3505 ui.status(_('grafting %s\n') % desc)
3506 if opts.get('dry_run'):
3506 if opts.get('dry_run'):
3507 continue
3507 continue
3508
3508
3509 source = ctx.extra().get('source')
3509 source = ctx.extra().get('source')
3510 if not source:
3510 if not source:
3511 source = ctx.hex()
3511 source = ctx.hex()
3512 extra = {'source': source}
3512 extra = {'source': source}
3513 user = ctx.user()
3513 user = ctx.user()
3514 if opts.get('user'):
3514 if opts.get('user'):
3515 user = opts['user']
3515 user = opts['user']
3516 date = ctx.date()
3516 date = ctx.date()
3517 if opts.get('date'):
3517 if opts.get('date'):
3518 date = opts['date']
3518 date = opts['date']
3519 message = ctx.description()
3519 message = ctx.description()
3520 if opts.get('log'):
3520 if opts.get('log'):
3521 message += '\n(grafted from %s)' % ctx.hex()
3521 message += '\n(grafted from %s)' % ctx.hex()
3522
3522
3523 # we don't merge the first commit when continuing
3523 # we don't merge the first commit when continuing
3524 if not cont:
3524 if not cont:
3525 # perform the graft merge with p1(rev) as 'ancestor'
3525 # perform the graft merge with p1(rev) as 'ancestor'
3526 try:
3526 try:
3527 # ui.forcemerge is an internal variable, do not document
3527 # ui.forcemerge is an internal variable, do not document
3528 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3528 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3529 'graft')
3529 'graft')
3530 stats = mergemod.graft(repo, ctx, ctx.p1(),
3530 stats = mergemod.graft(repo, ctx, ctx.p1(),
3531 ['local', 'graft'])
3531 ['local', 'graft'])
3532 finally:
3532 finally:
3533 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3533 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3534 # report any conflicts
3534 # report any conflicts
3535 if stats and stats[3] > 0:
3535 if stats and stats[3] > 0:
3536 # write out state for --continue
3536 # write out state for --continue
3537 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3537 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3538 repo.vfs.write('graftstate', ''.join(nodelines))
3538 repo.vfs.write('graftstate', ''.join(nodelines))
3539 raise util.Abort(
3539 raise util.Abort(
3540 _("unresolved conflicts, can't continue"),
3540 _("unresolved conflicts, can't continue"),
3541 hint=_('use hg resolve and hg graft --continue'))
3541 hint=_('use hg resolve and hg graft --continue'))
3542 else:
3542 else:
3543 cont = False
3543 cont = False
3544
3544
3545 # commit
3545 # commit
3546 node = repo.commit(text=message, user=user,
3546 node = repo.commit(text=message, user=user,
3547 date=date, extra=extra, editor=editor)
3547 date=date, extra=extra, editor=editor)
3548 if node is None:
3548 if node is None:
3549 ui.warn(
3549 ui.warn(
3550 _('note: graft of %d:%s created no changes to commit\n') %
3550 _('note: graft of %d:%s created no changes to commit\n') %
3551 (ctx.rev(), ctx))
3551 (ctx.rev(), ctx))
3552 finally:
3552 finally:
3553 wlock.release()
3553 wlock.release()
3554
3554
3555 # remove state when we complete successfully
3555 # remove state when we complete successfully
3556 if not opts.get('dry_run'):
3556 if not opts.get('dry_run'):
3557 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3557 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3558
3558
3559 return 0
3559 return 0
3560
3560
3561 @command('grep',
3561 @command('grep',
3562 [('0', 'print0', None, _('end fields with NUL')),
3562 [('0', 'print0', None, _('end fields with NUL')),
3563 ('', 'all', None, _('print all revisions that match')),
3563 ('', 'all', None, _('print all revisions that match')),
3564 ('a', 'text', None, _('treat all files as text')),
3564 ('a', 'text', None, _('treat all files as text')),
3565 ('f', 'follow', None,
3565 ('f', 'follow', None,
3566 _('follow changeset history,'
3566 _('follow changeset history,'
3567 ' or file history across copies and renames')),
3567 ' or file history across copies and renames')),
3568 ('i', 'ignore-case', None, _('ignore case when matching')),
3568 ('i', 'ignore-case', None, _('ignore case when matching')),
3569 ('l', 'files-with-matches', None,
3569 ('l', 'files-with-matches', None,
3570 _('print only filenames and revisions that match')),
3570 _('print only filenames and revisions that match')),
3571 ('n', 'line-number', None, _('print matching line numbers')),
3571 ('n', 'line-number', None, _('print matching line numbers')),
3572 ('r', 'rev', [],
3572 ('r', 'rev', [],
3573 _('only search files changed within revision range'), _('REV')),
3573 _('only search files changed within revision range'), _('REV')),
3574 ('u', 'user', None, _('list the author (long with -v)')),
3574 ('u', 'user', None, _('list the author (long with -v)')),
3575 ('d', 'date', None, _('list the date (short with -q)')),
3575 ('d', 'date', None, _('list the date (short with -q)')),
3576 ] + walkopts,
3576 ] + walkopts,
3577 _('[OPTION]... PATTERN [FILE]...'),
3577 _('[OPTION]... PATTERN [FILE]...'),
3578 inferrepo=True)
3578 inferrepo=True)
3579 def grep(ui, repo, pattern, *pats, **opts):
3579 def grep(ui, repo, pattern, *pats, **opts):
3580 """search for a pattern in specified files and revisions
3580 """search for a pattern in specified files and revisions
3581
3581
3582 Search revisions of files for a regular expression.
3582 Search revisions of files for a regular expression.
3583
3583
3584 This command behaves differently than Unix grep. It only accepts
3584 This command behaves differently than Unix grep. It only accepts
3585 Python/Perl regexps. It searches repository history, not the
3585 Python/Perl regexps. It searches repository history, not the
3586 working directory. It always prints the revision number in which a
3586 working directory. It always prints the revision number in which a
3587 match appears.
3587 match appears.
3588
3588
3589 By default, grep only prints output for the first revision of a
3589 By default, grep only prints output for the first revision of a
3590 file in which it finds a match. To get it to print every revision
3590 file in which it finds a match. To get it to print every revision
3591 that contains a change in match status ("-" for a match that
3591 that contains a change in match status ("-" for a match that
3592 becomes a non-match, or "+" for a non-match that becomes a match),
3592 becomes a non-match, or "+" for a non-match that becomes a match),
3593 use the --all flag.
3593 use the --all flag.
3594
3594
3595 Returns 0 if a match is found, 1 otherwise.
3595 Returns 0 if a match is found, 1 otherwise.
3596 """
3596 """
3597 reflags = re.M
3597 reflags = re.M
3598 if opts.get('ignore_case'):
3598 if opts.get('ignore_case'):
3599 reflags |= re.I
3599 reflags |= re.I
3600 try:
3600 try:
3601 regexp = util.re.compile(pattern, reflags)
3601 regexp = util.re.compile(pattern, reflags)
3602 except re.error, inst:
3602 except re.error, inst:
3603 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3603 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3604 return 1
3604 return 1
3605 sep, eol = ':', '\n'
3605 sep, eol = ':', '\n'
3606 if opts.get('print0'):
3606 if opts.get('print0'):
3607 sep = eol = '\0'
3607 sep = eol = '\0'
3608
3608
3609 getfile = util.lrucachefunc(repo.file)
3609 getfile = util.lrucachefunc(repo.file)
3610
3610
3611 def matchlines(body):
3611 def matchlines(body):
3612 begin = 0
3612 begin = 0
3613 linenum = 0
3613 linenum = 0
3614 while begin < len(body):
3614 while begin < len(body):
3615 match = regexp.search(body, begin)
3615 match = regexp.search(body, begin)
3616 if not match:
3616 if not match:
3617 break
3617 break
3618 mstart, mend = match.span()
3618 mstart, mend = match.span()
3619 linenum += body.count('\n', begin, mstart) + 1
3619 linenum += body.count('\n', begin, mstart) + 1
3620 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3620 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3621 begin = body.find('\n', mend) + 1 or len(body) + 1
3621 begin = body.find('\n', mend) + 1 or len(body) + 1
3622 lend = begin - 1
3622 lend = begin - 1
3623 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3623 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3624
3624
3625 class linestate(object):
3625 class linestate(object):
3626 def __init__(self, line, linenum, colstart, colend):
3626 def __init__(self, line, linenum, colstart, colend):
3627 self.line = line
3627 self.line = line
3628 self.linenum = linenum
3628 self.linenum = linenum
3629 self.colstart = colstart
3629 self.colstart = colstart
3630 self.colend = colend
3630 self.colend = colend
3631
3631
3632 def __hash__(self):
3632 def __hash__(self):
3633 return hash((self.linenum, self.line))
3633 return hash((self.linenum, self.line))
3634
3634
3635 def __eq__(self, other):
3635 def __eq__(self, other):
3636 return self.line == other.line
3636 return self.line == other.line
3637
3637
3638 def __iter__(self):
3638 def __iter__(self):
3639 yield (self.line[:self.colstart], '')
3639 yield (self.line[:self.colstart], '')
3640 yield (self.line[self.colstart:self.colend], 'grep.match')
3640 yield (self.line[self.colstart:self.colend], 'grep.match')
3641 rest = self.line[self.colend:]
3641 rest = self.line[self.colend:]
3642 while rest != '':
3642 while rest != '':
3643 match = regexp.search(rest)
3643 match = regexp.search(rest)
3644 if not match:
3644 if not match:
3645 yield (rest, '')
3645 yield (rest, '')
3646 break
3646 break
3647 mstart, mend = match.span()
3647 mstart, mend = match.span()
3648 yield (rest[:mstart], '')
3648 yield (rest[:mstart], '')
3649 yield (rest[mstart:mend], 'grep.match')
3649 yield (rest[mstart:mend], 'grep.match')
3650 rest = rest[mend:]
3650 rest = rest[mend:]
3651
3651
3652 matches = {}
3652 matches = {}
3653 copies = {}
3653 copies = {}
3654 def grepbody(fn, rev, body):
3654 def grepbody(fn, rev, body):
3655 matches[rev].setdefault(fn, [])
3655 matches[rev].setdefault(fn, [])
3656 m = matches[rev][fn]
3656 m = matches[rev][fn]
3657 for lnum, cstart, cend, line in matchlines(body):
3657 for lnum, cstart, cend, line in matchlines(body):
3658 s = linestate(line, lnum, cstart, cend)
3658 s = linestate(line, lnum, cstart, cend)
3659 m.append(s)
3659 m.append(s)
3660
3660
3661 def difflinestates(a, b):
3661 def difflinestates(a, b):
3662 sm = difflib.SequenceMatcher(None, a, b)
3662 sm = difflib.SequenceMatcher(None, a, b)
3663 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3663 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3664 if tag == 'insert':
3664 if tag == 'insert':
3665 for i in xrange(blo, bhi):
3665 for i in xrange(blo, bhi):
3666 yield ('+', b[i])
3666 yield ('+', b[i])
3667 elif tag == 'delete':
3667 elif tag == 'delete':
3668 for i in xrange(alo, ahi):
3668 for i in xrange(alo, ahi):
3669 yield ('-', a[i])
3669 yield ('-', a[i])
3670 elif tag == 'replace':
3670 elif tag == 'replace':
3671 for i in xrange(alo, ahi):
3671 for i in xrange(alo, ahi):
3672 yield ('-', a[i])
3672 yield ('-', a[i])
3673 for i in xrange(blo, bhi):
3673 for i in xrange(blo, bhi):
3674 yield ('+', b[i])
3674 yield ('+', b[i])
3675
3675
3676 def display(fn, ctx, pstates, states):
3676 def display(fn, ctx, pstates, states):
3677 rev = ctx.rev()
3677 rev = ctx.rev()
3678 datefunc = ui.quiet and util.shortdate or util.datestr
3678 datefunc = ui.quiet and util.shortdate or util.datestr
3679 found = False
3679 found = False
3680 @util.cachefunc
3680 @util.cachefunc
3681 def binary():
3681 def binary():
3682 flog = getfile(fn)
3682 flog = getfile(fn)
3683 return util.binary(flog.read(ctx.filenode(fn)))
3683 return util.binary(flog.read(ctx.filenode(fn)))
3684
3684
3685 if opts.get('all'):
3685 if opts.get('all'):
3686 iter = difflinestates(pstates, states)
3686 iter = difflinestates(pstates, states)
3687 else:
3687 else:
3688 iter = [('', l) for l in states]
3688 iter = [('', l) for l in states]
3689 for change, l in iter:
3689 for change, l in iter:
3690 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3690 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3691
3691
3692 if opts.get('line_number'):
3692 if opts.get('line_number'):
3693 cols.append((str(l.linenum), 'grep.linenumber'))
3693 cols.append((str(l.linenum), 'grep.linenumber'))
3694 if opts.get('all'):
3694 if opts.get('all'):
3695 cols.append((change, 'grep.change'))
3695 cols.append((change, 'grep.change'))
3696 if opts.get('user'):
3696 if opts.get('user'):
3697 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3697 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3698 if opts.get('date'):
3698 if opts.get('date'):
3699 cols.append((datefunc(ctx.date()), 'grep.date'))
3699 cols.append((datefunc(ctx.date()), 'grep.date'))
3700 for col, label in cols[:-1]:
3700 for col, label in cols[:-1]:
3701 ui.write(col, label=label)
3701 ui.write(col, label=label)
3702 ui.write(sep, label='grep.sep')
3702 ui.write(sep, label='grep.sep')
3703 ui.write(cols[-1][0], label=cols[-1][1])
3703 ui.write(cols[-1][0], label=cols[-1][1])
3704 if not opts.get('files_with_matches'):
3704 if not opts.get('files_with_matches'):
3705 ui.write(sep, label='grep.sep')
3705 ui.write(sep, label='grep.sep')
3706 if not opts.get('text') and binary():
3706 if not opts.get('text') and binary():
3707 ui.write(" Binary file matches")
3707 ui.write(" Binary file matches")
3708 else:
3708 else:
3709 for s, label in l:
3709 for s, label in l:
3710 ui.write(s, label=label)
3710 ui.write(s, label=label)
3711 ui.write(eol)
3711 ui.write(eol)
3712 found = True
3712 found = True
3713 if opts.get('files_with_matches'):
3713 if opts.get('files_with_matches'):
3714 break
3714 break
3715 return found
3715 return found
3716
3716
3717 skip = {}
3717 skip = {}
3718 revfiles = {}
3718 revfiles = {}
3719 matchfn = scmutil.match(repo[None], pats, opts)
3719 matchfn = scmutil.match(repo[None], pats, opts)
3720 found = False
3720 found = False
3721 follow = opts.get('follow')
3721 follow = opts.get('follow')
3722
3722
3723 def prep(ctx, fns):
3723 def prep(ctx, fns):
3724 rev = ctx.rev()
3724 rev = ctx.rev()
3725 pctx = ctx.p1()
3725 pctx = ctx.p1()
3726 parent = pctx.rev()
3726 parent = pctx.rev()
3727 matches.setdefault(rev, {})
3727 matches.setdefault(rev, {})
3728 matches.setdefault(parent, {})
3728 matches.setdefault(parent, {})
3729 files = revfiles.setdefault(rev, [])
3729 files = revfiles.setdefault(rev, [])
3730 for fn in fns:
3730 for fn in fns:
3731 flog = getfile(fn)
3731 flog = getfile(fn)
3732 try:
3732 try:
3733 fnode = ctx.filenode(fn)
3733 fnode = ctx.filenode(fn)
3734 except error.LookupError:
3734 except error.LookupError:
3735 continue
3735 continue
3736
3736
3737 copied = flog.renamed(fnode)
3737 copied = flog.renamed(fnode)
3738 copy = follow and copied and copied[0]
3738 copy = follow and copied and copied[0]
3739 if copy:
3739 if copy:
3740 copies.setdefault(rev, {})[fn] = copy
3740 copies.setdefault(rev, {})[fn] = copy
3741 if fn in skip:
3741 if fn in skip:
3742 if copy:
3742 if copy:
3743 skip[copy] = True
3743 skip[copy] = True
3744 continue
3744 continue
3745 files.append(fn)
3745 files.append(fn)
3746
3746
3747 if fn not in matches[rev]:
3747 if fn not in matches[rev]:
3748 grepbody(fn, rev, flog.read(fnode))
3748 grepbody(fn, rev, flog.read(fnode))
3749
3749
3750 pfn = copy or fn
3750 pfn = copy or fn
3751 if pfn not in matches[parent]:
3751 if pfn not in matches[parent]:
3752 try:
3752 try:
3753 fnode = pctx.filenode(pfn)
3753 fnode = pctx.filenode(pfn)
3754 grepbody(pfn, parent, flog.read(fnode))
3754 grepbody(pfn, parent, flog.read(fnode))
3755 except error.LookupError:
3755 except error.LookupError:
3756 pass
3756 pass
3757
3757
3758 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3758 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3759 rev = ctx.rev()
3759 rev = ctx.rev()
3760 parent = ctx.p1().rev()
3760 parent = ctx.p1().rev()
3761 for fn in sorted(revfiles.get(rev, [])):
3761 for fn in sorted(revfiles.get(rev, [])):
3762 states = matches[rev][fn]
3762 states = matches[rev][fn]
3763 copy = copies.get(rev, {}).get(fn)
3763 copy = copies.get(rev, {}).get(fn)
3764 if fn in skip:
3764 if fn in skip:
3765 if copy:
3765 if copy:
3766 skip[copy] = True
3766 skip[copy] = True
3767 continue
3767 continue
3768 pstates = matches.get(parent, {}).get(copy or fn, [])
3768 pstates = matches.get(parent, {}).get(copy or fn, [])
3769 if pstates or states:
3769 if pstates or states:
3770 r = display(fn, ctx, pstates, states)
3770 r = display(fn, ctx, pstates, states)
3771 found = found or r
3771 found = found or r
3772 if r and not opts.get('all'):
3772 if r and not opts.get('all'):
3773 skip[fn] = True
3773 skip[fn] = True
3774 if copy:
3774 if copy:
3775 skip[copy] = True
3775 skip[copy] = True
3776 del matches[rev]
3776 del matches[rev]
3777 del revfiles[rev]
3777 del revfiles[rev]
3778
3778
3779 return not found
3779 return not found
3780
3780
3781 @command('heads',
3781 @command('heads',
3782 [('r', 'rev', '',
3782 [('r', 'rev', '',
3783 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3783 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3784 ('t', 'topo', False, _('show topological heads only')),
3784 ('t', 'topo', False, _('show topological heads only')),
3785 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3785 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3786 ('c', 'closed', False, _('show normal and closed branch heads')),
3786 ('c', 'closed', False, _('show normal and closed branch heads')),
3787 ] + templateopts,
3787 ] + templateopts,
3788 _('[-ct] [-r STARTREV] [REV]...'))
3788 _('[-ct] [-r STARTREV] [REV]...'))
3789 def heads(ui, repo, *branchrevs, **opts):
3789 def heads(ui, repo, *branchrevs, **opts):
3790 """show branch heads
3790 """show branch heads
3791
3791
3792 With no arguments, show all open branch heads in the repository.
3792 With no arguments, show all open branch heads in the repository.
3793 Branch heads are changesets that have no descendants on the
3793 Branch heads are changesets that have no descendants on the
3794 same branch. They are where development generally takes place and
3794 same branch. They are where development generally takes place and
3795 are the usual targets for update and merge operations.
3795 are the usual targets for update and merge operations.
3796
3796
3797 If one or more REVs are given, only open branch heads on the
3797 If one or more REVs are given, only open branch heads on the
3798 branches associated with the specified changesets are shown. This
3798 branches associated with the specified changesets are shown. This
3799 means that you can use :hg:`heads .` to see the heads on the
3799 means that you can use :hg:`heads .` to see the heads on the
3800 currently checked-out branch.
3800 currently checked-out branch.
3801
3801
3802 If -c/--closed is specified, also show branch heads marked closed
3802 If -c/--closed is specified, also show branch heads marked closed
3803 (see :hg:`commit --close-branch`).
3803 (see :hg:`commit --close-branch`).
3804
3804
3805 If STARTREV is specified, only those heads that are descendants of
3805 If STARTREV is specified, only those heads that are descendants of
3806 STARTREV will be displayed.
3806 STARTREV will be displayed.
3807
3807
3808 If -t/--topo is specified, named branch mechanics will be ignored and only
3808 If -t/--topo is specified, named branch mechanics will be ignored and only
3809 topological heads (changesets with no children) will be shown.
3809 topological heads (changesets with no children) will be shown.
3810
3810
3811 Returns 0 if matching heads are found, 1 if not.
3811 Returns 0 if matching heads are found, 1 if not.
3812 """
3812 """
3813
3813
3814 start = None
3814 start = None
3815 if 'rev' in opts:
3815 if 'rev' in opts:
3816 start = scmutil.revsingle(repo, opts['rev'], None).node()
3816 start = scmutil.revsingle(repo, opts['rev'], None).node()
3817
3817
3818 if opts.get('topo'):
3818 if opts.get('topo'):
3819 heads = [repo[h] for h in repo.heads(start)]
3819 heads = [repo[h] for h in repo.heads(start)]
3820 else:
3820 else:
3821 heads = []
3821 heads = []
3822 for branch in repo.branchmap():
3822 for branch in repo.branchmap():
3823 heads += repo.branchheads(branch, start, opts.get('closed'))
3823 heads += repo.branchheads(branch, start, opts.get('closed'))
3824 heads = [repo[h] for h in heads]
3824 heads = [repo[h] for h in heads]
3825
3825
3826 if branchrevs:
3826 if branchrevs:
3827 branches = set(repo[br].branch() for br in branchrevs)
3827 branches = set(repo[br].branch() for br in branchrevs)
3828 heads = [h for h in heads if h.branch() in branches]
3828 heads = [h for h in heads if h.branch() in branches]
3829
3829
3830 if opts.get('active') and branchrevs:
3830 if opts.get('active') and branchrevs:
3831 dagheads = repo.heads(start)
3831 dagheads = repo.heads(start)
3832 heads = [h for h in heads if h.node() in dagheads]
3832 heads = [h for h in heads if h.node() in dagheads]
3833
3833
3834 if branchrevs:
3834 if branchrevs:
3835 haveheads = set(h.branch() for h in heads)
3835 haveheads = set(h.branch() for h in heads)
3836 if branches - haveheads:
3836 if branches - haveheads:
3837 headless = ', '.join(b for b in branches - haveheads)
3837 headless = ', '.join(b for b in branches - haveheads)
3838 msg = _('no open branch heads found on branches %s')
3838 msg = _('no open branch heads found on branches %s')
3839 if opts.get('rev'):
3839 if opts.get('rev'):
3840 msg += _(' (started at %s)') % opts['rev']
3840 msg += _(' (started at %s)') % opts['rev']
3841 ui.warn((msg + '\n') % headless)
3841 ui.warn((msg + '\n') % headless)
3842
3842
3843 if not heads:
3843 if not heads:
3844 return 1
3844 return 1
3845
3845
3846 heads = sorted(heads, key=lambda x: -x.rev())
3846 heads = sorted(heads, key=lambda x: -x.rev())
3847 displayer = cmdutil.show_changeset(ui, repo, opts)
3847 displayer = cmdutil.show_changeset(ui, repo, opts)
3848 for ctx in heads:
3848 for ctx in heads:
3849 displayer.show(ctx)
3849 displayer.show(ctx)
3850 displayer.close()
3850 displayer.close()
3851
3851
3852 @command('help',
3852 @command('help',
3853 [('e', 'extension', None, _('show only help for extensions')),
3853 [('e', 'extension', None, _('show only help for extensions')),
3854 ('c', 'command', None, _('show only help for commands')),
3854 ('c', 'command', None, _('show only help for commands')),
3855 ('k', 'keyword', '', _('show topics matching keyword')),
3855 ('k', 'keyword', '', _('show topics matching keyword')),
3856 ],
3856 ],
3857 _('[-ec] [TOPIC]'),
3857 _('[-ec] [TOPIC]'),
3858 norepo=True)
3858 norepo=True)
3859 def help_(ui, name=None, **opts):
3859 def help_(ui, name=None, **opts):
3860 """show help for a given topic or a help overview
3860 """show help for a given topic or a help overview
3861
3861
3862 With no arguments, print a list of commands with short help messages.
3862 With no arguments, print a list of commands with short help messages.
3863
3863
3864 Given a topic, extension, or command name, print help for that
3864 Given a topic, extension, or command name, print help for that
3865 topic.
3865 topic.
3866
3866
3867 Returns 0 if successful.
3867 Returns 0 if successful.
3868 """
3868 """
3869
3869
3870 textwidth = min(ui.termwidth(), 80) - 2
3870 textwidth = min(ui.termwidth(), 80) - 2
3871
3871
3872 keep = []
3872 keep = []
3873 if ui.verbose:
3873 if ui.verbose:
3874 keep.append('verbose')
3874 keep.append('verbose')
3875 if sys.platform.startswith('win'):
3875 if sys.platform.startswith('win'):
3876 keep.append('windows')
3876 keep.append('windows')
3877 elif sys.platform == 'OpenVMS':
3877 elif sys.platform == 'OpenVMS':
3878 keep.append('vms')
3878 keep.append('vms')
3879 elif sys.platform == 'plan9':
3879 elif sys.platform == 'plan9':
3880 keep.append('plan9')
3880 keep.append('plan9')
3881 else:
3881 else:
3882 keep.append('unix')
3882 keep.append('unix')
3883 keep.append(sys.platform.lower())
3883 keep.append(sys.platform.lower())
3884
3884
3885 section = None
3885 section = None
3886 if name and '.' in name:
3886 if name and '.' in name:
3887 name, section = name.split('.', 1)
3887 name, section = name.split('.', 1)
3888
3888
3889 text = help.help_(ui, name, **opts)
3889 text = help.help_(ui, name, **opts)
3890
3890
3891 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3891 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3892 section=section)
3892 section=section)
3893 if section and not formatted:
3893 if section and not formatted:
3894 raise util.Abort(_("help section not found"))
3894 raise util.Abort(_("help section not found"))
3895
3895
3896 if 'verbose' in pruned:
3896 if 'verbose' in pruned:
3897 keep.append('omitted')
3897 keep.append('omitted')
3898 else:
3898 else:
3899 keep.append('notomitted')
3899 keep.append('notomitted')
3900 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3900 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3901 section=section)
3901 section=section)
3902 ui.write(formatted)
3902 ui.write(formatted)
3903
3903
3904
3904
3905 @command('identify|id',
3905 @command('identify|id',
3906 [('r', 'rev', '',
3906 [('r', 'rev', '',
3907 _('identify the specified revision'), _('REV')),
3907 _('identify the specified revision'), _('REV')),
3908 ('n', 'num', None, _('show local revision number')),
3908 ('n', 'num', None, _('show local revision number')),
3909 ('i', 'id', None, _('show global revision id')),
3909 ('i', 'id', None, _('show global revision id')),
3910 ('b', 'branch', None, _('show branch')),
3910 ('b', 'branch', None, _('show branch')),
3911 ('t', 'tags', None, _('show tags')),
3911 ('t', 'tags', None, _('show tags')),
3912 ('B', 'bookmarks', None, _('show bookmarks')),
3912 ('B', 'bookmarks', None, _('show bookmarks')),
3913 ] + remoteopts,
3913 ] + remoteopts,
3914 _('[-nibtB] [-r REV] [SOURCE]'),
3914 _('[-nibtB] [-r REV] [SOURCE]'),
3915 optionalrepo=True)
3915 optionalrepo=True)
3916 def identify(ui, repo, source=None, rev=None,
3916 def identify(ui, repo, source=None, rev=None,
3917 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3917 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3918 """identify the working copy or specified revision
3918 """identify the working copy or specified revision
3919
3919
3920 Print a summary identifying the repository state at REV using one or
3920 Print a summary identifying the repository state at REV using one or
3921 two parent hash identifiers, followed by a "+" if the working
3921 two parent hash identifiers, followed by a "+" if the working
3922 directory has uncommitted changes, the branch name (if not default),
3922 directory has uncommitted changes, the branch name (if not default),
3923 a list of tags, and a list of bookmarks.
3923 a list of tags, and a list of bookmarks.
3924
3924
3925 When REV is not given, print a summary of the current state of the
3925 When REV is not given, print a summary of the current state of the
3926 repository.
3926 repository.
3927
3927
3928 Specifying a path to a repository root or Mercurial bundle will
3928 Specifying a path to a repository root or Mercurial bundle will
3929 cause lookup to operate on that repository/bundle.
3929 cause lookup to operate on that repository/bundle.
3930
3930
3931 .. container:: verbose
3931 .. container:: verbose
3932
3932
3933 Examples:
3933 Examples:
3934
3934
3935 - generate a build identifier for the working directory::
3935 - generate a build identifier for the working directory::
3936
3936
3937 hg id --id > build-id.dat
3937 hg id --id > build-id.dat
3938
3938
3939 - find the revision corresponding to a tag::
3939 - find the revision corresponding to a tag::
3940
3940
3941 hg id -n -r 1.3
3941 hg id -n -r 1.3
3942
3942
3943 - check the most recent revision of a remote repository::
3943 - check the most recent revision of a remote repository::
3944
3944
3945 hg id -r tip http://selenic.com/hg/
3945 hg id -r tip http://selenic.com/hg/
3946
3946
3947 Returns 0 if successful.
3947 Returns 0 if successful.
3948 """
3948 """
3949
3949
3950 if not repo and not source:
3950 if not repo and not source:
3951 raise util.Abort(_("there is no Mercurial repository here "
3951 raise util.Abort(_("there is no Mercurial repository here "
3952 "(.hg not found)"))
3952 "(.hg not found)"))
3953
3953
3954 hexfunc = ui.debugflag and hex or short
3954 hexfunc = ui.debugflag and hex or short
3955 default = not (num or id or branch or tags or bookmarks)
3955 default = not (num or id or branch or tags or bookmarks)
3956 output = []
3956 output = []
3957 revs = []
3957 revs = []
3958
3958
3959 if source:
3959 if source:
3960 source, branches = hg.parseurl(ui.expandpath(source))
3960 source, branches = hg.parseurl(ui.expandpath(source))
3961 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3961 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3962 repo = peer.local()
3962 repo = peer.local()
3963 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3963 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3964
3964
3965 if not repo:
3965 if not repo:
3966 if num or branch or tags:
3966 if num or branch or tags:
3967 raise util.Abort(
3967 raise util.Abort(
3968 _("can't query remote revision number, branch, or tags"))
3968 _("can't query remote revision number, branch, or tags"))
3969 if not rev and revs:
3969 if not rev and revs:
3970 rev = revs[0]
3970 rev = revs[0]
3971 if not rev:
3971 if not rev:
3972 rev = "tip"
3972 rev = "tip"
3973
3973
3974 remoterev = peer.lookup(rev)
3974 remoterev = peer.lookup(rev)
3975 if default or id:
3975 if default or id:
3976 output = [hexfunc(remoterev)]
3976 output = [hexfunc(remoterev)]
3977
3977
3978 def getbms():
3978 def getbms():
3979 bms = []
3979 bms = []
3980
3980
3981 if 'bookmarks' in peer.listkeys('namespaces'):
3981 if 'bookmarks' in peer.listkeys('namespaces'):
3982 hexremoterev = hex(remoterev)
3982 hexremoterev = hex(remoterev)
3983 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3983 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3984 if bmr == hexremoterev]
3984 if bmr == hexremoterev]
3985
3985
3986 return sorted(bms)
3986 return sorted(bms)
3987
3987
3988 if bookmarks:
3988 if bookmarks:
3989 output.extend(getbms())
3989 output.extend(getbms())
3990 elif default and not ui.quiet:
3990 elif default and not ui.quiet:
3991 # multiple bookmarks for a single parent separated by '/'
3991 # multiple bookmarks for a single parent separated by '/'
3992 bm = '/'.join(getbms())
3992 bm = '/'.join(getbms())
3993 if bm:
3993 if bm:
3994 output.append(bm)
3994 output.append(bm)
3995 else:
3995 else:
3996 if not rev:
3996 if not rev:
3997 ctx = repo[None]
3997 ctx = repo[None]
3998 parents = ctx.parents()
3998 parents = ctx.parents()
3999 changed = ""
3999 changed = ""
4000 if default or id or num:
4000 if default or id or num:
4001 if (util.any(repo.status())
4001 if (util.any(repo.status())
4002 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4002 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4003 changed = '+'
4003 changed = '+'
4004 if default or id:
4004 if default or id:
4005 output = ["%s%s" %
4005 output = ["%s%s" %
4006 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4006 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4007 if num:
4007 if num:
4008 output.append("%s%s" %
4008 output.append("%s%s" %
4009 ('+'.join([str(p.rev()) for p in parents]), changed))
4009 ('+'.join([str(p.rev()) for p in parents]), changed))
4010 else:
4010 else:
4011 ctx = scmutil.revsingle(repo, rev)
4011 ctx = scmutil.revsingle(repo, rev)
4012 if default or id:
4012 if default or id:
4013 output = [hexfunc(ctx.node())]
4013 output = [hexfunc(ctx.node())]
4014 if num:
4014 if num:
4015 output.append(str(ctx.rev()))
4015 output.append(str(ctx.rev()))
4016
4016
4017 if default and not ui.quiet:
4017 if default and not ui.quiet:
4018 b = ctx.branch()
4018 b = ctx.branch()
4019 if b != 'default':
4019 if b != 'default':
4020 output.append("(%s)" % b)
4020 output.append("(%s)" % b)
4021
4021
4022 # multiple tags for a single parent separated by '/'
4022 # multiple tags for a single parent separated by '/'
4023 t = '/'.join(ctx.tags())
4023 t = '/'.join(ctx.tags())
4024 if t:
4024 if t:
4025 output.append(t)
4025 output.append(t)
4026
4026
4027 # multiple bookmarks for a single parent separated by '/'
4027 # multiple bookmarks for a single parent separated by '/'
4028 bm = '/'.join(ctx.bookmarks())
4028 bm = '/'.join(ctx.bookmarks())
4029 if bm:
4029 if bm:
4030 output.append(bm)
4030 output.append(bm)
4031 else:
4031 else:
4032 if branch:
4032 if branch:
4033 output.append(ctx.branch())
4033 output.append(ctx.branch())
4034
4034
4035 if tags:
4035 if tags:
4036 output.extend(ctx.tags())
4036 output.extend(ctx.tags())
4037
4037
4038 if bookmarks:
4038 if bookmarks:
4039 output.extend(ctx.bookmarks())
4039 output.extend(ctx.bookmarks())
4040
4040
4041 ui.write("%s\n" % ' '.join(output))
4041 ui.write("%s\n" % ' '.join(output))
4042
4042
4043 @command('import|patch',
4043 @command('import|patch',
4044 [('p', 'strip', 1,
4044 [('p', 'strip', 1,
4045 _('directory strip option for patch. This has the same '
4045 _('directory strip option for patch. This has the same '
4046 'meaning as the corresponding patch option'), _('NUM')),
4046 'meaning as the corresponding patch option'), _('NUM')),
4047 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4047 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4048 ('e', 'edit', False, _('invoke editor on commit messages')),
4048 ('e', 'edit', False, _('invoke editor on commit messages')),
4049 ('f', 'force', None,
4049 ('f', 'force', None,
4050 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4050 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4051 ('', 'no-commit', None,
4051 ('', 'no-commit', None,
4052 _("don't commit, just update the working directory")),
4052 _("don't commit, just update the working directory")),
4053 ('', 'bypass', None,
4053 ('', 'bypass', None,
4054 _("apply patch without touching the working directory")),
4054 _("apply patch without touching the working directory")),
4055 ('', 'partial', None,
4055 ('', 'partial', None,
4056 _('commit even if some hunks fail')),
4056 _('commit even if some hunks fail')),
4057 ('', 'exact', None,
4057 ('', 'exact', None,
4058 _('apply patch to the nodes from which it was generated')),
4058 _('apply patch to the nodes from which it was generated')),
4059 ('', 'import-branch', None,
4059 ('', 'import-branch', None,
4060 _('use any branch information in patch (implied by --exact)'))] +
4060 _('use any branch information in patch (implied by --exact)'))] +
4061 commitopts + commitopts2 + similarityopts,
4061 commitopts + commitopts2 + similarityopts,
4062 _('[OPTION]... PATCH...'))
4062 _('[OPTION]... PATCH...'))
4063 def import_(ui, repo, patch1=None, *patches, **opts):
4063 def import_(ui, repo, patch1=None, *patches, **opts):
4064 """import an ordered set of patches
4064 """import an ordered set of patches
4065
4065
4066 Import a list of patches and commit them individually (unless
4066 Import a list of patches and commit them individually (unless
4067 --no-commit is specified).
4067 --no-commit is specified).
4068
4068
4069 Because import first applies changes to the working directory,
4069 Because import first applies changes to the working directory,
4070 import will abort if there are outstanding changes.
4070 import will abort if there are outstanding changes.
4071
4071
4072 You can import a patch straight from a mail message. Even patches
4072 You can import a patch straight from a mail message. Even patches
4073 as attachments work (to use the body part, it must have type
4073 as attachments work (to use the body part, it must have type
4074 text/plain or text/x-patch). From and Subject headers of email
4074 text/plain or text/x-patch). From and Subject headers of email
4075 message are used as default committer and commit message. All
4075 message are used as default committer and commit message. All
4076 text/plain body parts before first diff are added to commit
4076 text/plain body parts before first diff are added to commit
4077 message.
4077 message.
4078
4078
4079 If the imported patch was generated by :hg:`export`, user and
4079 If the imported patch was generated by :hg:`export`, user and
4080 description from patch override values from message headers and
4080 description from patch override values from message headers and
4081 body. Values given on command line with -m/--message and -u/--user
4081 body. Values given on command line with -m/--message and -u/--user
4082 override these.
4082 override these.
4083
4083
4084 If --exact is specified, import will set the working directory to
4084 If --exact is specified, import will set the working directory to
4085 the parent of each patch before applying it, and will abort if the
4085 the parent of each patch before applying it, and will abort if the
4086 resulting changeset has a different ID than the one recorded in
4086 resulting changeset has a different ID than the one recorded in
4087 the patch. This may happen due to character set problems or other
4087 the patch. This may happen due to character set problems or other
4088 deficiencies in the text patch format.
4088 deficiencies in the text patch format.
4089
4089
4090 Use --bypass to apply and commit patches directly to the
4090 Use --bypass to apply and commit patches directly to the
4091 repository, not touching the working directory. Without --exact,
4091 repository, not touching the working directory. Without --exact,
4092 patches will be applied on top of the working directory parent
4092 patches will be applied on top of the working directory parent
4093 revision.
4093 revision.
4094
4094
4095 With -s/--similarity, hg will attempt to discover renames and
4095 With -s/--similarity, hg will attempt to discover renames and
4096 copies in the patch in the same way as :hg:`addremove`.
4096 copies in the patch in the same way as :hg:`addremove`.
4097
4097
4098 Use --partial to ensure a changeset will be created from the patch
4098 Use --partial to ensure a changeset will be created from the patch
4099 even if some hunks fail to apply. Hunks that fail to apply will be
4099 even if some hunks fail to apply. Hunks that fail to apply will be
4100 written to a <target-file>.rej file. Conflicts can then be resolved
4100 written to a <target-file>.rej file. Conflicts can then be resolved
4101 by hand before :hg:`commit --amend` is run to update the created
4101 by hand before :hg:`commit --amend` is run to update the created
4102 changeset. This flag exists to let people import patches that
4102 changeset. This flag exists to let people import patches that
4103 partially apply without losing the associated metadata (author,
4103 partially apply without losing the associated metadata (author,
4104 date, description, ...). Note that when none of the hunk applies
4104 date, description, ...). Note that when none of the hunk applies
4105 cleanly, :hg:`import --partial` will create an empty changeset,
4105 cleanly, :hg:`import --partial` will create an empty changeset,
4106 importing only the patch metadata.
4106 importing only the patch metadata.
4107
4107
4108 To read a patch from standard input, use "-" as the patch name. If
4108 To read a patch from standard input, use "-" as the patch name. If
4109 a URL is specified, the patch will be downloaded from it.
4109 a URL is specified, the patch will be downloaded from it.
4110 See :hg:`help dates` for a list of formats valid for -d/--date.
4110 See :hg:`help dates` for a list of formats valid for -d/--date.
4111
4111
4112 .. container:: verbose
4112 .. container:: verbose
4113
4113
4114 Examples:
4114 Examples:
4115
4115
4116 - import a traditional patch from a website and detect renames::
4116 - import a traditional patch from a website and detect renames::
4117
4117
4118 hg import -s 80 http://example.com/bugfix.patch
4118 hg import -s 80 http://example.com/bugfix.patch
4119
4119
4120 - import a changeset from an hgweb server::
4120 - import a changeset from an hgweb server::
4121
4121
4122 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4122 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4123
4123
4124 - import all the patches in an Unix-style mbox::
4124 - import all the patches in an Unix-style mbox::
4125
4125
4126 hg import incoming-patches.mbox
4126 hg import incoming-patches.mbox
4127
4127
4128 - attempt to exactly restore an exported changeset (not always
4128 - attempt to exactly restore an exported changeset (not always
4129 possible)::
4129 possible)::
4130
4130
4131 hg import --exact proposed-fix.patch
4131 hg import --exact proposed-fix.patch
4132
4132
4133 Returns 0 on success, 1 on partial success (see --partial).
4133 Returns 0 on success, 1 on partial success (see --partial).
4134 """
4134 """
4135
4135
4136 if not patch1:
4136 if not patch1:
4137 raise util.Abort(_('need at least one patch to import'))
4137 raise util.Abort(_('need at least one patch to import'))
4138
4138
4139 patches = (patch1,) + patches
4139 patches = (patch1,) + patches
4140
4140
4141 date = opts.get('date')
4141 date = opts.get('date')
4142 if date:
4142 if date:
4143 opts['date'] = util.parsedate(date)
4143 opts['date'] = util.parsedate(date)
4144
4144
4145 update = not opts.get('bypass')
4145 update = not opts.get('bypass')
4146 if not update and opts.get('no_commit'):
4146 if not update and opts.get('no_commit'):
4147 raise util.Abort(_('cannot use --no-commit with --bypass'))
4147 raise util.Abort(_('cannot use --no-commit with --bypass'))
4148 try:
4148 try:
4149 sim = float(opts.get('similarity') or 0)
4149 sim = float(opts.get('similarity') or 0)
4150 except ValueError:
4150 except ValueError:
4151 raise util.Abort(_('similarity must be a number'))
4151 raise util.Abort(_('similarity must be a number'))
4152 if sim < 0 or sim > 100:
4152 if sim < 0 or sim > 100:
4153 raise util.Abort(_('similarity must be between 0 and 100'))
4153 raise util.Abort(_('similarity must be between 0 and 100'))
4154 if sim and not update:
4154 if sim and not update:
4155 raise util.Abort(_('cannot use --similarity with --bypass'))
4155 raise util.Abort(_('cannot use --similarity with --bypass'))
4156 if opts.get('exact') and opts.get('edit'):
4156 if opts.get('exact') and opts.get('edit'):
4157 raise util.Abort(_('cannot use --exact with --edit'))
4157 raise util.Abort(_('cannot use --exact with --edit'))
4158
4158
4159 if update:
4159 if update:
4160 cmdutil.checkunfinished(repo)
4160 cmdutil.checkunfinished(repo)
4161 if (opts.get('exact') or not opts.get('force')) and update:
4161 if (opts.get('exact') or not opts.get('force')) and update:
4162 cmdutil.bailifchanged(repo)
4162 cmdutil.bailifchanged(repo)
4163
4163
4164 base = opts["base"]
4164 base = opts["base"]
4165 wlock = lock = tr = None
4165 wlock = lock = tr = None
4166 msgs = []
4166 msgs = []
4167 ret = 0
4167 ret = 0
4168
4168
4169
4169
4170 try:
4170 try:
4171 try:
4171 try:
4172 wlock = repo.wlock()
4172 wlock = repo.wlock()
4173 repo.dirstate.beginparentchange()
4173 repo.dirstate.beginparentchange()
4174 if not opts.get('no_commit'):
4174 if not opts.get('no_commit'):
4175 lock = repo.lock()
4175 lock = repo.lock()
4176 tr = repo.transaction('import')
4176 tr = repo.transaction('import')
4177 parents = repo.parents()
4177 parents = repo.parents()
4178 for patchurl in patches:
4178 for patchurl in patches:
4179 if patchurl == '-':
4179 if patchurl == '-':
4180 ui.status(_('applying patch from stdin\n'))
4180 ui.status(_('applying patch from stdin\n'))
4181 patchfile = ui.fin
4181 patchfile = ui.fin
4182 patchurl = 'stdin' # for error message
4182 patchurl = 'stdin' # for error message
4183 else:
4183 else:
4184 patchurl = os.path.join(base, patchurl)
4184 patchurl = os.path.join(base, patchurl)
4185 ui.status(_('applying %s\n') % patchurl)
4185 ui.status(_('applying %s\n') % patchurl)
4186 patchfile = hg.openpath(ui, patchurl)
4186 patchfile = hg.openpath(ui, patchurl)
4187
4187
4188 haspatch = False
4188 haspatch = False
4189 for hunk in patch.split(patchfile):
4189 for hunk in patch.split(patchfile):
4190 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4190 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4191 parents, opts,
4191 parents, opts,
4192 msgs, hg.clean)
4192 msgs, hg.clean)
4193 if msg:
4193 if msg:
4194 haspatch = True
4194 haspatch = True
4195 ui.note(msg + '\n')
4195 ui.note(msg + '\n')
4196 if update or opts.get('exact'):
4196 if update or opts.get('exact'):
4197 parents = repo.parents()
4197 parents = repo.parents()
4198 else:
4198 else:
4199 parents = [repo[node]]
4199 parents = [repo[node]]
4200 if rej:
4200 if rej:
4201 ui.write_err(_("patch applied partially\n"))
4201 ui.write_err(_("patch applied partially\n"))
4202 ui.write_err(_("(fix the .rej files and run "
4202 ui.write_err(_("(fix the .rej files and run "
4203 "`hg commit --amend`)\n"))
4203 "`hg commit --amend`)\n"))
4204 ret = 1
4204 ret = 1
4205 break
4205 break
4206
4206
4207 if not haspatch:
4207 if not haspatch:
4208 raise util.Abort(_('%s: no diffs found') % patchurl)
4208 raise util.Abort(_('%s: no diffs found') % patchurl)
4209
4209
4210 if tr:
4210 if tr:
4211 tr.close()
4211 tr.close()
4212 if msgs:
4212 if msgs:
4213 repo.savecommitmessage('\n* * *\n'.join(msgs))
4213 repo.savecommitmessage('\n* * *\n'.join(msgs))
4214 repo.dirstate.endparentchange()
4214 repo.dirstate.endparentchange()
4215 return ret
4215 return ret
4216 except: # re-raises
4216 except: # re-raises
4217 # wlock.release() indirectly calls dirstate.write(): since
4217 # wlock.release() indirectly calls dirstate.write(): since
4218 # we're crashing, we do not want to change the working dir
4218 # we're crashing, we do not want to change the working dir
4219 # parent after all, so make sure it writes nothing
4219 # parent after all, so make sure it writes nothing
4220 repo.dirstate.invalidate()
4220 repo.dirstate.invalidate()
4221 raise
4221 raise
4222 finally:
4222 finally:
4223 if tr:
4223 if tr:
4224 tr.release()
4224 tr.release()
4225 release(lock, wlock)
4225 release(lock, wlock)
4226
4226
4227 @command('incoming|in',
4227 @command('incoming|in',
4228 [('f', 'force', None,
4228 [('f', 'force', None,
4229 _('run even if remote repository is unrelated')),
4229 _('run even if remote repository is unrelated')),
4230 ('n', 'newest-first', None, _('show newest record first')),
4230 ('n', 'newest-first', None, _('show newest record first')),
4231 ('', 'bundle', '',
4231 ('', 'bundle', '',
4232 _('file to store the bundles into'), _('FILE')),
4232 _('file to store the bundles into'), _('FILE')),
4233 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4233 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4234 ('B', 'bookmarks', False, _("compare bookmarks")),
4234 ('B', 'bookmarks', False, _("compare bookmarks")),
4235 ('b', 'branch', [],
4235 ('b', 'branch', [],
4236 _('a specific branch you would like to pull'), _('BRANCH')),
4236 _('a specific branch you would like to pull'), _('BRANCH')),
4237 ] + logopts + remoteopts + subrepoopts,
4237 ] + logopts + remoteopts + subrepoopts,
4238 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4238 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4239 def incoming(ui, repo, source="default", **opts):
4239 def incoming(ui, repo, source="default", **opts):
4240 """show new changesets found in source
4240 """show new changesets found in source
4241
4241
4242 Show new changesets found in the specified path/URL or the default
4242 Show new changesets found in the specified path/URL or the default
4243 pull location. These are the changesets that would have been pulled
4243 pull location. These are the changesets that would have been pulled
4244 if a pull at the time you issued this command.
4244 if a pull at the time you issued this command.
4245
4245
4246 For remote repository, using --bundle avoids downloading the
4246 For remote repository, using --bundle avoids downloading the
4247 changesets twice if the incoming is followed by a pull.
4247 changesets twice if the incoming is followed by a pull.
4248
4248
4249 See pull for valid source format details.
4249 See pull for valid source format details.
4250
4250
4251 .. container:: verbose
4251 .. container:: verbose
4252
4252
4253 Examples:
4253 Examples:
4254
4254
4255 - show incoming changes with patches and full description::
4255 - show incoming changes with patches and full description::
4256
4256
4257 hg incoming -vp
4257 hg incoming -vp
4258
4258
4259 - show incoming changes excluding merges, store a bundle::
4259 - show incoming changes excluding merges, store a bundle::
4260
4260
4261 hg in -vpM --bundle incoming.hg
4261 hg in -vpM --bundle incoming.hg
4262 hg pull incoming.hg
4262 hg pull incoming.hg
4263
4263
4264 - briefly list changes inside a bundle::
4264 - briefly list changes inside a bundle::
4265
4265
4266 hg in changes.hg -T "{desc|firstline}\\n"
4266 hg in changes.hg -T "{desc|firstline}\\n"
4267
4267
4268 Returns 0 if there are incoming changes, 1 otherwise.
4268 Returns 0 if there are incoming changes, 1 otherwise.
4269 """
4269 """
4270 if opts.get('graph'):
4270 if opts.get('graph'):
4271 cmdutil.checkunsupportedgraphflags([], opts)
4271 cmdutil.checkunsupportedgraphflags([], opts)
4272 def display(other, chlist, displayer):
4272 def display(other, chlist, displayer):
4273 revdag = cmdutil.graphrevs(other, chlist, opts)
4273 revdag = cmdutil.graphrevs(other, chlist, opts)
4274 showparents = [ctx.node() for ctx in repo[None].parents()]
4274 showparents = [ctx.node() for ctx in repo[None].parents()]
4275 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4275 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4276 graphmod.asciiedges)
4276 graphmod.asciiedges)
4277
4277
4278 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4278 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4279 return 0
4279 return 0
4280
4280
4281 if opts.get('bundle') and opts.get('subrepos'):
4281 if opts.get('bundle') and opts.get('subrepos'):
4282 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4282 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4283
4283
4284 if opts.get('bookmarks'):
4284 if opts.get('bookmarks'):
4285 source, branches = hg.parseurl(ui.expandpath(source),
4285 source, branches = hg.parseurl(ui.expandpath(source),
4286 opts.get('branch'))
4286 opts.get('branch'))
4287 other = hg.peer(repo, opts, source)
4287 other = hg.peer(repo, opts, source)
4288 if 'bookmarks' not in other.listkeys('namespaces'):
4288 if 'bookmarks' not in other.listkeys('namespaces'):
4289 ui.warn(_("remote doesn't support bookmarks\n"))
4289 ui.warn(_("remote doesn't support bookmarks\n"))
4290 return 0
4290 return 0
4291 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4291 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4292 return bookmarks.diff(ui, repo, other)
4292 return bookmarks.diff(ui, repo, other)
4293
4293
4294 repo._subtoppath = ui.expandpath(source)
4294 repo._subtoppath = ui.expandpath(source)
4295 try:
4295 try:
4296 return hg.incoming(ui, repo, source, opts)
4296 return hg.incoming(ui, repo, source, opts)
4297 finally:
4297 finally:
4298 del repo._subtoppath
4298 del repo._subtoppath
4299
4299
4300
4300
4301 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4301 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4302 norepo=True)
4302 norepo=True)
4303 def init(ui, dest=".", **opts):
4303 def init(ui, dest=".", **opts):
4304 """create a new repository in the given directory
4304 """create a new repository in the given directory
4305
4305
4306 Initialize a new repository in the given directory. If the given
4306 Initialize a new repository in the given directory. If the given
4307 directory does not exist, it will be created.
4307 directory does not exist, it will be created.
4308
4308
4309 If no directory is given, the current directory is used.
4309 If no directory is given, the current directory is used.
4310
4310
4311 It is possible to specify an ``ssh://`` URL as the destination.
4311 It is possible to specify an ``ssh://`` URL as the destination.
4312 See :hg:`help urls` for more information.
4312 See :hg:`help urls` for more information.
4313
4313
4314 Returns 0 on success.
4314 Returns 0 on success.
4315 """
4315 """
4316 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4316 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4317
4317
4318 @command('locate',
4318 @command('locate',
4319 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4319 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4320 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4320 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4321 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4321 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4322 ] + walkopts,
4322 ] + walkopts,
4323 _('[OPTION]... [PATTERN]...'))
4323 _('[OPTION]... [PATTERN]...'))
4324 def locate(ui, repo, *pats, **opts):
4324 def locate(ui, repo, *pats, **opts):
4325 """locate files matching specific patterns (DEPRECATED)
4325 """locate files matching specific patterns (DEPRECATED)
4326
4326
4327 Print files under Mercurial control in the working directory whose
4327 Print files under Mercurial control in the working directory whose
4328 names match the given patterns.
4328 names match the given patterns.
4329
4329
4330 By default, this command searches all directories in the working
4330 By default, this command searches all directories in the working
4331 directory. To search just the current directory and its
4331 directory. To search just the current directory and its
4332 subdirectories, use "--include .".
4332 subdirectories, use "--include .".
4333
4333
4334 If no patterns are given to match, this command prints the names
4334 If no patterns are given to match, this command prints the names
4335 of all files under Mercurial control in the working directory.
4335 of all files under Mercurial control in the working directory.
4336
4336
4337 If you want to feed the output of this command into the "xargs"
4337 If you want to feed the output of this command into the "xargs"
4338 command, use the -0 option to both this command and "xargs". This
4338 command, use the -0 option to both this command and "xargs". This
4339 will avoid the problem of "xargs" treating single filenames that
4339 will avoid the problem of "xargs" treating single filenames that
4340 contain whitespace as multiple filenames.
4340 contain whitespace as multiple filenames.
4341
4341
4342 See :hg:`help files` for a more versatile command.
4342 See :hg:`help files` for a more versatile command.
4343
4343
4344 Returns 0 if a match is found, 1 otherwise.
4344 Returns 0 if a match is found, 1 otherwise.
4345 """
4345 """
4346 end = opts.get('print0') and '\0' or '\n'
4346 end = opts.get('print0') and '\0' or '\n'
4347 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4347 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4348
4348
4349 ret = 1
4349 ret = 1
4350 ctx = repo[rev]
4350 ctx = repo[rev]
4351 m = scmutil.match(ctx, pats, opts, default='relglob')
4351 m = scmutil.match(ctx, pats, opts, default='relglob')
4352 m.bad = lambda x, y: False
4352 m.bad = lambda x, y: False
4353
4353
4354 for abs in ctx.matches(m):
4354 for abs in ctx.matches(m):
4355 if opts.get('fullpath'):
4355 if opts.get('fullpath'):
4356 ui.write(repo.wjoin(abs), end)
4356 ui.write(repo.wjoin(abs), end)
4357 else:
4357 else:
4358 ui.write(((pats and m.rel(abs)) or abs), end)
4358 ui.write(((pats and m.rel(abs)) or abs), end)
4359 ret = 0
4359 ret = 0
4360
4360
4361 return ret
4361 return ret
4362
4362
4363 @command('^log|history',
4363 @command('^log|history',
4364 [('f', 'follow', None,
4364 [('f', 'follow', None,
4365 _('follow changeset history, or file history across copies and renames')),
4365 _('follow changeset history, or file history across copies and renames')),
4366 ('', 'follow-first', None,
4366 ('', 'follow-first', None,
4367 _('only follow the first parent of merge changesets (DEPRECATED)')),
4367 _('only follow the first parent of merge changesets (DEPRECATED)')),
4368 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4368 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4369 ('C', 'copies', None, _('show copied files')),
4369 ('C', 'copies', None, _('show copied files')),
4370 ('k', 'keyword', [],
4370 ('k', 'keyword', [],
4371 _('do case-insensitive search for a given text'), _('TEXT')),
4371 _('do case-insensitive search for a given text'), _('TEXT')),
4372 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4372 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4373 ('', 'removed', None, _('include revisions where files were removed')),
4373 ('', 'removed', None, _('include revisions where files were removed')),
4374 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4374 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4375 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4375 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4376 ('', 'only-branch', [],
4376 ('', 'only-branch', [],
4377 _('show only changesets within the given named branch (DEPRECATED)'),
4377 _('show only changesets within the given named branch (DEPRECATED)'),
4378 _('BRANCH')),
4378 _('BRANCH')),
4379 ('b', 'branch', [],
4379 ('b', 'branch', [],
4380 _('show changesets within the given named branch'), _('BRANCH')),
4380 _('show changesets within the given named branch'), _('BRANCH')),
4381 ('P', 'prune', [],
4381 ('P', 'prune', [],
4382 _('do not display revision or any of its ancestors'), _('REV')),
4382 _('do not display revision or any of its ancestors'), _('REV')),
4383 ] + logopts + walkopts,
4383 ] + logopts + walkopts,
4384 _('[OPTION]... [FILE]'),
4384 _('[OPTION]... [FILE]'),
4385 inferrepo=True)
4385 inferrepo=True)
4386 def log(ui, repo, *pats, **opts):
4386 def log(ui, repo, *pats, **opts):
4387 """show revision history of entire repository or files
4387 """show revision history of entire repository or files
4388
4388
4389 Print the revision history of the specified files or the entire
4389 Print the revision history of the specified files or the entire
4390 project.
4390 project.
4391
4391
4392 If no revision range is specified, the default is ``tip:0`` unless
4392 If no revision range is specified, the default is ``tip:0`` unless
4393 --follow is set, in which case the working directory parent is
4393 --follow is set, in which case the working directory parent is
4394 used as the starting revision.
4394 used as the starting revision.
4395
4395
4396 File history is shown without following rename or copy history of
4396 File history is shown without following rename or copy history of
4397 files. Use -f/--follow with a filename to follow history across
4397 files. Use -f/--follow with a filename to follow history across
4398 renames and copies. --follow without a filename will only show
4398 renames and copies. --follow without a filename will only show
4399 ancestors or descendants of the starting revision.
4399 ancestors or descendants of the starting revision.
4400
4400
4401 By default this command prints revision number and changeset id,
4401 By default this command prints revision number and changeset id,
4402 tags, non-trivial parents, user, date and time, and a summary for
4402 tags, non-trivial parents, user, date and time, and a summary for
4403 each commit. When the -v/--verbose switch is used, the list of
4403 each commit. When the -v/--verbose switch is used, the list of
4404 changed files and full commit message are shown.
4404 changed files and full commit message are shown.
4405
4405
4406 With --graph the revisions are shown as an ASCII art DAG with the most
4406 With --graph the revisions are shown as an ASCII art DAG with the most
4407 recent changeset at the top.
4407 recent changeset at the top.
4408 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4408 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4409 and '+' represents a fork where the changeset from the lines below is a
4409 and '+' represents a fork where the changeset from the lines below is a
4410 parent of the 'o' merge on the same line.
4410 parent of the 'o' merge on the same line.
4411
4411
4412 .. note::
4412 .. note::
4413
4413
4414 log -p/--patch may generate unexpected diff output for merge
4414 log -p/--patch may generate unexpected diff output for merge
4415 changesets, as it will only compare the merge changeset against
4415 changesets, as it will only compare the merge changeset against
4416 its first parent. Also, only files different from BOTH parents
4416 its first parent. Also, only files different from BOTH parents
4417 will appear in files:.
4417 will appear in files:.
4418
4418
4419 .. note::
4419 .. note::
4420
4420
4421 for performance reasons, log FILE may omit duplicate changes
4421 for performance reasons, log FILE may omit duplicate changes
4422 made on branches and will not show removals or mode changes. To
4422 made on branches and will not show removals or mode changes. To
4423 see all such changes, use the --removed switch.
4423 see all such changes, use the --removed switch.
4424
4424
4425 .. container:: verbose
4425 .. container:: verbose
4426
4426
4427 Some examples:
4427 Some examples:
4428
4428
4429 - changesets with full descriptions and file lists::
4429 - changesets with full descriptions and file lists::
4430
4430
4431 hg log -v
4431 hg log -v
4432
4432
4433 - changesets ancestral to the working directory::
4433 - changesets ancestral to the working directory::
4434
4434
4435 hg log -f
4435 hg log -f
4436
4436
4437 - last 10 commits on the current branch::
4437 - last 10 commits on the current branch::
4438
4438
4439 hg log -l 10 -b .
4439 hg log -l 10 -b .
4440
4440
4441 - changesets showing all modifications of a file, including removals::
4441 - changesets showing all modifications of a file, including removals::
4442
4442
4443 hg log --removed file.c
4443 hg log --removed file.c
4444
4444
4445 - all changesets that touch a directory, with diffs, excluding merges::
4445 - all changesets that touch a directory, with diffs, excluding merges::
4446
4446
4447 hg log -Mp lib/
4447 hg log -Mp lib/
4448
4448
4449 - all revision numbers that match a keyword::
4449 - all revision numbers that match a keyword::
4450
4450
4451 hg log -k bug --template "{rev}\\n"
4451 hg log -k bug --template "{rev}\\n"
4452
4452
4453 - list available log templates::
4453 - list available log templates::
4454
4454
4455 hg log -T list
4455 hg log -T list
4456
4456
4457 - check if a given changeset is included in a tagged release::
4457 - check if a given changeset is included in a tagged release::
4458
4458
4459 hg log -r "a21ccf and ancestor(1.9)"
4459 hg log -r "a21ccf and ancestor(1.9)"
4460
4460
4461 - find all changesets by some user in a date range::
4461 - find all changesets by some user in a date range::
4462
4462
4463 hg log -k alice -d "may 2008 to jul 2008"
4463 hg log -k alice -d "may 2008 to jul 2008"
4464
4464
4465 - summary of all changesets after the last tag::
4465 - summary of all changesets after the last tag::
4466
4466
4467 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4467 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4468
4468
4469 See :hg:`help dates` for a list of formats valid for -d/--date.
4469 See :hg:`help dates` for a list of formats valid for -d/--date.
4470
4470
4471 See :hg:`help revisions` and :hg:`help revsets` for more about
4471 See :hg:`help revisions` and :hg:`help revsets` for more about
4472 specifying revisions.
4472 specifying revisions.
4473
4473
4474 See :hg:`help templates` for more about pre-packaged styles and
4474 See :hg:`help templates` for more about pre-packaged styles and
4475 specifying custom templates.
4475 specifying custom templates.
4476
4476
4477 Returns 0 on success.
4477 Returns 0 on success.
4478
4478
4479 """
4479 """
4480 if opts.get('graph'):
4480 if opts.get('graph'):
4481 return cmdutil.graphlog(ui, repo, *pats, **opts)
4481 return cmdutil.graphlog(ui, repo, *pats, **opts)
4482
4482
4483 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4483 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4484 limit = cmdutil.loglimit(opts)
4484 limit = cmdutil.loglimit(opts)
4485 count = 0
4485 count = 0
4486
4486
4487 getrenamed = None
4487 getrenamed = None
4488 if opts.get('copies'):
4488 if opts.get('copies'):
4489 endrev = None
4489 endrev = None
4490 if opts.get('rev'):
4490 if opts.get('rev'):
4491 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4491 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4492 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4492 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4493
4493
4494 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4494 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4495 for rev in revs:
4495 for rev in revs:
4496 if count == limit:
4496 if count == limit:
4497 break
4497 break
4498 ctx = repo[rev]
4498 ctx = repo[rev]
4499 copies = None
4499 copies = None
4500 if getrenamed is not None and rev:
4500 if getrenamed is not None and rev:
4501 copies = []
4501 copies = []
4502 for fn in ctx.files():
4502 for fn in ctx.files():
4503 rename = getrenamed(fn, rev)
4503 rename = getrenamed(fn, rev)
4504 if rename:
4504 if rename:
4505 copies.append((fn, rename[0]))
4505 copies.append((fn, rename[0]))
4506 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4506 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4507 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4507 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4508 if displayer.flush(rev):
4508 if displayer.flush(rev):
4509 count += 1
4509 count += 1
4510
4510
4511 displayer.close()
4511 displayer.close()
4512
4512
4513 @command('manifest',
4513 @command('manifest',
4514 [('r', 'rev', '', _('revision to display'), _('REV')),
4514 [('r', 'rev', '', _('revision to display'), _('REV')),
4515 ('', 'all', False, _("list files from all revisions"))]
4515 ('', 'all', False, _("list files from all revisions"))]
4516 + formatteropts,
4516 + formatteropts,
4517 _('[-r REV]'))
4517 _('[-r REV]'))
4518 def manifest(ui, repo, node=None, rev=None, **opts):
4518 def manifest(ui, repo, node=None, rev=None, **opts):
4519 """output the current or given revision of the project manifest
4519 """output the current or given revision of the project manifest
4520
4520
4521 Print a list of version controlled files for the given revision.
4521 Print a list of version controlled files for the given revision.
4522 If no revision is given, the first parent of the working directory
4522 If no revision is given, the first parent of the working directory
4523 is used, or the null revision if no revision is checked out.
4523 is used, or the null revision if no revision is checked out.
4524
4524
4525 With -v, print file permissions, symlink and executable bits.
4525 With -v, print file permissions, symlink and executable bits.
4526 With --debug, print file revision hashes.
4526 With --debug, print file revision hashes.
4527
4527
4528 If option --all is specified, the list of all files from all revisions
4528 If option --all is specified, the list of all files from all revisions
4529 is printed. This includes deleted and renamed files.
4529 is printed. This includes deleted and renamed files.
4530
4530
4531 Returns 0 on success.
4531 Returns 0 on success.
4532 """
4532 """
4533
4533
4534 fm = ui.formatter('manifest', opts)
4534 fm = ui.formatter('manifest', opts)
4535
4535
4536 if opts.get('all'):
4536 if opts.get('all'):
4537 if rev or node:
4537 if rev or node:
4538 raise util.Abort(_("can't specify a revision with --all"))
4538 raise util.Abort(_("can't specify a revision with --all"))
4539
4539
4540 res = []
4540 res = []
4541 prefix = "data/"
4541 prefix = "data/"
4542 suffix = ".i"
4542 suffix = ".i"
4543 plen = len(prefix)
4543 plen = len(prefix)
4544 slen = len(suffix)
4544 slen = len(suffix)
4545 lock = repo.lock()
4545 lock = repo.lock()
4546 try:
4546 try:
4547 for fn, b, size in repo.store.datafiles():
4547 for fn, b, size in repo.store.datafiles():
4548 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4548 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4549 res.append(fn[plen:-slen])
4549 res.append(fn[plen:-slen])
4550 finally:
4550 finally:
4551 lock.release()
4551 lock.release()
4552 for f in res:
4552 for f in res:
4553 fm.startitem()
4553 fm.startitem()
4554 fm.write("path", '%s\n', f)
4554 fm.write("path", '%s\n', f)
4555 fm.end()
4555 fm.end()
4556 return
4556 return
4557
4557
4558 if rev and node:
4558 if rev and node:
4559 raise util.Abort(_("please specify just one revision"))
4559 raise util.Abort(_("please specify just one revision"))
4560
4560
4561 if not node:
4561 if not node:
4562 node = rev
4562 node = rev
4563
4563
4564 char = {'l': '@', 'x': '*', '': ''}
4564 char = {'l': '@', 'x': '*', '': ''}
4565 mode = {'l': '644', 'x': '755', '': '644'}
4565 mode = {'l': '644', 'x': '755', '': '644'}
4566 ctx = scmutil.revsingle(repo, node)
4566 ctx = scmutil.revsingle(repo, node)
4567 mf = ctx.manifest()
4567 mf = ctx.manifest()
4568 for f in ctx:
4568 for f in ctx:
4569 fm.startitem()
4569 fm.startitem()
4570 fl = ctx[f].flags()
4570 fl = ctx[f].flags()
4571 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4571 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4572 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4572 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4573 fm.write('path', '%s\n', f)
4573 fm.write('path', '%s\n', f)
4574 fm.end()
4574 fm.end()
4575
4575
4576 @command('^merge',
4576 @command('^merge',
4577 [('f', 'force', None,
4577 [('f', 'force', None,
4578 _('force a merge including outstanding changes (DEPRECATED)')),
4578 _('force a merge including outstanding changes (DEPRECATED)')),
4579 ('r', 'rev', '', _('revision to merge'), _('REV')),
4579 ('r', 'rev', '', _('revision to merge'), _('REV')),
4580 ('P', 'preview', None,
4580 ('P', 'preview', None,
4581 _('review revisions to merge (no merge is performed)'))
4581 _('review revisions to merge (no merge is performed)'))
4582 ] + mergetoolopts,
4582 ] + mergetoolopts,
4583 _('[-P] [-f] [[-r] REV]'))
4583 _('[-P] [-f] [[-r] REV]'))
4584 def merge(ui, repo, node=None, **opts):
4584 def merge(ui, repo, node=None, **opts):
4585 """merge another revision into working directory
4585 """merge another revision into working directory
4586
4586
4587 The current working directory is updated with all changes made in
4587 The current working directory is updated with all changes made in
4588 the requested revision since the last common predecessor revision.
4588 the requested revision since the last common predecessor revision.
4589
4589
4590 Files that changed between either parent are marked as changed for
4590 Files that changed between either parent are marked as changed for
4591 the next commit and a commit must be performed before any further
4591 the next commit and a commit must be performed before any further
4592 updates to the repository are allowed. The next commit will have
4592 updates to the repository are allowed. The next commit will have
4593 two parents.
4593 two parents.
4594
4594
4595 ``--tool`` can be used to specify the merge tool used for file
4595 ``--tool`` can be used to specify the merge tool used for file
4596 merges. It overrides the HGMERGE environment variable and your
4596 merges. It overrides the HGMERGE environment variable and your
4597 configuration files. See :hg:`help merge-tools` for options.
4597 configuration files. See :hg:`help merge-tools` for options.
4598
4598
4599 If no revision is specified, the working directory's parent is a
4599 If no revision is specified, the working directory's parent is a
4600 head revision, and the current branch contains exactly one other
4600 head revision, and the current branch contains exactly one other
4601 head, the other head is merged with by default. Otherwise, an
4601 head, the other head is merged with by default. Otherwise, an
4602 explicit revision with which to merge with must be provided.
4602 explicit revision with which to merge with must be provided.
4603
4603
4604 :hg:`resolve` must be used to resolve unresolved files.
4604 :hg:`resolve` must be used to resolve unresolved files.
4605
4605
4606 To undo an uncommitted merge, use :hg:`update --clean .` which
4606 To undo an uncommitted merge, use :hg:`update --clean .` which
4607 will check out a clean copy of the original merge parent, losing
4607 will check out a clean copy of the original merge parent, losing
4608 all changes.
4608 all changes.
4609
4609
4610 Returns 0 on success, 1 if there are unresolved files.
4610 Returns 0 on success, 1 if there are unresolved files.
4611 """
4611 """
4612
4612
4613 if opts.get('rev') and node:
4613 if opts.get('rev') and node:
4614 raise util.Abort(_("please specify just one revision"))
4614 raise util.Abort(_("please specify just one revision"))
4615 if not node:
4615 if not node:
4616 node = opts.get('rev')
4616 node = opts.get('rev')
4617
4617
4618 if node:
4618 if node:
4619 node = scmutil.revsingle(repo, node).node()
4619 node = scmutil.revsingle(repo, node).node()
4620
4620
4621 if not node and repo._bookmarkcurrent:
4621 if not node and repo._bookmarkcurrent:
4622 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4622 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4623 curhead = repo[repo._bookmarkcurrent].node()
4623 curhead = repo[repo._bookmarkcurrent].node()
4624 if len(bmheads) == 2:
4624 if len(bmheads) == 2:
4625 if curhead == bmheads[0]:
4625 if curhead == bmheads[0]:
4626 node = bmheads[1]
4626 node = bmheads[1]
4627 else:
4627 else:
4628 node = bmheads[0]
4628 node = bmheads[0]
4629 elif len(bmheads) > 2:
4629 elif len(bmheads) > 2:
4630 raise util.Abort(_("multiple matching bookmarks to merge - "
4630 raise util.Abort(_("multiple matching bookmarks to merge - "
4631 "please merge with an explicit rev or bookmark"),
4631 "please merge with an explicit rev or bookmark"),
4632 hint=_("run 'hg heads' to see all heads"))
4632 hint=_("run 'hg heads' to see all heads"))
4633 elif len(bmheads) <= 1:
4633 elif len(bmheads) <= 1:
4634 raise util.Abort(_("no matching bookmark to merge - "
4634 raise util.Abort(_("no matching bookmark to merge - "
4635 "please merge with an explicit rev or bookmark"),
4635 "please merge with an explicit rev or bookmark"),
4636 hint=_("run 'hg heads' to see all heads"))
4636 hint=_("run 'hg heads' to see all heads"))
4637
4637
4638 if not node and not repo._bookmarkcurrent:
4638 if not node and not repo._bookmarkcurrent:
4639 branch = repo[None].branch()
4639 branch = repo[None].branch()
4640 bheads = repo.branchheads(branch)
4640 bheads = repo.branchheads(branch)
4641 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4641 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4642
4642
4643 if len(nbhs) > 2:
4643 if len(nbhs) > 2:
4644 raise util.Abort(_("branch '%s' has %d heads - "
4644 raise util.Abort(_("branch '%s' has %d heads - "
4645 "please merge with an explicit rev")
4645 "please merge with an explicit rev")
4646 % (branch, len(bheads)),
4646 % (branch, len(bheads)),
4647 hint=_("run 'hg heads .' to see heads"))
4647 hint=_("run 'hg heads .' to see heads"))
4648
4648
4649 parent = repo.dirstate.p1()
4649 parent = repo.dirstate.p1()
4650 if len(nbhs) <= 1:
4650 if len(nbhs) <= 1:
4651 if len(bheads) > 1:
4651 if len(bheads) > 1:
4652 raise util.Abort(_("heads are bookmarked - "
4652 raise util.Abort(_("heads are bookmarked - "
4653 "please merge with an explicit rev"),
4653 "please merge with an explicit rev"),
4654 hint=_("run 'hg heads' to see all heads"))
4654 hint=_("run 'hg heads' to see all heads"))
4655 if len(repo.heads()) > 1:
4655 if len(repo.heads()) > 1:
4656 raise util.Abort(_("branch '%s' has one head - "
4656 raise util.Abort(_("branch '%s' has one head - "
4657 "please merge with an explicit rev")
4657 "please merge with an explicit rev")
4658 % branch,
4658 % branch,
4659 hint=_("run 'hg heads' to see all heads"))
4659 hint=_("run 'hg heads' to see all heads"))
4660 msg, hint = _('nothing to merge'), None
4660 msg, hint = _('nothing to merge'), None
4661 if parent != repo.lookup(branch):
4661 if parent != repo.lookup(branch):
4662 hint = _("use 'hg update' instead")
4662 hint = _("use 'hg update' instead")
4663 raise util.Abort(msg, hint=hint)
4663 raise util.Abort(msg, hint=hint)
4664
4664
4665 if parent not in bheads:
4665 if parent not in bheads:
4666 raise util.Abort(_('working directory not at a head revision'),
4666 raise util.Abort(_('working directory not at a head revision'),
4667 hint=_("use 'hg update' or merge with an "
4667 hint=_("use 'hg update' or merge with an "
4668 "explicit revision"))
4668 "explicit revision"))
4669 if parent == nbhs[0]:
4669 if parent == nbhs[0]:
4670 node = nbhs[-1]
4670 node = nbhs[-1]
4671 else:
4671 else:
4672 node = nbhs[0]
4672 node = nbhs[0]
4673
4673
4674 if opts.get('preview'):
4674 if opts.get('preview'):
4675 # find nodes that are ancestors of p2 but not of p1
4675 # find nodes that are ancestors of p2 but not of p1
4676 p1 = repo.lookup('.')
4676 p1 = repo.lookup('.')
4677 p2 = repo.lookup(node)
4677 p2 = repo.lookup(node)
4678 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4678 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4679
4679
4680 displayer = cmdutil.show_changeset(ui, repo, opts)
4680 displayer = cmdutil.show_changeset(ui, repo, opts)
4681 for node in nodes:
4681 for node in nodes:
4682 displayer.show(repo[node])
4682 displayer.show(repo[node])
4683 displayer.close()
4683 displayer.close()
4684 return 0
4684 return 0
4685
4685
4686 try:
4686 try:
4687 # ui.forcemerge is an internal variable, do not document
4687 # ui.forcemerge is an internal variable, do not document
4688 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4688 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4689 return hg.merge(repo, node, force=opts.get('force'))
4689 return hg.merge(repo, node, force=opts.get('force'))
4690 finally:
4690 finally:
4691 ui.setconfig('ui', 'forcemerge', '', 'merge')
4691 ui.setconfig('ui', 'forcemerge', '', 'merge')
4692
4692
4693 @command('outgoing|out',
4693 @command('outgoing|out',
4694 [('f', 'force', None, _('run even when the destination is unrelated')),
4694 [('f', 'force', None, _('run even when the destination is unrelated')),
4695 ('r', 'rev', [],
4695 ('r', 'rev', [],
4696 _('a changeset intended to be included in the destination'), _('REV')),
4696 _('a changeset intended to be included in the destination'), _('REV')),
4697 ('n', 'newest-first', None, _('show newest record first')),
4697 ('n', 'newest-first', None, _('show newest record first')),
4698 ('B', 'bookmarks', False, _('compare bookmarks')),
4698 ('B', 'bookmarks', False, _('compare bookmarks')),
4699 ('b', 'branch', [], _('a specific branch you would like to push'),
4699 ('b', 'branch', [], _('a specific branch you would like to push'),
4700 _('BRANCH')),
4700 _('BRANCH')),
4701 ] + logopts + remoteopts + subrepoopts,
4701 ] + logopts + remoteopts + subrepoopts,
4702 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4702 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4703 def outgoing(ui, repo, dest=None, **opts):
4703 def outgoing(ui, repo, dest=None, **opts):
4704 """show changesets not found in the destination
4704 """show changesets not found in the destination
4705
4705
4706 Show changesets not found in the specified destination repository
4706 Show changesets not found in the specified destination repository
4707 or the default push location. These are the changesets that would
4707 or the default push location. These are the changesets that would
4708 be pushed if a push was requested.
4708 be pushed if a push was requested.
4709
4709
4710 See pull for details of valid destination formats.
4710 See pull for details of valid destination formats.
4711
4711
4712 Returns 0 if there are outgoing changes, 1 otherwise.
4712 Returns 0 if there are outgoing changes, 1 otherwise.
4713 """
4713 """
4714 if opts.get('graph'):
4714 if opts.get('graph'):
4715 cmdutil.checkunsupportedgraphflags([], opts)
4715 cmdutil.checkunsupportedgraphflags([], opts)
4716 o, other = hg._outgoing(ui, repo, dest, opts)
4716 o, other = hg._outgoing(ui, repo, dest, opts)
4717 if not o:
4717 if not o:
4718 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4718 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4719 return
4719 return
4720
4720
4721 revdag = cmdutil.graphrevs(repo, o, opts)
4721 revdag = cmdutil.graphrevs(repo, o, opts)
4722 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4722 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4723 showparents = [ctx.node() for ctx in repo[None].parents()]
4723 showparents = [ctx.node() for ctx in repo[None].parents()]
4724 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4724 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4725 graphmod.asciiedges)
4725 graphmod.asciiedges)
4726 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4726 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4727 return 0
4727 return 0
4728
4728
4729 if opts.get('bookmarks'):
4729 if opts.get('bookmarks'):
4730 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4730 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4731 dest, branches = hg.parseurl(dest, opts.get('branch'))
4731 dest, branches = hg.parseurl(dest, opts.get('branch'))
4732 other = hg.peer(repo, opts, dest)
4732 other = hg.peer(repo, opts, dest)
4733 if 'bookmarks' not in other.listkeys('namespaces'):
4733 if 'bookmarks' not in other.listkeys('namespaces'):
4734 ui.warn(_("remote doesn't support bookmarks\n"))
4734 ui.warn(_("remote doesn't support bookmarks\n"))
4735 return 0
4735 return 0
4736 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4736 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4737 return bookmarks.diff(ui, other, repo)
4737 return bookmarks.diff(ui, other, repo)
4738
4738
4739 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4739 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4740 try:
4740 try:
4741 return hg.outgoing(ui, repo, dest, opts)
4741 return hg.outgoing(ui, repo, dest, opts)
4742 finally:
4742 finally:
4743 del repo._subtoppath
4743 del repo._subtoppath
4744
4744
4745 @command('parents',
4745 @command('parents',
4746 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4746 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4747 ] + templateopts,
4747 ] + templateopts,
4748 _('[-r REV] [FILE]'),
4748 _('[-r REV] [FILE]'),
4749 inferrepo=True)
4749 inferrepo=True)
4750 def parents(ui, repo, file_=None, **opts):
4750 def parents(ui, repo, file_=None, **opts):
4751 """show the parents of the working directory or revision (DEPRECATED)
4751 """show the parents of the working directory or revision (DEPRECATED)
4752
4752
4753 Print the working directory's parent revisions. If a revision is
4753 Print the working directory's parent revisions. If a revision is
4754 given via -r/--rev, the parent of that revision will be printed.
4754 given via -r/--rev, the parent of that revision will be printed.
4755 If a file argument is given, the revision in which the file was
4755 If a file argument is given, the revision in which the file was
4756 last changed (before the working directory revision or the
4756 last changed (before the working directory revision or the
4757 argument to --rev if given) is printed.
4757 argument to --rev if given) is printed.
4758
4758
4759 See :hg:`summary` and :hg:`help revsets` for related information.
4759 See :hg:`summary` and :hg:`help revsets` for related information.
4760
4760
4761 Returns 0 on success.
4761 Returns 0 on success.
4762 """
4762 """
4763
4763
4764 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4764 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4765
4765
4766 if file_:
4766 if file_:
4767 m = scmutil.match(ctx, (file_,), opts)
4767 m = scmutil.match(ctx, (file_,), opts)
4768 if m.anypats() or len(m.files()) != 1:
4768 if m.anypats() or len(m.files()) != 1:
4769 raise util.Abort(_('can only specify an explicit filename'))
4769 raise util.Abort(_('can only specify an explicit filename'))
4770 file_ = m.files()[0]
4770 file_ = m.files()[0]
4771 filenodes = []
4771 filenodes = []
4772 for cp in ctx.parents():
4772 for cp in ctx.parents():
4773 if not cp:
4773 if not cp:
4774 continue
4774 continue
4775 try:
4775 try:
4776 filenodes.append(cp.filenode(file_))
4776 filenodes.append(cp.filenode(file_))
4777 except error.LookupError:
4777 except error.LookupError:
4778 pass
4778 pass
4779 if not filenodes:
4779 if not filenodes:
4780 raise util.Abort(_("'%s' not found in manifest!") % file_)
4780 raise util.Abort(_("'%s' not found in manifest!") % file_)
4781 p = []
4781 p = []
4782 for fn in filenodes:
4782 for fn in filenodes:
4783 fctx = repo.filectx(file_, fileid=fn)
4783 fctx = repo.filectx(file_, fileid=fn)
4784 p.append(fctx.node())
4784 p.append(fctx.node())
4785 else:
4785 else:
4786 p = [cp.node() for cp in ctx.parents()]
4786 p = [cp.node() for cp in ctx.parents()]
4787
4787
4788 displayer = cmdutil.show_changeset(ui, repo, opts)
4788 displayer = cmdutil.show_changeset(ui, repo, opts)
4789 for n in p:
4789 for n in p:
4790 if n != nullid:
4790 if n != nullid:
4791 displayer.show(repo[n])
4791 displayer.show(repo[n])
4792 displayer.close()
4792 displayer.close()
4793
4793
4794 @command('paths', [], _('[NAME]'), optionalrepo=True)
4794 @command('paths', [], _('[NAME]'), optionalrepo=True)
4795 def paths(ui, repo, search=None):
4795 def paths(ui, repo, search=None):
4796 """show aliases for remote repositories
4796 """show aliases for remote repositories
4797
4797
4798 Show definition of symbolic path name NAME. If no name is given,
4798 Show definition of symbolic path name NAME. If no name is given,
4799 show definition of all available names.
4799 show definition of all available names.
4800
4800
4801 Option -q/--quiet suppresses all output when searching for NAME
4801 Option -q/--quiet suppresses all output when searching for NAME
4802 and shows only the path names when listing all definitions.
4802 and shows only the path names when listing all definitions.
4803
4803
4804 Path names are defined in the [paths] section of your
4804 Path names are defined in the [paths] section of your
4805 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4805 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4806 repository, ``.hg/hgrc`` is used, too.
4806 repository, ``.hg/hgrc`` is used, too.
4807
4807
4808 The path names ``default`` and ``default-push`` have a special
4808 The path names ``default`` and ``default-push`` have a special
4809 meaning. When performing a push or pull operation, they are used
4809 meaning. When performing a push or pull operation, they are used
4810 as fallbacks if no location is specified on the command-line.
4810 as fallbacks if no location is specified on the command-line.
4811 When ``default-push`` is set, it will be used for push and
4811 When ``default-push`` is set, it will be used for push and
4812 ``default`` will be used for pull; otherwise ``default`` is used
4812 ``default`` will be used for pull; otherwise ``default`` is used
4813 as the fallback for both. When cloning a repository, the clone
4813 as the fallback for both. When cloning a repository, the clone
4814 source is written as ``default`` in ``.hg/hgrc``. Note that
4814 source is written as ``default`` in ``.hg/hgrc``. Note that
4815 ``default`` and ``default-push`` apply to all inbound (e.g.
4815 ``default`` and ``default-push`` apply to all inbound (e.g.
4816 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4816 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4817 :hg:`bundle`) operations.
4817 :hg:`bundle`) operations.
4818
4818
4819 See :hg:`help urls` for more information.
4819 See :hg:`help urls` for more information.
4820
4820
4821 Returns 0 on success.
4821 Returns 0 on success.
4822 """
4822 """
4823 if search:
4823 if search:
4824 for name, path in ui.configitems("paths"):
4824 for name, path in ui.configitems("paths"):
4825 if name == search:
4825 if name == search:
4826 ui.status("%s\n" % util.hidepassword(path))
4826 ui.status("%s\n" % util.hidepassword(path))
4827 return
4827 return
4828 if not ui.quiet:
4828 if not ui.quiet:
4829 ui.warn(_("not found!\n"))
4829 ui.warn(_("not found!\n"))
4830 return 1
4830 return 1
4831 else:
4831 else:
4832 for name, path in ui.configitems("paths"):
4832 for name, path in ui.configitems("paths"):
4833 if ui.quiet:
4833 if ui.quiet:
4834 ui.write("%s\n" % name)
4834 ui.write("%s\n" % name)
4835 else:
4835 else:
4836 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4836 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4837
4837
4838 @command('phase',
4838 @command('phase',
4839 [('p', 'public', False, _('set changeset phase to public')),
4839 [('p', 'public', False, _('set changeset phase to public')),
4840 ('d', 'draft', False, _('set changeset phase to draft')),
4840 ('d', 'draft', False, _('set changeset phase to draft')),
4841 ('s', 'secret', False, _('set changeset phase to secret')),
4841 ('s', 'secret', False, _('set changeset phase to secret')),
4842 ('f', 'force', False, _('allow to move boundary backward')),
4842 ('f', 'force', False, _('allow to move boundary backward')),
4843 ('r', 'rev', [], _('target revision'), _('REV')),
4843 ('r', 'rev', [], _('target revision'), _('REV')),
4844 ],
4844 ],
4845 _('[-p|-d|-s] [-f] [-r] REV...'))
4845 _('[-p|-d|-s] [-f] [-r] REV...'))
4846 def phase(ui, repo, *revs, **opts):
4846 def phase(ui, repo, *revs, **opts):
4847 """set or show the current phase name
4847 """set or show the current phase name
4848
4848
4849 With no argument, show the phase name of specified revisions.
4849 With no argument, show the phase name of specified revisions.
4850
4850
4851 With one of -p/--public, -d/--draft or -s/--secret, change the
4851 With one of -p/--public, -d/--draft or -s/--secret, change the
4852 phase value of the specified revisions.
4852 phase value of the specified revisions.
4853
4853
4854 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4854 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4855 lower phase to an higher phase. Phases are ordered as follows::
4855 lower phase to an higher phase. Phases are ordered as follows::
4856
4856
4857 public < draft < secret
4857 public < draft < secret
4858
4858
4859 Returns 0 on success, 1 if no phases were changed or some could not
4859 Returns 0 on success, 1 if no phases were changed or some could not
4860 be changed.
4860 be changed.
4861 """
4861 """
4862 # search for a unique phase argument
4862 # search for a unique phase argument
4863 targetphase = None
4863 targetphase = None
4864 for idx, name in enumerate(phases.phasenames):
4864 for idx, name in enumerate(phases.phasenames):
4865 if opts[name]:
4865 if opts[name]:
4866 if targetphase is not None:
4866 if targetphase is not None:
4867 raise util.Abort(_('only one phase can be specified'))
4867 raise util.Abort(_('only one phase can be specified'))
4868 targetphase = idx
4868 targetphase = idx
4869
4869
4870 # look for specified revision
4870 # look for specified revision
4871 revs = list(revs)
4871 revs = list(revs)
4872 revs.extend(opts['rev'])
4872 revs.extend(opts['rev'])
4873 if not revs:
4873 if not revs:
4874 raise util.Abort(_('no revisions specified'))
4874 raise util.Abort(_('no revisions specified'))
4875
4875
4876 revs = scmutil.revrange(repo, revs)
4876 revs = scmutil.revrange(repo, revs)
4877
4877
4878 lock = None
4878 lock = None
4879 ret = 0
4879 ret = 0
4880 if targetphase is None:
4880 if targetphase is None:
4881 # display
4881 # display
4882 for r in revs:
4882 for r in revs:
4883 ctx = repo[r]
4883 ctx = repo[r]
4884 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4884 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4885 else:
4885 else:
4886 tr = None
4886 tr = None
4887 lock = repo.lock()
4887 lock = repo.lock()
4888 try:
4888 try:
4889 tr = repo.transaction("phase")
4889 tr = repo.transaction("phase")
4890 # set phase
4890 # set phase
4891 if not revs:
4891 if not revs:
4892 raise util.Abort(_('empty revision set'))
4892 raise util.Abort(_('empty revision set'))
4893 nodes = [repo[r].node() for r in revs]
4893 nodes = [repo[r].node() for r in revs]
4894 # moving revision from public to draft may hide them
4894 # moving revision from public to draft may hide them
4895 # We have to check result on an unfiltered repository
4895 # We have to check result on an unfiltered repository
4896 unfi = repo.unfiltered()
4896 unfi = repo.unfiltered()
4897 getphase = unfi._phasecache.phase
4897 getphase = unfi._phasecache.phase
4898 olddata = [getphase(unfi, r) for r in unfi]
4898 olddata = [getphase(unfi, r) for r in unfi]
4899 phases.advanceboundary(repo, tr, targetphase, nodes)
4899 phases.advanceboundary(repo, tr, targetphase, nodes)
4900 if opts['force']:
4900 if opts['force']:
4901 phases.retractboundary(repo, tr, targetphase, nodes)
4901 phases.retractboundary(repo, tr, targetphase, nodes)
4902 tr.close()
4902 tr.close()
4903 finally:
4903 finally:
4904 if tr is not None:
4904 if tr is not None:
4905 tr.release()
4905 tr.release()
4906 lock.release()
4906 lock.release()
4907 getphase = unfi._phasecache.phase
4907 getphase = unfi._phasecache.phase
4908 newdata = [getphase(unfi, r) for r in unfi]
4908 newdata = [getphase(unfi, r) for r in unfi]
4909 changes = sum(newdata[r] != olddata[r] for r in unfi)
4909 changes = sum(newdata[r] != olddata[r] for r in unfi)
4910 cl = unfi.changelog
4910 cl = unfi.changelog
4911 rejected = [n for n in nodes
4911 rejected = [n for n in nodes
4912 if newdata[cl.rev(n)] < targetphase]
4912 if newdata[cl.rev(n)] < targetphase]
4913 if rejected:
4913 if rejected:
4914 ui.warn(_('cannot move %i changesets to a higher '
4914 ui.warn(_('cannot move %i changesets to a higher '
4915 'phase, use --force\n') % len(rejected))
4915 'phase, use --force\n') % len(rejected))
4916 ret = 1
4916 ret = 1
4917 if changes:
4917 if changes:
4918 msg = _('phase changed for %i changesets\n') % changes
4918 msg = _('phase changed for %i changesets\n') % changes
4919 if ret:
4919 if ret:
4920 ui.status(msg)
4920 ui.status(msg)
4921 else:
4921 else:
4922 ui.note(msg)
4922 ui.note(msg)
4923 else:
4923 else:
4924 ui.warn(_('no phases changed\n'))
4924 ui.warn(_('no phases changed\n'))
4925 ret = 1
4925 ret = 1
4926 return ret
4926 return ret
4927
4927
4928 def postincoming(ui, repo, modheads, optupdate, checkout):
4928 def postincoming(ui, repo, modheads, optupdate, checkout):
4929 if modheads == 0:
4929 if modheads == 0:
4930 return
4930 return
4931 if optupdate:
4931 if optupdate:
4932 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4932 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4933 try:
4933 try:
4934 ret = hg.update(repo, checkout)
4934 ret = hg.update(repo, checkout)
4935 except util.Abort, inst:
4935 except util.Abort, inst:
4936 ui.warn(_("not updating: %s\n") % str(inst))
4936 ui.warn(_("not updating: %s\n") % str(inst))
4937 if inst.hint:
4937 if inst.hint:
4938 ui.warn(_("(%s)\n") % inst.hint)
4938 ui.warn(_("(%s)\n") % inst.hint)
4939 return 0
4939 return 0
4940 if not ret and not checkout:
4940 if not ret and not checkout:
4941 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4941 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4942 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4942 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4943 return ret
4943 return ret
4944 if modheads > 1:
4944 if modheads > 1:
4945 currentbranchheads = len(repo.branchheads())
4945 currentbranchheads = len(repo.branchheads())
4946 if currentbranchheads == modheads:
4946 if currentbranchheads == modheads:
4947 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4947 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4948 elif currentbranchheads > 1:
4948 elif currentbranchheads > 1:
4949 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4949 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4950 "merge)\n"))
4950 "merge)\n"))
4951 else:
4951 else:
4952 ui.status(_("(run 'hg heads' to see heads)\n"))
4952 ui.status(_("(run 'hg heads' to see heads)\n"))
4953 else:
4953 else:
4954 ui.status(_("(run 'hg update' to get a working copy)\n"))
4954 ui.status(_("(run 'hg update' to get a working copy)\n"))
4955
4955
4956 @command('^pull',
4956 @command('^pull',
4957 [('u', 'update', None,
4957 [('u', 'update', None,
4958 _('update to new branch head if changesets were pulled')),
4958 _('update to new branch head if changesets were pulled')),
4959 ('f', 'force', None, _('run even when remote repository is unrelated')),
4959 ('f', 'force', None, _('run even when remote repository is unrelated')),
4960 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4960 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4961 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4961 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4962 ('b', 'branch', [], _('a specific branch you would like to pull'),
4962 ('b', 'branch', [], _('a specific branch you would like to pull'),
4963 _('BRANCH')),
4963 _('BRANCH')),
4964 ] + remoteopts,
4964 ] + remoteopts,
4965 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4965 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4966 def pull(ui, repo, source="default", **opts):
4966 def pull(ui, repo, source="default", **opts):
4967 """pull changes from the specified source
4967 """pull changes from the specified source
4968
4968
4969 Pull changes from a remote repository to a local one.
4969 Pull changes from a remote repository to a local one.
4970
4970
4971 This finds all changes from the repository at the specified path
4971 This finds all changes from the repository at the specified path
4972 or URL and adds them to a local repository (the current one unless
4972 or URL and adds them to a local repository (the current one unless
4973 -R is specified). By default, this does not update the copy of the
4973 -R is specified). By default, this does not update the copy of the
4974 project in the working directory.
4974 project in the working directory.
4975
4975
4976 Use :hg:`incoming` if you want to see what would have been added
4976 Use :hg:`incoming` if you want to see what would have been added
4977 by a pull at the time you issued this command. If you then decide
4977 by a pull at the time you issued this command. If you then decide
4978 to add those changes to the repository, you should use :hg:`pull
4978 to add those changes to the repository, you should use :hg:`pull
4979 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4979 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4980
4980
4981 If SOURCE is omitted, the 'default' path will be used.
4981 If SOURCE is omitted, the 'default' path will be used.
4982 See :hg:`help urls` for more information.
4982 See :hg:`help urls` for more information.
4983
4983
4984 Returns 0 on success, 1 if an update had unresolved files.
4984 Returns 0 on success, 1 if an update had unresolved files.
4985 """
4985 """
4986 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4986 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4987 other = hg.peer(repo, opts, source)
4987 other = hg.peer(repo, opts, source)
4988 try:
4988 try:
4989 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4989 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4990 revs, checkout = hg.addbranchrevs(repo, other, branches,
4990 revs, checkout = hg.addbranchrevs(repo, other, branches,
4991 opts.get('rev'))
4991 opts.get('rev'))
4992
4992
4993 remotebookmarks = other.listkeys('bookmarks')
4993 remotebookmarks = other.listkeys('bookmarks')
4994
4994
4995 if opts.get('bookmark'):
4995 if opts.get('bookmark'):
4996 if not revs:
4996 if not revs:
4997 revs = []
4997 revs = []
4998 for b in opts['bookmark']:
4998 for b in opts['bookmark']:
4999 if b not in remotebookmarks:
4999 if b not in remotebookmarks:
5000 raise util.Abort(_('remote bookmark %s not found!') % b)
5000 raise util.Abort(_('remote bookmark %s not found!') % b)
5001 revs.append(remotebookmarks[b])
5001 revs.append(remotebookmarks[b])
5002
5002
5003 if revs:
5003 if revs:
5004 try:
5004 try:
5005 revs = [other.lookup(rev) for rev in revs]
5005 revs = [other.lookup(rev) for rev in revs]
5006 except error.CapabilityError:
5006 except error.CapabilityError:
5007 err = _("other repository doesn't support revision lookup, "
5007 err = _("other repository doesn't support revision lookup, "
5008 "so a rev cannot be specified.")
5008 "so a rev cannot be specified.")
5009 raise util.Abort(err)
5009 raise util.Abort(err)
5010
5010
5011 modheads = exchange.pull(repo, other, heads=revs,
5011 modheads = exchange.pull(repo, other, heads=revs,
5012 force=opts.get('force'),
5012 force=opts.get('force'),
5013 bookmarks=opts.get('bookmark', ())).cgresult
5013 bookmarks=opts.get('bookmark', ())).cgresult
5014 if checkout:
5014 if checkout:
5015 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5015 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5016 repo._subtoppath = source
5016 repo._subtoppath = source
5017 try:
5017 try:
5018 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5018 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5019
5019
5020 finally:
5020 finally:
5021 del repo._subtoppath
5021 del repo._subtoppath
5022
5022
5023 finally:
5023 finally:
5024 other.close()
5024 other.close()
5025 return ret
5025 return ret
5026
5026
5027 @command('^push',
5027 @command('^push',
5028 [('f', 'force', None, _('force push')),
5028 [('f', 'force', None, _('force push')),
5029 ('r', 'rev', [],
5029 ('r', 'rev', [],
5030 _('a changeset intended to be included in the destination'),
5030 _('a changeset intended to be included in the destination'),
5031 _('REV')),
5031 _('REV')),
5032 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5032 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5033 ('b', 'branch', [],
5033 ('b', 'branch', [],
5034 _('a specific branch you would like to push'), _('BRANCH')),
5034 _('a specific branch you would like to push'), _('BRANCH')),
5035 ('', 'new-branch', False, _('allow pushing a new branch')),
5035 ('', 'new-branch', False, _('allow pushing a new branch')),
5036 ] + remoteopts,
5036 ] + remoteopts,
5037 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5037 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5038 def push(ui, repo, dest=None, **opts):
5038 def push(ui, repo, dest=None, **opts):
5039 """push changes to the specified destination
5039 """push changes to the specified destination
5040
5040
5041 Push changesets from the local repository to the specified
5041 Push changesets from the local repository to the specified
5042 destination.
5042 destination.
5043
5043
5044 This operation is symmetrical to pull: it is identical to a pull
5044 This operation is symmetrical to pull: it is identical to a pull
5045 in the destination repository from the current one.
5045 in the destination repository from the current one.
5046
5046
5047 By default, push will not allow creation of new heads at the
5047 By default, push will not allow creation of new heads at the
5048 destination, since multiple heads would make it unclear which head
5048 destination, since multiple heads would make it unclear which head
5049 to use. In this situation, it is recommended to pull and merge
5049 to use. In this situation, it is recommended to pull and merge
5050 before pushing.
5050 before pushing.
5051
5051
5052 Use --new-branch if you want to allow push to create a new named
5052 Use --new-branch if you want to allow push to create a new named
5053 branch that is not present at the destination. This allows you to
5053 branch that is not present at the destination. This allows you to
5054 only create a new branch without forcing other changes.
5054 only create a new branch without forcing other changes.
5055
5055
5056 .. note::
5056 .. note::
5057
5057
5058 Extra care should be taken with the -f/--force option,
5058 Extra care should be taken with the -f/--force option,
5059 which will push all new heads on all branches, an action which will
5059 which will push all new heads on all branches, an action which will
5060 almost always cause confusion for collaborators.
5060 almost always cause confusion for collaborators.
5061
5061
5062 If -r/--rev is used, the specified revision and all its ancestors
5062 If -r/--rev is used, the specified revision and all its ancestors
5063 will be pushed to the remote repository.
5063 will be pushed to the remote repository.
5064
5064
5065 If -B/--bookmark is used, the specified bookmarked revision, its
5065 If -B/--bookmark is used, the specified bookmarked revision, its
5066 ancestors, and the bookmark will be pushed to the remote
5066 ancestors, and the bookmark will be pushed to the remote
5067 repository.
5067 repository.
5068
5068
5069 Please see :hg:`help urls` for important details about ``ssh://``
5069 Please see :hg:`help urls` for important details about ``ssh://``
5070 URLs. If DESTINATION is omitted, a default path will be used.
5070 URLs. If DESTINATION is omitted, a default path will be used.
5071
5071
5072 Returns 0 if push was successful, 1 if nothing to push.
5072 Returns 0 if push was successful, 1 if nothing to push.
5073 """
5073 """
5074
5074
5075 if opts.get('bookmark'):
5075 if opts.get('bookmark'):
5076 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5076 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5077 for b in opts['bookmark']:
5077 for b in opts['bookmark']:
5078 # translate -B options to -r so changesets get pushed
5078 # translate -B options to -r so changesets get pushed
5079 if b in repo._bookmarks:
5079 if b in repo._bookmarks:
5080 opts.setdefault('rev', []).append(b)
5080 opts.setdefault('rev', []).append(b)
5081 else:
5081 else:
5082 # if we try to push a deleted bookmark, translate it to null
5082 # if we try to push a deleted bookmark, translate it to null
5083 # this lets simultaneous -r, -b options continue working
5083 # this lets simultaneous -r, -b options continue working
5084 opts.setdefault('rev', []).append("null")
5084 opts.setdefault('rev', []).append("null")
5085
5085
5086 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5086 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5087 dest, branches = hg.parseurl(dest, opts.get('branch'))
5087 dest, branches = hg.parseurl(dest, opts.get('branch'))
5088 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5088 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5089 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5089 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5090 try:
5090 try:
5091 other = hg.peer(repo, opts, dest)
5091 other = hg.peer(repo, opts, dest)
5092 except error.RepoError:
5092 except error.RepoError:
5093 if dest == "default-push":
5093 if dest == "default-push":
5094 raise util.Abort(_("default repository not configured!"),
5094 raise util.Abort(_("default repository not configured!"),
5095 hint=_('see the "path" section in "hg help config"'))
5095 hint=_('see the "path" section in "hg help config"'))
5096 else:
5096 else:
5097 raise
5097 raise
5098
5098
5099 if revs:
5099 if revs:
5100 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5100 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5101
5101
5102 repo._subtoppath = dest
5102 repo._subtoppath = dest
5103 try:
5103 try:
5104 # push subrepos depth-first for coherent ordering
5104 # push subrepos depth-first for coherent ordering
5105 c = repo['']
5105 c = repo['']
5106 subs = c.substate # only repos that are committed
5106 subs = c.substate # only repos that are committed
5107 for s in sorted(subs):
5107 for s in sorted(subs):
5108 result = c.sub(s).push(opts)
5108 result = c.sub(s).push(opts)
5109 if result == 0:
5109 if result == 0:
5110 return not result
5110 return not result
5111 finally:
5111 finally:
5112 del repo._subtoppath
5112 del repo._subtoppath
5113 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5113 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5114 newbranch=opts.get('new_branch'),
5114 newbranch=opts.get('new_branch'),
5115 bookmarks=opts.get('bookmark', ()))
5115 bookmarks=opts.get('bookmark', ()))
5116
5116
5117 result = not pushop.cgresult
5117 result = not pushop.cgresult
5118
5118
5119 if pushop.bkresult is not None:
5119 if pushop.bkresult is not None:
5120 if pushop.bkresult == 2:
5120 if pushop.bkresult == 2:
5121 result = 2
5121 result = 2
5122 elif not result and pushop.bkresult:
5122 elif not result and pushop.bkresult:
5123 result = 2
5123 result = 2
5124
5124
5125 return result
5125 return result
5126
5126
5127 @command('recover', [])
5127 @command('recover', [])
5128 def recover(ui, repo):
5128 def recover(ui, repo):
5129 """roll back an interrupted transaction
5129 """roll back an interrupted transaction
5130
5130
5131 Recover from an interrupted commit or pull.
5131 Recover from an interrupted commit or pull.
5132
5132
5133 This command tries to fix the repository status after an
5133 This command tries to fix the repository status after an
5134 interrupted operation. It should only be necessary when Mercurial
5134 interrupted operation. It should only be necessary when Mercurial
5135 suggests it.
5135 suggests it.
5136
5136
5137 Returns 0 if successful, 1 if nothing to recover or verify fails.
5137 Returns 0 if successful, 1 if nothing to recover or verify fails.
5138 """
5138 """
5139 if repo.recover():
5139 if repo.recover():
5140 return hg.verify(repo)
5140 return hg.verify(repo)
5141 return 1
5141 return 1
5142
5142
5143 @command('^remove|rm',
5143 @command('^remove|rm',
5144 [('A', 'after', None, _('record delete for missing files')),
5144 [('A', 'after', None, _('record delete for missing files')),
5145 ('f', 'force', None,
5145 ('f', 'force', None,
5146 _('remove (and delete) file even if added or modified')),
5146 _('remove (and delete) file even if added or modified')),
5147 ] + subrepoopts + walkopts,
5147 ] + subrepoopts + walkopts,
5148 _('[OPTION]... FILE...'),
5148 _('[OPTION]... FILE...'),
5149 inferrepo=True)
5149 inferrepo=True)
5150 def remove(ui, repo, *pats, **opts):
5150 def remove(ui, repo, *pats, **opts):
5151 """remove the specified files on the next commit
5151 """remove the specified files on the next commit
5152
5152
5153 Schedule the indicated files for removal from the current branch.
5153 Schedule the indicated files for removal from the current branch.
5154
5154
5155 This command schedules the files to be removed at the next commit.
5155 This command schedules the files to be removed at the next commit.
5156 To undo a remove before that, see :hg:`revert`. To undo added
5156 To undo a remove before that, see :hg:`revert`. To undo added
5157 files, see :hg:`forget`.
5157 files, see :hg:`forget`.
5158
5158
5159 .. container:: verbose
5159 .. container:: verbose
5160
5160
5161 -A/--after can be used to remove only files that have already
5161 -A/--after can be used to remove only files that have already
5162 been deleted, -f/--force can be used to force deletion, and -Af
5162 been deleted, -f/--force can be used to force deletion, and -Af
5163 can be used to remove files from the next revision without
5163 can be used to remove files from the next revision without
5164 deleting them from the working directory.
5164 deleting them from the working directory.
5165
5165
5166 The following table details the behavior of remove for different
5166 The following table details the behavior of remove for different
5167 file states (columns) and option combinations (rows). The file
5167 file states (columns) and option combinations (rows). The file
5168 states are Added [A], Clean [C], Modified [M] and Missing [!]
5168 states are Added [A], Clean [C], Modified [M] and Missing [!]
5169 (as reported by :hg:`status`). The actions are Warn, Remove
5169 (as reported by :hg:`status`). The actions are Warn, Remove
5170 (from branch) and Delete (from disk):
5170 (from branch) and Delete (from disk):
5171
5171
5172 ========= == == == ==
5172 ========= == == == ==
5173 opt/state A C M !
5173 opt/state A C M !
5174 ========= == == == ==
5174 ========= == == == ==
5175 none W RD W R
5175 none W RD W R
5176 -f R RD RD R
5176 -f R RD RD R
5177 -A W W W R
5177 -A W W W R
5178 -Af R R R R
5178 -Af R R R R
5179 ========= == == == ==
5179 ========= == == == ==
5180
5180
5181 Note that remove never deletes files in Added [A] state from the
5181 Note that remove never deletes files in Added [A] state from the
5182 working directory, not even if option --force is specified.
5182 working directory, not even if option --force is specified.
5183
5183
5184 Returns 0 on success, 1 if any warnings encountered.
5184 Returns 0 on success, 1 if any warnings encountered.
5185 """
5185 """
5186
5186
5187 after, force = opts.get('after'), opts.get('force')
5187 after, force = opts.get('after'), opts.get('force')
5188 if not pats and not after:
5188 if not pats and not after:
5189 raise util.Abort(_('no files specified'))
5189 raise util.Abort(_('no files specified'))
5190
5190
5191 m = scmutil.match(repo[None], pats, opts)
5191 m = scmutil.match(repo[None], pats, opts)
5192 subrepos = opts.get('subrepos')
5192 subrepos = opts.get('subrepos')
5193 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5193 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5194
5194
5195 @command('rename|move|mv',
5195 @command('rename|move|mv',
5196 [('A', 'after', None, _('record a rename that has already occurred')),
5196 [('A', 'after', None, _('record a rename that has already occurred')),
5197 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5197 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5198 ] + walkopts + dryrunopts,
5198 ] + walkopts + dryrunopts,
5199 _('[OPTION]... SOURCE... DEST'))
5199 _('[OPTION]... SOURCE... DEST'))
5200 def rename(ui, repo, *pats, **opts):
5200 def rename(ui, repo, *pats, **opts):
5201 """rename files; equivalent of copy + remove
5201 """rename files; equivalent of copy + remove
5202
5202
5203 Mark dest as copies of sources; mark sources for deletion. If dest
5203 Mark dest as copies of sources; mark sources for deletion. If dest
5204 is a directory, copies are put in that directory. If dest is a
5204 is a directory, copies are put in that directory. If dest is a
5205 file, there can only be one source.
5205 file, there can only be one source.
5206
5206
5207 By default, this command copies the contents of files as they
5207 By default, this command copies the contents of files as they
5208 exist in the working directory. If invoked with -A/--after, the
5208 exist in the working directory. If invoked with -A/--after, the
5209 operation is recorded, but no copying is performed.
5209 operation is recorded, but no copying is performed.
5210
5210
5211 This command takes effect at the next commit. To undo a rename
5211 This command takes effect at the next commit. To undo a rename
5212 before that, see :hg:`revert`.
5212 before that, see :hg:`revert`.
5213
5213
5214 Returns 0 on success, 1 if errors are encountered.
5214 Returns 0 on success, 1 if errors are encountered.
5215 """
5215 """
5216 wlock = repo.wlock(False)
5216 wlock = repo.wlock(False)
5217 try:
5217 try:
5218 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5218 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5219 finally:
5219 finally:
5220 wlock.release()
5220 wlock.release()
5221
5221
5222 @command('resolve',
5222 @command('resolve',
5223 [('a', 'all', None, _('select all unresolved files')),
5223 [('a', 'all', None, _('select all unresolved files')),
5224 ('l', 'list', None, _('list state of files needing merge')),
5224 ('l', 'list', None, _('list state of files needing merge')),
5225 ('m', 'mark', None, _('mark files as resolved')),
5225 ('m', 'mark', None, _('mark files as resolved')),
5226 ('u', 'unmark', None, _('mark files as unresolved')),
5226 ('u', 'unmark', None, _('mark files as unresolved')),
5227 ('n', 'no-status', None, _('hide status prefix'))]
5227 ('n', 'no-status', None, _('hide status prefix'))]
5228 + mergetoolopts + walkopts,
5228 + mergetoolopts + walkopts,
5229 _('[OPTION]... [FILE]...'),
5229 _('[OPTION]... [FILE]...'),
5230 inferrepo=True)
5230 inferrepo=True)
5231 def resolve(ui, repo, *pats, **opts):
5231 def resolve(ui, repo, *pats, **opts):
5232 """redo merges or set/view the merge status of files
5232 """redo merges or set/view the merge status of files
5233
5233
5234 Merges with unresolved conflicts are often the result of
5234 Merges with unresolved conflicts are often the result of
5235 non-interactive merging using the ``internal:merge`` configuration
5235 non-interactive merging using the ``internal:merge`` configuration
5236 setting, or a command-line merge tool like ``diff3``. The resolve
5236 setting, or a command-line merge tool like ``diff3``. The resolve
5237 command is used to manage the files involved in a merge, after
5237 command is used to manage the files involved in a merge, after
5238 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5238 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5239 working directory must have two parents). See :hg:`help
5239 working directory must have two parents). See :hg:`help
5240 merge-tools` for information on configuring merge tools.
5240 merge-tools` for information on configuring merge tools.
5241
5241
5242 The resolve command can be used in the following ways:
5242 The resolve command can be used in the following ways:
5243
5243
5244 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5244 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5245 files, discarding any previous merge attempts. Re-merging is not
5245 files, discarding any previous merge attempts. Re-merging is not
5246 performed for files already marked as resolved. Use ``--all/-a``
5246 performed for files already marked as resolved. Use ``--all/-a``
5247 to select all unresolved files. ``--tool`` can be used to specify
5247 to select all unresolved files. ``--tool`` can be used to specify
5248 the merge tool used for the given files. It overrides the HGMERGE
5248 the merge tool used for the given files. It overrides the HGMERGE
5249 environment variable and your configuration files. Previous file
5249 environment variable and your configuration files. Previous file
5250 contents are saved with a ``.orig`` suffix.
5250 contents are saved with a ``.orig`` suffix.
5251
5251
5252 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5252 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5253 (e.g. after having manually fixed-up the files). The default is
5253 (e.g. after having manually fixed-up the files). The default is
5254 to mark all unresolved files.
5254 to mark all unresolved files.
5255
5255
5256 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5256 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5257 default is to mark all resolved files.
5257 default is to mark all resolved files.
5258
5258
5259 - :hg:`resolve -l`: list files which had or still have conflicts.
5259 - :hg:`resolve -l`: list files which had or still have conflicts.
5260 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5260 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5261
5261
5262 Note that Mercurial will not let you commit files with unresolved
5262 Note that Mercurial will not let you commit files with unresolved
5263 merge conflicts. You must use :hg:`resolve -m ...` before you can
5263 merge conflicts. You must use :hg:`resolve -m ...` before you can
5264 commit after a conflicting merge.
5264 commit after a conflicting merge.
5265
5265
5266 Returns 0 on success, 1 if any files fail a resolve attempt.
5266 Returns 0 on success, 1 if any files fail a resolve attempt.
5267 """
5267 """
5268
5268
5269 all, mark, unmark, show, nostatus = \
5269 all, mark, unmark, show, nostatus = \
5270 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5270 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5271
5271
5272 if (show and (mark or unmark)) or (mark and unmark):
5272 if (show and (mark or unmark)) or (mark and unmark):
5273 raise util.Abort(_("too many options specified"))
5273 raise util.Abort(_("too many options specified"))
5274 if pats and all:
5274 if pats and all:
5275 raise util.Abort(_("can't specify --all and patterns"))
5275 raise util.Abort(_("can't specify --all and patterns"))
5276 if not (all or pats or show or mark or unmark):
5276 if not (all or pats or show or mark or unmark):
5277 raise util.Abort(_('no files or directories specified'),
5277 raise util.Abort(_('no files or directories specified'),
5278 hint=('use --all to remerge all files'))
5278 hint=('use --all to remerge all files'))
5279
5279
5280 wlock = repo.wlock()
5280 wlock = repo.wlock()
5281 try:
5281 try:
5282 ms = mergemod.mergestate(repo)
5282 ms = mergemod.mergestate(repo)
5283
5283
5284 if not (ms.active() or repo.dirstate.p2() != nullid) and not show:
5284 if not (ms.active() or repo.dirstate.p2() != nullid) and not show:
5285 raise util.Abort(
5285 raise util.Abort(
5286 _('resolve command not applicable when not merging'))
5286 _('resolve command not applicable when not merging'))
5287
5287
5288 m = scmutil.match(repo[None], pats, opts)
5288 m = scmutil.match(repo[None], pats, opts)
5289 ret = 0
5289 ret = 0
5290 didwork = False
5290 didwork = False
5291
5291
5292 for f in ms:
5292 for f in ms:
5293 if not m(f):
5293 if not m(f):
5294 continue
5294 continue
5295
5295
5296 didwork = True
5296 didwork = True
5297
5297
5298 if show:
5298 if show:
5299 if nostatus:
5299 if nostatus:
5300 ui.write("%s\n" % f)
5300 ui.write("%s\n" % f)
5301 else:
5301 else:
5302 ui.write("%s %s\n" % (ms[f].upper(), f),
5302 ui.write("%s %s\n" % (ms[f].upper(), f),
5303 label='resolve.' +
5303 label='resolve.' +
5304 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5304 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5305 elif mark:
5305 elif mark:
5306 ms.mark(f, "r")
5306 ms.mark(f, "r")
5307 elif unmark:
5307 elif unmark:
5308 ms.mark(f, "u")
5308 ms.mark(f, "u")
5309 else:
5309 else:
5310 wctx = repo[None]
5310 wctx = repo[None]
5311
5311
5312 # backup pre-resolve (merge uses .orig for its own purposes)
5312 # backup pre-resolve (merge uses .orig for its own purposes)
5313 a = repo.wjoin(f)
5313 a = repo.wjoin(f)
5314 util.copyfile(a, a + ".resolve")
5314 util.copyfile(a, a + ".resolve")
5315
5315
5316 try:
5316 try:
5317 # resolve file
5317 # resolve file
5318 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5318 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5319 'resolve')
5319 'resolve')
5320 if ms.resolve(f, wctx):
5320 if ms.resolve(f, wctx):
5321 ret = 1
5321 ret = 1
5322 finally:
5322 finally:
5323 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5323 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5324 ms.commit()
5324 ms.commit()
5325
5325
5326 # replace filemerge's .orig file with our resolve file
5326 # replace filemerge's .orig file with our resolve file
5327 util.rename(a + ".resolve", a + ".orig")
5327 util.rename(a + ".resolve", a + ".orig")
5328
5328
5329 ms.commit()
5329 ms.commit()
5330
5330
5331 if not didwork and pats:
5331 if not didwork and pats and not show:
5332 ui.warn(_("arguments do not match paths that need resolving\n"))
5332 ui.warn(_("arguments do not match paths that need resolving\n"))
5333
5333
5334 finally:
5334 finally:
5335 wlock.release()
5335 wlock.release()
5336
5336
5337 # Nudge users into finishing an unfinished operation. We don't print
5337 # Nudge users into finishing an unfinished operation. We don't print
5338 # this with the list/show operation because we want list/show to remain
5338 # this with the list/show operation because we want list/show to remain
5339 # machine readable.
5339 # machine readable.
5340 if not list(ms.unresolved()) and not show:
5340 if not list(ms.unresolved()) and not show:
5341 ui.status(_('(no more unresolved files)\n'))
5341 ui.status(_('(no more unresolved files)\n'))
5342
5342
5343 return ret
5343 return ret
5344
5344
5345 @command('revert',
5345 @command('revert',
5346 [('a', 'all', None, _('revert all changes when no arguments given')),
5346 [('a', 'all', None, _('revert all changes when no arguments given')),
5347 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5347 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5348 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5348 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5349 ('C', 'no-backup', None, _('do not save backup copies of files')),
5349 ('C', 'no-backup', None, _('do not save backup copies of files')),
5350 ] + walkopts + dryrunopts,
5350 ] + walkopts + dryrunopts,
5351 _('[OPTION]... [-r REV] [NAME]...'))
5351 _('[OPTION]... [-r REV] [NAME]...'))
5352 def revert(ui, repo, *pats, **opts):
5352 def revert(ui, repo, *pats, **opts):
5353 """restore files to their checkout state
5353 """restore files to their checkout state
5354
5354
5355 .. note::
5355 .. note::
5356
5356
5357 To check out earlier revisions, you should use :hg:`update REV`.
5357 To check out earlier revisions, you should use :hg:`update REV`.
5358 To cancel an uncommitted merge (and lose your changes),
5358 To cancel an uncommitted merge (and lose your changes),
5359 use :hg:`update --clean .`.
5359 use :hg:`update --clean .`.
5360
5360
5361 With no revision specified, revert the specified files or directories
5361 With no revision specified, revert the specified files or directories
5362 to the contents they had in the parent of the working directory.
5362 to the contents they had in the parent of the working directory.
5363 This restores the contents of files to an unmodified
5363 This restores the contents of files to an unmodified
5364 state and unschedules adds, removes, copies, and renames. If the
5364 state and unschedules adds, removes, copies, and renames. If the
5365 working directory has two parents, you must explicitly specify a
5365 working directory has two parents, you must explicitly specify a
5366 revision.
5366 revision.
5367
5367
5368 Using the -r/--rev or -d/--date options, revert the given files or
5368 Using the -r/--rev or -d/--date options, revert the given files or
5369 directories to their states as of a specific revision. Because
5369 directories to their states as of a specific revision. Because
5370 revert does not change the working directory parents, this will
5370 revert does not change the working directory parents, this will
5371 cause these files to appear modified. This can be helpful to "back
5371 cause these files to appear modified. This can be helpful to "back
5372 out" some or all of an earlier change. See :hg:`backout` for a
5372 out" some or all of an earlier change. See :hg:`backout` for a
5373 related method.
5373 related method.
5374
5374
5375 Modified files are saved with a .orig suffix before reverting.
5375 Modified files are saved with a .orig suffix before reverting.
5376 To disable these backups, use --no-backup.
5376 To disable these backups, use --no-backup.
5377
5377
5378 See :hg:`help dates` for a list of formats valid for -d/--date.
5378 See :hg:`help dates` for a list of formats valid for -d/--date.
5379
5379
5380 Returns 0 on success.
5380 Returns 0 on success.
5381 """
5381 """
5382
5382
5383 if opts.get("date"):
5383 if opts.get("date"):
5384 if opts.get("rev"):
5384 if opts.get("rev"):
5385 raise util.Abort(_("you can't specify a revision and a date"))
5385 raise util.Abort(_("you can't specify a revision and a date"))
5386 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5386 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5387
5387
5388 parent, p2 = repo.dirstate.parents()
5388 parent, p2 = repo.dirstate.parents()
5389 if not opts.get('rev') and p2 != nullid:
5389 if not opts.get('rev') and p2 != nullid:
5390 # revert after merge is a trap for new users (issue2915)
5390 # revert after merge is a trap for new users (issue2915)
5391 raise util.Abort(_('uncommitted merge with no revision specified'),
5391 raise util.Abort(_('uncommitted merge with no revision specified'),
5392 hint=_('use "hg update" or see "hg help revert"'))
5392 hint=_('use "hg update" or see "hg help revert"'))
5393
5393
5394 ctx = scmutil.revsingle(repo, opts.get('rev'))
5394 ctx = scmutil.revsingle(repo, opts.get('rev'))
5395
5395
5396 if not pats and not opts.get('all'):
5396 if not pats and not opts.get('all'):
5397 msg = _("no files or directories specified")
5397 msg = _("no files or directories specified")
5398 if p2 != nullid:
5398 if p2 != nullid:
5399 hint = _("uncommitted merge, use --all to discard all changes,"
5399 hint = _("uncommitted merge, use --all to discard all changes,"
5400 " or 'hg update -C .' to abort the merge")
5400 " or 'hg update -C .' to abort the merge")
5401 raise util.Abort(msg, hint=hint)
5401 raise util.Abort(msg, hint=hint)
5402 dirty = util.any(repo.status())
5402 dirty = util.any(repo.status())
5403 node = ctx.node()
5403 node = ctx.node()
5404 if node != parent:
5404 if node != parent:
5405 if dirty:
5405 if dirty:
5406 hint = _("uncommitted changes, use --all to discard all"
5406 hint = _("uncommitted changes, use --all to discard all"
5407 " changes, or 'hg update %s' to update") % ctx.rev()
5407 " changes, or 'hg update %s' to update") % ctx.rev()
5408 else:
5408 else:
5409 hint = _("use --all to revert all files,"
5409 hint = _("use --all to revert all files,"
5410 " or 'hg update %s' to update") % ctx.rev()
5410 " or 'hg update %s' to update") % ctx.rev()
5411 elif dirty:
5411 elif dirty:
5412 hint = _("uncommitted changes, use --all to discard all changes")
5412 hint = _("uncommitted changes, use --all to discard all changes")
5413 else:
5413 else:
5414 hint = _("use --all to revert all files")
5414 hint = _("use --all to revert all files")
5415 raise util.Abort(msg, hint=hint)
5415 raise util.Abort(msg, hint=hint)
5416
5416
5417 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5417 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5418
5418
5419 @command('rollback', dryrunopts +
5419 @command('rollback', dryrunopts +
5420 [('f', 'force', False, _('ignore safety measures'))])
5420 [('f', 'force', False, _('ignore safety measures'))])
5421 def rollback(ui, repo, **opts):
5421 def rollback(ui, repo, **opts):
5422 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5422 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5423
5423
5424 Please use :hg:`commit --amend` instead of rollback to correct
5424 Please use :hg:`commit --amend` instead of rollback to correct
5425 mistakes in the last commit.
5425 mistakes in the last commit.
5426
5426
5427 This command should be used with care. There is only one level of
5427 This command should be used with care. There is only one level of
5428 rollback, and there is no way to undo a rollback. It will also
5428 rollback, and there is no way to undo a rollback. It will also
5429 restore the dirstate at the time of the last transaction, losing
5429 restore the dirstate at the time of the last transaction, losing
5430 any dirstate changes since that time. This command does not alter
5430 any dirstate changes since that time. This command does not alter
5431 the working directory.
5431 the working directory.
5432
5432
5433 Transactions are used to encapsulate the effects of all commands
5433 Transactions are used to encapsulate the effects of all commands
5434 that create new changesets or propagate existing changesets into a
5434 that create new changesets or propagate existing changesets into a
5435 repository.
5435 repository.
5436
5436
5437 .. container:: verbose
5437 .. container:: verbose
5438
5438
5439 For example, the following commands are transactional, and their
5439 For example, the following commands are transactional, and their
5440 effects can be rolled back:
5440 effects can be rolled back:
5441
5441
5442 - commit
5442 - commit
5443 - import
5443 - import
5444 - pull
5444 - pull
5445 - push (with this repository as the destination)
5445 - push (with this repository as the destination)
5446 - unbundle
5446 - unbundle
5447
5447
5448 To avoid permanent data loss, rollback will refuse to rollback a
5448 To avoid permanent data loss, rollback will refuse to rollback a
5449 commit transaction if it isn't checked out. Use --force to
5449 commit transaction if it isn't checked out. Use --force to
5450 override this protection.
5450 override this protection.
5451
5451
5452 This command is not intended for use on public repositories. Once
5452 This command is not intended for use on public repositories. Once
5453 changes are visible for pull by other users, rolling a transaction
5453 changes are visible for pull by other users, rolling a transaction
5454 back locally is ineffective (someone else may already have pulled
5454 back locally is ineffective (someone else may already have pulled
5455 the changes). Furthermore, a race is possible with readers of the
5455 the changes). Furthermore, a race is possible with readers of the
5456 repository; for example an in-progress pull from the repository
5456 repository; for example an in-progress pull from the repository
5457 may fail if a rollback is performed.
5457 may fail if a rollback is performed.
5458
5458
5459 Returns 0 on success, 1 if no rollback data is available.
5459 Returns 0 on success, 1 if no rollback data is available.
5460 """
5460 """
5461 return repo.rollback(dryrun=opts.get('dry_run'),
5461 return repo.rollback(dryrun=opts.get('dry_run'),
5462 force=opts.get('force'))
5462 force=opts.get('force'))
5463
5463
5464 @command('root', [])
5464 @command('root', [])
5465 def root(ui, repo):
5465 def root(ui, repo):
5466 """print the root (top) of the current working directory
5466 """print the root (top) of the current working directory
5467
5467
5468 Print the root directory of the current repository.
5468 Print the root directory of the current repository.
5469
5469
5470 Returns 0 on success.
5470 Returns 0 on success.
5471 """
5471 """
5472 ui.write(repo.root + "\n")
5472 ui.write(repo.root + "\n")
5473
5473
5474 @command('^serve',
5474 @command('^serve',
5475 [('A', 'accesslog', '', _('name of access log file to write to'),
5475 [('A', 'accesslog', '', _('name of access log file to write to'),
5476 _('FILE')),
5476 _('FILE')),
5477 ('d', 'daemon', None, _('run server in background')),
5477 ('d', 'daemon', None, _('run server in background')),
5478 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5478 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5479 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5479 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5480 # use string type, then we can check if something was passed
5480 # use string type, then we can check if something was passed
5481 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5481 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5482 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5482 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5483 _('ADDR')),
5483 _('ADDR')),
5484 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5484 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5485 _('PREFIX')),
5485 _('PREFIX')),
5486 ('n', 'name', '',
5486 ('n', 'name', '',
5487 _('name to show in web pages (default: working directory)'), _('NAME')),
5487 _('name to show in web pages (default: working directory)'), _('NAME')),
5488 ('', 'web-conf', '',
5488 ('', 'web-conf', '',
5489 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5489 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5490 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5490 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5491 _('FILE')),
5491 _('FILE')),
5492 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5492 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5493 ('', 'stdio', None, _('for remote clients')),
5493 ('', 'stdio', None, _('for remote clients')),
5494 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5494 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5495 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5495 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5496 ('', 'style', '', _('template style to use'), _('STYLE')),
5496 ('', 'style', '', _('template style to use'), _('STYLE')),
5497 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5497 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5498 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5498 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5499 _('[OPTION]...'),
5499 _('[OPTION]...'),
5500 optionalrepo=True)
5500 optionalrepo=True)
5501 def serve(ui, repo, **opts):
5501 def serve(ui, repo, **opts):
5502 """start stand-alone webserver
5502 """start stand-alone webserver
5503
5503
5504 Start a local HTTP repository browser and pull server. You can use
5504 Start a local HTTP repository browser and pull server. You can use
5505 this for ad-hoc sharing and browsing of repositories. It is
5505 this for ad-hoc sharing and browsing of repositories. It is
5506 recommended to use a real web server to serve a repository for
5506 recommended to use a real web server to serve a repository for
5507 longer periods of time.
5507 longer periods of time.
5508
5508
5509 Please note that the server does not implement access control.
5509 Please note that the server does not implement access control.
5510 This means that, by default, anybody can read from the server and
5510 This means that, by default, anybody can read from the server and
5511 nobody can write to it by default. Set the ``web.allow_push``
5511 nobody can write to it by default. Set the ``web.allow_push``
5512 option to ``*`` to allow everybody to push to the server. You
5512 option to ``*`` to allow everybody to push to the server. You
5513 should use a real web server if you need to authenticate users.
5513 should use a real web server if you need to authenticate users.
5514
5514
5515 By default, the server logs accesses to stdout and errors to
5515 By default, the server logs accesses to stdout and errors to
5516 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5516 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5517 files.
5517 files.
5518
5518
5519 To have the server choose a free port number to listen on, specify
5519 To have the server choose a free port number to listen on, specify
5520 a port number of 0; in this case, the server will print the port
5520 a port number of 0; in this case, the server will print the port
5521 number it uses.
5521 number it uses.
5522
5522
5523 Returns 0 on success.
5523 Returns 0 on success.
5524 """
5524 """
5525
5525
5526 if opts["stdio"] and opts["cmdserver"]:
5526 if opts["stdio"] and opts["cmdserver"]:
5527 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5527 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5528
5528
5529 if opts["stdio"]:
5529 if opts["stdio"]:
5530 if repo is None:
5530 if repo is None:
5531 raise error.RepoError(_("there is no Mercurial repository here"
5531 raise error.RepoError(_("there is no Mercurial repository here"
5532 " (.hg not found)"))
5532 " (.hg not found)"))
5533 s = sshserver.sshserver(ui, repo)
5533 s = sshserver.sshserver(ui, repo)
5534 s.serve_forever()
5534 s.serve_forever()
5535
5535
5536 if opts["cmdserver"]:
5536 if opts["cmdserver"]:
5537 service = commandserver.createservice(ui, repo, opts)
5537 service = commandserver.createservice(ui, repo, opts)
5538 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5538 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5539
5539
5540 # this way we can check if something was given in the command-line
5540 # this way we can check if something was given in the command-line
5541 if opts.get('port'):
5541 if opts.get('port'):
5542 opts['port'] = util.getport(opts.get('port'))
5542 opts['port'] = util.getport(opts.get('port'))
5543
5543
5544 baseui = repo and repo.baseui or ui
5544 baseui = repo and repo.baseui or ui
5545 optlist = ("name templates style address port prefix ipv6"
5545 optlist = ("name templates style address port prefix ipv6"
5546 " accesslog errorlog certificate encoding")
5546 " accesslog errorlog certificate encoding")
5547 for o in optlist.split():
5547 for o in optlist.split():
5548 val = opts.get(o, '')
5548 val = opts.get(o, '')
5549 if val in (None, ''): # should check against default options instead
5549 if val in (None, ''): # should check against default options instead
5550 continue
5550 continue
5551 baseui.setconfig("web", o, val, 'serve')
5551 baseui.setconfig("web", o, val, 'serve')
5552 if repo and repo.ui != baseui:
5552 if repo and repo.ui != baseui:
5553 repo.ui.setconfig("web", o, val, 'serve')
5553 repo.ui.setconfig("web", o, val, 'serve')
5554
5554
5555 o = opts.get('web_conf') or opts.get('webdir_conf')
5555 o = opts.get('web_conf') or opts.get('webdir_conf')
5556 if not o:
5556 if not o:
5557 if not repo:
5557 if not repo:
5558 raise error.RepoError(_("there is no Mercurial repository"
5558 raise error.RepoError(_("there is no Mercurial repository"
5559 " here (.hg not found)"))
5559 " here (.hg not found)"))
5560 o = repo
5560 o = repo
5561
5561
5562 app = hgweb.hgweb(o, baseui=baseui)
5562 app = hgweb.hgweb(o, baseui=baseui)
5563 service = httpservice(ui, app, opts)
5563 service = httpservice(ui, app, opts)
5564 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5564 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5565
5565
5566 class httpservice(object):
5566 class httpservice(object):
5567 def __init__(self, ui, app, opts):
5567 def __init__(self, ui, app, opts):
5568 self.ui = ui
5568 self.ui = ui
5569 self.app = app
5569 self.app = app
5570 self.opts = opts
5570 self.opts = opts
5571
5571
5572 def init(self):
5572 def init(self):
5573 util.setsignalhandler()
5573 util.setsignalhandler()
5574 self.httpd = hgweb_server.create_server(self.ui, self.app)
5574 self.httpd = hgweb_server.create_server(self.ui, self.app)
5575
5575
5576 if self.opts['port'] and not self.ui.verbose:
5576 if self.opts['port'] and not self.ui.verbose:
5577 return
5577 return
5578
5578
5579 if self.httpd.prefix:
5579 if self.httpd.prefix:
5580 prefix = self.httpd.prefix.strip('/') + '/'
5580 prefix = self.httpd.prefix.strip('/') + '/'
5581 else:
5581 else:
5582 prefix = ''
5582 prefix = ''
5583
5583
5584 port = ':%d' % self.httpd.port
5584 port = ':%d' % self.httpd.port
5585 if port == ':80':
5585 if port == ':80':
5586 port = ''
5586 port = ''
5587
5587
5588 bindaddr = self.httpd.addr
5588 bindaddr = self.httpd.addr
5589 if bindaddr == '0.0.0.0':
5589 if bindaddr == '0.0.0.0':
5590 bindaddr = '*'
5590 bindaddr = '*'
5591 elif ':' in bindaddr: # IPv6
5591 elif ':' in bindaddr: # IPv6
5592 bindaddr = '[%s]' % bindaddr
5592 bindaddr = '[%s]' % bindaddr
5593
5593
5594 fqaddr = self.httpd.fqaddr
5594 fqaddr = self.httpd.fqaddr
5595 if ':' in fqaddr:
5595 if ':' in fqaddr:
5596 fqaddr = '[%s]' % fqaddr
5596 fqaddr = '[%s]' % fqaddr
5597 if self.opts['port']:
5597 if self.opts['port']:
5598 write = self.ui.status
5598 write = self.ui.status
5599 else:
5599 else:
5600 write = self.ui.write
5600 write = self.ui.write
5601 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5601 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5602 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5602 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5603 self.ui.flush() # avoid buffering of status message
5603 self.ui.flush() # avoid buffering of status message
5604
5604
5605 def run(self):
5605 def run(self):
5606 self.httpd.serve_forever()
5606 self.httpd.serve_forever()
5607
5607
5608
5608
5609 @command('^status|st',
5609 @command('^status|st',
5610 [('A', 'all', None, _('show status of all files')),
5610 [('A', 'all', None, _('show status of all files')),
5611 ('m', 'modified', None, _('show only modified files')),
5611 ('m', 'modified', None, _('show only modified files')),
5612 ('a', 'added', None, _('show only added files')),
5612 ('a', 'added', None, _('show only added files')),
5613 ('r', 'removed', None, _('show only removed files')),
5613 ('r', 'removed', None, _('show only removed files')),
5614 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5614 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5615 ('c', 'clean', None, _('show only files without changes')),
5615 ('c', 'clean', None, _('show only files without changes')),
5616 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5616 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5617 ('i', 'ignored', None, _('show only ignored files')),
5617 ('i', 'ignored', None, _('show only ignored files')),
5618 ('n', 'no-status', None, _('hide status prefix')),
5618 ('n', 'no-status', None, _('hide status prefix')),
5619 ('C', 'copies', None, _('show source of copied files')),
5619 ('C', 'copies', None, _('show source of copied files')),
5620 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5620 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5621 ('', 'rev', [], _('show difference from revision'), _('REV')),
5621 ('', 'rev', [], _('show difference from revision'), _('REV')),
5622 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5622 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5623 ] + walkopts + subrepoopts + formatteropts,
5623 ] + walkopts + subrepoopts + formatteropts,
5624 _('[OPTION]... [FILE]...'),
5624 _('[OPTION]... [FILE]...'),
5625 inferrepo=True)
5625 inferrepo=True)
5626 def status(ui, repo, *pats, **opts):
5626 def status(ui, repo, *pats, **opts):
5627 """show changed files in the working directory
5627 """show changed files in the working directory
5628
5628
5629 Show status of files in the repository. If names are given, only
5629 Show status of files in the repository. If names are given, only
5630 files that match are shown. Files that are clean or ignored or
5630 files that match are shown. Files that are clean or ignored or
5631 the source of a copy/move operation, are not listed unless
5631 the source of a copy/move operation, are not listed unless
5632 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5632 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5633 Unless options described with "show only ..." are given, the
5633 Unless options described with "show only ..." are given, the
5634 options -mardu are used.
5634 options -mardu are used.
5635
5635
5636 Option -q/--quiet hides untracked (unknown and ignored) files
5636 Option -q/--quiet hides untracked (unknown and ignored) files
5637 unless explicitly requested with -u/--unknown or -i/--ignored.
5637 unless explicitly requested with -u/--unknown or -i/--ignored.
5638
5638
5639 .. note::
5639 .. note::
5640
5640
5641 status may appear to disagree with diff if permissions have
5641 status may appear to disagree with diff if permissions have
5642 changed or a merge has occurred. The standard diff format does
5642 changed or a merge has occurred. The standard diff format does
5643 not report permission changes and diff only reports changes
5643 not report permission changes and diff only reports changes
5644 relative to one merge parent.
5644 relative to one merge parent.
5645
5645
5646 If one revision is given, it is used as the base revision.
5646 If one revision is given, it is used as the base revision.
5647 If two revisions are given, the differences between them are
5647 If two revisions are given, the differences between them are
5648 shown. The --change option can also be used as a shortcut to list
5648 shown. The --change option can also be used as a shortcut to list
5649 the changed files of a revision from its first parent.
5649 the changed files of a revision from its first parent.
5650
5650
5651 The codes used to show the status of files are::
5651 The codes used to show the status of files are::
5652
5652
5653 M = modified
5653 M = modified
5654 A = added
5654 A = added
5655 R = removed
5655 R = removed
5656 C = clean
5656 C = clean
5657 ! = missing (deleted by non-hg command, but still tracked)
5657 ! = missing (deleted by non-hg command, but still tracked)
5658 ? = not tracked
5658 ? = not tracked
5659 I = ignored
5659 I = ignored
5660 = origin of the previous file (with --copies)
5660 = origin of the previous file (with --copies)
5661
5661
5662 .. container:: verbose
5662 .. container:: verbose
5663
5663
5664 Examples:
5664 Examples:
5665
5665
5666 - show changes in the working directory relative to a
5666 - show changes in the working directory relative to a
5667 changeset::
5667 changeset::
5668
5668
5669 hg status --rev 9353
5669 hg status --rev 9353
5670
5670
5671 - show all changes including copies in an existing changeset::
5671 - show all changes including copies in an existing changeset::
5672
5672
5673 hg status --copies --change 9353
5673 hg status --copies --change 9353
5674
5674
5675 - get a NUL separated list of added files, suitable for xargs::
5675 - get a NUL separated list of added files, suitable for xargs::
5676
5676
5677 hg status -an0
5677 hg status -an0
5678
5678
5679 Returns 0 on success.
5679 Returns 0 on success.
5680 """
5680 """
5681
5681
5682 revs = opts.get('rev')
5682 revs = opts.get('rev')
5683 change = opts.get('change')
5683 change = opts.get('change')
5684
5684
5685 if revs and change:
5685 if revs and change:
5686 msg = _('cannot specify --rev and --change at the same time')
5686 msg = _('cannot specify --rev and --change at the same time')
5687 raise util.Abort(msg)
5687 raise util.Abort(msg)
5688 elif change:
5688 elif change:
5689 node2 = scmutil.revsingle(repo, change, None).node()
5689 node2 = scmutil.revsingle(repo, change, None).node()
5690 node1 = repo[node2].p1().node()
5690 node1 = repo[node2].p1().node()
5691 else:
5691 else:
5692 node1, node2 = scmutil.revpair(repo, revs)
5692 node1, node2 = scmutil.revpair(repo, revs)
5693
5693
5694 cwd = (pats and repo.getcwd()) or ''
5694 cwd = (pats and repo.getcwd()) or ''
5695 end = opts.get('print0') and '\0' or '\n'
5695 end = opts.get('print0') and '\0' or '\n'
5696 copy = {}
5696 copy = {}
5697 states = 'modified added removed deleted unknown ignored clean'.split()
5697 states = 'modified added removed deleted unknown ignored clean'.split()
5698 show = [k for k in states if opts.get(k)]
5698 show = [k for k in states if opts.get(k)]
5699 if opts.get('all'):
5699 if opts.get('all'):
5700 show += ui.quiet and (states[:4] + ['clean']) or states
5700 show += ui.quiet and (states[:4] + ['clean']) or states
5701 if not show:
5701 if not show:
5702 show = ui.quiet and states[:4] or states[:5]
5702 show = ui.quiet and states[:4] or states[:5]
5703
5703
5704 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5704 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5705 'ignored' in show, 'clean' in show, 'unknown' in show,
5705 'ignored' in show, 'clean' in show, 'unknown' in show,
5706 opts.get('subrepos'))
5706 opts.get('subrepos'))
5707 changestates = zip(states, 'MAR!?IC', stat)
5707 changestates = zip(states, 'MAR!?IC', stat)
5708
5708
5709 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5709 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5710 copy = copies.pathcopies(repo[node1], repo[node2])
5710 copy = copies.pathcopies(repo[node1], repo[node2])
5711
5711
5712 fm = ui.formatter('status', opts)
5712 fm = ui.formatter('status', opts)
5713 fmt = '%s' + end
5713 fmt = '%s' + end
5714 showchar = not opts.get('no_status')
5714 showchar = not opts.get('no_status')
5715
5715
5716 for state, char, files in changestates:
5716 for state, char, files in changestates:
5717 if state in show:
5717 if state in show:
5718 label = 'status.' + state
5718 label = 'status.' + state
5719 for f in files:
5719 for f in files:
5720 fm.startitem()
5720 fm.startitem()
5721 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5721 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5722 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5722 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5723 if f in copy:
5723 if f in copy:
5724 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5724 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5725 label='status.copied')
5725 label='status.copied')
5726 fm.end()
5726 fm.end()
5727
5727
5728 @command('^summary|sum',
5728 @command('^summary|sum',
5729 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5729 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5730 def summary(ui, repo, **opts):
5730 def summary(ui, repo, **opts):
5731 """summarize working directory state
5731 """summarize working directory state
5732
5732
5733 This generates a brief summary of the working directory state,
5733 This generates a brief summary of the working directory state,
5734 including parents, branch, commit status, and available updates.
5734 including parents, branch, commit status, and available updates.
5735
5735
5736 With the --remote option, this will check the default paths for
5736 With the --remote option, this will check the default paths for
5737 incoming and outgoing changes. This can be time-consuming.
5737 incoming and outgoing changes. This can be time-consuming.
5738
5738
5739 Returns 0 on success.
5739 Returns 0 on success.
5740 """
5740 """
5741
5741
5742 ctx = repo[None]
5742 ctx = repo[None]
5743 parents = ctx.parents()
5743 parents = ctx.parents()
5744 pnode = parents[0].node()
5744 pnode = parents[0].node()
5745 marks = []
5745 marks = []
5746
5746
5747 for p in parents:
5747 for p in parents:
5748 # label with log.changeset (instead of log.parent) since this
5748 # label with log.changeset (instead of log.parent) since this
5749 # shows a working directory parent *changeset*:
5749 # shows a working directory parent *changeset*:
5750 # i18n: column positioning for "hg summary"
5750 # i18n: column positioning for "hg summary"
5751 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5751 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5752 label='log.changeset changeset.%s' % p.phasestr())
5752 label='log.changeset changeset.%s' % p.phasestr())
5753 ui.write(' '.join(p.tags()), label='log.tag')
5753 ui.write(' '.join(p.tags()), label='log.tag')
5754 if p.bookmarks():
5754 if p.bookmarks():
5755 marks.extend(p.bookmarks())
5755 marks.extend(p.bookmarks())
5756 if p.rev() == -1:
5756 if p.rev() == -1:
5757 if not len(repo):
5757 if not len(repo):
5758 ui.write(_(' (empty repository)'))
5758 ui.write(_(' (empty repository)'))
5759 else:
5759 else:
5760 ui.write(_(' (no revision checked out)'))
5760 ui.write(_(' (no revision checked out)'))
5761 ui.write('\n')
5761 ui.write('\n')
5762 if p.description():
5762 if p.description():
5763 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5763 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5764 label='log.summary')
5764 label='log.summary')
5765
5765
5766 branch = ctx.branch()
5766 branch = ctx.branch()
5767 bheads = repo.branchheads(branch)
5767 bheads = repo.branchheads(branch)
5768 # i18n: column positioning for "hg summary"
5768 # i18n: column positioning for "hg summary"
5769 m = _('branch: %s\n') % branch
5769 m = _('branch: %s\n') % branch
5770 if branch != 'default':
5770 if branch != 'default':
5771 ui.write(m, label='log.branch')
5771 ui.write(m, label='log.branch')
5772 else:
5772 else:
5773 ui.status(m, label='log.branch')
5773 ui.status(m, label='log.branch')
5774
5774
5775 if marks:
5775 if marks:
5776 current = repo._bookmarkcurrent
5776 current = repo._bookmarkcurrent
5777 # i18n: column positioning for "hg summary"
5777 # i18n: column positioning for "hg summary"
5778 ui.write(_('bookmarks:'), label='log.bookmark')
5778 ui.write(_('bookmarks:'), label='log.bookmark')
5779 if current is not None:
5779 if current is not None:
5780 if current in marks:
5780 if current in marks:
5781 ui.write(' *' + current, label='bookmarks.current')
5781 ui.write(' *' + current, label='bookmarks.current')
5782 marks.remove(current)
5782 marks.remove(current)
5783 else:
5783 else:
5784 ui.write(' [%s]' % current, label='bookmarks.current')
5784 ui.write(' [%s]' % current, label='bookmarks.current')
5785 for m in marks:
5785 for m in marks:
5786 ui.write(' ' + m, label='log.bookmark')
5786 ui.write(' ' + m, label='log.bookmark')
5787 ui.write('\n', label='log.bookmark')
5787 ui.write('\n', label='log.bookmark')
5788
5788
5789 status = repo.status(unknown=True)
5789 status = repo.status(unknown=True)
5790
5790
5791 c = repo.dirstate.copies()
5791 c = repo.dirstate.copies()
5792 copied, renamed = [], []
5792 copied, renamed = [], []
5793 for d, s in c.iteritems():
5793 for d, s in c.iteritems():
5794 if s in status.removed:
5794 if s in status.removed:
5795 status.removed.remove(s)
5795 status.removed.remove(s)
5796 renamed.append(d)
5796 renamed.append(d)
5797 else:
5797 else:
5798 copied.append(d)
5798 copied.append(d)
5799 if d in status.added:
5799 if d in status.added:
5800 status.added.remove(d)
5800 status.added.remove(d)
5801
5801
5802 ms = mergemod.mergestate(repo)
5802 ms = mergemod.mergestate(repo)
5803 unresolved = [f for f in ms if ms[f] == 'u']
5803 unresolved = [f for f in ms if ms[f] == 'u']
5804
5804
5805 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5805 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5806
5806
5807 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5807 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5808 (ui.label(_('%d added'), 'status.added'), status.added),
5808 (ui.label(_('%d added'), 'status.added'), status.added),
5809 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5809 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5810 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5810 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5811 (ui.label(_('%d copied'), 'status.copied'), copied),
5811 (ui.label(_('%d copied'), 'status.copied'), copied),
5812 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5812 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5813 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5813 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5814 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5814 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5815 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5815 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5816 t = []
5816 t = []
5817 for l, s in labels:
5817 for l, s in labels:
5818 if s:
5818 if s:
5819 t.append(l % len(s))
5819 t.append(l % len(s))
5820
5820
5821 t = ', '.join(t)
5821 t = ', '.join(t)
5822 cleanworkdir = False
5822 cleanworkdir = False
5823
5823
5824 if repo.vfs.exists('updatestate'):
5824 if repo.vfs.exists('updatestate'):
5825 t += _(' (interrupted update)')
5825 t += _(' (interrupted update)')
5826 elif len(parents) > 1:
5826 elif len(parents) > 1:
5827 t += _(' (merge)')
5827 t += _(' (merge)')
5828 elif branch != parents[0].branch():
5828 elif branch != parents[0].branch():
5829 t += _(' (new branch)')
5829 t += _(' (new branch)')
5830 elif (parents[0].closesbranch() and
5830 elif (parents[0].closesbranch() and
5831 pnode in repo.branchheads(branch, closed=True)):
5831 pnode in repo.branchheads(branch, closed=True)):
5832 t += _(' (head closed)')
5832 t += _(' (head closed)')
5833 elif not (status.modified or status.added or status.removed or renamed or
5833 elif not (status.modified or status.added or status.removed or renamed or
5834 copied or subs):
5834 copied or subs):
5835 t += _(' (clean)')
5835 t += _(' (clean)')
5836 cleanworkdir = True
5836 cleanworkdir = True
5837 elif pnode not in bheads:
5837 elif pnode not in bheads:
5838 t += _(' (new branch head)')
5838 t += _(' (new branch head)')
5839
5839
5840 if cleanworkdir:
5840 if cleanworkdir:
5841 # i18n: column positioning for "hg summary"
5841 # i18n: column positioning for "hg summary"
5842 ui.status(_('commit: %s\n') % t.strip())
5842 ui.status(_('commit: %s\n') % t.strip())
5843 else:
5843 else:
5844 # i18n: column positioning for "hg summary"
5844 # i18n: column positioning for "hg summary"
5845 ui.write(_('commit: %s\n') % t.strip())
5845 ui.write(_('commit: %s\n') % t.strip())
5846
5846
5847 # all ancestors of branch heads - all ancestors of parent = new csets
5847 # all ancestors of branch heads - all ancestors of parent = new csets
5848 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5848 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5849 bheads))
5849 bheads))
5850
5850
5851 if new == 0:
5851 if new == 0:
5852 # i18n: column positioning for "hg summary"
5852 # i18n: column positioning for "hg summary"
5853 ui.status(_('update: (current)\n'))
5853 ui.status(_('update: (current)\n'))
5854 elif pnode not in bheads:
5854 elif pnode not in bheads:
5855 # i18n: column positioning for "hg summary"
5855 # i18n: column positioning for "hg summary"
5856 ui.write(_('update: %d new changesets (update)\n') % new)
5856 ui.write(_('update: %d new changesets (update)\n') % new)
5857 else:
5857 else:
5858 # i18n: column positioning for "hg summary"
5858 # i18n: column positioning for "hg summary"
5859 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5859 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5860 (new, len(bheads)))
5860 (new, len(bheads)))
5861
5861
5862 cmdutil.summaryhooks(ui, repo)
5862 cmdutil.summaryhooks(ui, repo)
5863
5863
5864 if opts.get('remote'):
5864 if opts.get('remote'):
5865 needsincoming, needsoutgoing = True, True
5865 needsincoming, needsoutgoing = True, True
5866 else:
5866 else:
5867 needsincoming, needsoutgoing = False, False
5867 needsincoming, needsoutgoing = False, False
5868 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5868 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5869 if i:
5869 if i:
5870 needsincoming = True
5870 needsincoming = True
5871 if o:
5871 if o:
5872 needsoutgoing = True
5872 needsoutgoing = True
5873 if not needsincoming and not needsoutgoing:
5873 if not needsincoming and not needsoutgoing:
5874 return
5874 return
5875
5875
5876 def getincoming():
5876 def getincoming():
5877 source, branches = hg.parseurl(ui.expandpath('default'))
5877 source, branches = hg.parseurl(ui.expandpath('default'))
5878 sbranch = branches[0]
5878 sbranch = branches[0]
5879 try:
5879 try:
5880 other = hg.peer(repo, {}, source)
5880 other = hg.peer(repo, {}, source)
5881 except error.RepoError:
5881 except error.RepoError:
5882 if opts.get('remote'):
5882 if opts.get('remote'):
5883 raise
5883 raise
5884 return source, sbranch, None, None, None
5884 return source, sbranch, None, None, None
5885 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5885 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5886 if revs:
5886 if revs:
5887 revs = [other.lookup(rev) for rev in revs]
5887 revs = [other.lookup(rev) for rev in revs]
5888 ui.debug('comparing with %s\n' % util.hidepassword(source))
5888 ui.debug('comparing with %s\n' % util.hidepassword(source))
5889 repo.ui.pushbuffer()
5889 repo.ui.pushbuffer()
5890 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5890 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5891 repo.ui.popbuffer()
5891 repo.ui.popbuffer()
5892 return source, sbranch, other, commoninc, commoninc[1]
5892 return source, sbranch, other, commoninc, commoninc[1]
5893
5893
5894 if needsincoming:
5894 if needsincoming:
5895 source, sbranch, sother, commoninc, incoming = getincoming()
5895 source, sbranch, sother, commoninc, incoming = getincoming()
5896 else:
5896 else:
5897 source = sbranch = sother = commoninc = incoming = None
5897 source = sbranch = sother = commoninc = incoming = None
5898
5898
5899 def getoutgoing():
5899 def getoutgoing():
5900 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5900 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5901 dbranch = branches[0]
5901 dbranch = branches[0]
5902 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5902 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5903 if source != dest:
5903 if source != dest:
5904 try:
5904 try:
5905 dother = hg.peer(repo, {}, dest)
5905 dother = hg.peer(repo, {}, dest)
5906 except error.RepoError:
5906 except error.RepoError:
5907 if opts.get('remote'):
5907 if opts.get('remote'):
5908 raise
5908 raise
5909 return dest, dbranch, None, None
5909 return dest, dbranch, None, None
5910 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5910 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5911 elif sother is None:
5911 elif sother is None:
5912 # there is no explicit destination peer, but source one is invalid
5912 # there is no explicit destination peer, but source one is invalid
5913 return dest, dbranch, None, None
5913 return dest, dbranch, None, None
5914 else:
5914 else:
5915 dother = sother
5915 dother = sother
5916 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5916 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5917 common = None
5917 common = None
5918 else:
5918 else:
5919 common = commoninc
5919 common = commoninc
5920 if revs:
5920 if revs:
5921 revs = [repo.lookup(rev) for rev in revs]
5921 revs = [repo.lookup(rev) for rev in revs]
5922 repo.ui.pushbuffer()
5922 repo.ui.pushbuffer()
5923 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5923 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5924 commoninc=common)
5924 commoninc=common)
5925 repo.ui.popbuffer()
5925 repo.ui.popbuffer()
5926 return dest, dbranch, dother, outgoing
5926 return dest, dbranch, dother, outgoing
5927
5927
5928 if needsoutgoing:
5928 if needsoutgoing:
5929 dest, dbranch, dother, outgoing = getoutgoing()
5929 dest, dbranch, dother, outgoing = getoutgoing()
5930 else:
5930 else:
5931 dest = dbranch = dother = outgoing = None
5931 dest = dbranch = dother = outgoing = None
5932
5932
5933 if opts.get('remote'):
5933 if opts.get('remote'):
5934 t = []
5934 t = []
5935 if incoming:
5935 if incoming:
5936 t.append(_('1 or more incoming'))
5936 t.append(_('1 or more incoming'))
5937 o = outgoing.missing
5937 o = outgoing.missing
5938 if o:
5938 if o:
5939 t.append(_('%d outgoing') % len(o))
5939 t.append(_('%d outgoing') % len(o))
5940 other = dother or sother
5940 other = dother or sother
5941 if 'bookmarks' in other.listkeys('namespaces'):
5941 if 'bookmarks' in other.listkeys('namespaces'):
5942 lmarks = repo.listkeys('bookmarks')
5942 lmarks = repo.listkeys('bookmarks')
5943 rmarks = other.listkeys('bookmarks')
5943 rmarks = other.listkeys('bookmarks')
5944 diff = set(rmarks) - set(lmarks)
5944 diff = set(rmarks) - set(lmarks)
5945 if len(diff) > 0:
5945 if len(diff) > 0:
5946 t.append(_('%d incoming bookmarks') % len(diff))
5946 t.append(_('%d incoming bookmarks') % len(diff))
5947 diff = set(lmarks) - set(rmarks)
5947 diff = set(lmarks) - set(rmarks)
5948 if len(diff) > 0:
5948 if len(diff) > 0:
5949 t.append(_('%d outgoing bookmarks') % len(diff))
5949 t.append(_('%d outgoing bookmarks') % len(diff))
5950
5950
5951 if t:
5951 if t:
5952 # i18n: column positioning for "hg summary"
5952 # i18n: column positioning for "hg summary"
5953 ui.write(_('remote: %s\n') % (', '.join(t)))
5953 ui.write(_('remote: %s\n') % (', '.join(t)))
5954 else:
5954 else:
5955 # i18n: column positioning for "hg summary"
5955 # i18n: column positioning for "hg summary"
5956 ui.status(_('remote: (synced)\n'))
5956 ui.status(_('remote: (synced)\n'))
5957
5957
5958 cmdutil.summaryremotehooks(ui, repo, opts,
5958 cmdutil.summaryremotehooks(ui, repo, opts,
5959 ((source, sbranch, sother, commoninc),
5959 ((source, sbranch, sother, commoninc),
5960 (dest, dbranch, dother, outgoing)))
5960 (dest, dbranch, dother, outgoing)))
5961
5961
5962 @command('tag',
5962 @command('tag',
5963 [('f', 'force', None, _('force tag')),
5963 [('f', 'force', None, _('force tag')),
5964 ('l', 'local', None, _('make the tag local')),
5964 ('l', 'local', None, _('make the tag local')),
5965 ('r', 'rev', '', _('revision to tag'), _('REV')),
5965 ('r', 'rev', '', _('revision to tag'), _('REV')),
5966 ('', 'remove', None, _('remove a tag')),
5966 ('', 'remove', None, _('remove a tag')),
5967 # -l/--local is already there, commitopts cannot be used
5967 # -l/--local is already there, commitopts cannot be used
5968 ('e', 'edit', None, _('invoke editor on commit messages')),
5968 ('e', 'edit', None, _('invoke editor on commit messages')),
5969 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5969 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5970 ] + commitopts2,
5970 ] + commitopts2,
5971 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5971 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5972 def tag(ui, repo, name1, *names, **opts):
5972 def tag(ui, repo, name1, *names, **opts):
5973 """add one or more tags for the current or given revision
5973 """add one or more tags for the current or given revision
5974
5974
5975 Name a particular revision using <name>.
5975 Name a particular revision using <name>.
5976
5976
5977 Tags are used to name particular revisions of the repository and are
5977 Tags are used to name particular revisions of the repository and are
5978 very useful to compare different revisions, to go back to significant
5978 very useful to compare different revisions, to go back to significant
5979 earlier versions or to mark branch points as releases, etc. Changing
5979 earlier versions or to mark branch points as releases, etc. Changing
5980 an existing tag is normally disallowed; use -f/--force to override.
5980 an existing tag is normally disallowed; use -f/--force to override.
5981
5981
5982 If no revision is given, the parent of the working directory is
5982 If no revision is given, the parent of the working directory is
5983 used.
5983 used.
5984
5984
5985 To facilitate version control, distribution, and merging of tags,
5985 To facilitate version control, distribution, and merging of tags,
5986 they are stored as a file named ".hgtags" which is managed similarly
5986 they are stored as a file named ".hgtags" which is managed similarly
5987 to other project files and can be hand-edited if necessary. This
5987 to other project files and can be hand-edited if necessary. This
5988 also means that tagging creates a new commit. The file
5988 also means that tagging creates a new commit. The file
5989 ".hg/localtags" is used for local tags (not shared among
5989 ".hg/localtags" is used for local tags (not shared among
5990 repositories).
5990 repositories).
5991
5991
5992 Tag commits are usually made at the head of a branch. If the parent
5992 Tag commits are usually made at the head of a branch. If the parent
5993 of the working directory is not a branch head, :hg:`tag` aborts; use
5993 of the working directory is not a branch head, :hg:`tag` aborts; use
5994 -f/--force to force the tag commit to be based on a non-head
5994 -f/--force to force the tag commit to be based on a non-head
5995 changeset.
5995 changeset.
5996
5996
5997 See :hg:`help dates` for a list of formats valid for -d/--date.
5997 See :hg:`help dates` for a list of formats valid for -d/--date.
5998
5998
5999 Since tag names have priority over branch names during revision
5999 Since tag names have priority over branch names during revision
6000 lookup, using an existing branch name as a tag name is discouraged.
6000 lookup, using an existing branch name as a tag name is discouraged.
6001
6001
6002 Returns 0 on success.
6002 Returns 0 on success.
6003 """
6003 """
6004 wlock = lock = None
6004 wlock = lock = None
6005 try:
6005 try:
6006 wlock = repo.wlock()
6006 wlock = repo.wlock()
6007 lock = repo.lock()
6007 lock = repo.lock()
6008 rev_ = "."
6008 rev_ = "."
6009 names = [t.strip() for t in (name1,) + names]
6009 names = [t.strip() for t in (name1,) + names]
6010 if len(names) != len(set(names)):
6010 if len(names) != len(set(names)):
6011 raise util.Abort(_('tag names must be unique'))
6011 raise util.Abort(_('tag names must be unique'))
6012 for n in names:
6012 for n in names:
6013 scmutil.checknewlabel(repo, n, 'tag')
6013 scmutil.checknewlabel(repo, n, 'tag')
6014 if not n:
6014 if not n:
6015 raise util.Abort(_('tag names cannot consist entirely of '
6015 raise util.Abort(_('tag names cannot consist entirely of '
6016 'whitespace'))
6016 'whitespace'))
6017 if opts.get('rev') and opts.get('remove'):
6017 if opts.get('rev') and opts.get('remove'):
6018 raise util.Abort(_("--rev and --remove are incompatible"))
6018 raise util.Abort(_("--rev and --remove are incompatible"))
6019 if opts.get('rev'):
6019 if opts.get('rev'):
6020 rev_ = opts['rev']
6020 rev_ = opts['rev']
6021 message = opts.get('message')
6021 message = opts.get('message')
6022 if opts.get('remove'):
6022 if opts.get('remove'):
6023 expectedtype = opts.get('local') and 'local' or 'global'
6023 expectedtype = opts.get('local') and 'local' or 'global'
6024 for n in names:
6024 for n in names:
6025 if not repo.tagtype(n):
6025 if not repo.tagtype(n):
6026 raise util.Abort(_("tag '%s' does not exist") % n)
6026 raise util.Abort(_("tag '%s' does not exist") % n)
6027 if repo.tagtype(n) != expectedtype:
6027 if repo.tagtype(n) != expectedtype:
6028 if expectedtype == 'global':
6028 if expectedtype == 'global':
6029 raise util.Abort(_("tag '%s' is not a global tag") % n)
6029 raise util.Abort(_("tag '%s' is not a global tag") % n)
6030 else:
6030 else:
6031 raise util.Abort(_("tag '%s' is not a local tag") % n)
6031 raise util.Abort(_("tag '%s' is not a local tag") % n)
6032 rev_ = nullid
6032 rev_ = nullid
6033 if not message:
6033 if not message:
6034 # we don't translate commit messages
6034 # we don't translate commit messages
6035 message = 'Removed tag %s' % ', '.join(names)
6035 message = 'Removed tag %s' % ', '.join(names)
6036 elif not opts.get('force'):
6036 elif not opts.get('force'):
6037 for n in names:
6037 for n in names:
6038 if n in repo.tags():
6038 if n in repo.tags():
6039 raise util.Abort(_("tag '%s' already exists "
6039 raise util.Abort(_("tag '%s' already exists "
6040 "(use -f to force)") % n)
6040 "(use -f to force)") % n)
6041 if not opts.get('local'):
6041 if not opts.get('local'):
6042 p1, p2 = repo.dirstate.parents()
6042 p1, p2 = repo.dirstate.parents()
6043 if p2 != nullid:
6043 if p2 != nullid:
6044 raise util.Abort(_('uncommitted merge'))
6044 raise util.Abort(_('uncommitted merge'))
6045 bheads = repo.branchheads()
6045 bheads = repo.branchheads()
6046 if not opts.get('force') and bheads and p1 not in bheads:
6046 if not opts.get('force') and bheads and p1 not in bheads:
6047 raise util.Abort(_('not at a branch head (use -f to force)'))
6047 raise util.Abort(_('not at a branch head (use -f to force)'))
6048 r = scmutil.revsingle(repo, rev_).node()
6048 r = scmutil.revsingle(repo, rev_).node()
6049
6049
6050 if not message:
6050 if not message:
6051 # we don't translate commit messages
6051 # we don't translate commit messages
6052 message = ('Added tag %s for changeset %s' %
6052 message = ('Added tag %s for changeset %s' %
6053 (', '.join(names), short(r)))
6053 (', '.join(names), short(r)))
6054
6054
6055 date = opts.get('date')
6055 date = opts.get('date')
6056 if date:
6056 if date:
6057 date = util.parsedate(date)
6057 date = util.parsedate(date)
6058
6058
6059 if opts.get('remove'):
6059 if opts.get('remove'):
6060 editform = 'tag.remove'
6060 editform = 'tag.remove'
6061 else:
6061 else:
6062 editform = 'tag.add'
6062 editform = 'tag.add'
6063 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6063 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6064
6064
6065 # don't allow tagging the null rev
6065 # don't allow tagging the null rev
6066 if (not opts.get('remove') and
6066 if (not opts.get('remove') and
6067 scmutil.revsingle(repo, rev_).rev() == nullrev):
6067 scmutil.revsingle(repo, rev_).rev() == nullrev):
6068 raise util.Abort(_("cannot tag null revision"))
6068 raise util.Abort(_("cannot tag null revision"))
6069
6069
6070 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6070 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6071 editor=editor)
6071 editor=editor)
6072 finally:
6072 finally:
6073 release(lock, wlock)
6073 release(lock, wlock)
6074
6074
6075 @command('tags', formatteropts, '')
6075 @command('tags', formatteropts, '')
6076 def tags(ui, repo, **opts):
6076 def tags(ui, repo, **opts):
6077 """list repository tags
6077 """list repository tags
6078
6078
6079 This lists both regular and local tags. When the -v/--verbose
6079 This lists both regular and local tags. When the -v/--verbose
6080 switch is used, a third column "local" is printed for local tags.
6080 switch is used, a third column "local" is printed for local tags.
6081
6081
6082 Returns 0 on success.
6082 Returns 0 on success.
6083 """
6083 """
6084
6084
6085 fm = ui.formatter('tags', opts)
6085 fm = ui.formatter('tags', opts)
6086 hexfunc = fm.hexfunc
6086 hexfunc = fm.hexfunc
6087 tagtype = ""
6087 tagtype = ""
6088
6088
6089 for t, n in reversed(repo.tagslist()):
6089 for t, n in reversed(repo.tagslist()):
6090 hn = hexfunc(n)
6090 hn = hexfunc(n)
6091 label = 'tags.normal'
6091 label = 'tags.normal'
6092 tagtype = ''
6092 tagtype = ''
6093 if repo.tagtype(t) == 'local':
6093 if repo.tagtype(t) == 'local':
6094 label = 'tags.local'
6094 label = 'tags.local'
6095 tagtype = 'local'
6095 tagtype = 'local'
6096
6096
6097 fm.startitem()
6097 fm.startitem()
6098 fm.write('tag', '%s', t, label=label)
6098 fm.write('tag', '%s', t, label=label)
6099 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6099 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6100 fm.condwrite(not ui.quiet, 'rev node', fmt,
6100 fm.condwrite(not ui.quiet, 'rev node', fmt,
6101 repo.changelog.rev(n), hn, label=label)
6101 repo.changelog.rev(n), hn, label=label)
6102 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6102 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6103 tagtype, label=label)
6103 tagtype, label=label)
6104 fm.plain('\n')
6104 fm.plain('\n')
6105 fm.end()
6105 fm.end()
6106
6106
6107 @command('tip',
6107 @command('tip',
6108 [('p', 'patch', None, _('show patch')),
6108 [('p', 'patch', None, _('show patch')),
6109 ('g', 'git', None, _('use git extended diff format')),
6109 ('g', 'git', None, _('use git extended diff format')),
6110 ] + templateopts,
6110 ] + templateopts,
6111 _('[-p] [-g]'))
6111 _('[-p] [-g]'))
6112 def tip(ui, repo, **opts):
6112 def tip(ui, repo, **opts):
6113 """show the tip revision (DEPRECATED)
6113 """show the tip revision (DEPRECATED)
6114
6114
6115 The tip revision (usually just called the tip) is the changeset
6115 The tip revision (usually just called the tip) is the changeset
6116 most recently added to the repository (and therefore the most
6116 most recently added to the repository (and therefore the most
6117 recently changed head).
6117 recently changed head).
6118
6118
6119 If you have just made a commit, that commit will be the tip. If
6119 If you have just made a commit, that commit will be the tip. If
6120 you have just pulled changes from another repository, the tip of
6120 you have just pulled changes from another repository, the tip of
6121 that repository becomes the current tip. The "tip" tag is special
6121 that repository becomes the current tip. The "tip" tag is special
6122 and cannot be renamed or assigned to a different changeset.
6122 and cannot be renamed or assigned to a different changeset.
6123
6123
6124 This command is deprecated, please use :hg:`heads` instead.
6124 This command is deprecated, please use :hg:`heads` instead.
6125
6125
6126 Returns 0 on success.
6126 Returns 0 on success.
6127 """
6127 """
6128 displayer = cmdutil.show_changeset(ui, repo, opts)
6128 displayer = cmdutil.show_changeset(ui, repo, opts)
6129 displayer.show(repo['tip'])
6129 displayer.show(repo['tip'])
6130 displayer.close()
6130 displayer.close()
6131
6131
6132 @command('unbundle',
6132 @command('unbundle',
6133 [('u', 'update', None,
6133 [('u', 'update', None,
6134 _('update to new branch head if changesets were unbundled'))],
6134 _('update to new branch head if changesets were unbundled'))],
6135 _('[-u] FILE...'))
6135 _('[-u] FILE...'))
6136 def unbundle(ui, repo, fname1, *fnames, **opts):
6136 def unbundle(ui, repo, fname1, *fnames, **opts):
6137 """apply one or more changegroup files
6137 """apply one or more changegroup files
6138
6138
6139 Apply one or more compressed changegroup files generated by the
6139 Apply one or more compressed changegroup files generated by the
6140 bundle command.
6140 bundle command.
6141
6141
6142 Returns 0 on success, 1 if an update has unresolved files.
6142 Returns 0 on success, 1 if an update has unresolved files.
6143 """
6143 """
6144 fnames = (fname1,) + fnames
6144 fnames = (fname1,) + fnames
6145
6145
6146 lock = repo.lock()
6146 lock = repo.lock()
6147 try:
6147 try:
6148 for fname in fnames:
6148 for fname in fnames:
6149 f = hg.openpath(ui, fname)
6149 f = hg.openpath(ui, fname)
6150 gen = exchange.readbundle(ui, f, fname)
6150 gen = exchange.readbundle(ui, f, fname)
6151 if isinstance(gen, bundle2.unbundle20):
6151 if isinstance(gen, bundle2.unbundle20):
6152 tr = repo.transaction('unbundle')
6152 tr = repo.transaction('unbundle')
6153 try:
6153 try:
6154 op = bundle2.processbundle(repo, gen, lambda: tr)
6154 op = bundle2.processbundle(repo, gen, lambda: tr)
6155 tr.close()
6155 tr.close()
6156 finally:
6156 finally:
6157 if tr:
6157 if tr:
6158 tr.release()
6158 tr.release()
6159 changes = [r.get('result', 0)
6159 changes = [r.get('result', 0)
6160 for r in op.records['changegroup']]
6160 for r in op.records['changegroup']]
6161 modheads = changegroup.combineresults(changes)
6161 modheads = changegroup.combineresults(changes)
6162 else:
6162 else:
6163 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6163 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6164 'bundle:' + fname)
6164 'bundle:' + fname)
6165 finally:
6165 finally:
6166 lock.release()
6166 lock.release()
6167
6167
6168 return postincoming(ui, repo, modheads, opts.get('update'), None)
6168 return postincoming(ui, repo, modheads, opts.get('update'), None)
6169
6169
6170 @command('^update|up|checkout|co',
6170 @command('^update|up|checkout|co',
6171 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6171 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6172 ('c', 'check', None,
6172 ('c', 'check', None,
6173 _('update across branches if no uncommitted changes')),
6173 _('update across branches if no uncommitted changes')),
6174 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6174 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6175 ('r', 'rev', '', _('revision'), _('REV'))
6175 ('r', 'rev', '', _('revision'), _('REV'))
6176 ] + mergetoolopts,
6176 ] + mergetoolopts,
6177 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6177 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6178 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6178 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6179 tool=None):
6179 tool=None):
6180 """update working directory (or switch revisions)
6180 """update working directory (or switch revisions)
6181
6181
6182 Update the repository's working directory to the specified
6182 Update the repository's working directory to the specified
6183 changeset. If no changeset is specified, update to the tip of the
6183 changeset. If no changeset is specified, update to the tip of the
6184 current named branch and move the current bookmark (see :hg:`help
6184 current named branch and move the current bookmark (see :hg:`help
6185 bookmarks`).
6185 bookmarks`).
6186
6186
6187 Update sets the working directory's parent revision to the specified
6187 Update sets the working directory's parent revision to the specified
6188 changeset (see :hg:`help parents`).
6188 changeset (see :hg:`help parents`).
6189
6189
6190 If the changeset is not a descendant or ancestor of the working
6190 If the changeset is not a descendant or ancestor of the working
6191 directory's parent, the update is aborted. With the -c/--check
6191 directory's parent, the update is aborted. With the -c/--check
6192 option, the working directory is checked for uncommitted changes; if
6192 option, the working directory is checked for uncommitted changes; if
6193 none are found, the working directory is updated to the specified
6193 none are found, the working directory is updated to the specified
6194 changeset.
6194 changeset.
6195
6195
6196 .. container:: verbose
6196 .. container:: verbose
6197
6197
6198 The following rules apply when the working directory contains
6198 The following rules apply when the working directory contains
6199 uncommitted changes:
6199 uncommitted changes:
6200
6200
6201 1. If neither -c/--check nor -C/--clean is specified, and if
6201 1. If neither -c/--check nor -C/--clean is specified, and if
6202 the requested changeset is an ancestor or descendant of
6202 the requested changeset is an ancestor or descendant of
6203 the working directory's parent, the uncommitted changes
6203 the working directory's parent, the uncommitted changes
6204 are merged into the requested changeset and the merged
6204 are merged into the requested changeset and the merged
6205 result is left uncommitted. If the requested changeset is
6205 result is left uncommitted. If the requested changeset is
6206 not an ancestor or descendant (that is, it is on another
6206 not an ancestor or descendant (that is, it is on another
6207 branch), the update is aborted and the uncommitted changes
6207 branch), the update is aborted and the uncommitted changes
6208 are preserved.
6208 are preserved.
6209
6209
6210 2. With the -c/--check option, the update is aborted and the
6210 2. With the -c/--check option, the update is aborted and the
6211 uncommitted changes are preserved.
6211 uncommitted changes are preserved.
6212
6212
6213 3. With the -C/--clean option, uncommitted changes are discarded and
6213 3. With the -C/--clean option, uncommitted changes are discarded and
6214 the working directory is updated to the requested changeset.
6214 the working directory is updated to the requested changeset.
6215
6215
6216 To cancel an uncommitted merge (and lose your changes), use
6216 To cancel an uncommitted merge (and lose your changes), use
6217 :hg:`update --clean .`.
6217 :hg:`update --clean .`.
6218
6218
6219 Use null as the changeset to remove the working directory (like
6219 Use null as the changeset to remove the working directory (like
6220 :hg:`clone -U`).
6220 :hg:`clone -U`).
6221
6221
6222 If you want to revert just one file to an older revision, use
6222 If you want to revert just one file to an older revision, use
6223 :hg:`revert [-r REV] NAME`.
6223 :hg:`revert [-r REV] NAME`.
6224
6224
6225 See :hg:`help dates` for a list of formats valid for -d/--date.
6225 See :hg:`help dates` for a list of formats valid for -d/--date.
6226
6226
6227 Returns 0 on success, 1 if there are unresolved files.
6227 Returns 0 on success, 1 if there are unresolved files.
6228 """
6228 """
6229 if rev and node:
6229 if rev and node:
6230 raise util.Abort(_("please specify just one revision"))
6230 raise util.Abort(_("please specify just one revision"))
6231
6231
6232 if rev is None or rev == '':
6232 if rev is None or rev == '':
6233 rev = node
6233 rev = node
6234
6234
6235 cmdutil.clearunfinished(repo)
6235 cmdutil.clearunfinished(repo)
6236
6236
6237 # with no argument, we also move the current bookmark, if any
6237 # with no argument, we also move the current bookmark, if any
6238 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6238 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6239
6239
6240 # if we defined a bookmark, we have to remember the original bookmark name
6240 # if we defined a bookmark, we have to remember the original bookmark name
6241 brev = rev
6241 brev = rev
6242 rev = scmutil.revsingle(repo, rev, rev).rev()
6242 rev = scmutil.revsingle(repo, rev, rev).rev()
6243
6243
6244 if check and clean:
6244 if check and clean:
6245 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6245 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6246
6246
6247 if date:
6247 if date:
6248 if rev is not None:
6248 if rev is not None:
6249 raise util.Abort(_("you can't specify a revision and a date"))
6249 raise util.Abort(_("you can't specify a revision and a date"))
6250 rev = cmdutil.finddate(ui, repo, date)
6250 rev = cmdutil.finddate(ui, repo, date)
6251
6251
6252 if check:
6252 if check:
6253 c = repo[None]
6253 c = repo[None]
6254 if c.dirty(merge=False, branch=False, missing=True):
6254 if c.dirty(merge=False, branch=False, missing=True):
6255 raise util.Abort(_("uncommitted changes"))
6255 raise util.Abort(_("uncommitted changes"))
6256 if rev is None:
6256 if rev is None:
6257 rev = repo[repo[None].branch()].rev()
6257 rev = repo[repo[None].branch()].rev()
6258
6258
6259 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6259 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6260
6260
6261 if clean:
6261 if clean:
6262 ret = hg.clean(repo, rev)
6262 ret = hg.clean(repo, rev)
6263 else:
6263 else:
6264 ret = hg.update(repo, rev)
6264 ret = hg.update(repo, rev)
6265
6265
6266 if not ret and movemarkfrom:
6266 if not ret and movemarkfrom:
6267 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6267 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6268 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6268 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6269 elif brev in repo._bookmarks:
6269 elif brev in repo._bookmarks:
6270 bookmarks.setcurrent(repo, brev)
6270 bookmarks.setcurrent(repo, brev)
6271 ui.status(_("(activating bookmark %s)\n") % brev)
6271 ui.status(_("(activating bookmark %s)\n") % brev)
6272 elif brev:
6272 elif brev:
6273 if repo._bookmarkcurrent:
6273 if repo._bookmarkcurrent:
6274 ui.status(_("(leaving bookmark %s)\n") %
6274 ui.status(_("(leaving bookmark %s)\n") %
6275 repo._bookmarkcurrent)
6275 repo._bookmarkcurrent)
6276 bookmarks.unsetcurrent(repo)
6276 bookmarks.unsetcurrent(repo)
6277
6277
6278 return ret
6278 return ret
6279
6279
6280 @command('verify', [])
6280 @command('verify', [])
6281 def verify(ui, repo):
6281 def verify(ui, repo):
6282 """verify the integrity of the repository
6282 """verify the integrity of the repository
6283
6283
6284 Verify the integrity of the current repository.
6284 Verify the integrity of the current repository.
6285
6285
6286 This will perform an extensive check of the repository's
6286 This will perform an extensive check of the repository's
6287 integrity, validating the hashes and checksums of each entry in
6287 integrity, validating the hashes and checksums of each entry in
6288 the changelog, manifest, and tracked files, as well as the
6288 the changelog, manifest, and tracked files, as well as the
6289 integrity of their crosslinks and indices.
6289 integrity of their crosslinks and indices.
6290
6290
6291 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6291 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6292 for more information about recovery from corruption of the
6292 for more information about recovery from corruption of the
6293 repository.
6293 repository.
6294
6294
6295 Returns 0 on success, 1 if errors are encountered.
6295 Returns 0 on success, 1 if errors are encountered.
6296 """
6296 """
6297 return hg.verify(repo)
6297 return hg.verify(repo)
6298
6298
6299 @command('version', [], norepo=True)
6299 @command('version', [], norepo=True)
6300 def version_(ui):
6300 def version_(ui):
6301 """output version and copyright information"""
6301 """output version and copyright information"""
6302 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6302 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6303 % util.version())
6303 % util.version())
6304 ui.status(_(
6304 ui.status(_(
6305 "(see http://mercurial.selenic.com for more information)\n"
6305 "(see http://mercurial.selenic.com for more information)\n"
6306 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6306 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6307 "This is free software; see the source for copying conditions. "
6307 "This is free software; see the source for copying conditions. "
6308 "There is NO\nwarranty; "
6308 "There is NO\nwarranty; "
6309 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6309 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6310 ))
6310 ))
6311
6311
6312 ui.note(_("\nEnabled extensions:\n\n"))
6312 ui.note(_("\nEnabled extensions:\n\n"))
6313 if ui.verbose:
6313 if ui.verbose:
6314 # format names and versions into columns
6314 # format names and versions into columns
6315 names = []
6315 names = []
6316 vers = []
6316 vers = []
6317 for name, module in extensions.extensions():
6317 for name, module in extensions.extensions():
6318 names.append(name)
6318 names.append(name)
6319 vers.append(extensions.moduleversion(module))
6319 vers.append(extensions.moduleversion(module))
6320 if names:
6320 if names:
6321 maxnamelen = max(len(n) for n in names)
6321 maxnamelen = max(len(n) for n in names)
6322 for i, name in enumerate(names):
6322 for i, name in enumerate(names):
6323 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6323 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,149 +1,150 b''
1 test that a commit clears the merge state.
1 test that a commit clears the merge state.
2
2
3 $ hg init repo
3 $ hg init repo
4 $ cd repo
4 $ cd repo
5
5
6 $ echo foo > file1
6 $ echo foo > file1
7 $ echo foo > file2
7 $ echo foo > file2
8 $ hg commit -Am 'add files'
8 $ hg commit -Am 'add files'
9 adding file1
9 adding file1
10 adding file2
10 adding file2
11
11
12 $ echo bar >> file1
12 $ echo bar >> file1
13 $ echo bar >> file2
13 $ echo bar >> file2
14 $ hg commit -Am 'append bar to files'
14 $ hg commit -Am 'append bar to files'
15
15
16 create a second head with conflicting edits
16 create a second head with conflicting edits
17
17
18 $ hg up -C 0
18 $ hg up -C 0
19 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
19 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 $ echo baz >> file1
20 $ echo baz >> file1
21 $ echo baz >> file2
21 $ echo baz >> file2
22 $ hg commit -Am 'append baz to files'
22 $ hg commit -Am 'append baz to files'
23 created new head
23 created new head
24
24
25 create a third head with no conflicting edits
25 create a third head with no conflicting edits
26 $ hg up -qC 0
26 $ hg up -qC 0
27 $ echo foo > file3
27 $ echo foo > file3
28 $ hg commit -Am 'add non-conflicting file'
28 $ hg commit -Am 'add non-conflicting file'
29 adding file3
29 adding file3
30 created new head
30 created new head
31
31
32 failing merge
32 failing merge
33
33
34 $ hg up -qC 2
34 $ hg up -qC 2
35 $ hg merge --tool=internal:fail 1
35 $ hg merge --tool=internal:fail 1
36 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
36 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
37 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
37 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
38 [1]
38 [1]
39
39
40 resolve -l should contain unresolved entries
40 resolve -l should contain unresolved entries
41
41
42 $ hg resolve -l
42 $ hg resolve -l
43 U file1
43 U file1
44 U file2
44 U file2
45
45
46 resolving an unknown path should emit a warning
46 resolving an unknown path should emit a warning, but not for -l
47
47
48 $ hg resolve -m does-not-exist
48 $ hg resolve -m does-not-exist
49 arguments do not match paths that need resolving
49 arguments do not match paths that need resolving
50 $ hg resolve -l does-not-exist
50
51
51 resolve the failure
52 resolve the failure
52
53
53 $ echo resolved > file1
54 $ echo resolved > file1
54 $ hg resolve -m file1
55 $ hg resolve -m file1
55
56
56 resolve -l should show resolved file as resolved
57 resolve -l should show resolved file as resolved
57
58
58 $ hg resolve -l
59 $ hg resolve -l
59 R file1
60 R file1
60 U file2
61 U file2
61
62
62 resolve -m without paths should mark all resolved
63 resolve -m without paths should mark all resolved
63
64
64 $ hg resolve -m
65 $ hg resolve -m
65 (no more unresolved files)
66 (no more unresolved files)
66 $ hg commit -m 'resolved'
67 $ hg commit -m 'resolved'
67
68
68 resolve -l should be empty after commit
69 resolve -l should be empty after commit
69
70
70 $ hg resolve -l
71 $ hg resolve -l
71
72
72 resolve --all should abort when no merge in progress
73 resolve --all should abort when no merge in progress
73
74
74 $ hg resolve --all
75 $ hg resolve --all
75 abort: resolve command not applicable when not merging
76 abort: resolve command not applicable when not merging
76 [255]
77 [255]
77
78
78 resolve -m should abort when no merge in progress
79 resolve -m should abort when no merge in progress
79
80
80 $ hg resolve -m
81 $ hg resolve -m
81 abort: resolve command not applicable when not merging
82 abort: resolve command not applicable when not merging
82 [255]
83 [255]
83
84
84 set up conflict-free merge
85 set up conflict-free merge
85
86
86 $ hg up -qC 3
87 $ hg up -qC 3
87 $ hg merge 1
88 $ hg merge 1
88 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 (branch merge, don't forget to commit)
90 (branch merge, don't forget to commit)
90
91
91 resolve --all should do nothing in merge without conflicts
92 resolve --all should do nothing in merge without conflicts
92 $ hg resolve --all
93 $ hg resolve --all
93 (no more unresolved files)
94 (no more unresolved files)
94
95
95 resolve -m should do nothing in merge without conflicts
96 resolve -m should do nothing in merge without conflicts
96
97
97 $ hg resolve -m
98 $ hg resolve -m
98 (no more unresolved files)
99 (no more unresolved files)
99
100
100 get back to conflicting state
101 get back to conflicting state
101
102
102 $ hg up -qC 2
103 $ hg up -qC 2
103 $ hg merge --tool=internal:fail 1
104 $ hg merge --tool=internal:fail 1
104 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
105 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
105 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
106 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
106 [1]
107 [1]
107
108
108 resolve without arguments should suggest --all
109 resolve without arguments should suggest --all
109 $ hg resolve
110 $ hg resolve
110 abort: no files or directories specified
111 abort: no files or directories specified
111 (use --all to remerge all files)
112 (use --all to remerge all files)
112 [255]
113 [255]
113
114
114 resolve --all should re-merge all unresolved files
115 resolve --all should re-merge all unresolved files
115 $ hg resolve -q --all
116 $ hg resolve -q --all
116 warning: conflicts during merge.
117 warning: conflicts during merge.
117 merging file1 incomplete! (edit conflicts, then use 'hg resolve --mark')
118 merging file1 incomplete! (edit conflicts, then use 'hg resolve --mark')
118 warning: conflicts during merge.
119 warning: conflicts during merge.
119 merging file2 incomplete! (edit conflicts, then use 'hg resolve --mark')
120 merging file2 incomplete! (edit conflicts, then use 'hg resolve --mark')
120 [1]
121 [1]
121 $ grep '<<<' file1 > /dev/null
122 $ grep '<<<' file1 > /dev/null
122 $ grep '<<<' file2 > /dev/null
123 $ grep '<<<' file2 > /dev/null
123
124
124 resolve <file> should re-merge file
125 resolve <file> should re-merge file
125 $ echo resolved > file1
126 $ echo resolved > file1
126 $ hg resolve -q file1
127 $ hg resolve -q file1
127 warning: conflicts during merge.
128 warning: conflicts during merge.
128 merging file1 incomplete! (edit conflicts, then use 'hg resolve --mark')
129 merging file1 incomplete! (edit conflicts, then use 'hg resolve --mark')
129 [1]
130 [1]
130 $ grep '<<<' file1 > /dev/null
131 $ grep '<<<' file1 > /dev/null
131
132
132 resolve <file> should do nothing if 'file' was marked resolved
133 resolve <file> should do nothing if 'file' was marked resolved
133 $ echo resolved > file1
134 $ echo resolved > file1
134 $ hg resolve -m file1
135 $ hg resolve -m file1
135 $ hg resolve -q file1
136 $ hg resolve -q file1
136 $ cat file1
137 $ cat file1
137 resolved
138 resolved
138
139
139 test crashed merge with empty mergestate
140 test crashed merge with empty mergestate
140
141
141 $ hg up -qC 1
142 $ hg up -qC 1
142 $ mkdir .hg/merge
143 $ mkdir .hg/merge
143 $ touch .hg/merge/state
144 $ touch .hg/merge/state
144
145
145 resolve -l should be empty
146 resolve -l should be empty
146
147
147 $ hg resolve -l
148 $ hg resolve -l
148
149
149 $ cd ..
150 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now