##// END OF EJS Templates
incoming: hide help about use of --bundle option by default...
Yuya Nishihara -
r24248:913347bc default
parent child Browse files
Show More
@@ -1,6333 +1,6333 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, unused_allcmds = cmdutil.findpossible(cmd, table)
1949 cmdlist, unused_allcmds = 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. For example, neither the working copy nor the dirstate
2896 be used with care. For example, neither the working copy nor the dirstate
2897 is updated, so file status may be incorrect after running this command.
2897 is updated, so file status may be incorrect after running this command.
2898
2898
2899 Returns 0 on success.
2899 Returns 0 on success.
2900 """
2900 """
2901
2901
2902 r1 = scmutil.revsingle(repo, rev1).node()
2902 r1 = scmutil.revsingle(repo, rev1).node()
2903 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2903 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2904
2904
2905 wlock = repo.wlock()
2905 wlock = repo.wlock()
2906 try:
2906 try:
2907 repo.dirstate.beginparentchange()
2907 repo.dirstate.beginparentchange()
2908 repo.setparents(r1, r2)
2908 repo.setparents(r1, r2)
2909 repo.dirstate.endparentchange()
2909 repo.dirstate.endparentchange()
2910 finally:
2910 finally:
2911 wlock.release()
2911 wlock.release()
2912
2912
2913 @command('debugdirstate|debugstate',
2913 @command('debugdirstate|debugstate',
2914 [('', 'nodates', None, _('do not display the saved mtime')),
2914 [('', 'nodates', None, _('do not display the saved mtime')),
2915 ('', 'datesort', None, _('sort by saved mtime'))],
2915 ('', 'datesort', None, _('sort by saved mtime'))],
2916 _('[OPTION]...'))
2916 _('[OPTION]...'))
2917 def debugstate(ui, repo, nodates=None, datesort=None):
2917 def debugstate(ui, repo, nodates=None, datesort=None):
2918 """show the contents of the current dirstate"""
2918 """show the contents of the current dirstate"""
2919 timestr = ""
2919 timestr = ""
2920 if datesort:
2920 if datesort:
2921 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2921 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2922 else:
2922 else:
2923 keyfunc = None # sort by filename
2923 keyfunc = None # sort by filename
2924 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2924 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2925 if ent[3] == -1:
2925 if ent[3] == -1:
2926 timestr = 'unset '
2926 timestr = 'unset '
2927 elif nodates:
2927 elif nodates:
2928 timestr = 'set '
2928 timestr = 'set '
2929 else:
2929 else:
2930 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2930 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2931 time.localtime(ent[3]))
2931 time.localtime(ent[3]))
2932 if ent[1] & 020000:
2932 if ent[1] & 020000:
2933 mode = 'lnk'
2933 mode = 'lnk'
2934 else:
2934 else:
2935 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2935 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2936 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2936 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2937 for f in repo.dirstate.copies():
2937 for f in repo.dirstate.copies():
2938 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2938 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2939
2939
2940 @command('debugsub',
2940 @command('debugsub',
2941 [('r', 'rev', '',
2941 [('r', 'rev', '',
2942 _('revision to check'), _('REV'))],
2942 _('revision to check'), _('REV'))],
2943 _('[-r REV] [REV]'))
2943 _('[-r REV] [REV]'))
2944 def debugsub(ui, repo, rev=None):
2944 def debugsub(ui, repo, rev=None):
2945 ctx = scmutil.revsingle(repo, rev, None)
2945 ctx = scmutil.revsingle(repo, rev, None)
2946 for k, v in sorted(ctx.substate.items()):
2946 for k, v in sorted(ctx.substate.items()):
2947 ui.write(('path %s\n') % k)
2947 ui.write(('path %s\n') % k)
2948 ui.write((' source %s\n') % v[0])
2948 ui.write((' source %s\n') % v[0])
2949 ui.write((' revision %s\n') % v[1])
2949 ui.write((' revision %s\n') % v[1])
2950
2950
2951 @command('debugsuccessorssets',
2951 @command('debugsuccessorssets',
2952 [],
2952 [],
2953 _('[REV]'))
2953 _('[REV]'))
2954 def debugsuccessorssets(ui, repo, *revs):
2954 def debugsuccessorssets(ui, repo, *revs):
2955 """show set of successors for revision
2955 """show set of successors for revision
2956
2956
2957 A successors set of changeset A is a consistent group of revisions that
2957 A successors set of changeset A is a consistent group of revisions that
2958 succeed A. It contains non-obsolete changesets only.
2958 succeed A. It contains non-obsolete changesets only.
2959
2959
2960 In most cases a changeset A has a single successors set containing a single
2960 In most cases a changeset A has a single successors set containing a single
2961 successor (changeset A replaced by A').
2961 successor (changeset A replaced by A').
2962
2962
2963 A changeset that is made obsolete with no successors are called "pruned".
2963 A changeset that is made obsolete with no successors are called "pruned".
2964 Such changesets have no successors sets at all.
2964 Such changesets have no successors sets at all.
2965
2965
2966 A changeset that has been "split" will have a successors set containing
2966 A changeset that has been "split" will have a successors set containing
2967 more than one successor.
2967 more than one successor.
2968
2968
2969 A changeset that has been rewritten in multiple different ways is called
2969 A changeset that has been rewritten in multiple different ways is called
2970 "divergent". Such changesets have multiple successor sets (each of which
2970 "divergent". Such changesets have multiple successor sets (each of which
2971 may also be split, i.e. have multiple successors).
2971 may also be split, i.e. have multiple successors).
2972
2972
2973 Results are displayed as follows::
2973 Results are displayed as follows::
2974
2974
2975 <rev1>
2975 <rev1>
2976 <successors-1A>
2976 <successors-1A>
2977 <rev2>
2977 <rev2>
2978 <successors-2A>
2978 <successors-2A>
2979 <successors-2B1> <successors-2B2> <successors-2B3>
2979 <successors-2B1> <successors-2B2> <successors-2B3>
2980
2980
2981 Here rev2 has two possible (i.e. divergent) successors sets. The first
2981 Here rev2 has two possible (i.e. divergent) successors sets. The first
2982 holds one element, whereas the second holds three (i.e. the changeset has
2982 holds one element, whereas the second holds three (i.e. the changeset has
2983 been split).
2983 been split).
2984 """
2984 """
2985 # passed to successorssets caching computation from one call to another
2985 # passed to successorssets caching computation from one call to another
2986 cache = {}
2986 cache = {}
2987 ctx2str = str
2987 ctx2str = str
2988 node2str = short
2988 node2str = short
2989 if ui.debug():
2989 if ui.debug():
2990 def ctx2str(ctx):
2990 def ctx2str(ctx):
2991 return ctx.hex()
2991 return ctx.hex()
2992 node2str = hex
2992 node2str = hex
2993 for rev in scmutil.revrange(repo, revs):
2993 for rev in scmutil.revrange(repo, revs):
2994 ctx = repo[rev]
2994 ctx = repo[rev]
2995 ui.write('%s\n'% ctx2str(ctx))
2995 ui.write('%s\n'% ctx2str(ctx))
2996 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2996 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2997 if succsset:
2997 if succsset:
2998 ui.write(' ')
2998 ui.write(' ')
2999 ui.write(node2str(succsset[0]))
2999 ui.write(node2str(succsset[0]))
3000 for node in succsset[1:]:
3000 for node in succsset[1:]:
3001 ui.write(' ')
3001 ui.write(' ')
3002 ui.write(node2str(node))
3002 ui.write(node2str(node))
3003 ui.write('\n')
3003 ui.write('\n')
3004
3004
3005 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3005 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3006 def debugwalk(ui, repo, *pats, **opts):
3006 def debugwalk(ui, repo, *pats, **opts):
3007 """show how files match on given patterns"""
3007 """show how files match on given patterns"""
3008 m = scmutil.match(repo[None], pats, opts)
3008 m = scmutil.match(repo[None], pats, opts)
3009 items = list(repo.walk(m))
3009 items = list(repo.walk(m))
3010 if not items:
3010 if not items:
3011 return
3011 return
3012 f = lambda fn: fn
3012 f = lambda fn: fn
3013 if ui.configbool('ui', 'slash') and os.sep != '/':
3013 if ui.configbool('ui', 'slash') and os.sep != '/':
3014 f = lambda fn: util.normpath(fn)
3014 f = lambda fn: util.normpath(fn)
3015 fmt = 'f %%-%ds %%-%ds %%s' % (
3015 fmt = 'f %%-%ds %%-%ds %%s' % (
3016 max([len(abs) for abs in items]),
3016 max([len(abs) for abs in items]),
3017 max([len(m.rel(abs)) for abs in items]))
3017 max([len(m.rel(abs)) for abs in items]))
3018 for abs in items:
3018 for abs in items:
3019 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3019 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3020 ui.write("%s\n" % line.rstrip())
3020 ui.write("%s\n" % line.rstrip())
3021
3021
3022 @command('debugwireargs',
3022 @command('debugwireargs',
3023 [('', 'three', '', 'three'),
3023 [('', 'three', '', 'three'),
3024 ('', 'four', '', 'four'),
3024 ('', 'four', '', 'four'),
3025 ('', 'five', '', 'five'),
3025 ('', 'five', '', 'five'),
3026 ] + remoteopts,
3026 ] + remoteopts,
3027 _('REPO [OPTIONS]... [ONE [TWO]]'),
3027 _('REPO [OPTIONS]... [ONE [TWO]]'),
3028 norepo=True)
3028 norepo=True)
3029 def debugwireargs(ui, repopath, *vals, **opts):
3029 def debugwireargs(ui, repopath, *vals, **opts):
3030 repo = hg.peer(ui, opts, repopath)
3030 repo = hg.peer(ui, opts, repopath)
3031 for opt in remoteopts:
3031 for opt in remoteopts:
3032 del opts[opt[1]]
3032 del opts[opt[1]]
3033 args = {}
3033 args = {}
3034 for k, v in opts.iteritems():
3034 for k, v in opts.iteritems():
3035 if v:
3035 if v:
3036 args[k] = v
3036 args[k] = v
3037 # run twice to check that we don't mess up the stream for the next command
3037 # run twice to check that we don't mess up the stream for the next command
3038 res1 = repo.debugwireargs(*vals, **args)
3038 res1 = repo.debugwireargs(*vals, **args)
3039 res2 = repo.debugwireargs(*vals, **args)
3039 res2 = repo.debugwireargs(*vals, **args)
3040 ui.write("%s\n" % res1)
3040 ui.write("%s\n" % res1)
3041 if res1 != res2:
3041 if res1 != res2:
3042 ui.warn("%s\n" % res2)
3042 ui.warn("%s\n" % res2)
3043
3043
3044 @command('^diff',
3044 @command('^diff',
3045 [('r', 'rev', [], _('revision'), _('REV')),
3045 [('r', 'rev', [], _('revision'), _('REV')),
3046 ('c', 'change', '', _('change made by revision'), _('REV'))
3046 ('c', 'change', '', _('change made by revision'), _('REV'))
3047 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3047 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3048 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3048 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3049 inferrepo=True)
3049 inferrepo=True)
3050 def diff(ui, repo, *pats, **opts):
3050 def diff(ui, repo, *pats, **opts):
3051 """diff repository (or selected files)
3051 """diff repository (or selected files)
3052
3052
3053 Show differences between revisions for the specified files.
3053 Show differences between revisions for the specified files.
3054
3054
3055 Differences between files are shown using the unified diff format.
3055 Differences between files are shown using the unified diff format.
3056
3056
3057 .. note::
3057 .. note::
3058
3058
3059 diff may generate unexpected results for merges, as it will
3059 diff may generate unexpected results for merges, as it will
3060 default to comparing against the working directory's first
3060 default to comparing against the working directory's first
3061 parent changeset if no revisions are specified.
3061 parent changeset if no revisions are specified.
3062
3062
3063 When two revision arguments are given, then changes are shown
3063 When two revision arguments are given, then changes are shown
3064 between those revisions. If only one revision is specified then
3064 between those revisions. If only one revision is specified then
3065 that revision is compared to the working directory, and, when no
3065 that revision is compared to the working directory, and, when no
3066 revisions are specified, the working directory files are compared
3066 revisions are specified, the working directory files are compared
3067 to its parent.
3067 to its parent.
3068
3068
3069 Alternatively you can specify -c/--change with a revision to see
3069 Alternatively you can specify -c/--change with a revision to see
3070 the changes in that changeset relative to its first parent.
3070 the changes in that changeset relative to its first parent.
3071
3071
3072 Without the -a/--text option, diff will avoid generating diffs of
3072 Without the -a/--text option, diff will avoid generating diffs of
3073 files it detects as binary. With -a, diff will generate a diff
3073 files it detects as binary. With -a, diff will generate a diff
3074 anyway, probably with undesirable results.
3074 anyway, probably with undesirable results.
3075
3075
3076 Use the -g/--git option to generate diffs in the git extended diff
3076 Use the -g/--git option to generate diffs in the git extended diff
3077 format. For more information, read :hg:`help diffs`.
3077 format. For more information, read :hg:`help diffs`.
3078
3078
3079 .. container:: verbose
3079 .. container:: verbose
3080
3080
3081 Examples:
3081 Examples:
3082
3082
3083 - compare a file in the current working directory to its parent::
3083 - compare a file in the current working directory to its parent::
3084
3084
3085 hg diff foo.c
3085 hg diff foo.c
3086
3086
3087 - compare two historical versions of a directory, with rename info::
3087 - compare two historical versions of a directory, with rename info::
3088
3088
3089 hg diff --git -r 1.0:1.2 lib/
3089 hg diff --git -r 1.0:1.2 lib/
3090
3090
3091 - get change stats relative to the last change on some date::
3091 - get change stats relative to the last change on some date::
3092
3092
3093 hg diff --stat -r "date('may 2')"
3093 hg diff --stat -r "date('may 2')"
3094
3094
3095 - diff all newly-added files that contain a keyword::
3095 - diff all newly-added files that contain a keyword::
3096
3096
3097 hg diff "set:added() and grep(GNU)"
3097 hg diff "set:added() and grep(GNU)"
3098
3098
3099 - compare a revision and its parents::
3099 - compare a revision and its parents::
3100
3100
3101 hg diff -c 9353 # compare against first parent
3101 hg diff -c 9353 # compare against first parent
3102 hg diff -r 9353^:9353 # same using revset syntax
3102 hg diff -r 9353^:9353 # same using revset syntax
3103 hg diff -r 9353^2:9353 # compare against the second parent
3103 hg diff -r 9353^2:9353 # compare against the second parent
3104
3104
3105 Returns 0 on success.
3105 Returns 0 on success.
3106 """
3106 """
3107
3107
3108 revs = opts.get('rev')
3108 revs = opts.get('rev')
3109 change = opts.get('change')
3109 change = opts.get('change')
3110 stat = opts.get('stat')
3110 stat = opts.get('stat')
3111 reverse = opts.get('reverse')
3111 reverse = opts.get('reverse')
3112
3112
3113 if revs and change:
3113 if revs and change:
3114 msg = _('cannot specify --rev and --change at the same time')
3114 msg = _('cannot specify --rev and --change at the same time')
3115 raise util.Abort(msg)
3115 raise util.Abort(msg)
3116 elif change:
3116 elif change:
3117 node2 = scmutil.revsingle(repo, change, None).node()
3117 node2 = scmutil.revsingle(repo, change, None).node()
3118 node1 = repo[node2].p1().node()
3118 node1 = repo[node2].p1().node()
3119 else:
3119 else:
3120 node1, node2 = scmutil.revpair(repo, revs)
3120 node1, node2 = scmutil.revpair(repo, revs)
3121
3121
3122 if reverse:
3122 if reverse:
3123 node1, node2 = node2, node1
3123 node1, node2 = node2, node1
3124
3124
3125 diffopts = patch.diffallopts(ui, opts)
3125 diffopts = patch.diffallopts(ui, opts)
3126 m = scmutil.match(repo[node2], pats, opts)
3126 m = scmutil.match(repo[node2], pats, opts)
3127 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3127 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3128 listsubrepos=opts.get('subrepos'))
3128 listsubrepos=opts.get('subrepos'))
3129
3129
3130 @command('^export',
3130 @command('^export',
3131 [('o', 'output', '',
3131 [('o', 'output', '',
3132 _('print output to file with formatted name'), _('FORMAT')),
3132 _('print output to file with formatted name'), _('FORMAT')),
3133 ('', 'switch-parent', None, _('diff against the second parent')),
3133 ('', 'switch-parent', None, _('diff against the second parent')),
3134 ('r', 'rev', [], _('revisions to export'), _('REV')),
3134 ('r', 'rev', [], _('revisions to export'), _('REV')),
3135 ] + diffopts,
3135 ] + diffopts,
3136 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3136 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3137 def export(ui, repo, *changesets, **opts):
3137 def export(ui, repo, *changesets, **opts):
3138 """dump the header and diffs for one or more changesets
3138 """dump the header and diffs for one or more changesets
3139
3139
3140 Print the changeset header and diffs for one or more revisions.
3140 Print the changeset header and diffs for one or more revisions.
3141 If no revision is given, the parent of the working directory is used.
3141 If no revision is given, the parent of the working directory is used.
3142
3142
3143 The information shown in the changeset header is: author, date,
3143 The information shown in the changeset header is: author, date,
3144 branch name (if non-default), changeset hash, parent(s) and commit
3144 branch name (if non-default), changeset hash, parent(s) and commit
3145 comment.
3145 comment.
3146
3146
3147 .. note::
3147 .. note::
3148
3148
3149 export may generate unexpected diff output for merge
3149 export may generate unexpected diff output for merge
3150 changesets, as it will compare the merge changeset against its
3150 changesets, as it will compare the merge changeset against its
3151 first parent only.
3151 first parent only.
3152
3152
3153 Output may be to a file, in which case the name of the file is
3153 Output may be to a file, in which case the name of the file is
3154 given using a format string. The formatting rules are as follows:
3154 given using a format string. The formatting rules are as follows:
3155
3155
3156 :``%%``: literal "%" character
3156 :``%%``: literal "%" character
3157 :``%H``: changeset hash (40 hexadecimal digits)
3157 :``%H``: changeset hash (40 hexadecimal digits)
3158 :``%N``: number of patches being generated
3158 :``%N``: number of patches being generated
3159 :``%R``: changeset revision number
3159 :``%R``: changeset revision number
3160 :``%b``: basename of the exporting repository
3160 :``%b``: basename of the exporting repository
3161 :``%h``: short-form changeset hash (12 hexadecimal digits)
3161 :``%h``: short-form changeset hash (12 hexadecimal digits)
3162 :``%m``: first line of the commit message (only alphanumeric characters)
3162 :``%m``: first line of the commit message (only alphanumeric characters)
3163 :``%n``: zero-padded sequence number, starting at 1
3163 :``%n``: zero-padded sequence number, starting at 1
3164 :``%r``: zero-padded changeset revision number
3164 :``%r``: zero-padded changeset revision number
3165
3165
3166 Without the -a/--text option, export will avoid generating diffs
3166 Without the -a/--text option, export will avoid generating diffs
3167 of files it detects as binary. With -a, export will generate a
3167 of files it detects as binary. With -a, export will generate a
3168 diff anyway, probably with undesirable results.
3168 diff anyway, probably with undesirable results.
3169
3169
3170 Use the -g/--git option to generate diffs in the git extended diff
3170 Use the -g/--git option to generate diffs in the git extended diff
3171 format. See :hg:`help diffs` for more information.
3171 format. See :hg:`help diffs` for more information.
3172
3172
3173 With the --switch-parent option, the diff will be against the
3173 With the --switch-parent option, the diff will be against the
3174 second parent. It can be useful to review a merge.
3174 second parent. It can be useful to review a merge.
3175
3175
3176 .. container:: verbose
3176 .. container:: verbose
3177
3177
3178 Examples:
3178 Examples:
3179
3179
3180 - use export and import to transplant a bugfix to the current
3180 - use export and import to transplant a bugfix to the current
3181 branch::
3181 branch::
3182
3182
3183 hg export -r 9353 | hg import -
3183 hg export -r 9353 | hg import -
3184
3184
3185 - export all the changesets between two revisions to a file with
3185 - export all the changesets between two revisions to a file with
3186 rename information::
3186 rename information::
3187
3187
3188 hg export --git -r 123:150 > changes.txt
3188 hg export --git -r 123:150 > changes.txt
3189
3189
3190 - split outgoing changes into a series of patches with
3190 - split outgoing changes into a series of patches with
3191 descriptive names::
3191 descriptive names::
3192
3192
3193 hg export -r "outgoing()" -o "%n-%m.patch"
3193 hg export -r "outgoing()" -o "%n-%m.patch"
3194
3194
3195 Returns 0 on success.
3195 Returns 0 on success.
3196 """
3196 """
3197 changesets += tuple(opts.get('rev', []))
3197 changesets += tuple(opts.get('rev', []))
3198 if not changesets:
3198 if not changesets:
3199 changesets = ['.']
3199 changesets = ['.']
3200 revs = scmutil.revrange(repo, changesets)
3200 revs = scmutil.revrange(repo, changesets)
3201 if not revs:
3201 if not revs:
3202 raise util.Abort(_("export requires at least one changeset"))
3202 raise util.Abort(_("export requires at least one changeset"))
3203 if len(revs) > 1:
3203 if len(revs) > 1:
3204 ui.note(_('exporting patches:\n'))
3204 ui.note(_('exporting patches:\n'))
3205 else:
3205 else:
3206 ui.note(_('exporting patch:\n'))
3206 ui.note(_('exporting patch:\n'))
3207 cmdutil.export(repo, revs, template=opts.get('output'),
3207 cmdutil.export(repo, revs, template=opts.get('output'),
3208 switch_parent=opts.get('switch_parent'),
3208 switch_parent=opts.get('switch_parent'),
3209 opts=patch.diffallopts(ui, opts))
3209 opts=patch.diffallopts(ui, opts))
3210
3210
3211 @command('files',
3211 @command('files',
3212 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3212 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3213 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3213 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3214 ] + walkopts + formatteropts,
3214 ] + walkopts + formatteropts,
3215 _('[OPTION]... [PATTERN]...'))
3215 _('[OPTION]... [PATTERN]...'))
3216 def files(ui, repo, *pats, **opts):
3216 def files(ui, repo, *pats, **opts):
3217 """list tracked files
3217 """list tracked files
3218
3218
3219 Print files under Mercurial control in the working directory or
3219 Print files under Mercurial control in the working directory or
3220 specified revision whose names match the given patterns (excluding
3220 specified revision whose names match the given patterns (excluding
3221 removed files).
3221 removed files).
3222
3222
3223 If no patterns are given to match, this command prints the names
3223 If no patterns are given to match, this command prints the names
3224 of all files under Mercurial control in the working copy.
3224 of all files under Mercurial control in the working copy.
3225
3225
3226 .. container:: verbose
3226 .. container:: verbose
3227
3227
3228 Examples:
3228 Examples:
3229
3229
3230 - list all files under the current directory::
3230 - list all files under the current directory::
3231
3231
3232 hg files .
3232 hg files .
3233
3233
3234 - shows sizes and flags for current revision::
3234 - shows sizes and flags for current revision::
3235
3235
3236 hg files -vr .
3236 hg files -vr .
3237
3237
3238 - list all files named README::
3238 - list all files named README::
3239
3239
3240 hg files -I "**/README"
3240 hg files -I "**/README"
3241
3241
3242 - list all binary files::
3242 - list all binary files::
3243
3243
3244 hg files "set:binary()"
3244 hg files "set:binary()"
3245
3245
3246 - find files containing a regular expression::
3246 - find files containing a regular expression::
3247
3247
3248 hg files "set:grep('bob')"
3248 hg files "set:grep('bob')"
3249
3249
3250 - search tracked file contents with xargs and grep::
3250 - search tracked file contents with xargs and grep::
3251
3251
3252 hg files -0 | xargs -0 grep foo
3252 hg files -0 | xargs -0 grep foo
3253
3253
3254 See :hg:`help patterns` and :hg:`help filesets` for more information
3254 See :hg:`help patterns` and :hg:`help filesets` for more information
3255 on specifying file patterns.
3255 on specifying file patterns.
3256
3256
3257 Returns 0 if a match is found, 1 otherwise.
3257 Returns 0 if a match is found, 1 otherwise.
3258
3258
3259 """
3259 """
3260 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3260 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3261 rev = ctx.rev()
3261 rev = ctx.rev()
3262 ret = 1
3262 ret = 1
3263
3263
3264 end = '\n'
3264 end = '\n'
3265 if opts.get('print0'):
3265 if opts.get('print0'):
3266 end = '\0'
3266 end = '\0'
3267 fm = ui.formatter('files', opts)
3267 fm = ui.formatter('files', opts)
3268 fmt = '%s' + end
3268 fmt = '%s' + end
3269
3269
3270 m = scmutil.match(ctx, pats, opts)
3270 m = scmutil.match(ctx, pats, opts)
3271 ds = repo.dirstate
3271 ds = repo.dirstate
3272 for f in ctx.matches(m):
3272 for f in ctx.matches(m):
3273 if rev is None and ds[f] == 'r':
3273 if rev is None and ds[f] == 'r':
3274 continue
3274 continue
3275 fm.startitem()
3275 fm.startitem()
3276 if ui.verbose:
3276 if ui.verbose:
3277 fc = ctx[f]
3277 fc = ctx[f]
3278 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3278 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3279 fm.data(abspath=f)
3279 fm.data(abspath=f)
3280 fm.write('path', fmt, m.rel(f))
3280 fm.write('path', fmt, m.rel(f))
3281 ret = 0
3281 ret = 0
3282
3282
3283 fm.end()
3283 fm.end()
3284
3284
3285 return ret
3285 return ret
3286
3286
3287 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3287 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3288 def forget(ui, repo, *pats, **opts):
3288 def forget(ui, repo, *pats, **opts):
3289 """forget the specified files on the next commit
3289 """forget the specified files on the next commit
3290
3290
3291 Mark the specified files so they will no longer be tracked
3291 Mark the specified files so they will no longer be tracked
3292 after the next commit.
3292 after the next commit.
3293
3293
3294 This only removes files from the current branch, not from the
3294 This only removes files from the current branch, not from the
3295 entire project history, and it does not delete them from the
3295 entire project history, and it does not delete them from the
3296 working directory.
3296 working directory.
3297
3297
3298 To undo a forget before the next commit, see :hg:`add`.
3298 To undo a forget before the next commit, see :hg:`add`.
3299
3299
3300 .. container:: verbose
3300 .. container:: verbose
3301
3301
3302 Examples:
3302 Examples:
3303
3303
3304 - forget newly-added binary files::
3304 - forget newly-added binary files::
3305
3305
3306 hg forget "set:added() and binary()"
3306 hg forget "set:added() and binary()"
3307
3307
3308 - forget files that would be excluded by .hgignore::
3308 - forget files that would be excluded by .hgignore::
3309
3309
3310 hg forget "set:hgignore()"
3310 hg forget "set:hgignore()"
3311
3311
3312 Returns 0 on success.
3312 Returns 0 on success.
3313 """
3313 """
3314
3314
3315 if not pats:
3315 if not pats:
3316 raise util.Abort(_('no files specified'))
3316 raise util.Abort(_('no files specified'))
3317
3317
3318 m = scmutil.match(repo[None], pats, opts)
3318 m = scmutil.match(repo[None], pats, opts)
3319 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3319 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3320 return rejected and 1 or 0
3320 return rejected and 1 or 0
3321
3321
3322 @command(
3322 @command(
3323 'graft',
3323 'graft',
3324 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3324 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3325 ('c', 'continue', False, _('resume interrupted graft')),
3325 ('c', 'continue', False, _('resume interrupted graft')),
3326 ('e', 'edit', False, _('invoke editor on commit messages')),
3326 ('e', 'edit', False, _('invoke editor on commit messages')),
3327 ('', 'log', None, _('append graft info to log message')),
3327 ('', 'log', None, _('append graft info to log message')),
3328 ('f', 'force', False, _('force graft')),
3328 ('f', 'force', False, _('force graft')),
3329 ('D', 'currentdate', False,
3329 ('D', 'currentdate', False,
3330 _('record the current date as commit date')),
3330 _('record the current date as commit date')),
3331 ('U', 'currentuser', False,
3331 ('U', 'currentuser', False,
3332 _('record the current user as committer'), _('DATE'))]
3332 _('record the current user as committer'), _('DATE'))]
3333 + commitopts2 + mergetoolopts + dryrunopts,
3333 + commitopts2 + mergetoolopts + dryrunopts,
3334 _('[OPTION]... [-r] REV...'))
3334 _('[OPTION]... [-r] REV...'))
3335 def graft(ui, repo, *revs, **opts):
3335 def graft(ui, repo, *revs, **opts):
3336 '''copy changes from other branches onto the current branch
3336 '''copy changes from other branches onto the current branch
3337
3337
3338 This command uses Mercurial's merge logic to copy individual
3338 This command uses Mercurial's merge logic to copy individual
3339 changes from other branches without merging branches in the
3339 changes from other branches without merging branches in the
3340 history graph. This is sometimes known as 'backporting' or
3340 history graph. This is sometimes known as 'backporting' or
3341 'cherry-picking'. By default, graft will copy user, date, and
3341 'cherry-picking'. By default, graft will copy user, date, and
3342 description from the source changesets.
3342 description from the source changesets.
3343
3343
3344 Changesets that are ancestors of the current revision, that have
3344 Changesets that are ancestors of the current revision, that have
3345 already been grafted, or that are merges will be skipped.
3345 already been grafted, or that are merges will be skipped.
3346
3346
3347 If --log is specified, log messages will have a comment appended
3347 If --log is specified, log messages will have a comment appended
3348 of the form::
3348 of the form::
3349
3349
3350 (grafted from CHANGESETHASH)
3350 (grafted from CHANGESETHASH)
3351
3351
3352 If --force is specified, revisions will be grafted even if they
3352 If --force is specified, revisions will be grafted even if they
3353 are already ancestors of or have been grafted to the destination.
3353 are already ancestors of or have been grafted to the destination.
3354 This is useful when the revisions have since been backed out.
3354 This is useful when the revisions have since been backed out.
3355
3355
3356 If a graft merge results in conflicts, the graft process is
3356 If a graft merge results in conflicts, the graft process is
3357 interrupted so that the current merge can be manually resolved.
3357 interrupted so that the current merge can be manually resolved.
3358 Once all conflicts are addressed, the graft process can be
3358 Once all conflicts are addressed, the graft process can be
3359 continued with the -c/--continue option.
3359 continued with the -c/--continue option.
3360
3360
3361 .. note::
3361 .. note::
3362
3362
3363 The -c/--continue option does not reapply earlier options, except
3363 The -c/--continue option does not reapply earlier options, except
3364 for --force.
3364 for --force.
3365
3365
3366 .. container:: verbose
3366 .. container:: verbose
3367
3367
3368 Examples:
3368 Examples:
3369
3369
3370 - copy a single change to the stable branch and edit its description::
3370 - copy a single change to the stable branch and edit its description::
3371
3371
3372 hg update stable
3372 hg update stable
3373 hg graft --edit 9393
3373 hg graft --edit 9393
3374
3374
3375 - graft a range of changesets with one exception, updating dates::
3375 - graft a range of changesets with one exception, updating dates::
3376
3376
3377 hg graft -D "2085::2093 and not 2091"
3377 hg graft -D "2085::2093 and not 2091"
3378
3378
3379 - continue a graft after resolving conflicts::
3379 - continue a graft after resolving conflicts::
3380
3380
3381 hg graft -c
3381 hg graft -c
3382
3382
3383 - show the source of a grafted changeset::
3383 - show the source of a grafted changeset::
3384
3384
3385 hg log --debug -r .
3385 hg log --debug -r .
3386
3386
3387 See :hg:`help revisions` and :hg:`help revsets` for more about
3387 See :hg:`help revisions` and :hg:`help revsets` for more about
3388 specifying revisions.
3388 specifying revisions.
3389
3389
3390 Returns 0 on successful completion.
3390 Returns 0 on successful completion.
3391 '''
3391 '''
3392
3392
3393 revs = list(revs)
3393 revs = list(revs)
3394 revs.extend(opts['rev'])
3394 revs.extend(opts['rev'])
3395
3395
3396 if not opts.get('user') and opts.get('currentuser'):
3396 if not opts.get('user') and opts.get('currentuser'):
3397 opts['user'] = ui.username()
3397 opts['user'] = ui.username()
3398 if not opts.get('date') and opts.get('currentdate'):
3398 if not opts.get('date') and opts.get('currentdate'):
3399 opts['date'] = "%d %d" % util.makedate()
3399 opts['date'] = "%d %d" % util.makedate()
3400
3400
3401 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3401 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3402
3402
3403 cont = False
3403 cont = False
3404 if opts['continue']:
3404 if opts['continue']:
3405 cont = True
3405 cont = True
3406 if revs:
3406 if revs:
3407 raise util.Abort(_("can't specify --continue and revisions"))
3407 raise util.Abort(_("can't specify --continue and revisions"))
3408 # read in unfinished revisions
3408 # read in unfinished revisions
3409 try:
3409 try:
3410 nodes = repo.vfs.read('graftstate').splitlines()
3410 nodes = repo.vfs.read('graftstate').splitlines()
3411 revs = [repo[node].rev() for node in nodes]
3411 revs = [repo[node].rev() for node in nodes]
3412 except IOError, inst:
3412 except IOError, inst:
3413 if inst.errno != errno.ENOENT:
3413 if inst.errno != errno.ENOENT:
3414 raise
3414 raise
3415 raise util.Abort(_("no graft state found, can't continue"))
3415 raise util.Abort(_("no graft state found, can't continue"))
3416 else:
3416 else:
3417 cmdutil.checkunfinished(repo)
3417 cmdutil.checkunfinished(repo)
3418 cmdutil.bailifchanged(repo)
3418 cmdutil.bailifchanged(repo)
3419 if not revs:
3419 if not revs:
3420 raise util.Abort(_('no revisions specified'))
3420 raise util.Abort(_('no revisions specified'))
3421 revs = scmutil.revrange(repo, revs)
3421 revs = scmutil.revrange(repo, revs)
3422
3422
3423 skipped = set()
3423 skipped = set()
3424 # check for merges
3424 # check for merges
3425 for rev in repo.revs('%ld and merge()', revs):
3425 for rev in repo.revs('%ld and merge()', revs):
3426 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3426 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3427 skipped.add(rev)
3427 skipped.add(rev)
3428 revs = [r for r in revs if r not in skipped]
3428 revs = [r for r in revs if r not in skipped]
3429 if not revs:
3429 if not revs:
3430 return -1
3430 return -1
3431
3431
3432 # Don't check in the --continue case, in effect retaining --force across
3432 # Don't check in the --continue case, in effect retaining --force across
3433 # --continues. That's because without --force, any revisions we decided to
3433 # --continues. That's because without --force, any revisions we decided to
3434 # skip would have been filtered out here, so they wouldn't have made their
3434 # skip would have been filtered out here, so they wouldn't have made their
3435 # way to the graftstate. With --force, any revisions we would have otherwise
3435 # way to the graftstate. With --force, any revisions we would have otherwise
3436 # skipped would not have been filtered out, and if they hadn't been applied
3436 # skipped would not have been filtered out, and if they hadn't been applied
3437 # already, they'd have been in the graftstate.
3437 # already, they'd have been in the graftstate.
3438 if not (cont or opts.get('force')):
3438 if not (cont or opts.get('force')):
3439 # check for ancestors of dest branch
3439 # check for ancestors of dest branch
3440 crev = repo['.'].rev()
3440 crev = repo['.'].rev()
3441 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3441 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3442 # Cannot use x.remove(y) on smart set, this has to be a list.
3442 # Cannot use x.remove(y) on smart set, this has to be a list.
3443 # XXX make this lazy in the future
3443 # XXX make this lazy in the future
3444 revs = list(revs)
3444 revs = list(revs)
3445 # don't mutate while iterating, create a copy
3445 # don't mutate while iterating, create a copy
3446 for rev in list(revs):
3446 for rev in list(revs):
3447 if rev in ancestors:
3447 if rev in ancestors:
3448 ui.warn(_('skipping ancestor revision %d:%s\n') %
3448 ui.warn(_('skipping ancestor revision %d:%s\n') %
3449 (rev, repo[rev]))
3449 (rev, repo[rev]))
3450 # XXX remove on list is slow
3450 # XXX remove on list is slow
3451 revs.remove(rev)
3451 revs.remove(rev)
3452 if not revs:
3452 if not revs:
3453 return -1
3453 return -1
3454
3454
3455 # analyze revs for earlier grafts
3455 # analyze revs for earlier grafts
3456 ids = {}
3456 ids = {}
3457 for ctx in repo.set("%ld", revs):
3457 for ctx in repo.set("%ld", revs):
3458 ids[ctx.hex()] = ctx.rev()
3458 ids[ctx.hex()] = ctx.rev()
3459 n = ctx.extra().get('source')
3459 n = ctx.extra().get('source')
3460 if n:
3460 if n:
3461 ids[n] = ctx.rev()
3461 ids[n] = ctx.rev()
3462
3462
3463 # check ancestors for earlier grafts
3463 # check ancestors for earlier grafts
3464 ui.debug('scanning for duplicate grafts\n')
3464 ui.debug('scanning for duplicate grafts\n')
3465
3465
3466 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3466 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3467 ctx = repo[rev]
3467 ctx = repo[rev]
3468 n = ctx.extra().get('source')
3468 n = ctx.extra().get('source')
3469 if n in ids:
3469 if n in ids:
3470 try:
3470 try:
3471 r = repo[n].rev()
3471 r = repo[n].rev()
3472 except error.RepoLookupError:
3472 except error.RepoLookupError:
3473 r = None
3473 r = None
3474 if r in revs:
3474 if r in revs:
3475 ui.warn(_('skipping revision %d:%s '
3475 ui.warn(_('skipping revision %d:%s '
3476 '(already grafted to %d:%s)\n')
3476 '(already grafted to %d:%s)\n')
3477 % (r, repo[r], rev, ctx))
3477 % (r, repo[r], rev, ctx))
3478 revs.remove(r)
3478 revs.remove(r)
3479 elif ids[n] in revs:
3479 elif ids[n] in revs:
3480 if r is None:
3480 if r is None:
3481 ui.warn(_('skipping already grafted revision %d:%s '
3481 ui.warn(_('skipping already grafted revision %d:%s '
3482 '(%d:%s also has unknown origin %s)\n')
3482 '(%d:%s also has unknown origin %s)\n')
3483 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3483 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3484 else:
3484 else:
3485 ui.warn(_('skipping already grafted revision %d:%s '
3485 ui.warn(_('skipping already grafted revision %d:%s '
3486 '(%d:%s also has origin %d:%s)\n')
3486 '(%d:%s also has origin %d:%s)\n')
3487 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3487 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3488 revs.remove(ids[n])
3488 revs.remove(ids[n])
3489 elif ctx.hex() in ids:
3489 elif ctx.hex() in ids:
3490 r = ids[ctx.hex()]
3490 r = ids[ctx.hex()]
3491 ui.warn(_('skipping already grafted revision %d:%s '
3491 ui.warn(_('skipping already grafted revision %d:%s '
3492 '(was grafted from %d:%s)\n') %
3492 '(was grafted from %d:%s)\n') %
3493 (r, repo[r], rev, ctx))
3493 (r, repo[r], rev, ctx))
3494 revs.remove(r)
3494 revs.remove(r)
3495 if not revs:
3495 if not revs:
3496 return -1
3496 return -1
3497
3497
3498 wlock = repo.wlock()
3498 wlock = repo.wlock()
3499 try:
3499 try:
3500 for pos, ctx in enumerate(repo.set("%ld", revs)):
3500 for pos, ctx in enumerate(repo.set("%ld", revs)):
3501 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3501 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3502 ctx.description().split('\n', 1)[0])
3502 ctx.description().split('\n', 1)[0])
3503 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3503 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3504 if names:
3504 if names:
3505 desc += ' (%s)' % ' '.join(names)
3505 desc += ' (%s)' % ' '.join(names)
3506 ui.status(_('grafting %s\n') % desc)
3506 ui.status(_('grafting %s\n') % desc)
3507 if opts.get('dry_run'):
3507 if opts.get('dry_run'):
3508 continue
3508 continue
3509
3509
3510 source = ctx.extra().get('source')
3510 source = ctx.extra().get('source')
3511 if not source:
3511 if not source:
3512 source = ctx.hex()
3512 source = ctx.hex()
3513 extra = {'source': source}
3513 extra = {'source': source}
3514 user = ctx.user()
3514 user = ctx.user()
3515 if opts.get('user'):
3515 if opts.get('user'):
3516 user = opts['user']
3516 user = opts['user']
3517 date = ctx.date()
3517 date = ctx.date()
3518 if opts.get('date'):
3518 if opts.get('date'):
3519 date = opts['date']
3519 date = opts['date']
3520 message = ctx.description()
3520 message = ctx.description()
3521 if opts.get('log'):
3521 if opts.get('log'):
3522 message += '\n(grafted from %s)' % ctx.hex()
3522 message += '\n(grafted from %s)' % ctx.hex()
3523
3523
3524 # we don't merge the first commit when continuing
3524 # we don't merge the first commit when continuing
3525 if not cont:
3525 if not cont:
3526 # perform the graft merge with p1(rev) as 'ancestor'
3526 # perform the graft merge with p1(rev) as 'ancestor'
3527 try:
3527 try:
3528 # ui.forcemerge is an internal variable, do not document
3528 # ui.forcemerge is an internal variable, do not document
3529 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3529 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3530 'graft')
3530 'graft')
3531 stats = mergemod.graft(repo, ctx, ctx.p1(),
3531 stats = mergemod.graft(repo, ctx, ctx.p1(),
3532 ['local', 'graft'])
3532 ['local', 'graft'])
3533 finally:
3533 finally:
3534 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3534 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3535 # report any conflicts
3535 # report any conflicts
3536 if stats and stats[3] > 0:
3536 if stats and stats[3] > 0:
3537 # write out state for --continue
3537 # write out state for --continue
3538 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3538 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3539 repo.vfs.write('graftstate', ''.join(nodelines))
3539 repo.vfs.write('graftstate', ''.join(nodelines))
3540 raise util.Abort(
3540 raise util.Abort(
3541 _("unresolved conflicts, can't continue"),
3541 _("unresolved conflicts, can't continue"),
3542 hint=_('use hg resolve and hg graft --continue'))
3542 hint=_('use hg resolve and hg graft --continue'))
3543 else:
3543 else:
3544 cont = False
3544 cont = False
3545
3545
3546 # commit
3546 # commit
3547 node = repo.commit(text=message, user=user,
3547 node = repo.commit(text=message, user=user,
3548 date=date, extra=extra, editor=editor)
3548 date=date, extra=extra, editor=editor)
3549 if node is None:
3549 if node is None:
3550 ui.warn(
3550 ui.warn(
3551 _('note: graft of %d:%s created no changes to commit\n') %
3551 _('note: graft of %d:%s created no changes to commit\n') %
3552 (ctx.rev(), ctx))
3552 (ctx.rev(), ctx))
3553 finally:
3553 finally:
3554 wlock.release()
3554 wlock.release()
3555
3555
3556 # remove state when we complete successfully
3556 # remove state when we complete successfully
3557 if not opts.get('dry_run'):
3557 if not opts.get('dry_run'):
3558 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3558 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3559
3559
3560 return 0
3560 return 0
3561
3561
3562 @command('grep',
3562 @command('grep',
3563 [('0', 'print0', None, _('end fields with NUL')),
3563 [('0', 'print0', None, _('end fields with NUL')),
3564 ('', 'all', None, _('print all revisions that match')),
3564 ('', 'all', None, _('print all revisions that match')),
3565 ('a', 'text', None, _('treat all files as text')),
3565 ('a', 'text', None, _('treat all files as text')),
3566 ('f', 'follow', None,
3566 ('f', 'follow', None,
3567 _('follow changeset history,'
3567 _('follow changeset history,'
3568 ' or file history across copies and renames')),
3568 ' or file history across copies and renames')),
3569 ('i', 'ignore-case', None, _('ignore case when matching')),
3569 ('i', 'ignore-case', None, _('ignore case when matching')),
3570 ('l', 'files-with-matches', None,
3570 ('l', 'files-with-matches', None,
3571 _('print only filenames and revisions that match')),
3571 _('print only filenames and revisions that match')),
3572 ('n', 'line-number', None, _('print matching line numbers')),
3572 ('n', 'line-number', None, _('print matching line numbers')),
3573 ('r', 'rev', [],
3573 ('r', 'rev', [],
3574 _('only search files changed within revision range'), _('REV')),
3574 _('only search files changed within revision range'), _('REV')),
3575 ('u', 'user', None, _('list the author (long with -v)')),
3575 ('u', 'user', None, _('list the author (long with -v)')),
3576 ('d', 'date', None, _('list the date (short with -q)')),
3576 ('d', 'date', None, _('list the date (short with -q)')),
3577 ] + walkopts,
3577 ] + walkopts,
3578 _('[OPTION]... PATTERN [FILE]...'),
3578 _('[OPTION]... PATTERN [FILE]...'),
3579 inferrepo=True)
3579 inferrepo=True)
3580 def grep(ui, repo, pattern, *pats, **opts):
3580 def grep(ui, repo, pattern, *pats, **opts):
3581 """search for a pattern in specified files and revisions
3581 """search for a pattern in specified files and revisions
3582
3582
3583 Search revisions of files for a regular expression.
3583 Search revisions of files for a regular expression.
3584
3584
3585 This command behaves differently than Unix grep. It only accepts
3585 This command behaves differently than Unix grep. It only accepts
3586 Python/Perl regexps. It searches repository history, not the
3586 Python/Perl regexps. It searches repository history, not the
3587 working directory. It always prints the revision number in which a
3587 working directory. It always prints the revision number in which a
3588 match appears.
3588 match appears.
3589
3589
3590 By default, grep only prints output for the first revision of a
3590 By default, grep only prints output for the first revision of a
3591 file in which it finds a match. To get it to print every revision
3591 file in which it finds a match. To get it to print every revision
3592 that contains a change in match status ("-" for a match that
3592 that contains a change in match status ("-" for a match that
3593 becomes a non-match, or "+" for a non-match that becomes a match),
3593 becomes a non-match, or "+" for a non-match that becomes a match),
3594 use the --all flag.
3594 use the --all flag.
3595
3595
3596 Returns 0 if a match is found, 1 otherwise.
3596 Returns 0 if a match is found, 1 otherwise.
3597 """
3597 """
3598 reflags = re.M
3598 reflags = re.M
3599 if opts.get('ignore_case'):
3599 if opts.get('ignore_case'):
3600 reflags |= re.I
3600 reflags |= re.I
3601 try:
3601 try:
3602 regexp = util.re.compile(pattern, reflags)
3602 regexp = util.re.compile(pattern, reflags)
3603 except re.error, inst:
3603 except re.error, inst:
3604 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3604 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3605 return 1
3605 return 1
3606 sep, eol = ':', '\n'
3606 sep, eol = ':', '\n'
3607 if opts.get('print0'):
3607 if opts.get('print0'):
3608 sep = eol = '\0'
3608 sep = eol = '\0'
3609
3609
3610 getfile = util.lrucachefunc(repo.file)
3610 getfile = util.lrucachefunc(repo.file)
3611
3611
3612 def matchlines(body):
3612 def matchlines(body):
3613 begin = 0
3613 begin = 0
3614 linenum = 0
3614 linenum = 0
3615 while begin < len(body):
3615 while begin < len(body):
3616 match = regexp.search(body, begin)
3616 match = regexp.search(body, begin)
3617 if not match:
3617 if not match:
3618 break
3618 break
3619 mstart, mend = match.span()
3619 mstart, mend = match.span()
3620 linenum += body.count('\n', begin, mstart) + 1
3620 linenum += body.count('\n', begin, mstart) + 1
3621 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3621 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3622 begin = body.find('\n', mend) + 1 or len(body) + 1
3622 begin = body.find('\n', mend) + 1 or len(body) + 1
3623 lend = begin - 1
3623 lend = begin - 1
3624 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3624 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3625
3625
3626 class linestate(object):
3626 class linestate(object):
3627 def __init__(self, line, linenum, colstart, colend):
3627 def __init__(self, line, linenum, colstart, colend):
3628 self.line = line
3628 self.line = line
3629 self.linenum = linenum
3629 self.linenum = linenum
3630 self.colstart = colstart
3630 self.colstart = colstart
3631 self.colend = colend
3631 self.colend = colend
3632
3632
3633 def __hash__(self):
3633 def __hash__(self):
3634 return hash((self.linenum, self.line))
3634 return hash((self.linenum, self.line))
3635
3635
3636 def __eq__(self, other):
3636 def __eq__(self, other):
3637 return self.line == other.line
3637 return self.line == other.line
3638
3638
3639 def __iter__(self):
3639 def __iter__(self):
3640 yield (self.line[:self.colstart], '')
3640 yield (self.line[:self.colstart], '')
3641 yield (self.line[self.colstart:self.colend], 'grep.match')
3641 yield (self.line[self.colstart:self.colend], 'grep.match')
3642 rest = self.line[self.colend:]
3642 rest = self.line[self.colend:]
3643 while rest != '':
3643 while rest != '':
3644 match = regexp.search(rest)
3644 match = regexp.search(rest)
3645 if not match:
3645 if not match:
3646 yield (rest, '')
3646 yield (rest, '')
3647 break
3647 break
3648 mstart, mend = match.span()
3648 mstart, mend = match.span()
3649 yield (rest[:mstart], '')
3649 yield (rest[:mstart], '')
3650 yield (rest[mstart:mend], 'grep.match')
3650 yield (rest[mstart:mend], 'grep.match')
3651 rest = rest[mend:]
3651 rest = rest[mend:]
3652
3652
3653 matches = {}
3653 matches = {}
3654 copies = {}
3654 copies = {}
3655 def grepbody(fn, rev, body):
3655 def grepbody(fn, rev, body):
3656 matches[rev].setdefault(fn, [])
3656 matches[rev].setdefault(fn, [])
3657 m = matches[rev][fn]
3657 m = matches[rev][fn]
3658 for lnum, cstart, cend, line in matchlines(body):
3658 for lnum, cstart, cend, line in matchlines(body):
3659 s = linestate(line, lnum, cstart, cend)
3659 s = linestate(line, lnum, cstart, cend)
3660 m.append(s)
3660 m.append(s)
3661
3661
3662 def difflinestates(a, b):
3662 def difflinestates(a, b):
3663 sm = difflib.SequenceMatcher(None, a, b)
3663 sm = difflib.SequenceMatcher(None, a, b)
3664 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3664 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3665 if tag == 'insert':
3665 if tag == 'insert':
3666 for i in xrange(blo, bhi):
3666 for i in xrange(blo, bhi):
3667 yield ('+', b[i])
3667 yield ('+', b[i])
3668 elif tag == 'delete':
3668 elif tag == 'delete':
3669 for i in xrange(alo, ahi):
3669 for i in xrange(alo, ahi):
3670 yield ('-', a[i])
3670 yield ('-', a[i])
3671 elif tag == 'replace':
3671 elif tag == 'replace':
3672 for i in xrange(alo, ahi):
3672 for i in xrange(alo, ahi):
3673 yield ('-', a[i])
3673 yield ('-', a[i])
3674 for i in xrange(blo, bhi):
3674 for i in xrange(blo, bhi):
3675 yield ('+', b[i])
3675 yield ('+', b[i])
3676
3676
3677 def display(fn, ctx, pstates, states):
3677 def display(fn, ctx, pstates, states):
3678 rev = ctx.rev()
3678 rev = ctx.rev()
3679 datefunc = ui.quiet and util.shortdate or util.datestr
3679 datefunc = ui.quiet and util.shortdate or util.datestr
3680 found = False
3680 found = False
3681 @util.cachefunc
3681 @util.cachefunc
3682 def binary():
3682 def binary():
3683 flog = getfile(fn)
3683 flog = getfile(fn)
3684 return util.binary(flog.read(ctx.filenode(fn)))
3684 return util.binary(flog.read(ctx.filenode(fn)))
3685
3685
3686 if opts.get('all'):
3686 if opts.get('all'):
3687 iter = difflinestates(pstates, states)
3687 iter = difflinestates(pstates, states)
3688 else:
3688 else:
3689 iter = [('', l) for l in states]
3689 iter = [('', l) for l in states]
3690 for change, l in iter:
3690 for change, l in iter:
3691 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3691 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3692
3692
3693 if opts.get('line_number'):
3693 if opts.get('line_number'):
3694 cols.append((str(l.linenum), 'grep.linenumber'))
3694 cols.append((str(l.linenum), 'grep.linenumber'))
3695 if opts.get('all'):
3695 if opts.get('all'):
3696 cols.append((change, 'grep.change'))
3696 cols.append((change, 'grep.change'))
3697 if opts.get('user'):
3697 if opts.get('user'):
3698 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3698 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3699 if opts.get('date'):
3699 if opts.get('date'):
3700 cols.append((datefunc(ctx.date()), 'grep.date'))
3700 cols.append((datefunc(ctx.date()), 'grep.date'))
3701 for col, label in cols[:-1]:
3701 for col, label in cols[:-1]:
3702 ui.write(col, label=label)
3702 ui.write(col, label=label)
3703 ui.write(sep, label='grep.sep')
3703 ui.write(sep, label='grep.sep')
3704 ui.write(cols[-1][0], label=cols[-1][1])
3704 ui.write(cols[-1][0], label=cols[-1][1])
3705 if not opts.get('files_with_matches'):
3705 if not opts.get('files_with_matches'):
3706 ui.write(sep, label='grep.sep')
3706 ui.write(sep, label='grep.sep')
3707 if not opts.get('text') and binary():
3707 if not opts.get('text') and binary():
3708 ui.write(" Binary file matches")
3708 ui.write(" Binary file matches")
3709 else:
3709 else:
3710 for s, label in l:
3710 for s, label in l:
3711 ui.write(s, label=label)
3711 ui.write(s, label=label)
3712 ui.write(eol)
3712 ui.write(eol)
3713 found = True
3713 found = True
3714 if opts.get('files_with_matches'):
3714 if opts.get('files_with_matches'):
3715 break
3715 break
3716 return found
3716 return found
3717
3717
3718 skip = {}
3718 skip = {}
3719 revfiles = {}
3719 revfiles = {}
3720 matchfn = scmutil.match(repo[None], pats, opts)
3720 matchfn = scmutil.match(repo[None], pats, opts)
3721 found = False
3721 found = False
3722 follow = opts.get('follow')
3722 follow = opts.get('follow')
3723
3723
3724 def prep(ctx, fns):
3724 def prep(ctx, fns):
3725 rev = ctx.rev()
3725 rev = ctx.rev()
3726 pctx = ctx.p1()
3726 pctx = ctx.p1()
3727 parent = pctx.rev()
3727 parent = pctx.rev()
3728 matches.setdefault(rev, {})
3728 matches.setdefault(rev, {})
3729 matches.setdefault(parent, {})
3729 matches.setdefault(parent, {})
3730 files = revfiles.setdefault(rev, [])
3730 files = revfiles.setdefault(rev, [])
3731 for fn in fns:
3731 for fn in fns:
3732 flog = getfile(fn)
3732 flog = getfile(fn)
3733 try:
3733 try:
3734 fnode = ctx.filenode(fn)
3734 fnode = ctx.filenode(fn)
3735 except error.LookupError:
3735 except error.LookupError:
3736 continue
3736 continue
3737
3737
3738 copied = flog.renamed(fnode)
3738 copied = flog.renamed(fnode)
3739 copy = follow and copied and copied[0]
3739 copy = follow and copied and copied[0]
3740 if copy:
3740 if copy:
3741 copies.setdefault(rev, {})[fn] = copy
3741 copies.setdefault(rev, {})[fn] = copy
3742 if fn in skip:
3742 if fn in skip:
3743 if copy:
3743 if copy:
3744 skip[copy] = True
3744 skip[copy] = True
3745 continue
3745 continue
3746 files.append(fn)
3746 files.append(fn)
3747
3747
3748 if fn not in matches[rev]:
3748 if fn not in matches[rev]:
3749 grepbody(fn, rev, flog.read(fnode))
3749 grepbody(fn, rev, flog.read(fnode))
3750
3750
3751 pfn = copy or fn
3751 pfn = copy or fn
3752 if pfn not in matches[parent]:
3752 if pfn not in matches[parent]:
3753 try:
3753 try:
3754 fnode = pctx.filenode(pfn)
3754 fnode = pctx.filenode(pfn)
3755 grepbody(pfn, parent, flog.read(fnode))
3755 grepbody(pfn, parent, flog.read(fnode))
3756 except error.LookupError:
3756 except error.LookupError:
3757 pass
3757 pass
3758
3758
3759 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3759 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3760 rev = ctx.rev()
3760 rev = ctx.rev()
3761 parent = ctx.p1().rev()
3761 parent = ctx.p1().rev()
3762 for fn in sorted(revfiles.get(rev, [])):
3762 for fn in sorted(revfiles.get(rev, [])):
3763 states = matches[rev][fn]
3763 states = matches[rev][fn]
3764 copy = copies.get(rev, {}).get(fn)
3764 copy = copies.get(rev, {}).get(fn)
3765 if fn in skip:
3765 if fn in skip:
3766 if copy:
3766 if copy:
3767 skip[copy] = True
3767 skip[copy] = True
3768 continue
3768 continue
3769 pstates = matches.get(parent, {}).get(copy or fn, [])
3769 pstates = matches.get(parent, {}).get(copy or fn, [])
3770 if pstates or states:
3770 if pstates or states:
3771 r = display(fn, ctx, pstates, states)
3771 r = display(fn, ctx, pstates, states)
3772 found = found or r
3772 found = found or r
3773 if r and not opts.get('all'):
3773 if r and not opts.get('all'):
3774 skip[fn] = True
3774 skip[fn] = True
3775 if copy:
3775 if copy:
3776 skip[copy] = True
3776 skip[copy] = True
3777 del matches[rev]
3777 del matches[rev]
3778 del revfiles[rev]
3778 del revfiles[rev]
3779
3779
3780 return not found
3780 return not found
3781
3781
3782 @command('heads',
3782 @command('heads',
3783 [('r', 'rev', '',
3783 [('r', 'rev', '',
3784 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3784 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3785 ('t', 'topo', False, _('show topological heads only')),
3785 ('t', 'topo', False, _('show topological heads only')),
3786 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3786 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3787 ('c', 'closed', False, _('show normal and closed branch heads')),
3787 ('c', 'closed', False, _('show normal and closed branch heads')),
3788 ] + templateopts,
3788 ] + templateopts,
3789 _('[-ct] [-r STARTREV] [REV]...'))
3789 _('[-ct] [-r STARTREV] [REV]...'))
3790 def heads(ui, repo, *branchrevs, **opts):
3790 def heads(ui, repo, *branchrevs, **opts):
3791 """show branch heads
3791 """show branch heads
3792
3792
3793 With no arguments, show all open branch heads in the repository.
3793 With no arguments, show all open branch heads in the repository.
3794 Branch heads are changesets that have no descendants on the
3794 Branch heads are changesets that have no descendants on the
3795 same branch. They are where development generally takes place and
3795 same branch. They are where development generally takes place and
3796 are the usual targets for update and merge operations.
3796 are the usual targets for update and merge operations.
3797
3797
3798 If one or more REVs are given, only open branch heads on the
3798 If one or more REVs are given, only open branch heads on the
3799 branches associated with the specified changesets are shown. This
3799 branches associated with the specified changesets are shown. This
3800 means that you can use :hg:`heads .` to see the heads on the
3800 means that you can use :hg:`heads .` to see the heads on the
3801 currently checked-out branch.
3801 currently checked-out branch.
3802
3802
3803 If -c/--closed is specified, also show branch heads marked closed
3803 If -c/--closed is specified, also show branch heads marked closed
3804 (see :hg:`commit --close-branch`).
3804 (see :hg:`commit --close-branch`).
3805
3805
3806 If STARTREV is specified, only those heads that are descendants of
3806 If STARTREV is specified, only those heads that are descendants of
3807 STARTREV will be displayed.
3807 STARTREV will be displayed.
3808
3808
3809 If -t/--topo is specified, named branch mechanics will be ignored and only
3809 If -t/--topo is specified, named branch mechanics will be ignored and only
3810 topological heads (changesets with no children) will be shown.
3810 topological heads (changesets with no children) will be shown.
3811
3811
3812 Returns 0 if matching heads are found, 1 if not.
3812 Returns 0 if matching heads are found, 1 if not.
3813 """
3813 """
3814
3814
3815 start = None
3815 start = None
3816 if 'rev' in opts:
3816 if 'rev' in opts:
3817 start = scmutil.revsingle(repo, opts['rev'], None).node()
3817 start = scmutil.revsingle(repo, opts['rev'], None).node()
3818
3818
3819 if opts.get('topo'):
3819 if opts.get('topo'):
3820 heads = [repo[h] for h in repo.heads(start)]
3820 heads = [repo[h] for h in repo.heads(start)]
3821 else:
3821 else:
3822 heads = []
3822 heads = []
3823 for branch in repo.branchmap():
3823 for branch in repo.branchmap():
3824 heads += repo.branchheads(branch, start, opts.get('closed'))
3824 heads += repo.branchheads(branch, start, opts.get('closed'))
3825 heads = [repo[h] for h in heads]
3825 heads = [repo[h] for h in heads]
3826
3826
3827 if branchrevs:
3827 if branchrevs:
3828 branches = set(repo[br].branch() for br in branchrevs)
3828 branches = set(repo[br].branch() for br in branchrevs)
3829 heads = [h for h in heads if h.branch() in branches]
3829 heads = [h for h in heads if h.branch() in branches]
3830
3830
3831 if opts.get('active') and branchrevs:
3831 if opts.get('active') and branchrevs:
3832 dagheads = repo.heads(start)
3832 dagheads = repo.heads(start)
3833 heads = [h for h in heads if h.node() in dagheads]
3833 heads = [h for h in heads if h.node() in dagheads]
3834
3834
3835 if branchrevs:
3835 if branchrevs:
3836 haveheads = set(h.branch() for h in heads)
3836 haveheads = set(h.branch() for h in heads)
3837 if branches - haveheads:
3837 if branches - haveheads:
3838 headless = ', '.join(b for b in branches - haveheads)
3838 headless = ', '.join(b for b in branches - haveheads)
3839 msg = _('no open branch heads found on branches %s')
3839 msg = _('no open branch heads found on branches %s')
3840 if opts.get('rev'):
3840 if opts.get('rev'):
3841 msg += _(' (started at %s)') % opts['rev']
3841 msg += _(' (started at %s)') % opts['rev']
3842 ui.warn((msg + '\n') % headless)
3842 ui.warn((msg + '\n') % headless)
3843
3843
3844 if not heads:
3844 if not heads:
3845 return 1
3845 return 1
3846
3846
3847 heads = sorted(heads, key=lambda x: -x.rev())
3847 heads = sorted(heads, key=lambda x: -x.rev())
3848 displayer = cmdutil.show_changeset(ui, repo, opts)
3848 displayer = cmdutil.show_changeset(ui, repo, opts)
3849 for ctx in heads:
3849 for ctx in heads:
3850 displayer.show(ctx)
3850 displayer.show(ctx)
3851 displayer.close()
3851 displayer.close()
3852
3852
3853 @command('help',
3853 @command('help',
3854 [('e', 'extension', None, _('show only help for extensions')),
3854 [('e', 'extension', None, _('show only help for extensions')),
3855 ('c', 'command', None, _('show only help for commands')),
3855 ('c', 'command', None, _('show only help for commands')),
3856 ('k', 'keyword', '', _('show topics matching keyword')),
3856 ('k', 'keyword', '', _('show topics matching keyword')),
3857 ],
3857 ],
3858 _('[-ec] [TOPIC]'),
3858 _('[-ec] [TOPIC]'),
3859 norepo=True)
3859 norepo=True)
3860 def help_(ui, name=None, **opts):
3860 def help_(ui, name=None, **opts):
3861 """show help for a given topic or a help overview
3861 """show help for a given topic or a help overview
3862
3862
3863 With no arguments, print a list of commands with short help messages.
3863 With no arguments, print a list of commands with short help messages.
3864
3864
3865 Given a topic, extension, or command name, print help for that
3865 Given a topic, extension, or command name, print help for that
3866 topic.
3866 topic.
3867
3867
3868 Returns 0 if successful.
3868 Returns 0 if successful.
3869 """
3869 """
3870
3870
3871 textwidth = min(ui.termwidth(), 80) - 2
3871 textwidth = min(ui.termwidth(), 80) - 2
3872
3872
3873 keep = []
3873 keep = []
3874 if ui.verbose:
3874 if ui.verbose:
3875 keep.append('verbose')
3875 keep.append('verbose')
3876 if sys.platform.startswith('win'):
3876 if sys.platform.startswith('win'):
3877 keep.append('windows')
3877 keep.append('windows')
3878 elif sys.platform == 'OpenVMS':
3878 elif sys.platform == 'OpenVMS':
3879 keep.append('vms')
3879 keep.append('vms')
3880 elif sys.platform == 'plan9':
3880 elif sys.platform == 'plan9':
3881 keep.append('plan9')
3881 keep.append('plan9')
3882 else:
3882 else:
3883 keep.append('unix')
3883 keep.append('unix')
3884 keep.append(sys.platform.lower())
3884 keep.append(sys.platform.lower())
3885
3885
3886 section = None
3886 section = None
3887 if name and '.' in name:
3887 if name and '.' in name:
3888 name, section = name.split('.', 1)
3888 name, section = name.split('.', 1)
3889
3889
3890 text = help.help_(ui, name, **opts)
3890 text = help.help_(ui, name, **opts)
3891
3891
3892 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3892 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3893 section=section)
3893 section=section)
3894 if section and not formatted:
3894 if section and not formatted:
3895 raise util.Abort(_("help section not found"))
3895 raise util.Abort(_("help section not found"))
3896
3896
3897 if 'verbose' in pruned:
3897 if 'verbose' in pruned:
3898 keep.append('omitted')
3898 keep.append('omitted')
3899 else:
3899 else:
3900 keep.append('notomitted')
3900 keep.append('notomitted')
3901 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3901 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3902 section=section)
3902 section=section)
3903 ui.write(formatted)
3903 ui.write(formatted)
3904
3904
3905
3905
3906 @command('identify|id',
3906 @command('identify|id',
3907 [('r', 'rev', '',
3907 [('r', 'rev', '',
3908 _('identify the specified revision'), _('REV')),
3908 _('identify the specified revision'), _('REV')),
3909 ('n', 'num', None, _('show local revision number')),
3909 ('n', 'num', None, _('show local revision number')),
3910 ('i', 'id', None, _('show global revision id')),
3910 ('i', 'id', None, _('show global revision id')),
3911 ('b', 'branch', None, _('show branch')),
3911 ('b', 'branch', None, _('show branch')),
3912 ('t', 'tags', None, _('show tags')),
3912 ('t', 'tags', None, _('show tags')),
3913 ('B', 'bookmarks', None, _('show bookmarks')),
3913 ('B', 'bookmarks', None, _('show bookmarks')),
3914 ] + remoteopts,
3914 ] + remoteopts,
3915 _('[-nibtB] [-r REV] [SOURCE]'),
3915 _('[-nibtB] [-r REV] [SOURCE]'),
3916 optionalrepo=True)
3916 optionalrepo=True)
3917 def identify(ui, repo, source=None, rev=None,
3917 def identify(ui, repo, source=None, rev=None,
3918 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3918 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3919 """identify the working copy or specified revision
3919 """identify the working copy or specified revision
3920
3920
3921 Print a summary identifying the repository state at REV using one or
3921 Print a summary identifying the repository state at REV using one or
3922 two parent hash identifiers, followed by a "+" if the working
3922 two parent hash identifiers, followed by a "+" if the working
3923 directory has uncommitted changes, the branch name (if not default),
3923 directory has uncommitted changes, the branch name (if not default),
3924 a list of tags, and a list of bookmarks.
3924 a list of tags, and a list of bookmarks.
3925
3925
3926 When REV is not given, print a summary of the current state of the
3926 When REV is not given, print a summary of the current state of the
3927 repository.
3927 repository.
3928
3928
3929 Specifying a path to a repository root or Mercurial bundle will
3929 Specifying a path to a repository root or Mercurial bundle will
3930 cause lookup to operate on that repository/bundle.
3930 cause lookup to operate on that repository/bundle.
3931
3931
3932 .. container:: verbose
3932 .. container:: verbose
3933
3933
3934 Examples:
3934 Examples:
3935
3935
3936 - generate a build identifier for the working directory::
3936 - generate a build identifier for the working directory::
3937
3937
3938 hg id --id > build-id.dat
3938 hg id --id > build-id.dat
3939
3939
3940 - find the revision corresponding to a tag::
3940 - find the revision corresponding to a tag::
3941
3941
3942 hg id -n -r 1.3
3942 hg id -n -r 1.3
3943
3943
3944 - check the most recent revision of a remote repository::
3944 - check the most recent revision of a remote repository::
3945
3945
3946 hg id -r tip http://selenic.com/hg/
3946 hg id -r tip http://selenic.com/hg/
3947
3947
3948 Returns 0 if successful.
3948 Returns 0 if successful.
3949 """
3949 """
3950
3950
3951 if not repo and not source:
3951 if not repo and not source:
3952 raise util.Abort(_("there is no Mercurial repository here "
3952 raise util.Abort(_("there is no Mercurial repository here "
3953 "(.hg not found)"))
3953 "(.hg not found)"))
3954
3954
3955 hexfunc = ui.debugflag and hex or short
3955 hexfunc = ui.debugflag and hex or short
3956 default = not (num or id or branch or tags or bookmarks)
3956 default = not (num or id or branch or tags or bookmarks)
3957 output = []
3957 output = []
3958 revs = []
3958 revs = []
3959
3959
3960 if source:
3960 if source:
3961 source, branches = hg.parseurl(ui.expandpath(source))
3961 source, branches = hg.parseurl(ui.expandpath(source))
3962 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3962 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3963 repo = peer.local()
3963 repo = peer.local()
3964 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3964 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3965
3965
3966 if not repo:
3966 if not repo:
3967 if num or branch or tags:
3967 if num or branch or tags:
3968 raise util.Abort(
3968 raise util.Abort(
3969 _("can't query remote revision number, branch, or tags"))
3969 _("can't query remote revision number, branch, or tags"))
3970 if not rev and revs:
3970 if not rev and revs:
3971 rev = revs[0]
3971 rev = revs[0]
3972 if not rev:
3972 if not rev:
3973 rev = "tip"
3973 rev = "tip"
3974
3974
3975 remoterev = peer.lookup(rev)
3975 remoterev = peer.lookup(rev)
3976 if default or id:
3976 if default or id:
3977 output = [hexfunc(remoterev)]
3977 output = [hexfunc(remoterev)]
3978
3978
3979 def getbms():
3979 def getbms():
3980 bms = []
3980 bms = []
3981
3981
3982 if 'bookmarks' in peer.listkeys('namespaces'):
3982 if 'bookmarks' in peer.listkeys('namespaces'):
3983 hexremoterev = hex(remoterev)
3983 hexremoterev = hex(remoterev)
3984 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3984 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3985 if bmr == hexremoterev]
3985 if bmr == hexremoterev]
3986
3986
3987 return sorted(bms)
3987 return sorted(bms)
3988
3988
3989 if bookmarks:
3989 if bookmarks:
3990 output.extend(getbms())
3990 output.extend(getbms())
3991 elif default and not ui.quiet:
3991 elif default and not ui.quiet:
3992 # multiple bookmarks for a single parent separated by '/'
3992 # multiple bookmarks for a single parent separated by '/'
3993 bm = '/'.join(getbms())
3993 bm = '/'.join(getbms())
3994 if bm:
3994 if bm:
3995 output.append(bm)
3995 output.append(bm)
3996 else:
3996 else:
3997 if not rev:
3997 if not rev:
3998 ctx = repo[None]
3998 ctx = repo[None]
3999 parents = ctx.parents()
3999 parents = ctx.parents()
4000 changed = ""
4000 changed = ""
4001 if default or id or num:
4001 if default or id or num:
4002 if (util.any(repo.status())
4002 if (util.any(repo.status())
4003 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4003 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4004 changed = '+'
4004 changed = '+'
4005 if default or id:
4005 if default or id:
4006 output = ["%s%s" %
4006 output = ["%s%s" %
4007 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4007 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4008 if num:
4008 if num:
4009 output.append("%s%s" %
4009 output.append("%s%s" %
4010 ('+'.join([str(p.rev()) for p in parents]), changed))
4010 ('+'.join([str(p.rev()) for p in parents]), changed))
4011 else:
4011 else:
4012 ctx = scmutil.revsingle(repo, rev)
4012 ctx = scmutil.revsingle(repo, rev)
4013 if default or id:
4013 if default or id:
4014 output = [hexfunc(ctx.node())]
4014 output = [hexfunc(ctx.node())]
4015 if num:
4015 if num:
4016 output.append(str(ctx.rev()))
4016 output.append(str(ctx.rev()))
4017
4017
4018 if default and not ui.quiet:
4018 if default and not ui.quiet:
4019 b = ctx.branch()
4019 b = ctx.branch()
4020 if b != 'default':
4020 if b != 'default':
4021 output.append("(%s)" % b)
4021 output.append("(%s)" % b)
4022
4022
4023 # multiple tags for a single parent separated by '/'
4023 # multiple tags for a single parent separated by '/'
4024 t = '/'.join(ctx.tags())
4024 t = '/'.join(ctx.tags())
4025 if t:
4025 if t:
4026 output.append(t)
4026 output.append(t)
4027
4027
4028 # multiple bookmarks for a single parent separated by '/'
4028 # multiple bookmarks for a single parent separated by '/'
4029 bm = '/'.join(ctx.bookmarks())
4029 bm = '/'.join(ctx.bookmarks())
4030 if bm:
4030 if bm:
4031 output.append(bm)
4031 output.append(bm)
4032 else:
4032 else:
4033 if branch:
4033 if branch:
4034 output.append(ctx.branch())
4034 output.append(ctx.branch())
4035
4035
4036 if tags:
4036 if tags:
4037 output.extend(ctx.tags())
4037 output.extend(ctx.tags())
4038
4038
4039 if bookmarks:
4039 if bookmarks:
4040 output.extend(ctx.bookmarks())
4040 output.extend(ctx.bookmarks())
4041
4041
4042 ui.write("%s\n" % ' '.join(output))
4042 ui.write("%s\n" % ' '.join(output))
4043
4043
4044 @command('import|patch',
4044 @command('import|patch',
4045 [('p', 'strip', 1,
4045 [('p', 'strip', 1,
4046 _('directory strip option for patch. This has the same '
4046 _('directory strip option for patch. This has the same '
4047 'meaning as the corresponding patch option'), _('NUM')),
4047 'meaning as the corresponding patch option'), _('NUM')),
4048 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4048 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4049 ('e', 'edit', False, _('invoke editor on commit messages')),
4049 ('e', 'edit', False, _('invoke editor on commit messages')),
4050 ('f', 'force', None,
4050 ('f', 'force', None,
4051 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4051 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4052 ('', 'no-commit', None,
4052 ('', 'no-commit', None,
4053 _("don't commit, just update the working directory")),
4053 _("don't commit, just update the working directory")),
4054 ('', 'bypass', None,
4054 ('', 'bypass', None,
4055 _("apply patch without touching the working directory")),
4055 _("apply patch without touching the working directory")),
4056 ('', 'partial', None,
4056 ('', 'partial', None,
4057 _('commit even if some hunks fail')),
4057 _('commit even if some hunks fail')),
4058 ('', 'exact', None,
4058 ('', 'exact', None,
4059 _('apply patch to the nodes from which it was generated')),
4059 _('apply patch to the nodes from which it was generated')),
4060 ('', 'import-branch', None,
4060 ('', 'import-branch', None,
4061 _('use any branch information in patch (implied by --exact)'))] +
4061 _('use any branch information in patch (implied by --exact)'))] +
4062 commitopts + commitopts2 + similarityopts,
4062 commitopts + commitopts2 + similarityopts,
4063 _('[OPTION]... PATCH...'))
4063 _('[OPTION]... PATCH...'))
4064 def import_(ui, repo, patch1=None, *patches, **opts):
4064 def import_(ui, repo, patch1=None, *patches, **opts):
4065 """import an ordered set of patches
4065 """import an ordered set of patches
4066
4066
4067 Import a list of patches and commit them individually (unless
4067 Import a list of patches and commit them individually (unless
4068 --no-commit is specified).
4068 --no-commit is specified).
4069
4069
4070 Because import first applies changes to the working directory,
4070 Because import first applies changes to the working directory,
4071 import will abort if there are outstanding changes.
4071 import will abort if there are outstanding changes.
4072
4072
4073 You can import a patch straight from a mail message. Even patches
4073 You can import a patch straight from a mail message. Even patches
4074 as attachments work (to use the body part, it must have type
4074 as attachments work (to use the body part, it must have type
4075 text/plain or text/x-patch). From and Subject headers of email
4075 text/plain or text/x-patch). From and Subject headers of email
4076 message are used as default committer and commit message. All
4076 message are used as default committer and commit message. All
4077 text/plain body parts before first diff are added to commit
4077 text/plain body parts before first diff are added to commit
4078 message.
4078 message.
4079
4079
4080 If the imported patch was generated by :hg:`export`, user and
4080 If the imported patch was generated by :hg:`export`, user and
4081 description from patch override values from message headers and
4081 description from patch override values from message headers and
4082 body. Values given on command line with -m/--message and -u/--user
4082 body. Values given on command line with -m/--message and -u/--user
4083 override these.
4083 override these.
4084
4084
4085 If --exact is specified, import will set the working directory to
4085 If --exact is specified, import will set the working directory to
4086 the parent of each patch before applying it, and will abort if the
4086 the parent of each patch before applying it, and will abort if the
4087 resulting changeset has a different ID than the one recorded in
4087 resulting changeset has a different ID than the one recorded in
4088 the patch. This may happen due to character set problems or other
4088 the patch. This may happen due to character set problems or other
4089 deficiencies in the text patch format.
4089 deficiencies in the text patch format.
4090
4090
4091 Use --bypass to apply and commit patches directly to the
4091 Use --bypass to apply and commit patches directly to the
4092 repository, not touching the working directory. Without --exact,
4092 repository, not touching the working directory. Without --exact,
4093 patches will be applied on top of the working directory parent
4093 patches will be applied on top of the working directory parent
4094 revision.
4094 revision.
4095
4095
4096 With -s/--similarity, hg will attempt to discover renames and
4096 With -s/--similarity, hg will attempt to discover renames and
4097 copies in the patch in the same way as :hg:`addremove`.
4097 copies in the patch in the same way as :hg:`addremove`.
4098
4098
4099 Use --partial to ensure a changeset will be created from the patch
4099 Use --partial to ensure a changeset will be created from the patch
4100 even if some hunks fail to apply. Hunks that fail to apply will be
4100 even if some hunks fail to apply. Hunks that fail to apply will be
4101 written to a <target-file>.rej file. Conflicts can then be resolved
4101 written to a <target-file>.rej file. Conflicts can then be resolved
4102 by hand before :hg:`commit --amend` is run to update the created
4102 by hand before :hg:`commit --amend` is run to update the created
4103 changeset. This flag exists to let people import patches that
4103 changeset. This flag exists to let people import patches that
4104 partially apply without losing the associated metadata (author,
4104 partially apply without losing the associated metadata (author,
4105 date, description, ...). Note that when none of the hunk applies
4105 date, description, ...). Note that when none of the hunk applies
4106 cleanly, :hg:`import --partial` will create an empty changeset,
4106 cleanly, :hg:`import --partial` will create an empty changeset,
4107 importing only the patch metadata.
4107 importing only the patch metadata.
4108
4108
4109 To read a patch from standard input, use "-" as the patch name. If
4109 To read a patch from standard input, use "-" as the patch name. If
4110 a URL is specified, the patch will be downloaded from it.
4110 a URL is specified, the patch will be downloaded from it.
4111 See :hg:`help dates` for a list of formats valid for -d/--date.
4111 See :hg:`help dates` for a list of formats valid for -d/--date.
4112
4112
4113 .. container:: verbose
4113 .. container:: verbose
4114
4114
4115 Examples:
4115 Examples:
4116
4116
4117 - import a traditional patch from a website and detect renames::
4117 - import a traditional patch from a website and detect renames::
4118
4118
4119 hg import -s 80 http://example.com/bugfix.patch
4119 hg import -s 80 http://example.com/bugfix.patch
4120
4120
4121 - import a changeset from an hgweb server::
4121 - import a changeset from an hgweb server::
4122
4122
4123 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4123 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4124
4124
4125 - import all the patches in an Unix-style mbox::
4125 - import all the patches in an Unix-style mbox::
4126
4126
4127 hg import incoming-patches.mbox
4127 hg import incoming-patches.mbox
4128
4128
4129 - attempt to exactly restore an exported changeset (not always
4129 - attempt to exactly restore an exported changeset (not always
4130 possible)::
4130 possible)::
4131
4131
4132 hg import --exact proposed-fix.patch
4132 hg import --exact proposed-fix.patch
4133
4133
4134 Returns 0 on success, 1 on partial success (see --partial).
4134 Returns 0 on success, 1 on partial success (see --partial).
4135 """
4135 """
4136
4136
4137 if not patch1:
4137 if not patch1:
4138 raise util.Abort(_('need at least one patch to import'))
4138 raise util.Abort(_('need at least one patch to import'))
4139
4139
4140 patches = (patch1,) + patches
4140 patches = (patch1,) + patches
4141
4141
4142 date = opts.get('date')
4142 date = opts.get('date')
4143 if date:
4143 if date:
4144 opts['date'] = util.parsedate(date)
4144 opts['date'] = util.parsedate(date)
4145
4145
4146 update = not opts.get('bypass')
4146 update = not opts.get('bypass')
4147 if not update and opts.get('no_commit'):
4147 if not update and opts.get('no_commit'):
4148 raise util.Abort(_('cannot use --no-commit with --bypass'))
4148 raise util.Abort(_('cannot use --no-commit with --bypass'))
4149 try:
4149 try:
4150 sim = float(opts.get('similarity') or 0)
4150 sim = float(opts.get('similarity') or 0)
4151 except ValueError:
4151 except ValueError:
4152 raise util.Abort(_('similarity must be a number'))
4152 raise util.Abort(_('similarity must be a number'))
4153 if sim < 0 or sim > 100:
4153 if sim < 0 or sim > 100:
4154 raise util.Abort(_('similarity must be between 0 and 100'))
4154 raise util.Abort(_('similarity must be between 0 and 100'))
4155 if sim and not update:
4155 if sim and not update:
4156 raise util.Abort(_('cannot use --similarity with --bypass'))
4156 raise util.Abort(_('cannot use --similarity with --bypass'))
4157 if opts.get('exact') and opts.get('edit'):
4157 if opts.get('exact') and opts.get('edit'):
4158 raise util.Abort(_('cannot use --exact with --edit'))
4158 raise util.Abort(_('cannot use --exact with --edit'))
4159
4159
4160 if update:
4160 if update:
4161 cmdutil.checkunfinished(repo)
4161 cmdutil.checkunfinished(repo)
4162 if (opts.get('exact') or not opts.get('force')) and update:
4162 if (opts.get('exact') or not opts.get('force')) and update:
4163 cmdutil.bailifchanged(repo)
4163 cmdutil.bailifchanged(repo)
4164
4164
4165 base = opts["base"]
4165 base = opts["base"]
4166 wlock = lock = tr = None
4166 wlock = lock = tr = None
4167 msgs = []
4167 msgs = []
4168 ret = 0
4168 ret = 0
4169
4169
4170
4170
4171 try:
4171 try:
4172 try:
4172 try:
4173 wlock = repo.wlock()
4173 wlock = repo.wlock()
4174 repo.dirstate.beginparentchange()
4174 repo.dirstate.beginparentchange()
4175 if not opts.get('no_commit'):
4175 if not opts.get('no_commit'):
4176 lock = repo.lock()
4176 lock = repo.lock()
4177 tr = repo.transaction('import')
4177 tr = repo.transaction('import')
4178 parents = repo.parents()
4178 parents = repo.parents()
4179 for patchurl in patches:
4179 for patchurl in patches:
4180 if patchurl == '-':
4180 if patchurl == '-':
4181 ui.status(_('applying patch from stdin\n'))
4181 ui.status(_('applying patch from stdin\n'))
4182 patchfile = ui.fin
4182 patchfile = ui.fin
4183 patchurl = 'stdin' # for error message
4183 patchurl = 'stdin' # for error message
4184 else:
4184 else:
4185 patchurl = os.path.join(base, patchurl)
4185 patchurl = os.path.join(base, patchurl)
4186 ui.status(_('applying %s\n') % patchurl)
4186 ui.status(_('applying %s\n') % patchurl)
4187 patchfile = hg.openpath(ui, patchurl)
4187 patchfile = hg.openpath(ui, patchurl)
4188
4188
4189 haspatch = False
4189 haspatch = False
4190 for hunk in patch.split(patchfile):
4190 for hunk in patch.split(patchfile):
4191 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4191 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4192 parents, opts,
4192 parents, opts,
4193 msgs, hg.clean)
4193 msgs, hg.clean)
4194 if msg:
4194 if msg:
4195 haspatch = True
4195 haspatch = True
4196 ui.note(msg + '\n')
4196 ui.note(msg + '\n')
4197 if update or opts.get('exact'):
4197 if update or opts.get('exact'):
4198 parents = repo.parents()
4198 parents = repo.parents()
4199 else:
4199 else:
4200 parents = [repo[node]]
4200 parents = [repo[node]]
4201 if rej:
4201 if rej:
4202 ui.write_err(_("patch applied partially\n"))
4202 ui.write_err(_("patch applied partially\n"))
4203 ui.write_err(_("(fix the .rej files and run "
4203 ui.write_err(_("(fix the .rej files and run "
4204 "`hg commit --amend`)\n"))
4204 "`hg commit --amend`)\n"))
4205 ret = 1
4205 ret = 1
4206 break
4206 break
4207
4207
4208 if not haspatch:
4208 if not haspatch:
4209 raise util.Abort(_('%s: no diffs found') % patchurl)
4209 raise util.Abort(_('%s: no diffs found') % patchurl)
4210
4210
4211 if tr:
4211 if tr:
4212 tr.close()
4212 tr.close()
4213 if msgs:
4213 if msgs:
4214 repo.savecommitmessage('\n* * *\n'.join(msgs))
4214 repo.savecommitmessage('\n* * *\n'.join(msgs))
4215 repo.dirstate.endparentchange()
4215 repo.dirstate.endparentchange()
4216 return ret
4216 return ret
4217 except: # re-raises
4217 except: # re-raises
4218 # wlock.release() indirectly calls dirstate.write(): since
4218 # wlock.release() indirectly calls dirstate.write(): since
4219 # we're crashing, we do not want to change the working dir
4219 # we're crashing, we do not want to change the working dir
4220 # parent after all, so make sure it writes nothing
4220 # parent after all, so make sure it writes nothing
4221 repo.dirstate.invalidate()
4221 repo.dirstate.invalidate()
4222 raise
4222 raise
4223 finally:
4223 finally:
4224 if tr:
4224 if tr:
4225 tr.release()
4225 tr.release()
4226 release(lock, wlock)
4226 release(lock, wlock)
4227
4227
4228 @command('incoming|in',
4228 @command('incoming|in',
4229 [('f', 'force', None,
4229 [('f', 'force', None,
4230 _('run even if remote repository is unrelated')),
4230 _('run even if remote repository is unrelated')),
4231 ('n', 'newest-first', None, _('show newest record first')),
4231 ('n', 'newest-first', None, _('show newest record first')),
4232 ('', 'bundle', '',
4232 ('', 'bundle', '',
4233 _('file to store the bundles into'), _('FILE')),
4233 _('file to store the bundles into'), _('FILE')),
4234 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4234 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4235 ('B', 'bookmarks', False, _("compare bookmarks")),
4235 ('B', 'bookmarks', False, _("compare bookmarks")),
4236 ('b', 'branch', [],
4236 ('b', 'branch', [],
4237 _('a specific branch you would like to pull'), _('BRANCH')),
4237 _('a specific branch you would like to pull'), _('BRANCH')),
4238 ] + logopts + remoteopts + subrepoopts,
4238 ] + logopts + remoteopts + subrepoopts,
4239 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4239 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4240 def incoming(ui, repo, source="default", **opts):
4240 def incoming(ui, repo, source="default", **opts):
4241 """show new changesets found in source
4241 """show new changesets found in source
4242
4242
4243 Show new changesets found in the specified path/URL or the default
4243 Show new changesets found in the specified path/URL or the default
4244 pull location. These are the changesets that would have been pulled
4244 pull location. These are the changesets that would have been pulled
4245 if a pull at the time you issued this command.
4245 if a pull at the time you issued this command.
4246
4246
4247 For remote repository, using --bundle avoids downloading the
4248 changesets twice if the incoming is followed by a pull.
4249
4250 See pull for valid source format details.
4247 See pull for valid source format details.
4251
4248
4252 .. container:: verbose
4249 .. container:: verbose
4253
4250
4251 For remote repository, using --bundle avoids downloading the
4252 changesets twice if the incoming is followed by a pull.
4253
4254 Examples:
4254 Examples:
4255
4255
4256 - show incoming changes with patches and full description::
4256 - show incoming changes with patches and full description::
4257
4257
4258 hg incoming -vp
4258 hg incoming -vp
4259
4259
4260 - show incoming changes excluding merges, store a bundle::
4260 - show incoming changes excluding merges, store a bundle::
4261
4261
4262 hg in -vpM --bundle incoming.hg
4262 hg in -vpM --bundle incoming.hg
4263 hg pull incoming.hg
4263 hg pull incoming.hg
4264
4264
4265 - briefly list changes inside a bundle::
4265 - briefly list changes inside a bundle::
4266
4266
4267 hg in changes.hg -T "{desc|firstline}\\n"
4267 hg in changes.hg -T "{desc|firstline}\\n"
4268
4268
4269 Returns 0 if there are incoming changes, 1 otherwise.
4269 Returns 0 if there are incoming changes, 1 otherwise.
4270 """
4270 """
4271 if opts.get('graph'):
4271 if opts.get('graph'):
4272 cmdutil.checkunsupportedgraphflags([], opts)
4272 cmdutil.checkunsupportedgraphflags([], opts)
4273 def display(other, chlist, displayer):
4273 def display(other, chlist, displayer):
4274 revdag = cmdutil.graphrevs(other, chlist, opts)
4274 revdag = cmdutil.graphrevs(other, chlist, opts)
4275 showparents = [ctx.node() for ctx in repo[None].parents()]
4275 showparents = [ctx.node() for ctx in repo[None].parents()]
4276 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4276 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4277 graphmod.asciiedges)
4277 graphmod.asciiedges)
4278
4278
4279 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4279 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4280 return 0
4280 return 0
4281
4281
4282 if opts.get('bundle') and opts.get('subrepos'):
4282 if opts.get('bundle') and opts.get('subrepos'):
4283 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4283 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4284
4284
4285 if opts.get('bookmarks'):
4285 if opts.get('bookmarks'):
4286 source, branches = hg.parseurl(ui.expandpath(source),
4286 source, branches = hg.parseurl(ui.expandpath(source),
4287 opts.get('branch'))
4287 opts.get('branch'))
4288 other = hg.peer(repo, opts, source)
4288 other = hg.peer(repo, opts, source)
4289 if 'bookmarks' not in other.listkeys('namespaces'):
4289 if 'bookmarks' not in other.listkeys('namespaces'):
4290 ui.warn(_("remote doesn't support bookmarks\n"))
4290 ui.warn(_("remote doesn't support bookmarks\n"))
4291 return 0
4291 return 0
4292 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4292 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4293 return bookmarks.diff(ui, repo, other)
4293 return bookmarks.diff(ui, repo, other)
4294
4294
4295 repo._subtoppath = ui.expandpath(source)
4295 repo._subtoppath = ui.expandpath(source)
4296 try:
4296 try:
4297 return hg.incoming(ui, repo, source, opts)
4297 return hg.incoming(ui, repo, source, opts)
4298 finally:
4298 finally:
4299 del repo._subtoppath
4299 del repo._subtoppath
4300
4300
4301
4301
4302 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4302 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4303 norepo=True)
4303 norepo=True)
4304 def init(ui, dest=".", **opts):
4304 def init(ui, dest=".", **opts):
4305 """create a new repository in the given directory
4305 """create a new repository in the given directory
4306
4306
4307 Initialize a new repository in the given directory. If the given
4307 Initialize a new repository in the given directory. If the given
4308 directory does not exist, it will be created.
4308 directory does not exist, it will be created.
4309
4309
4310 If no directory is given, the current directory is used.
4310 If no directory is given, the current directory is used.
4311
4311
4312 It is possible to specify an ``ssh://`` URL as the destination.
4312 It is possible to specify an ``ssh://`` URL as the destination.
4313 See :hg:`help urls` for more information.
4313 See :hg:`help urls` for more information.
4314
4314
4315 Returns 0 on success.
4315 Returns 0 on success.
4316 """
4316 """
4317 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4317 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4318
4318
4319 @command('locate',
4319 @command('locate',
4320 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4320 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4321 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4321 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4322 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4322 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4323 ] + walkopts,
4323 ] + walkopts,
4324 _('[OPTION]... [PATTERN]...'))
4324 _('[OPTION]... [PATTERN]...'))
4325 def locate(ui, repo, *pats, **opts):
4325 def locate(ui, repo, *pats, **opts):
4326 """locate files matching specific patterns (DEPRECATED)
4326 """locate files matching specific patterns (DEPRECATED)
4327
4327
4328 Print files under Mercurial control in the working directory whose
4328 Print files under Mercurial control in the working directory whose
4329 names match the given patterns.
4329 names match the given patterns.
4330
4330
4331 By default, this command searches all directories in the working
4331 By default, this command searches all directories in the working
4332 directory. To search just the current directory and its
4332 directory. To search just the current directory and its
4333 subdirectories, use "--include .".
4333 subdirectories, use "--include .".
4334
4334
4335 If no patterns are given to match, this command prints the names
4335 If no patterns are given to match, this command prints the names
4336 of all files under Mercurial control in the working directory.
4336 of all files under Mercurial control in the working directory.
4337
4337
4338 If you want to feed the output of this command into the "xargs"
4338 If you want to feed the output of this command into the "xargs"
4339 command, use the -0 option to both this command and "xargs". This
4339 command, use the -0 option to both this command and "xargs". This
4340 will avoid the problem of "xargs" treating single filenames that
4340 will avoid the problem of "xargs" treating single filenames that
4341 contain whitespace as multiple filenames.
4341 contain whitespace as multiple filenames.
4342
4342
4343 See :hg:`help files` for a more versatile command.
4343 See :hg:`help files` for a more versatile command.
4344
4344
4345 Returns 0 if a match is found, 1 otherwise.
4345 Returns 0 if a match is found, 1 otherwise.
4346 """
4346 """
4347 end = opts.get('print0') and '\0' or '\n'
4347 end = opts.get('print0') and '\0' or '\n'
4348 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4348 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4349
4349
4350 ret = 1
4350 ret = 1
4351 ctx = repo[rev]
4351 ctx = repo[rev]
4352 m = scmutil.match(ctx, pats, opts, default='relglob')
4352 m = scmutil.match(ctx, pats, opts, default='relglob')
4353 m.bad = lambda x, y: False
4353 m.bad = lambda x, y: False
4354
4354
4355 for abs in ctx.matches(m):
4355 for abs in ctx.matches(m):
4356 if opts.get('fullpath'):
4356 if opts.get('fullpath'):
4357 ui.write(repo.wjoin(abs), end)
4357 ui.write(repo.wjoin(abs), end)
4358 else:
4358 else:
4359 ui.write(((pats and m.rel(abs)) or abs), end)
4359 ui.write(((pats and m.rel(abs)) or abs), end)
4360 ret = 0
4360 ret = 0
4361
4361
4362 return ret
4362 return ret
4363
4363
4364 @command('^log|history',
4364 @command('^log|history',
4365 [('f', 'follow', None,
4365 [('f', 'follow', None,
4366 _('follow changeset history, or file history across copies and renames')),
4366 _('follow changeset history, or file history across copies and renames')),
4367 ('', 'follow-first', None,
4367 ('', 'follow-first', None,
4368 _('only follow the first parent of merge changesets (DEPRECATED)')),
4368 _('only follow the first parent of merge changesets (DEPRECATED)')),
4369 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4369 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4370 ('C', 'copies', None, _('show copied files')),
4370 ('C', 'copies', None, _('show copied files')),
4371 ('k', 'keyword', [],
4371 ('k', 'keyword', [],
4372 _('do case-insensitive search for a given text'), _('TEXT')),
4372 _('do case-insensitive search for a given text'), _('TEXT')),
4373 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4373 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4374 ('', 'removed', None, _('include revisions where files were removed')),
4374 ('', 'removed', None, _('include revisions where files were removed')),
4375 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4375 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4376 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4376 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4377 ('', 'only-branch', [],
4377 ('', 'only-branch', [],
4378 _('show only changesets within the given named branch (DEPRECATED)'),
4378 _('show only changesets within the given named branch (DEPRECATED)'),
4379 _('BRANCH')),
4379 _('BRANCH')),
4380 ('b', 'branch', [],
4380 ('b', 'branch', [],
4381 _('show changesets within the given named branch'), _('BRANCH')),
4381 _('show changesets within the given named branch'), _('BRANCH')),
4382 ('P', 'prune', [],
4382 ('P', 'prune', [],
4383 _('do not display revision or any of its ancestors'), _('REV')),
4383 _('do not display revision or any of its ancestors'), _('REV')),
4384 ] + logopts + walkopts,
4384 ] + logopts + walkopts,
4385 _('[OPTION]... [FILE]'),
4385 _('[OPTION]... [FILE]'),
4386 inferrepo=True)
4386 inferrepo=True)
4387 def log(ui, repo, *pats, **opts):
4387 def log(ui, repo, *pats, **opts):
4388 """show revision history of entire repository or files
4388 """show revision history of entire repository or files
4389
4389
4390 Print the revision history of the specified files or the entire
4390 Print the revision history of the specified files or the entire
4391 project.
4391 project.
4392
4392
4393 If no revision range is specified, the default is ``tip:0`` unless
4393 If no revision range is specified, the default is ``tip:0`` unless
4394 --follow is set, in which case the working directory parent is
4394 --follow is set, in which case the working directory parent is
4395 used as the starting revision.
4395 used as the starting revision.
4396
4396
4397 File history is shown without following rename or copy history of
4397 File history is shown without following rename or copy history of
4398 files. Use -f/--follow with a filename to follow history across
4398 files. Use -f/--follow with a filename to follow history across
4399 renames and copies. --follow without a filename will only show
4399 renames and copies. --follow without a filename will only show
4400 ancestors or descendants of the starting revision.
4400 ancestors or descendants of the starting revision.
4401
4401
4402 By default this command prints revision number and changeset id,
4402 By default this command prints revision number and changeset id,
4403 tags, non-trivial parents, user, date and time, and a summary for
4403 tags, non-trivial parents, user, date and time, and a summary for
4404 each commit. When the -v/--verbose switch is used, the list of
4404 each commit. When the -v/--verbose switch is used, the list of
4405 changed files and full commit message are shown.
4405 changed files and full commit message are shown.
4406
4406
4407 With --graph the revisions are shown as an ASCII art DAG with the most
4407 With --graph the revisions are shown as an ASCII art DAG with the most
4408 recent changeset at the top.
4408 recent changeset at the top.
4409 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4409 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4410 and '+' represents a fork where the changeset from the lines below is a
4410 and '+' represents a fork where the changeset from the lines below is a
4411 parent of the 'o' merge on the same line.
4411 parent of the 'o' merge on the same line.
4412
4412
4413 .. note::
4413 .. note::
4414
4414
4415 log -p/--patch may generate unexpected diff output for merge
4415 log -p/--patch may generate unexpected diff output for merge
4416 changesets, as it will only compare the merge changeset against
4416 changesets, as it will only compare the merge changeset against
4417 its first parent. Also, only files different from BOTH parents
4417 its first parent. Also, only files different from BOTH parents
4418 will appear in files:.
4418 will appear in files:.
4419
4419
4420 .. note::
4420 .. note::
4421
4421
4422 for performance reasons, log FILE may omit duplicate changes
4422 for performance reasons, log FILE may omit duplicate changes
4423 made on branches and will not show removals or mode changes. To
4423 made on branches and will not show removals or mode changes. To
4424 see all such changes, use the --removed switch.
4424 see all such changes, use the --removed switch.
4425
4425
4426 .. container:: verbose
4426 .. container:: verbose
4427
4427
4428 Some examples:
4428 Some examples:
4429
4429
4430 - changesets with full descriptions and file lists::
4430 - changesets with full descriptions and file lists::
4431
4431
4432 hg log -v
4432 hg log -v
4433
4433
4434 - changesets ancestral to the working directory::
4434 - changesets ancestral to the working directory::
4435
4435
4436 hg log -f
4436 hg log -f
4437
4437
4438 - last 10 commits on the current branch::
4438 - last 10 commits on the current branch::
4439
4439
4440 hg log -l 10 -b .
4440 hg log -l 10 -b .
4441
4441
4442 - changesets showing all modifications of a file, including removals::
4442 - changesets showing all modifications of a file, including removals::
4443
4443
4444 hg log --removed file.c
4444 hg log --removed file.c
4445
4445
4446 - all changesets that touch a directory, with diffs, excluding merges::
4446 - all changesets that touch a directory, with diffs, excluding merges::
4447
4447
4448 hg log -Mp lib/
4448 hg log -Mp lib/
4449
4449
4450 - all revision numbers that match a keyword::
4450 - all revision numbers that match a keyword::
4451
4451
4452 hg log -k bug --template "{rev}\\n"
4452 hg log -k bug --template "{rev}\\n"
4453
4453
4454 - list available log templates::
4454 - list available log templates::
4455
4455
4456 hg log -T list
4456 hg log -T list
4457
4457
4458 - check if a given changeset is included in a tagged release::
4458 - check if a given changeset is included in a tagged release::
4459
4459
4460 hg log -r "a21ccf and ancestor(1.9)"
4460 hg log -r "a21ccf and ancestor(1.9)"
4461
4461
4462 - find all changesets by some user in a date range::
4462 - find all changesets by some user in a date range::
4463
4463
4464 hg log -k alice -d "may 2008 to jul 2008"
4464 hg log -k alice -d "may 2008 to jul 2008"
4465
4465
4466 - summary of all changesets after the last tag::
4466 - summary of all changesets after the last tag::
4467
4467
4468 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4468 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4469
4469
4470 See :hg:`help dates` for a list of formats valid for -d/--date.
4470 See :hg:`help dates` for a list of formats valid for -d/--date.
4471
4471
4472 See :hg:`help revisions` and :hg:`help revsets` for more about
4472 See :hg:`help revisions` and :hg:`help revsets` for more about
4473 specifying revisions.
4473 specifying revisions.
4474
4474
4475 See :hg:`help templates` for more about pre-packaged styles and
4475 See :hg:`help templates` for more about pre-packaged styles and
4476 specifying custom templates.
4476 specifying custom templates.
4477
4477
4478 Returns 0 on success.
4478 Returns 0 on success.
4479
4479
4480 """
4480 """
4481 if opts.get('follow') and opts.get('rev'):
4481 if opts.get('follow') and opts.get('rev'):
4482 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4482 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4483 del opts['follow']
4483 del opts['follow']
4484
4484
4485 if opts.get('graph'):
4485 if opts.get('graph'):
4486 return cmdutil.graphlog(ui, repo, *pats, **opts)
4486 return cmdutil.graphlog(ui, repo, *pats, **opts)
4487
4487
4488 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4488 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4489 limit = cmdutil.loglimit(opts)
4489 limit = cmdutil.loglimit(opts)
4490 count = 0
4490 count = 0
4491
4491
4492 getrenamed = None
4492 getrenamed = None
4493 if opts.get('copies'):
4493 if opts.get('copies'):
4494 endrev = None
4494 endrev = None
4495 if opts.get('rev'):
4495 if opts.get('rev'):
4496 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4496 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4497 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4497 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4498
4498
4499 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4499 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4500 for rev in revs:
4500 for rev in revs:
4501 if count == limit:
4501 if count == limit:
4502 break
4502 break
4503 ctx = repo[rev]
4503 ctx = repo[rev]
4504 copies = None
4504 copies = None
4505 if getrenamed is not None and rev:
4505 if getrenamed is not None and rev:
4506 copies = []
4506 copies = []
4507 for fn in ctx.files():
4507 for fn in ctx.files():
4508 rename = getrenamed(fn, rev)
4508 rename = getrenamed(fn, rev)
4509 if rename:
4509 if rename:
4510 copies.append((fn, rename[0]))
4510 copies.append((fn, rename[0]))
4511 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4511 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4512 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4512 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4513 if displayer.flush(rev):
4513 if displayer.flush(rev):
4514 count += 1
4514 count += 1
4515
4515
4516 displayer.close()
4516 displayer.close()
4517
4517
4518 @command('manifest',
4518 @command('manifest',
4519 [('r', 'rev', '', _('revision to display'), _('REV')),
4519 [('r', 'rev', '', _('revision to display'), _('REV')),
4520 ('', 'all', False, _("list files from all revisions"))]
4520 ('', 'all', False, _("list files from all revisions"))]
4521 + formatteropts,
4521 + formatteropts,
4522 _('[-r REV]'))
4522 _('[-r REV]'))
4523 def manifest(ui, repo, node=None, rev=None, **opts):
4523 def manifest(ui, repo, node=None, rev=None, **opts):
4524 """output the current or given revision of the project manifest
4524 """output the current or given revision of the project manifest
4525
4525
4526 Print a list of version controlled files for the given revision.
4526 Print a list of version controlled files for the given revision.
4527 If no revision is given, the first parent of the working directory
4527 If no revision is given, the first parent of the working directory
4528 is used, or the null revision if no revision is checked out.
4528 is used, or the null revision if no revision is checked out.
4529
4529
4530 With -v, print file permissions, symlink and executable bits.
4530 With -v, print file permissions, symlink and executable bits.
4531 With --debug, print file revision hashes.
4531 With --debug, print file revision hashes.
4532
4532
4533 If option --all is specified, the list of all files from all revisions
4533 If option --all is specified, the list of all files from all revisions
4534 is printed. This includes deleted and renamed files.
4534 is printed. This includes deleted and renamed files.
4535
4535
4536 Returns 0 on success.
4536 Returns 0 on success.
4537 """
4537 """
4538
4538
4539 fm = ui.formatter('manifest', opts)
4539 fm = ui.formatter('manifest', opts)
4540
4540
4541 if opts.get('all'):
4541 if opts.get('all'):
4542 if rev or node:
4542 if rev or node:
4543 raise util.Abort(_("can't specify a revision with --all"))
4543 raise util.Abort(_("can't specify a revision with --all"))
4544
4544
4545 res = []
4545 res = []
4546 prefix = "data/"
4546 prefix = "data/"
4547 suffix = ".i"
4547 suffix = ".i"
4548 plen = len(prefix)
4548 plen = len(prefix)
4549 slen = len(suffix)
4549 slen = len(suffix)
4550 lock = repo.lock()
4550 lock = repo.lock()
4551 try:
4551 try:
4552 for fn, b, size in repo.store.datafiles():
4552 for fn, b, size in repo.store.datafiles():
4553 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4553 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4554 res.append(fn[plen:-slen])
4554 res.append(fn[plen:-slen])
4555 finally:
4555 finally:
4556 lock.release()
4556 lock.release()
4557 for f in res:
4557 for f in res:
4558 fm.startitem()
4558 fm.startitem()
4559 fm.write("path", '%s\n', f)
4559 fm.write("path", '%s\n', f)
4560 fm.end()
4560 fm.end()
4561 return
4561 return
4562
4562
4563 if rev and node:
4563 if rev and node:
4564 raise util.Abort(_("please specify just one revision"))
4564 raise util.Abort(_("please specify just one revision"))
4565
4565
4566 if not node:
4566 if not node:
4567 node = rev
4567 node = rev
4568
4568
4569 char = {'l': '@', 'x': '*', '': ''}
4569 char = {'l': '@', 'x': '*', '': ''}
4570 mode = {'l': '644', 'x': '755', '': '644'}
4570 mode = {'l': '644', 'x': '755', '': '644'}
4571 ctx = scmutil.revsingle(repo, node)
4571 ctx = scmutil.revsingle(repo, node)
4572 mf = ctx.manifest()
4572 mf = ctx.manifest()
4573 for f in ctx:
4573 for f in ctx:
4574 fm.startitem()
4574 fm.startitem()
4575 fl = ctx[f].flags()
4575 fl = ctx[f].flags()
4576 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4576 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4577 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4577 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4578 fm.write('path', '%s\n', f)
4578 fm.write('path', '%s\n', f)
4579 fm.end()
4579 fm.end()
4580
4580
4581 @command('^merge',
4581 @command('^merge',
4582 [('f', 'force', None,
4582 [('f', 'force', None,
4583 _('force a merge including outstanding changes (DEPRECATED)')),
4583 _('force a merge including outstanding changes (DEPRECATED)')),
4584 ('r', 'rev', '', _('revision to merge'), _('REV')),
4584 ('r', 'rev', '', _('revision to merge'), _('REV')),
4585 ('P', 'preview', None,
4585 ('P', 'preview', None,
4586 _('review revisions to merge (no merge is performed)'))
4586 _('review revisions to merge (no merge is performed)'))
4587 ] + mergetoolopts,
4587 ] + mergetoolopts,
4588 _('[-P] [-f] [[-r] REV]'))
4588 _('[-P] [-f] [[-r] REV]'))
4589 def merge(ui, repo, node=None, **opts):
4589 def merge(ui, repo, node=None, **opts):
4590 """merge another revision into working directory
4590 """merge another revision into working directory
4591
4591
4592 The current working directory is updated with all changes made in
4592 The current working directory is updated with all changes made in
4593 the requested revision since the last common predecessor revision.
4593 the requested revision since the last common predecessor revision.
4594
4594
4595 Files that changed between either parent are marked as changed for
4595 Files that changed between either parent are marked as changed for
4596 the next commit and a commit must be performed before any further
4596 the next commit and a commit must be performed before any further
4597 updates to the repository are allowed. The next commit will have
4597 updates to the repository are allowed. The next commit will have
4598 two parents.
4598 two parents.
4599
4599
4600 ``--tool`` can be used to specify the merge tool used for file
4600 ``--tool`` can be used to specify the merge tool used for file
4601 merges. It overrides the HGMERGE environment variable and your
4601 merges. It overrides the HGMERGE environment variable and your
4602 configuration files. See :hg:`help merge-tools` for options.
4602 configuration files. See :hg:`help merge-tools` for options.
4603
4603
4604 If no revision is specified, the working directory's parent is a
4604 If no revision is specified, the working directory's parent is a
4605 head revision, and the current branch contains exactly one other
4605 head revision, and the current branch contains exactly one other
4606 head, the other head is merged with by default. Otherwise, an
4606 head, the other head is merged with by default. Otherwise, an
4607 explicit revision with which to merge with must be provided.
4607 explicit revision with which to merge with must be provided.
4608
4608
4609 :hg:`resolve` must be used to resolve unresolved files.
4609 :hg:`resolve` must be used to resolve unresolved files.
4610
4610
4611 To undo an uncommitted merge, use :hg:`update --clean .` which
4611 To undo an uncommitted merge, use :hg:`update --clean .` which
4612 will check out a clean copy of the original merge parent, losing
4612 will check out a clean copy of the original merge parent, losing
4613 all changes.
4613 all changes.
4614
4614
4615 Returns 0 on success, 1 if there are unresolved files.
4615 Returns 0 on success, 1 if there are unresolved files.
4616 """
4616 """
4617
4617
4618 if opts.get('rev') and node:
4618 if opts.get('rev') and node:
4619 raise util.Abort(_("please specify just one revision"))
4619 raise util.Abort(_("please specify just one revision"))
4620 if not node:
4620 if not node:
4621 node = opts.get('rev')
4621 node = opts.get('rev')
4622
4622
4623 if node:
4623 if node:
4624 node = scmutil.revsingle(repo, node).node()
4624 node = scmutil.revsingle(repo, node).node()
4625
4625
4626 if not node and repo._bookmarkcurrent:
4626 if not node and repo._bookmarkcurrent:
4627 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4627 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4628 curhead = repo[repo._bookmarkcurrent].node()
4628 curhead = repo[repo._bookmarkcurrent].node()
4629 if len(bmheads) == 2:
4629 if len(bmheads) == 2:
4630 if curhead == bmheads[0]:
4630 if curhead == bmheads[0]:
4631 node = bmheads[1]
4631 node = bmheads[1]
4632 else:
4632 else:
4633 node = bmheads[0]
4633 node = bmheads[0]
4634 elif len(bmheads) > 2:
4634 elif len(bmheads) > 2:
4635 raise util.Abort(_("multiple matching bookmarks to merge - "
4635 raise util.Abort(_("multiple matching bookmarks to merge - "
4636 "please merge with an explicit rev or bookmark"),
4636 "please merge with an explicit rev or bookmark"),
4637 hint=_("run 'hg heads' to see all heads"))
4637 hint=_("run 'hg heads' to see all heads"))
4638 elif len(bmheads) <= 1:
4638 elif len(bmheads) <= 1:
4639 raise util.Abort(_("no matching bookmark to merge - "
4639 raise util.Abort(_("no matching bookmark to merge - "
4640 "please merge with an explicit rev or bookmark"),
4640 "please merge with an explicit rev or bookmark"),
4641 hint=_("run 'hg heads' to see all heads"))
4641 hint=_("run 'hg heads' to see all heads"))
4642
4642
4643 if not node and not repo._bookmarkcurrent:
4643 if not node and not repo._bookmarkcurrent:
4644 branch = repo[None].branch()
4644 branch = repo[None].branch()
4645 bheads = repo.branchheads(branch)
4645 bheads = repo.branchheads(branch)
4646 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4646 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4647
4647
4648 if len(nbhs) > 2:
4648 if len(nbhs) > 2:
4649 raise util.Abort(_("branch '%s' has %d heads - "
4649 raise util.Abort(_("branch '%s' has %d heads - "
4650 "please merge with an explicit rev")
4650 "please merge with an explicit rev")
4651 % (branch, len(bheads)),
4651 % (branch, len(bheads)),
4652 hint=_("run 'hg heads .' to see heads"))
4652 hint=_("run 'hg heads .' to see heads"))
4653
4653
4654 parent = repo.dirstate.p1()
4654 parent = repo.dirstate.p1()
4655 if len(nbhs) <= 1:
4655 if len(nbhs) <= 1:
4656 if len(bheads) > 1:
4656 if len(bheads) > 1:
4657 raise util.Abort(_("heads are bookmarked - "
4657 raise util.Abort(_("heads are bookmarked - "
4658 "please merge with an explicit rev"),
4658 "please merge with an explicit rev"),
4659 hint=_("run 'hg heads' to see all heads"))
4659 hint=_("run 'hg heads' to see all heads"))
4660 if len(repo.heads()) > 1:
4660 if len(repo.heads()) > 1:
4661 raise util.Abort(_("branch '%s' has one head - "
4661 raise util.Abort(_("branch '%s' has one head - "
4662 "please merge with an explicit rev")
4662 "please merge with an explicit rev")
4663 % branch,
4663 % branch,
4664 hint=_("run 'hg heads' to see all heads"))
4664 hint=_("run 'hg heads' to see all heads"))
4665 msg, hint = _('nothing to merge'), None
4665 msg, hint = _('nothing to merge'), None
4666 if parent != repo.lookup(branch):
4666 if parent != repo.lookup(branch):
4667 hint = _("use 'hg update' instead")
4667 hint = _("use 'hg update' instead")
4668 raise util.Abort(msg, hint=hint)
4668 raise util.Abort(msg, hint=hint)
4669
4669
4670 if parent not in bheads:
4670 if parent not in bheads:
4671 raise util.Abort(_('working directory not at a head revision'),
4671 raise util.Abort(_('working directory not at a head revision'),
4672 hint=_("use 'hg update' or merge with an "
4672 hint=_("use 'hg update' or merge with an "
4673 "explicit revision"))
4673 "explicit revision"))
4674 if parent == nbhs[0]:
4674 if parent == nbhs[0]:
4675 node = nbhs[-1]
4675 node = nbhs[-1]
4676 else:
4676 else:
4677 node = nbhs[0]
4677 node = nbhs[0]
4678
4678
4679 if opts.get('preview'):
4679 if opts.get('preview'):
4680 # find nodes that are ancestors of p2 but not of p1
4680 # find nodes that are ancestors of p2 but not of p1
4681 p1 = repo.lookup('.')
4681 p1 = repo.lookup('.')
4682 p2 = repo.lookup(node)
4682 p2 = repo.lookup(node)
4683 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4683 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4684
4684
4685 displayer = cmdutil.show_changeset(ui, repo, opts)
4685 displayer = cmdutil.show_changeset(ui, repo, opts)
4686 for node in nodes:
4686 for node in nodes:
4687 displayer.show(repo[node])
4687 displayer.show(repo[node])
4688 displayer.close()
4688 displayer.close()
4689 return 0
4689 return 0
4690
4690
4691 try:
4691 try:
4692 # ui.forcemerge is an internal variable, do not document
4692 # ui.forcemerge is an internal variable, do not document
4693 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4693 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4694 return hg.merge(repo, node, force=opts.get('force'))
4694 return hg.merge(repo, node, force=opts.get('force'))
4695 finally:
4695 finally:
4696 ui.setconfig('ui', 'forcemerge', '', 'merge')
4696 ui.setconfig('ui', 'forcemerge', '', 'merge')
4697
4697
4698 @command('outgoing|out',
4698 @command('outgoing|out',
4699 [('f', 'force', None, _('run even when the destination is unrelated')),
4699 [('f', 'force', None, _('run even when the destination is unrelated')),
4700 ('r', 'rev', [],
4700 ('r', 'rev', [],
4701 _('a changeset intended to be included in the destination'), _('REV')),
4701 _('a changeset intended to be included in the destination'), _('REV')),
4702 ('n', 'newest-first', None, _('show newest record first')),
4702 ('n', 'newest-first', None, _('show newest record first')),
4703 ('B', 'bookmarks', False, _('compare bookmarks')),
4703 ('B', 'bookmarks', False, _('compare bookmarks')),
4704 ('b', 'branch', [], _('a specific branch you would like to push'),
4704 ('b', 'branch', [], _('a specific branch you would like to push'),
4705 _('BRANCH')),
4705 _('BRANCH')),
4706 ] + logopts + remoteopts + subrepoopts,
4706 ] + logopts + remoteopts + subrepoopts,
4707 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4707 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4708 def outgoing(ui, repo, dest=None, **opts):
4708 def outgoing(ui, repo, dest=None, **opts):
4709 """show changesets not found in the destination
4709 """show changesets not found in the destination
4710
4710
4711 Show changesets not found in the specified destination repository
4711 Show changesets not found in the specified destination repository
4712 or the default push location. These are the changesets that would
4712 or the default push location. These are the changesets that would
4713 be pushed if a push was requested.
4713 be pushed if a push was requested.
4714
4714
4715 See pull for details of valid destination formats.
4715 See pull for details of valid destination formats.
4716
4716
4717 Returns 0 if there are outgoing changes, 1 otherwise.
4717 Returns 0 if there are outgoing changes, 1 otherwise.
4718 """
4718 """
4719 if opts.get('graph'):
4719 if opts.get('graph'):
4720 cmdutil.checkunsupportedgraphflags([], opts)
4720 cmdutil.checkunsupportedgraphflags([], opts)
4721 o, other = hg._outgoing(ui, repo, dest, opts)
4721 o, other = hg._outgoing(ui, repo, dest, opts)
4722 if not o:
4722 if not o:
4723 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4723 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4724 return
4724 return
4725
4725
4726 revdag = cmdutil.graphrevs(repo, o, opts)
4726 revdag = cmdutil.graphrevs(repo, o, opts)
4727 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4727 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4728 showparents = [ctx.node() for ctx in repo[None].parents()]
4728 showparents = [ctx.node() for ctx in repo[None].parents()]
4729 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4729 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4730 graphmod.asciiedges)
4730 graphmod.asciiedges)
4731 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4731 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4732 return 0
4732 return 0
4733
4733
4734 if opts.get('bookmarks'):
4734 if opts.get('bookmarks'):
4735 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4735 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4736 dest, branches = hg.parseurl(dest, opts.get('branch'))
4736 dest, branches = hg.parseurl(dest, opts.get('branch'))
4737 other = hg.peer(repo, opts, dest)
4737 other = hg.peer(repo, opts, dest)
4738 if 'bookmarks' not in other.listkeys('namespaces'):
4738 if 'bookmarks' not in other.listkeys('namespaces'):
4739 ui.warn(_("remote doesn't support bookmarks\n"))
4739 ui.warn(_("remote doesn't support bookmarks\n"))
4740 return 0
4740 return 0
4741 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4741 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4742 return bookmarks.diff(ui, other, repo)
4742 return bookmarks.diff(ui, other, repo)
4743
4743
4744 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4744 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4745 try:
4745 try:
4746 return hg.outgoing(ui, repo, dest, opts)
4746 return hg.outgoing(ui, repo, dest, opts)
4747 finally:
4747 finally:
4748 del repo._subtoppath
4748 del repo._subtoppath
4749
4749
4750 @command('parents',
4750 @command('parents',
4751 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4751 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4752 ] + templateopts,
4752 ] + templateopts,
4753 _('[-r REV] [FILE]'),
4753 _('[-r REV] [FILE]'),
4754 inferrepo=True)
4754 inferrepo=True)
4755 def parents(ui, repo, file_=None, **opts):
4755 def parents(ui, repo, file_=None, **opts):
4756 """show the parents of the working directory or revision (DEPRECATED)
4756 """show the parents of the working directory or revision (DEPRECATED)
4757
4757
4758 Print the working directory's parent revisions. If a revision is
4758 Print the working directory's parent revisions. If a revision is
4759 given via -r/--rev, the parent of that revision will be printed.
4759 given via -r/--rev, the parent of that revision will be printed.
4760 If a file argument is given, the revision in which the file was
4760 If a file argument is given, the revision in which the file was
4761 last changed (before the working directory revision or the
4761 last changed (before the working directory revision or the
4762 argument to --rev if given) is printed.
4762 argument to --rev if given) is printed.
4763
4763
4764 See :hg:`summary` and :hg:`help revsets` for related information.
4764 See :hg:`summary` and :hg:`help revsets` for related information.
4765
4765
4766 Returns 0 on success.
4766 Returns 0 on success.
4767 """
4767 """
4768
4768
4769 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4769 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4770
4770
4771 if file_:
4771 if file_:
4772 m = scmutil.match(ctx, (file_,), opts)
4772 m = scmutil.match(ctx, (file_,), opts)
4773 if m.anypats() or len(m.files()) != 1:
4773 if m.anypats() or len(m.files()) != 1:
4774 raise util.Abort(_('can only specify an explicit filename'))
4774 raise util.Abort(_('can only specify an explicit filename'))
4775 file_ = m.files()[0]
4775 file_ = m.files()[0]
4776 filenodes = []
4776 filenodes = []
4777 for cp in ctx.parents():
4777 for cp in ctx.parents():
4778 if not cp:
4778 if not cp:
4779 continue
4779 continue
4780 try:
4780 try:
4781 filenodes.append(cp.filenode(file_))
4781 filenodes.append(cp.filenode(file_))
4782 except error.LookupError:
4782 except error.LookupError:
4783 pass
4783 pass
4784 if not filenodes:
4784 if not filenodes:
4785 raise util.Abort(_("'%s' not found in manifest!") % file_)
4785 raise util.Abort(_("'%s' not found in manifest!") % file_)
4786 p = []
4786 p = []
4787 for fn in filenodes:
4787 for fn in filenodes:
4788 fctx = repo.filectx(file_, fileid=fn)
4788 fctx = repo.filectx(file_, fileid=fn)
4789 p.append(fctx.node())
4789 p.append(fctx.node())
4790 else:
4790 else:
4791 p = [cp.node() for cp in ctx.parents()]
4791 p = [cp.node() for cp in ctx.parents()]
4792
4792
4793 displayer = cmdutil.show_changeset(ui, repo, opts)
4793 displayer = cmdutil.show_changeset(ui, repo, opts)
4794 for n in p:
4794 for n in p:
4795 if n != nullid:
4795 if n != nullid:
4796 displayer.show(repo[n])
4796 displayer.show(repo[n])
4797 displayer.close()
4797 displayer.close()
4798
4798
4799 @command('paths', [], _('[NAME]'), optionalrepo=True)
4799 @command('paths', [], _('[NAME]'), optionalrepo=True)
4800 def paths(ui, repo, search=None):
4800 def paths(ui, repo, search=None):
4801 """show aliases for remote repositories
4801 """show aliases for remote repositories
4802
4802
4803 Show definition of symbolic path name NAME. If no name is given,
4803 Show definition of symbolic path name NAME. If no name is given,
4804 show definition of all available names.
4804 show definition of all available names.
4805
4805
4806 Option -q/--quiet suppresses all output when searching for NAME
4806 Option -q/--quiet suppresses all output when searching for NAME
4807 and shows only the path names when listing all definitions.
4807 and shows only the path names when listing all definitions.
4808
4808
4809 Path names are defined in the [paths] section of your
4809 Path names are defined in the [paths] section of your
4810 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4810 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4811 repository, ``.hg/hgrc`` is used, too.
4811 repository, ``.hg/hgrc`` is used, too.
4812
4812
4813 The path names ``default`` and ``default-push`` have a special
4813 The path names ``default`` and ``default-push`` have a special
4814 meaning. When performing a push or pull operation, they are used
4814 meaning. When performing a push or pull operation, they are used
4815 as fallbacks if no location is specified on the command-line.
4815 as fallbacks if no location is specified on the command-line.
4816 When ``default-push`` is set, it will be used for push and
4816 When ``default-push`` is set, it will be used for push and
4817 ``default`` will be used for pull; otherwise ``default`` is used
4817 ``default`` will be used for pull; otherwise ``default`` is used
4818 as the fallback for both. When cloning a repository, the clone
4818 as the fallback for both. When cloning a repository, the clone
4819 source is written as ``default`` in ``.hg/hgrc``. Note that
4819 source is written as ``default`` in ``.hg/hgrc``. Note that
4820 ``default`` and ``default-push`` apply to all inbound (e.g.
4820 ``default`` and ``default-push`` apply to all inbound (e.g.
4821 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4821 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4822 :hg:`bundle`) operations.
4822 :hg:`bundle`) operations.
4823
4823
4824 See :hg:`help urls` for more information.
4824 See :hg:`help urls` for more information.
4825
4825
4826 Returns 0 on success.
4826 Returns 0 on success.
4827 """
4827 """
4828 if search:
4828 if search:
4829 for name, path in ui.configitems("paths"):
4829 for name, path in ui.configitems("paths"):
4830 if name == search:
4830 if name == search:
4831 ui.status("%s\n" % util.hidepassword(path))
4831 ui.status("%s\n" % util.hidepassword(path))
4832 return
4832 return
4833 if not ui.quiet:
4833 if not ui.quiet:
4834 ui.warn(_("not found!\n"))
4834 ui.warn(_("not found!\n"))
4835 return 1
4835 return 1
4836 else:
4836 else:
4837 for name, path in ui.configitems("paths"):
4837 for name, path in ui.configitems("paths"):
4838 if ui.quiet:
4838 if ui.quiet:
4839 ui.write("%s\n" % name)
4839 ui.write("%s\n" % name)
4840 else:
4840 else:
4841 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4841 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4842
4842
4843 @command('phase',
4843 @command('phase',
4844 [('p', 'public', False, _('set changeset phase to public')),
4844 [('p', 'public', False, _('set changeset phase to public')),
4845 ('d', 'draft', False, _('set changeset phase to draft')),
4845 ('d', 'draft', False, _('set changeset phase to draft')),
4846 ('s', 'secret', False, _('set changeset phase to secret')),
4846 ('s', 'secret', False, _('set changeset phase to secret')),
4847 ('f', 'force', False, _('allow to move boundary backward')),
4847 ('f', 'force', False, _('allow to move boundary backward')),
4848 ('r', 'rev', [], _('target revision'), _('REV')),
4848 ('r', 'rev', [], _('target revision'), _('REV')),
4849 ],
4849 ],
4850 _('[-p|-d|-s] [-f] [-r] REV...'))
4850 _('[-p|-d|-s] [-f] [-r] REV...'))
4851 def phase(ui, repo, *revs, **opts):
4851 def phase(ui, repo, *revs, **opts):
4852 """set or show the current phase name
4852 """set or show the current phase name
4853
4853
4854 With no argument, show the phase name of specified revisions.
4854 With no argument, show the phase name of specified revisions.
4855
4855
4856 With one of -p/--public, -d/--draft or -s/--secret, change the
4856 With one of -p/--public, -d/--draft or -s/--secret, change the
4857 phase value of the specified revisions.
4857 phase value of the specified revisions.
4858
4858
4859 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4859 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4860 lower phase to an higher phase. Phases are ordered as follows::
4860 lower phase to an higher phase. Phases are ordered as follows::
4861
4861
4862 public < draft < secret
4862 public < draft < secret
4863
4863
4864 Returns 0 on success, 1 if no phases were changed or some could not
4864 Returns 0 on success, 1 if no phases were changed or some could not
4865 be changed.
4865 be changed.
4866 """
4866 """
4867 # search for a unique phase argument
4867 # search for a unique phase argument
4868 targetphase = None
4868 targetphase = None
4869 for idx, name in enumerate(phases.phasenames):
4869 for idx, name in enumerate(phases.phasenames):
4870 if opts[name]:
4870 if opts[name]:
4871 if targetphase is not None:
4871 if targetphase is not None:
4872 raise util.Abort(_('only one phase can be specified'))
4872 raise util.Abort(_('only one phase can be specified'))
4873 targetphase = idx
4873 targetphase = idx
4874
4874
4875 # look for specified revision
4875 # look for specified revision
4876 revs = list(revs)
4876 revs = list(revs)
4877 revs.extend(opts['rev'])
4877 revs.extend(opts['rev'])
4878 if not revs:
4878 if not revs:
4879 raise util.Abort(_('no revisions specified'))
4879 raise util.Abort(_('no revisions specified'))
4880
4880
4881 revs = scmutil.revrange(repo, revs)
4881 revs = scmutil.revrange(repo, revs)
4882
4882
4883 lock = None
4883 lock = None
4884 ret = 0
4884 ret = 0
4885 if targetphase is None:
4885 if targetphase is None:
4886 # display
4886 # display
4887 for r in revs:
4887 for r in revs:
4888 ctx = repo[r]
4888 ctx = repo[r]
4889 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4889 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4890 else:
4890 else:
4891 tr = None
4891 tr = None
4892 lock = repo.lock()
4892 lock = repo.lock()
4893 try:
4893 try:
4894 tr = repo.transaction("phase")
4894 tr = repo.transaction("phase")
4895 # set phase
4895 # set phase
4896 if not revs:
4896 if not revs:
4897 raise util.Abort(_('empty revision set'))
4897 raise util.Abort(_('empty revision set'))
4898 nodes = [repo[r].node() for r in revs]
4898 nodes = [repo[r].node() for r in revs]
4899 # moving revision from public to draft may hide them
4899 # moving revision from public to draft may hide them
4900 # We have to check result on an unfiltered repository
4900 # We have to check result on an unfiltered repository
4901 unfi = repo.unfiltered()
4901 unfi = repo.unfiltered()
4902 getphase = unfi._phasecache.phase
4902 getphase = unfi._phasecache.phase
4903 olddata = [getphase(unfi, r) for r in unfi]
4903 olddata = [getphase(unfi, r) for r in unfi]
4904 phases.advanceboundary(repo, tr, targetphase, nodes)
4904 phases.advanceboundary(repo, tr, targetphase, nodes)
4905 if opts['force']:
4905 if opts['force']:
4906 phases.retractboundary(repo, tr, targetphase, nodes)
4906 phases.retractboundary(repo, tr, targetphase, nodes)
4907 tr.close()
4907 tr.close()
4908 finally:
4908 finally:
4909 if tr is not None:
4909 if tr is not None:
4910 tr.release()
4910 tr.release()
4911 lock.release()
4911 lock.release()
4912 getphase = unfi._phasecache.phase
4912 getphase = unfi._phasecache.phase
4913 newdata = [getphase(unfi, r) for r in unfi]
4913 newdata = [getphase(unfi, r) for r in unfi]
4914 changes = sum(newdata[r] != olddata[r] for r in unfi)
4914 changes = sum(newdata[r] != olddata[r] for r in unfi)
4915 cl = unfi.changelog
4915 cl = unfi.changelog
4916 rejected = [n for n in nodes
4916 rejected = [n for n in nodes
4917 if newdata[cl.rev(n)] < targetphase]
4917 if newdata[cl.rev(n)] < targetphase]
4918 if rejected:
4918 if rejected:
4919 ui.warn(_('cannot move %i changesets to a higher '
4919 ui.warn(_('cannot move %i changesets to a higher '
4920 'phase, use --force\n') % len(rejected))
4920 'phase, use --force\n') % len(rejected))
4921 ret = 1
4921 ret = 1
4922 if changes:
4922 if changes:
4923 msg = _('phase changed for %i changesets\n') % changes
4923 msg = _('phase changed for %i changesets\n') % changes
4924 if ret:
4924 if ret:
4925 ui.status(msg)
4925 ui.status(msg)
4926 else:
4926 else:
4927 ui.note(msg)
4927 ui.note(msg)
4928 else:
4928 else:
4929 ui.warn(_('no phases changed\n'))
4929 ui.warn(_('no phases changed\n'))
4930 ret = 1
4930 ret = 1
4931 return ret
4931 return ret
4932
4932
4933 def postincoming(ui, repo, modheads, optupdate, checkout):
4933 def postincoming(ui, repo, modheads, optupdate, checkout):
4934 if modheads == 0:
4934 if modheads == 0:
4935 return
4935 return
4936 if optupdate:
4936 if optupdate:
4937 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4937 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4938 try:
4938 try:
4939 ret = hg.update(repo, checkout)
4939 ret = hg.update(repo, checkout)
4940 except util.Abort, inst:
4940 except util.Abort, inst:
4941 ui.warn(_("not updating: %s\n") % str(inst))
4941 ui.warn(_("not updating: %s\n") % str(inst))
4942 if inst.hint:
4942 if inst.hint:
4943 ui.warn(_("(%s)\n") % inst.hint)
4943 ui.warn(_("(%s)\n") % inst.hint)
4944 return 0
4944 return 0
4945 if not ret and not checkout:
4945 if not ret and not checkout:
4946 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4946 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4947 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4947 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4948 return ret
4948 return ret
4949 if modheads > 1:
4949 if modheads > 1:
4950 currentbranchheads = len(repo.branchheads())
4950 currentbranchheads = len(repo.branchheads())
4951 if currentbranchheads == modheads:
4951 if currentbranchheads == modheads:
4952 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4952 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4953 elif currentbranchheads > 1:
4953 elif currentbranchheads > 1:
4954 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4954 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4955 "merge)\n"))
4955 "merge)\n"))
4956 else:
4956 else:
4957 ui.status(_("(run 'hg heads' to see heads)\n"))
4957 ui.status(_("(run 'hg heads' to see heads)\n"))
4958 else:
4958 else:
4959 ui.status(_("(run 'hg update' to get a working copy)\n"))
4959 ui.status(_("(run 'hg update' to get a working copy)\n"))
4960
4960
4961 @command('^pull',
4961 @command('^pull',
4962 [('u', 'update', None,
4962 [('u', 'update', None,
4963 _('update to new branch head if changesets were pulled')),
4963 _('update to new branch head if changesets were pulled')),
4964 ('f', 'force', None, _('run even when remote repository is unrelated')),
4964 ('f', 'force', None, _('run even when remote repository is unrelated')),
4965 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4965 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4966 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4966 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4967 ('b', 'branch', [], _('a specific branch you would like to pull'),
4967 ('b', 'branch', [], _('a specific branch you would like to pull'),
4968 _('BRANCH')),
4968 _('BRANCH')),
4969 ] + remoteopts,
4969 ] + remoteopts,
4970 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4970 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4971 def pull(ui, repo, source="default", **opts):
4971 def pull(ui, repo, source="default", **opts):
4972 """pull changes from the specified source
4972 """pull changes from the specified source
4973
4973
4974 Pull changes from a remote repository to a local one.
4974 Pull changes from a remote repository to a local one.
4975
4975
4976 This finds all changes from the repository at the specified path
4976 This finds all changes from the repository at the specified path
4977 or URL and adds them to a local repository (the current one unless
4977 or URL and adds them to a local repository (the current one unless
4978 -R is specified). By default, this does not update the copy of the
4978 -R is specified). By default, this does not update the copy of the
4979 project in the working directory.
4979 project in the working directory.
4980
4980
4981 Use :hg:`incoming` if you want to see what would have been added
4981 Use :hg:`incoming` if you want to see what would have been added
4982 by a pull at the time you issued this command. If you then decide
4982 by a pull at the time you issued this command. If you then decide
4983 to add those changes to the repository, you should use :hg:`pull
4983 to add those changes to the repository, you should use :hg:`pull
4984 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4984 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4985
4985
4986 If SOURCE is omitted, the 'default' path will be used.
4986 If SOURCE is omitted, the 'default' path will be used.
4987 See :hg:`help urls` for more information.
4987 See :hg:`help urls` for more information.
4988
4988
4989 Returns 0 on success, 1 if an update had unresolved files.
4989 Returns 0 on success, 1 if an update had unresolved files.
4990 """
4990 """
4991 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4991 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4992 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4992 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4993 other = hg.peer(repo, opts, source)
4993 other = hg.peer(repo, opts, source)
4994 try:
4994 try:
4995 revs, checkout = hg.addbranchrevs(repo, other, branches,
4995 revs, checkout = hg.addbranchrevs(repo, other, branches,
4996 opts.get('rev'))
4996 opts.get('rev'))
4997
4997
4998 remotebookmarks = other.listkeys('bookmarks')
4998 remotebookmarks = other.listkeys('bookmarks')
4999
4999
5000 if opts.get('bookmark'):
5000 if opts.get('bookmark'):
5001 if not revs:
5001 if not revs:
5002 revs = []
5002 revs = []
5003 for b in opts['bookmark']:
5003 for b in opts['bookmark']:
5004 if b not in remotebookmarks:
5004 if b not in remotebookmarks:
5005 raise util.Abort(_('remote bookmark %s not found!') % b)
5005 raise util.Abort(_('remote bookmark %s not found!') % b)
5006 revs.append(remotebookmarks[b])
5006 revs.append(remotebookmarks[b])
5007
5007
5008 if revs:
5008 if revs:
5009 try:
5009 try:
5010 revs = [other.lookup(rev) for rev in revs]
5010 revs = [other.lookup(rev) for rev in revs]
5011 except error.CapabilityError:
5011 except error.CapabilityError:
5012 err = _("other repository doesn't support revision lookup, "
5012 err = _("other repository doesn't support revision lookup, "
5013 "so a rev cannot be specified.")
5013 "so a rev cannot be specified.")
5014 raise util.Abort(err)
5014 raise util.Abort(err)
5015
5015
5016 modheads = exchange.pull(repo, other, heads=revs,
5016 modheads = exchange.pull(repo, other, heads=revs,
5017 force=opts.get('force'),
5017 force=opts.get('force'),
5018 bookmarks=opts.get('bookmark', ())).cgresult
5018 bookmarks=opts.get('bookmark', ())).cgresult
5019 if checkout:
5019 if checkout:
5020 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5020 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5021 repo._subtoppath = source
5021 repo._subtoppath = source
5022 try:
5022 try:
5023 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5023 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5024
5024
5025 finally:
5025 finally:
5026 del repo._subtoppath
5026 del repo._subtoppath
5027
5027
5028 finally:
5028 finally:
5029 other.close()
5029 other.close()
5030 return ret
5030 return ret
5031
5031
5032 @command('^push',
5032 @command('^push',
5033 [('f', 'force', None, _('force push')),
5033 [('f', 'force', None, _('force push')),
5034 ('r', 'rev', [],
5034 ('r', 'rev', [],
5035 _('a changeset intended to be included in the destination'),
5035 _('a changeset intended to be included in the destination'),
5036 _('REV')),
5036 _('REV')),
5037 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5037 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5038 ('b', 'branch', [],
5038 ('b', 'branch', [],
5039 _('a specific branch you would like to push'), _('BRANCH')),
5039 _('a specific branch you would like to push'), _('BRANCH')),
5040 ('', 'new-branch', False, _('allow pushing a new branch')),
5040 ('', 'new-branch', False, _('allow pushing a new branch')),
5041 ] + remoteopts,
5041 ] + remoteopts,
5042 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5042 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5043 def push(ui, repo, dest=None, **opts):
5043 def push(ui, repo, dest=None, **opts):
5044 """push changes to the specified destination
5044 """push changes to the specified destination
5045
5045
5046 Push changesets from the local repository to the specified
5046 Push changesets from the local repository to the specified
5047 destination.
5047 destination.
5048
5048
5049 This operation is symmetrical to pull: it is identical to a pull
5049 This operation is symmetrical to pull: it is identical to a pull
5050 in the destination repository from the current one.
5050 in the destination repository from the current one.
5051
5051
5052 By default, push will not allow creation of new heads at the
5052 By default, push will not allow creation of new heads at the
5053 destination, since multiple heads would make it unclear which head
5053 destination, since multiple heads would make it unclear which head
5054 to use. In this situation, it is recommended to pull and merge
5054 to use. In this situation, it is recommended to pull and merge
5055 before pushing.
5055 before pushing.
5056
5056
5057 Use --new-branch if you want to allow push to create a new named
5057 Use --new-branch if you want to allow push to create a new named
5058 branch that is not present at the destination. This allows you to
5058 branch that is not present at the destination. This allows you to
5059 only create a new branch without forcing other changes.
5059 only create a new branch without forcing other changes.
5060
5060
5061 .. note::
5061 .. note::
5062
5062
5063 Extra care should be taken with the -f/--force option,
5063 Extra care should be taken with the -f/--force option,
5064 which will push all new heads on all branches, an action which will
5064 which will push all new heads on all branches, an action which will
5065 almost always cause confusion for collaborators.
5065 almost always cause confusion for collaborators.
5066
5066
5067 If -r/--rev is used, the specified revision and all its ancestors
5067 If -r/--rev is used, the specified revision and all its ancestors
5068 will be pushed to the remote repository.
5068 will be pushed to the remote repository.
5069
5069
5070 If -B/--bookmark is used, the specified bookmarked revision, its
5070 If -B/--bookmark is used, the specified bookmarked revision, its
5071 ancestors, and the bookmark will be pushed to the remote
5071 ancestors, and the bookmark will be pushed to the remote
5072 repository.
5072 repository.
5073
5073
5074 Please see :hg:`help urls` for important details about ``ssh://``
5074 Please see :hg:`help urls` for important details about ``ssh://``
5075 URLs. If DESTINATION is omitted, a default path will be used.
5075 URLs. If DESTINATION is omitted, a default path will be used.
5076
5076
5077 Returns 0 if push was successful, 1 if nothing to push.
5077 Returns 0 if push was successful, 1 if nothing to push.
5078 """
5078 """
5079
5079
5080 if opts.get('bookmark'):
5080 if opts.get('bookmark'):
5081 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5081 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5082 for b in opts['bookmark']:
5082 for b in opts['bookmark']:
5083 # translate -B options to -r so changesets get pushed
5083 # translate -B options to -r so changesets get pushed
5084 if b in repo._bookmarks:
5084 if b in repo._bookmarks:
5085 opts.setdefault('rev', []).append(b)
5085 opts.setdefault('rev', []).append(b)
5086 else:
5086 else:
5087 # if we try to push a deleted bookmark, translate it to null
5087 # if we try to push a deleted bookmark, translate it to null
5088 # this lets simultaneous -r, -b options continue working
5088 # this lets simultaneous -r, -b options continue working
5089 opts.setdefault('rev', []).append("null")
5089 opts.setdefault('rev', []).append("null")
5090
5090
5091 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5091 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5092 dest, branches = hg.parseurl(dest, opts.get('branch'))
5092 dest, branches = hg.parseurl(dest, opts.get('branch'))
5093 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5093 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5094 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5094 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5095 try:
5095 try:
5096 other = hg.peer(repo, opts, dest)
5096 other = hg.peer(repo, opts, dest)
5097 except error.RepoError:
5097 except error.RepoError:
5098 if dest == "default-push":
5098 if dest == "default-push":
5099 raise util.Abort(_("default repository not configured!"),
5099 raise util.Abort(_("default repository not configured!"),
5100 hint=_('see the "path" section in "hg help config"'))
5100 hint=_('see the "path" section in "hg help config"'))
5101 else:
5101 else:
5102 raise
5102 raise
5103
5103
5104 if revs:
5104 if revs:
5105 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5105 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5106
5106
5107 repo._subtoppath = dest
5107 repo._subtoppath = dest
5108 try:
5108 try:
5109 # push subrepos depth-first for coherent ordering
5109 # push subrepos depth-first for coherent ordering
5110 c = repo['']
5110 c = repo['']
5111 subs = c.substate # only repos that are committed
5111 subs = c.substate # only repos that are committed
5112 for s in sorted(subs):
5112 for s in sorted(subs):
5113 result = c.sub(s).push(opts)
5113 result = c.sub(s).push(opts)
5114 if result == 0:
5114 if result == 0:
5115 return not result
5115 return not result
5116 finally:
5116 finally:
5117 del repo._subtoppath
5117 del repo._subtoppath
5118 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5118 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5119 newbranch=opts.get('new_branch'),
5119 newbranch=opts.get('new_branch'),
5120 bookmarks=opts.get('bookmark', ()))
5120 bookmarks=opts.get('bookmark', ()))
5121
5121
5122 result = not pushop.cgresult
5122 result = not pushop.cgresult
5123
5123
5124 if pushop.bkresult is not None:
5124 if pushop.bkresult is not None:
5125 if pushop.bkresult == 2:
5125 if pushop.bkresult == 2:
5126 result = 2
5126 result = 2
5127 elif not result and pushop.bkresult:
5127 elif not result and pushop.bkresult:
5128 result = 2
5128 result = 2
5129
5129
5130 return result
5130 return result
5131
5131
5132 @command('recover', [])
5132 @command('recover', [])
5133 def recover(ui, repo):
5133 def recover(ui, repo):
5134 """roll back an interrupted transaction
5134 """roll back an interrupted transaction
5135
5135
5136 Recover from an interrupted commit or pull.
5136 Recover from an interrupted commit or pull.
5137
5137
5138 This command tries to fix the repository status after an
5138 This command tries to fix the repository status after an
5139 interrupted operation. It should only be necessary when Mercurial
5139 interrupted operation. It should only be necessary when Mercurial
5140 suggests it.
5140 suggests it.
5141
5141
5142 Returns 0 if successful, 1 if nothing to recover or verify fails.
5142 Returns 0 if successful, 1 if nothing to recover or verify fails.
5143 """
5143 """
5144 if repo.recover():
5144 if repo.recover():
5145 return hg.verify(repo)
5145 return hg.verify(repo)
5146 return 1
5146 return 1
5147
5147
5148 @command('^remove|rm',
5148 @command('^remove|rm',
5149 [('A', 'after', None, _('record delete for missing files')),
5149 [('A', 'after', None, _('record delete for missing files')),
5150 ('f', 'force', None,
5150 ('f', 'force', None,
5151 _('remove (and delete) file even if added or modified')),
5151 _('remove (and delete) file even if added or modified')),
5152 ] + subrepoopts + walkopts,
5152 ] + subrepoopts + walkopts,
5153 _('[OPTION]... FILE...'),
5153 _('[OPTION]... FILE...'),
5154 inferrepo=True)
5154 inferrepo=True)
5155 def remove(ui, repo, *pats, **opts):
5155 def remove(ui, repo, *pats, **opts):
5156 """remove the specified files on the next commit
5156 """remove the specified files on the next commit
5157
5157
5158 Schedule the indicated files for removal from the current branch.
5158 Schedule the indicated files for removal from the current branch.
5159
5159
5160 This command schedules the files to be removed at the next commit.
5160 This command schedules the files to be removed at the next commit.
5161 To undo a remove before that, see :hg:`revert`. To undo added
5161 To undo a remove before that, see :hg:`revert`. To undo added
5162 files, see :hg:`forget`.
5162 files, see :hg:`forget`.
5163
5163
5164 .. container:: verbose
5164 .. container:: verbose
5165
5165
5166 -A/--after can be used to remove only files that have already
5166 -A/--after can be used to remove only files that have already
5167 been deleted, -f/--force can be used to force deletion, and -Af
5167 been deleted, -f/--force can be used to force deletion, and -Af
5168 can be used to remove files from the next revision without
5168 can be used to remove files from the next revision without
5169 deleting them from the working directory.
5169 deleting them from the working directory.
5170
5170
5171 The following table details the behavior of remove for different
5171 The following table details the behavior of remove for different
5172 file states (columns) and option combinations (rows). The file
5172 file states (columns) and option combinations (rows). The file
5173 states are Added [A], Clean [C], Modified [M] and Missing [!]
5173 states are Added [A], Clean [C], Modified [M] and Missing [!]
5174 (as reported by :hg:`status`). The actions are Warn, Remove
5174 (as reported by :hg:`status`). The actions are Warn, Remove
5175 (from branch) and Delete (from disk):
5175 (from branch) and Delete (from disk):
5176
5176
5177 ========= == == == ==
5177 ========= == == == ==
5178 opt/state A C M !
5178 opt/state A C M !
5179 ========= == == == ==
5179 ========= == == == ==
5180 none W RD W R
5180 none W RD W R
5181 -f R RD RD R
5181 -f R RD RD R
5182 -A W W W R
5182 -A W W W R
5183 -Af R R R R
5183 -Af R R R R
5184 ========= == == == ==
5184 ========= == == == ==
5185
5185
5186 Note that remove never deletes files in Added [A] state from the
5186 Note that remove never deletes files in Added [A] state from the
5187 working directory, not even if option --force is specified.
5187 working directory, not even if option --force is specified.
5188
5188
5189 Returns 0 on success, 1 if any warnings encountered.
5189 Returns 0 on success, 1 if any warnings encountered.
5190 """
5190 """
5191
5191
5192 after, force = opts.get('after'), opts.get('force')
5192 after, force = opts.get('after'), opts.get('force')
5193 if not pats and not after:
5193 if not pats and not after:
5194 raise util.Abort(_('no files specified'))
5194 raise util.Abort(_('no files specified'))
5195
5195
5196 m = scmutil.match(repo[None], pats, opts)
5196 m = scmutil.match(repo[None], pats, opts)
5197 subrepos = opts.get('subrepos')
5197 subrepos = opts.get('subrepos')
5198 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5198 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5199
5199
5200 @command('rename|move|mv',
5200 @command('rename|move|mv',
5201 [('A', 'after', None, _('record a rename that has already occurred')),
5201 [('A', 'after', None, _('record a rename that has already occurred')),
5202 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5202 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5203 ] + walkopts + dryrunopts,
5203 ] + walkopts + dryrunopts,
5204 _('[OPTION]... SOURCE... DEST'))
5204 _('[OPTION]... SOURCE... DEST'))
5205 def rename(ui, repo, *pats, **opts):
5205 def rename(ui, repo, *pats, **opts):
5206 """rename files; equivalent of copy + remove
5206 """rename files; equivalent of copy + remove
5207
5207
5208 Mark dest as copies of sources; mark sources for deletion. If dest
5208 Mark dest as copies of sources; mark sources for deletion. If dest
5209 is a directory, copies are put in that directory. If dest is a
5209 is a directory, copies are put in that directory. If dest is a
5210 file, there can only be one source.
5210 file, there can only be one source.
5211
5211
5212 By default, this command copies the contents of files as they
5212 By default, this command copies the contents of files as they
5213 exist in the working directory. If invoked with -A/--after, the
5213 exist in the working directory. If invoked with -A/--after, the
5214 operation is recorded, but no copying is performed.
5214 operation is recorded, but no copying is performed.
5215
5215
5216 This command takes effect at the next commit. To undo a rename
5216 This command takes effect at the next commit. To undo a rename
5217 before that, see :hg:`revert`.
5217 before that, see :hg:`revert`.
5218
5218
5219 Returns 0 on success, 1 if errors are encountered.
5219 Returns 0 on success, 1 if errors are encountered.
5220 """
5220 """
5221 wlock = repo.wlock(False)
5221 wlock = repo.wlock(False)
5222 try:
5222 try:
5223 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5223 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5224 finally:
5224 finally:
5225 wlock.release()
5225 wlock.release()
5226
5226
5227 @command('resolve',
5227 @command('resolve',
5228 [('a', 'all', None, _('select all unresolved files')),
5228 [('a', 'all', None, _('select all unresolved files')),
5229 ('l', 'list', None, _('list state of files needing merge')),
5229 ('l', 'list', None, _('list state of files needing merge')),
5230 ('m', 'mark', None, _('mark files as resolved')),
5230 ('m', 'mark', None, _('mark files as resolved')),
5231 ('u', 'unmark', None, _('mark files as unresolved')),
5231 ('u', 'unmark', None, _('mark files as unresolved')),
5232 ('n', 'no-status', None, _('hide status prefix'))]
5232 ('n', 'no-status', None, _('hide status prefix'))]
5233 + mergetoolopts + walkopts + formatteropts,
5233 + mergetoolopts + walkopts + formatteropts,
5234 _('[OPTION]... [FILE]...'),
5234 _('[OPTION]... [FILE]...'),
5235 inferrepo=True)
5235 inferrepo=True)
5236 def resolve(ui, repo, *pats, **opts):
5236 def resolve(ui, repo, *pats, **opts):
5237 """redo merges or set/view the merge status of files
5237 """redo merges or set/view the merge status of files
5238
5238
5239 Merges with unresolved conflicts are often the result of
5239 Merges with unresolved conflicts are often the result of
5240 non-interactive merging using the ``internal:merge`` configuration
5240 non-interactive merging using the ``internal:merge`` configuration
5241 setting, or a command-line merge tool like ``diff3``. The resolve
5241 setting, or a command-line merge tool like ``diff3``. The resolve
5242 command is used to manage the files involved in a merge, after
5242 command is used to manage the files involved in a merge, after
5243 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5243 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5244 working directory must have two parents). See :hg:`help
5244 working directory must have two parents). See :hg:`help
5245 merge-tools` for information on configuring merge tools.
5245 merge-tools` for information on configuring merge tools.
5246
5246
5247 The resolve command can be used in the following ways:
5247 The resolve command can be used in the following ways:
5248
5248
5249 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5249 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5250 files, discarding any previous merge attempts. Re-merging is not
5250 files, discarding any previous merge attempts. Re-merging is not
5251 performed for files already marked as resolved. Use ``--all/-a``
5251 performed for files already marked as resolved. Use ``--all/-a``
5252 to select all unresolved files. ``--tool`` can be used to specify
5252 to select all unresolved files. ``--tool`` can be used to specify
5253 the merge tool used for the given files. It overrides the HGMERGE
5253 the merge tool used for the given files. It overrides the HGMERGE
5254 environment variable and your configuration files. Previous file
5254 environment variable and your configuration files. Previous file
5255 contents are saved with a ``.orig`` suffix.
5255 contents are saved with a ``.orig`` suffix.
5256
5256
5257 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5257 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5258 (e.g. after having manually fixed-up the files). The default is
5258 (e.g. after having manually fixed-up the files). The default is
5259 to mark all unresolved files.
5259 to mark all unresolved files.
5260
5260
5261 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5261 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5262 default is to mark all resolved files.
5262 default is to mark all resolved files.
5263
5263
5264 - :hg:`resolve -l`: list files which had or still have conflicts.
5264 - :hg:`resolve -l`: list files which had or still have conflicts.
5265 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5265 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5266
5266
5267 Note that Mercurial will not let you commit files with unresolved
5267 Note that Mercurial will not let you commit files with unresolved
5268 merge conflicts. You must use :hg:`resolve -m ...` before you can
5268 merge conflicts. You must use :hg:`resolve -m ...` before you can
5269 commit after a conflicting merge.
5269 commit after a conflicting merge.
5270
5270
5271 Returns 0 on success, 1 if any files fail a resolve attempt.
5271 Returns 0 on success, 1 if any files fail a resolve attempt.
5272 """
5272 """
5273
5273
5274 all, mark, unmark, show, nostatus = \
5274 all, mark, unmark, show, nostatus = \
5275 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5275 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5276
5276
5277 if (show and (mark or unmark)) or (mark and unmark):
5277 if (show and (mark or unmark)) or (mark and unmark):
5278 raise util.Abort(_("too many options specified"))
5278 raise util.Abort(_("too many options specified"))
5279 if pats and all:
5279 if pats and all:
5280 raise util.Abort(_("can't specify --all and patterns"))
5280 raise util.Abort(_("can't specify --all and patterns"))
5281 if not (all or pats or show or mark or unmark):
5281 if not (all or pats or show or mark or unmark):
5282 raise util.Abort(_('no files or directories specified'),
5282 raise util.Abort(_('no files or directories specified'),
5283 hint=('use --all to remerge all files'))
5283 hint=('use --all to remerge all files'))
5284
5284
5285 if show:
5285 if show:
5286 fm = ui.formatter('resolve', opts)
5286 fm = ui.formatter('resolve', opts)
5287 ms = mergemod.mergestate(repo)
5287 ms = mergemod.mergestate(repo)
5288 m = scmutil.match(repo[None], pats, opts)
5288 m = scmutil.match(repo[None], pats, opts)
5289 for f in ms:
5289 for f in ms:
5290 if not m(f):
5290 if not m(f):
5291 continue
5291 continue
5292 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5292 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5293 fm.startitem()
5293 fm.startitem()
5294 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5294 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5295 fm.write('path', '%s\n', f, label=l)
5295 fm.write('path', '%s\n', f, label=l)
5296 fm.end()
5296 fm.end()
5297 return 0
5297 return 0
5298
5298
5299 wlock = repo.wlock()
5299 wlock = repo.wlock()
5300 try:
5300 try:
5301 ms = mergemod.mergestate(repo)
5301 ms = mergemod.mergestate(repo)
5302
5302
5303 if not (ms.active() or repo.dirstate.p2() != nullid):
5303 if not (ms.active() or repo.dirstate.p2() != nullid):
5304 raise util.Abort(
5304 raise util.Abort(
5305 _('resolve command not applicable when not merging'))
5305 _('resolve command not applicable when not merging'))
5306
5306
5307 m = scmutil.match(repo[None], pats, opts)
5307 m = scmutil.match(repo[None], pats, opts)
5308 ret = 0
5308 ret = 0
5309 didwork = False
5309 didwork = False
5310
5310
5311 for f in ms:
5311 for f in ms:
5312 if not m(f):
5312 if not m(f):
5313 continue
5313 continue
5314
5314
5315 didwork = True
5315 didwork = True
5316
5316
5317 if mark:
5317 if mark:
5318 ms.mark(f, "r")
5318 ms.mark(f, "r")
5319 elif unmark:
5319 elif unmark:
5320 ms.mark(f, "u")
5320 ms.mark(f, "u")
5321 else:
5321 else:
5322 wctx = repo[None]
5322 wctx = repo[None]
5323
5323
5324 # backup pre-resolve (merge uses .orig for its own purposes)
5324 # backup pre-resolve (merge uses .orig for its own purposes)
5325 a = repo.wjoin(f)
5325 a = repo.wjoin(f)
5326 util.copyfile(a, a + ".resolve")
5326 util.copyfile(a, a + ".resolve")
5327
5327
5328 try:
5328 try:
5329 # resolve file
5329 # resolve file
5330 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5330 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5331 'resolve')
5331 'resolve')
5332 if ms.resolve(f, wctx):
5332 if ms.resolve(f, wctx):
5333 ret = 1
5333 ret = 1
5334 finally:
5334 finally:
5335 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5335 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5336 ms.commit()
5336 ms.commit()
5337
5337
5338 # replace filemerge's .orig file with our resolve file
5338 # replace filemerge's .orig file with our resolve file
5339 util.rename(a + ".resolve", a + ".orig")
5339 util.rename(a + ".resolve", a + ".orig")
5340
5340
5341 ms.commit()
5341 ms.commit()
5342
5342
5343 if not didwork and pats:
5343 if not didwork and pats:
5344 ui.warn(_("arguments do not match paths that need resolving\n"))
5344 ui.warn(_("arguments do not match paths that need resolving\n"))
5345
5345
5346 finally:
5346 finally:
5347 wlock.release()
5347 wlock.release()
5348
5348
5349 # Nudge users into finishing an unfinished operation
5349 # Nudge users into finishing an unfinished operation
5350 if not list(ms.unresolved()):
5350 if not list(ms.unresolved()):
5351 ui.status(_('(no more unresolved files)\n'))
5351 ui.status(_('(no more unresolved files)\n'))
5352
5352
5353 return ret
5353 return ret
5354
5354
5355 @command('revert',
5355 @command('revert',
5356 [('a', 'all', None, _('revert all changes when no arguments given')),
5356 [('a', 'all', None, _('revert all changes when no arguments given')),
5357 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5357 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5358 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5358 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5359 ('C', 'no-backup', None, _('do not save backup copies of files')),
5359 ('C', 'no-backup', None, _('do not save backup copies of files')),
5360 ] + walkopts + dryrunopts,
5360 ] + walkopts + dryrunopts,
5361 _('[OPTION]... [-r REV] [NAME]...'))
5361 _('[OPTION]... [-r REV] [NAME]...'))
5362 def revert(ui, repo, *pats, **opts):
5362 def revert(ui, repo, *pats, **opts):
5363 """restore files to their checkout state
5363 """restore files to their checkout state
5364
5364
5365 .. note::
5365 .. note::
5366
5366
5367 To check out earlier revisions, you should use :hg:`update REV`.
5367 To check out earlier revisions, you should use :hg:`update REV`.
5368 To cancel an uncommitted merge (and lose your changes),
5368 To cancel an uncommitted merge (and lose your changes),
5369 use :hg:`update --clean .`.
5369 use :hg:`update --clean .`.
5370
5370
5371 With no revision specified, revert the specified files or directories
5371 With no revision specified, revert the specified files or directories
5372 to the contents they had in the parent of the working directory.
5372 to the contents they had in the parent of the working directory.
5373 This restores the contents of files to an unmodified
5373 This restores the contents of files to an unmodified
5374 state and unschedules adds, removes, copies, and renames. If the
5374 state and unschedules adds, removes, copies, and renames. If the
5375 working directory has two parents, you must explicitly specify a
5375 working directory has two parents, you must explicitly specify a
5376 revision.
5376 revision.
5377
5377
5378 Using the -r/--rev or -d/--date options, revert the given files or
5378 Using the -r/--rev or -d/--date options, revert the given files or
5379 directories to their states as of a specific revision. Because
5379 directories to their states as of a specific revision. Because
5380 revert does not change the working directory parents, this will
5380 revert does not change the working directory parents, this will
5381 cause these files to appear modified. This can be helpful to "back
5381 cause these files to appear modified. This can be helpful to "back
5382 out" some or all of an earlier change. See :hg:`backout` for a
5382 out" some or all of an earlier change. See :hg:`backout` for a
5383 related method.
5383 related method.
5384
5384
5385 Modified files are saved with a .orig suffix before reverting.
5385 Modified files are saved with a .orig suffix before reverting.
5386 To disable these backups, use --no-backup.
5386 To disable these backups, use --no-backup.
5387
5387
5388 See :hg:`help dates` for a list of formats valid for -d/--date.
5388 See :hg:`help dates` for a list of formats valid for -d/--date.
5389
5389
5390 Returns 0 on success.
5390 Returns 0 on success.
5391 """
5391 """
5392
5392
5393 if opts.get("date"):
5393 if opts.get("date"):
5394 if opts.get("rev"):
5394 if opts.get("rev"):
5395 raise util.Abort(_("you can't specify a revision and a date"))
5395 raise util.Abort(_("you can't specify a revision and a date"))
5396 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5396 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5397
5397
5398 parent, p2 = repo.dirstate.parents()
5398 parent, p2 = repo.dirstate.parents()
5399 if not opts.get('rev') and p2 != nullid:
5399 if not opts.get('rev') and p2 != nullid:
5400 # revert after merge is a trap for new users (issue2915)
5400 # revert after merge is a trap for new users (issue2915)
5401 raise util.Abort(_('uncommitted merge with no revision specified'),
5401 raise util.Abort(_('uncommitted merge with no revision specified'),
5402 hint=_('use "hg update" or see "hg help revert"'))
5402 hint=_('use "hg update" or see "hg help revert"'))
5403
5403
5404 ctx = scmutil.revsingle(repo, opts.get('rev'))
5404 ctx = scmutil.revsingle(repo, opts.get('rev'))
5405
5405
5406 if not pats and not opts.get('all'):
5406 if not pats and not opts.get('all'):
5407 msg = _("no files or directories specified")
5407 msg = _("no files or directories specified")
5408 if p2 != nullid:
5408 if p2 != nullid:
5409 hint = _("uncommitted merge, use --all to discard all changes,"
5409 hint = _("uncommitted merge, use --all to discard all changes,"
5410 " or 'hg update -C .' to abort the merge")
5410 " or 'hg update -C .' to abort the merge")
5411 raise util.Abort(msg, hint=hint)
5411 raise util.Abort(msg, hint=hint)
5412 dirty = util.any(repo.status())
5412 dirty = util.any(repo.status())
5413 node = ctx.node()
5413 node = ctx.node()
5414 if node != parent:
5414 if node != parent:
5415 if dirty:
5415 if dirty:
5416 hint = _("uncommitted changes, use --all to discard all"
5416 hint = _("uncommitted changes, use --all to discard all"
5417 " changes, or 'hg update %s' to update") % ctx.rev()
5417 " changes, or 'hg update %s' to update") % ctx.rev()
5418 else:
5418 else:
5419 hint = _("use --all to revert all files,"
5419 hint = _("use --all to revert all files,"
5420 " or 'hg update %s' to update") % ctx.rev()
5420 " or 'hg update %s' to update") % ctx.rev()
5421 elif dirty:
5421 elif dirty:
5422 hint = _("uncommitted changes, use --all to discard all changes")
5422 hint = _("uncommitted changes, use --all to discard all changes")
5423 else:
5423 else:
5424 hint = _("use --all to revert all files")
5424 hint = _("use --all to revert all files")
5425 raise util.Abort(msg, hint=hint)
5425 raise util.Abort(msg, hint=hint)
5426
5426
5427 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5427 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5428
5428
5429 @command('rollback', dryrunopts +
5429 @command('rollback', dryrunopts +
5430 [('f', 'force', False, _('ignore safety measures'))])
5430 [('f', 'force', False, _('ignore safety measures'))])
5431 def rollback(ui, repo, **opts):
5431 def rollback(ui, repo, **opts):
5432 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5432 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5433
5433
5434 Please use :hg:`commit --amend` instead of rollback to correct
5434 Please use :hg:`commit --amend` instead of rollback to correct
5435 mistakes in the last commit.
5435 mistakes in the last commit.
5436
5436
5437 This command should be used with care. There is only one level of
5437 This command should be used with care. There is only one level of
5438 rollback, and there is no way to undo a rollback. It will also
5438 rollback, and there is no way to undo a rollback. It will also
5439 restore the dirstate at the time of the last transaction, losing
5439 restore the dirstate at the time of the last transaction, losing
5440 any dirstate changes since that time. This command does not alter
5440 any dirstate changes since that time. This command does not alter
5441 the working directory.
5441 the working directory.
5442
5442
5443 Transactions are used to encapsulate the effects of all commands
5443 Transactions are used to encapsulate the effects of all commands
5444 that create new changesets or propagate existing changesets into a
5444 that create new changesets or propagate existing changesets into a
5445 repository.
5445 repository.
5446
5446
5447 .. container:: verbose
5447 .. container:: verbose
5448
5448
5449 For example, the following commands are transactional, and their
5449 For example, the following commands are transactional, and their
5450 effects can be rolled back:
5450 effects can be rolled back:
5451
5451
5452 - commit
5452 - commit
5453 - import
5453 - import
5454 - pull
5454 - pull
5455 - push (with this repository as the destination)
5455 - push (with this repository as the destination)
5456 - unbundle
5456 - unbundle
5457
5457
5458 To avoid permanent data loss, rollback will refuse to rollback a
5458 To avoid permanent data loss, rollback will refuse to rollback a
5459 commit transaction if it isn't checked out. Use --force to
5459 commit transaction if it isn't checked out. Use --force to
5460 override this protection.
5460 override this protection.
5461
5461
5462 This command is not intended for use on public repositories. Once
5462 This command is not intended for use on public repositories. Once
5463 changes are visible for pull by other users, rolling a transaction
5463 changes are visible for pull by other users, rolling a transaction
5464 back locally is ineffective (someone else may already have pulled
5464 back locally is ineffective (someone else may already have pulled
5465 the changes). Furthermore, a race is possible with readers of the
5465 the changes). Furthermore, a race is possible with readers of the
5466 repository; for example an in-progress pull from the repository
5466 repository; for example an in-progress pull from the repository
5467 may fail if a rollback is performed.
5467 may fail if a rollback is performed.
5468
5468
5469 Returns 0 on success, 1 if no rollback data is available.
5469 Returns 0 on success, 1 if no rollback data is available.
5470 """
5470 """
5471 return repo.rollback(dryrun=opts.get('dry_run'),
5471 return repo.rollback(dryrun=opts.get('dry_run'),
5472 force=opts.get('force'))
5472 force=opts.get('force'))
5473
5473
5474 @command('root', [])
5474 @command('root', [])
5475 def root(ui, repo):
5475 def root(ui, repo):
5476 """print the root (top) of the current working directory
5476 """print the root (top) of the current working directory
5477
5477
5478 Print the root directory of the current repository.
5478 Print the root directory of the current repository.
5479
5479
5480 Returns 0 on success.
5480 Returns 0 on success.
5481 """
5481 """
5482 ui.write(repo.root + "\n")
5482 ui.write(repo.root + "\n")
5483
5483
5484 @command('^serve',
5484 @command('^serve',
5485 [('A', 'accesslog', '', _('name of access log file to write to'),
5485 [('A', 'accesslog', '', _('name of access log file to write to'),
5486 _('FILE')),
5486 _('FILE')),
5487 ('d', 'daemon', None, _('run server in background')),
5487 ('d', 'daemon', None, _('run server in background')),
5488 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5488 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5489 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5489 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5490 # use string type, then we can check if something was passed
5490 # use string type, then we can check if something was passed
5491 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5491 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5492 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5492 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5493 _('ADDR')),
5493 _('ADDR')),
5494 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5494 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5495 _('PREFIX')),
5495 _('PREFIX')),
5496 ('n', 'name', '',
5496 ('n', 'name', '',
5497 _('name to show in web pages (default: working directory)'), _('NAME')),
5497 _('name to show in web pages (default: working directory)'), _('NAME')),
5498 ('', 'web-conf', '',
5498 ('', 'web-conf', '',
5499 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5499 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5500 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5500 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5501 _('FILE')),
5501 _('FILE')),
5502 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5502 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5503 ('', 'stdio', None, _('for remote clients')),
5503 ('', 'stdio', None, _('for remote clients')),
5504 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5504 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5505 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5505 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5506 ('', 'style', '', _('template style to use'), _('STYLE')),
5506 ('', 'style', '', _('template style to use'), _('STYLE')),
5507 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5507 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5508 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5508 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5509 _('[OPTION]...'),
5509 _('[OPTION]...'),
5510 optionalrepo=True)
5510 optionalrepo=True)
5511 def serve(ui, repo, **opts):
5511 def serve(ui, repo, **opts):
5512 """start stand-alone webserver
5512 """start stand-alone webserver
5513
5513
5514 Start a local HTTP repository browser and pull server. You can use
5514 Start a local HTTP repository browser and pull server. You can use
5515 this for ad-hoc sharing and browsing of repositories. It is
5515 this for ad-hoc sharing and browsing of repositories. It is
5516 recommended to use a real web server to serve a repository for
5516 recommended to use a real web server to serve a repository for
5517 longer periods of time.
5517 longer periods of time.
5518
5518
5519 Please note that the server does not implement access control.
5519 Please note that the server does not implement access control.
5520 This means that, by default, anybody can read from the server and
5520 This means that, by default, anybody can read from the server and
5521 nobody can write to it by default. Set the ``web.allow_push``
5521 nobody can write to it by default. Set the ``web.allow_push``
5522 option to ``*`` to allow everybody to push to the server. You
5522 option to ``*`` to allow everybody to push to the server. You
5523 should use a real web server if you need to authenticate users.
5523 should use a real web server if you need to authenticate users.
5524
5524
5525 By default, the server logs accesses to stdout and errors to
5525 By default, the server logs accesses to stdout and errors to
5526 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5526 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5527 files.
5527 files.
5528
5528
5529 To have the server choose a free port number to listen on, specify
5529 To have the server choose a free port number to listen on, specify
5530 a port number of 0; in this case, the server will print the port
5530 a port number of 0; in this case, the server will print the port
5531 number it uses.
5531 number it uses.
5532
5532
5533 Returns 0 on success.
5533 Returns 0 on success.
5534 """
5534 """
5535
5535
5536 if opts["stdio"] and opts["cmdserver"]:
5536 if opts["stdio"] and opts["cmdserver"]:
5537 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5537 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5538
5538
5539 if opts["stdio"]:
5539 if opts["stdio"]:
5540 if repo is None:
5540 if repo is None:
5541 raise error.RepoError(_("there is no Mercurial repository here"
5541 raise error.RepoError(_("there is no Mercurial repository here"
5542 " (.hg not found)"))
5542 " (.hg not found)"))
5543 s = sshserver.sshserver(ui, repo)
5543 s = sshserver.sshserver(ui, repo)
5544 s.serve_forever()
5544 s.serve_forever()
5545
5545
5546 if opts["cmdserver"]:
5546 if opts["cmdserver"]:
5547 service = commandserver.createservice(ui, repo, opts)
5547 service = commandserver.createservice(ui, repo, opts)
5548 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5548 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5549
5549
5550 # this way we can check if something was given in the command-line
5550 # this way we can check if something was given in the command-line
5551 if opts.get('port'):
5551 if opts.get('port'):
5552 opts['port'] = util.getport(opts.get('port'))
5552 opts['port'] = util.getport(opts.get('port'))
5553
5553
5554 baseui = repo and repo.baseui or ui
5554 baseui = repo and repo.baseui or ui
5555 optlist = ("name templates style address port prefix ipv6"
5555 optlist = ("name templates style address port prefix ipv6"
5556 " accesslog errorlog certificate encoding")
5556 " accesslog errorlog certificate encoding")
5557 for o in optlist.split():
5557 for o in optlist.split():
5558 val = opts.get(o, '')
5558 val = opts.get(o, '')
5559 if val in (None, ''): # should check against default options instead
5559 if val in (None, ''): # should check against default options instead
5560 continue
5560 continue
5561 baseui.setconfig("web", o, val, 'serve')
5561 baseui.setconfig("web", o, val, 'serve')
5562 if repo and repo.ui != baseui:
5562 if repo and repo.ui != baseui:
5563 repo.ui.setconfig("web", o, val, 'serve')
5563 repo.ui.setconfig("web", o, val, 'serve')
5564
5564
5565 o = opts.get('web_conf') or opts.get('webdir_conf')
5565 o = opts.get('web_conf') or opts.get('webdir_conf')
5566 if not o:
5566 if not o:
5567 if not repo:
5567 if not repo:
5568 raise error.RepoError(_("there is no Mercurial repository"
5568 raise error.RepoError(_("there is no Mercurial repository"
5569 " here (.hg not found)"))
5569 " here (.hg not found)"))
5570 o = repo
5570 o = repo
5571
5571
5572 app = hgweb.hgweb(o, baseui=baseui)
5572 app = hgweb.hgweb(o, baseui=baseui)
5573 service = httpservice(ui, app, opts)
5573 service = httpservice(ui, app, opts)
5574 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5574 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5575
5575
5576 class httpservice(object):
5576 class httpservice(object):
5577 def __init__(self, ui, app, opts):
5577 def __init__(self, ui, app, opts):
5578 self.ui = ui
5578 self.ui = ui
5579 self.app = app
5579 self.app = app
5580 self.opts = opts
5580 self.opts = opts
5581
5581
5582 def init(self):
5582 def init(self):
5583 util.setsignalhandler()
5583 util.setsignalhandler()
5584 self.httpd = hgweb_server.create_server(self.ui, self.app)
5584 self.httpd = hgweb_server.create_server(self.ui, self.app)
5585
5585
5586 if self.opts['port'] and not self.ui.verbose:
5586 if self.opts['port'] and not self.ui.verbose:
5587 return
5587 return
5588
5588
5589 if self.httpd.prefix:
5589 if self.httpd.prefix:
5590 prefix = self.httpd.prefix.strip('/') + '/'
5590 prefix = self.httpd.prefix.strip('/') + '/'
5591 else:
5591 else:
5592 prefix = ''
5592 prefix = ''
5593
5593
5594 port = ':%d' % self.httpd.port
5594 port = ':%d' % self.httpd.port
5595 if port == ':80':
5595 if port == ':80':
5596 port = ''
5596 port = ''
5597
5597
5598 bindaddr = self.httpd.addr
5598 bindaddr = self.httpd.addr
5599 if bindaddr == '0.0.0.0':
5599 if bindaddr == '0.0.0.0':
5600 bindaddr = '*'
5600 bindaddr = '*'
5601 elif ':' in bindaddr: # IPv6
5601 elif ':' in bindaddr: # IPv6
5602 bindaddr = '[%s]' % bindaddr
5602 bindaddr = '[%s]' % bindaddr
5603
5603
5604 fqaddr = self.httpd.fqaddr
5604 fqaddr = self.httpd.fqaddr
5605 if ':' in fqaddr:
5605 if ':' in fqaddr:
5606 fqaddr = '[%s]' % fqaddr
5606 fqaddr = '[%s]' % fqaddr
5607 if self.opts['port']:
5607 if self.opts['port']:
5608 write = self.ui.status
5608 write = self.ui.status
5609 else:
5609 else:
5610 write = self.ui.write
5610 write = self.ui.write
5611 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5611 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5612 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5612 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5613 self.ui.flush() # avoid buffering of status message
5613 self.ui.flush() # avoid buffering of status message
5614
5614
5615 def run(self):
5615 def run(self):
5616 self.httpd.serve_forever()
5616 self.httpd.serve_forever()
5617
5617
5618
5618
5619 @command('^status|st',
5619 @command('^status|st',
5620 [('A', 'all', None, _('show status of all files')),
5620 [('A', 'all', None, _('show status of all files')),
5621 ('m', 'modified', None, _('show only modified files')),
5621 ('m', 'modified', None, _('show only modified files')),
5622 ('a', 'added', None, _('show only added files')),
5622 ('a', 'added', None, _('show only added files')),
5623 ('r', 'removed', None, _('show only removed files')),
5623 ('r', 'removed', None, _('show only removed files')),
5624 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5624 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5625 ('c', 'clean', None, _('show only files without changes')),
5625 ('c', 'clean', None, _('show only files without changes')),
5626 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5626 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5627 ('i', 'ignored', None, _('show only ignored files')),
5627 ('i', 'ignored', None, _('show only ignored files')),
5628 ('n', 'no-status', None, _('hide status prefix')),
5628 ('n', 'no-status', None, _('hide status prefix')),
5629 ('C', 'copies', None, _('show source of copied files')),
5629 ('C', 'copies', None, _('show source of copied files')),
5630 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5630 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5631 ('', 'rev', [], _('show difference from revision'), _('REV')),
5631 ('', 'rev', [], _('show difference from revision'), _('REV')),
5632 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5632 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5633 ] + walkopts + subrepoopts + formatteropts,
5633 ] + walkopts + subrepoopts + formatteropts,
5634 _('[OPTION]... [FILE]...'),
5634 _('[OPTION]... [FILE]...'),
5635 inferrepo=True)
5635 inferrepo=True)
5636 def status(ui, repo, *pats, **opts):
5636 def status(ui, repo, *pats, **opts):
5637 """show changed files in the working directory
5637 """show changed files in the working directory
5638
5638
5639 Show status of files in the repository. If names are given, only
5639 Show status of files in the repository. If names are given, only
5640 files that match are shown. Files that are clean or ignored or
5640 files that match are shown. Files that are clean or ignored or
5641 the source of a copy/move operation, are not listed unless
5641 the source of a copy/move operation, are not listed unless
5642 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5642 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5643 Unless options described with "show only ..." are given, the
5643 Unless options described with "show only ..." are given, the
5644 options -mardu are used.
5644 options -mardu are used.
5645
5645
5646 Option -q/--quiet hides untracked (unknown and ignored) files
5646 Option -q/--quiet hides untracked (unknown and ignored) files
5647 unless explicitly requested with -u/--unknown or -i/--ignored.
5647 unless explicitly requested with -u/--unknown or -i/--ignored.
5648
5648
5649 .. note::
5649 .. note::
5650
5650
5651 status may appear to disagree with diff if permissions have
5651 status may appear to disagree with diff if permissions have
5652 changed or a merge has occurred. The standard diff format does
5652 changed or a merge has occurred. The standard diff format does
5653 not report permission changes and diff only reports changes
5653 not report permission changes and diff only reports changes
5654 relative to one merge parent.
5654 relative to one merge parent.
5655
5655
5656 If one revision is given, it is used as the base revision.
5656 If one revision is given, it is used as the base revision.
5657 If two revisions are given, the differences between them are
5657 If two revisions are given, the differences between them are
5658 shown. The --change option can also be used as a shortcut to list
5658 shown. The --change option can also be used as a shortcut to list
5659 the changed files of a revision from its first parent.
5659 the changed files of a revision from its first parent.
5660
5660
5661 The codes used to show the status of files are::
5661 The codes used to show the status of files are::
5662
5662
5663 M = modified
5663 M = modified
5664 A = added
5664 A = added
5665 R = removed
5665 R = removed
5666 C = clean
5666 C = clean
5667 ! = missing (deleted by non-hg command, but still tracked)
5667 ! = missing (deleted by non-hg command, but still tracked)
5668 ? = not tracked
5668 ? = not tracked
5669 I = ignored
5669 I = ignored
5670 = origin of the previous file (with --copies)
5670 = origin of the previous file (with --copies)
5671
5671
5672 .. container:: verbose
5672 .. container:: verbose
5673
5673
5674 Examples:
5674 Examples:
5675
5675
5676 - show changes in the working directory relative to a
5676 - show changes in the working directory relative to a
5677 changeset::
5677 changeset::
5678
5678
5679 hg status --rev 9353
5679 hg status --rev 9353
5680
5680
5681 - show all changes including copies in an existing changeset::
5681 - show all changes including copies in an existing changeset::
5682
5682
5683 hg status --copies --change 9353
5683 hg status --copies --change 9353
5684
5684
5685 - get a NUL separated list of added files, suitable for xargs::
5685 - get a NUL separated list of added files, suitable for xargs::
5686
5686
5687 hg status -an0
5687 hg status -an0
5688
5688
5689 Returns 0 on success.
5689 Returns 0 on success.
5690 """
5690 """
5691
5691
5692 revs = opts.get('rev')
5692 revs = opts.get('rev')
5693 change = opts.get('change')
5693 change = opts.get('change')
5694
5694
5695 if revs and change:
5695 if revs and change:
5696 msg = _('cannot specify --rev and --change at the same time')
5696 msg = _('cannot specify --rev and --change at the same time')
5697 raise util.Abort(msg)
5697 raise util.Abort(msg)
5698 elif change:
5698 elif change:
5699 node2 = scmutil.revsingle(repo, change, None).node()
5699 node2 = scmutil.revsingle(repo, change, None).node()
5700 node1 = repo[node2].p1().node()
5700 node1 = repo[node2].p1().node()
5701 else:
5701 else:
5702 node1, node2 = scmutil.revpair(repo, revs)
5702 node1, node2 = scmutil.revpair(repo, revs)
5703
5703
5704 cwd = (pats and repo.getcwd()) or ''
5704 cwd = (pats and repo.getcwd()) or ''
5705 end = opts.get('print0') and '\0' or '\n'
5705 end = opts.get('print0') and '\0' or '\n'
5706 copy = {}
5706 copy = {}
5707 states = 'modified added removed deleted unknown ignored clean'.split()
5707 states = 'modified added removed deleted unknown ignored clean'.split()
5708 show = [k for k in states if opts.get(k)]
5708 show = [k for k in states if opts.get(k)]
5709 if opts.get('all'):
5709 if opts.get('all'):
5710 show += ui.quiet and (states[:4] + ['clean']) or states
5710 show += ui.quiet and (states[:4] + ['clean']) or states
5711 if not show:
5711 if not show:
5712 show = ui.quiet and states[:4] or states[:5]
5712 show = ui.quiet and states[:4] or states[:5]
5713
5713
5714 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5714 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5715 'ignored' in show, 'clean' in show, 'unknown' in show,
5715 'ignored' in show, 'clean' in show, 'unknown' in show,
5716 opts.get('subrepos'))
5716 opts.get('subrepos'))
5717 changestates = zip(states, 'MAR!?IC', stat)
5717 changestates = zip(states, 'MAR!?IC', stat)
5718
5718
5719 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5719 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5720 copy = copies.pathcopies(repo[node1], repo[node2])
5720 copy = copies.pathcopies(repo[node1], repo[node2])
5721
5721
5722 fm = ui.formatter('status', opts)
5722 fm = ui.formatter('status', opts)
5723 fmt = '%s' + end
5723 fmt = '%s' + end
5724 showchar = not opts.get('no_status')
5724 showchar = not opts.get('no_status')
5725
5725
5726 for state, char, files in changestates:
5726 for state, char, files in changestates:
5727 if state in show:
5727 if state in show:
5728 label = 'status.' + state
5728 label = 'status.' + state
5729 for f in files:
5729 for f in files:
5730 fm.startitem()
5730 fm.startitem()
5731 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5731 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5732 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5732 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5733 if f in copy:
5733 if f in copy:
5734 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5734 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5735 label='status.copied')
5735 label='status.copied')
5736 fm.end()
5736 fm.end()
5737
5737
5738 @command('^summary|sum',
5738 @command('^summary|sum',
5739 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5739 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5740 def summary(ui, repo, **opts):
5740 def summary(ui, repo, **opts):
5741 """summarize working directory state
5741 """summarize working directory state
5742
5742
5743 This generates a brief summary of the working directory state,
5743 This generates a brief summary of the working directory state,
5744 including parents, branch, commit status, and available updates.
5744 including parents, branch, commit status, and available updates.
5745
5745
5746 With the --remote option, this will check the default paths for
5746 With the --remote option, this will check the default paths for
5747 incoming and outgoing changes. This can be time-consuming.
5747 incoming and outgoing changes. This can be time-consuming.
5748
5748
5749 Returns 0 on success.
5749 Returns 0 on success.
5750 """
5750 """
5751
5751
5752 ctx = repo[None]
5752 ctx = repo[None]
5753 parents = ctx.parents()
5753 parents = ctx.parents()
5754 pnode = parents[0].node()
5754 pnode = parents[0].node()
5755 marks = []
5755 marks = []
5756
5756
5757 for p in parents:
5757 for p in parents:
5758 # label with log.changeset (instead of log.parent) since this
5758 # label with log.changeset (instead of log.parent) since this
5759 # shows a working directory parent *changeset*:
5759 # shows a working directory parent *changeset*:
5760 # i18n: column positioning for "hg summary"
5760 # i18n: column positioning for "hg summary"
5761 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5761 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5762 label='log.changeset changeset.%s' % p.phasestr())
5762 label='log.changeset changeset.%s' % p.phasestr())
5763 ui.write(' '.join(p.tags()), label='log.tag')
5763 ui.write(' '.join(p.tags()), label='log.tag')
5764 if p.bookmarks():
5764 if p.bookmarks():
5765 marks.extend(p.bookmarks())
5765 marks.extend(p.bookmarks())
5766 if p.rev() == -1:
5766 if p.rev() == -1:
5767 if not len(repo):
5767 if not len(repo):
5768 ui.write(_(' (empty repository)'))
5768 ui.write(_(' (empty repository)'))
5769 else:
5769 else:
5770 ui.write(_(' (no revision checked out)'))
5770 ui.write(_(' (no revision checked out)'))
5771 ui.write('\n')
5771 ui.write('\n')
5772 if p.description():
5772 if p.description():
5773 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5773 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5774 label='log.summary')
5774 label='log.summary')
5775
5775
5776 branch = ctx.branch()
5776 branch = ctx.branch()
5777 bheads = repo.branchheads(branch)
5777 bheads = repo.branchheads(branch)
5778 # i18n: column positioning for "hg summary"
5778 # i18n: column positioning for "hg summary"
5779 m = _('branch: %s\n') % branch
5779 m = _('branch: %s\n') % branch
5780 if branch != 'default':
5780 if branch != 'default':
5781 ui.write(m, label='log.branch')
5781 ui.write(m, label='log.branch')
5782 else:
5782 else:
5783 ui.status(m, label='log.branch')
5783 ui.status(m, label='log.branch')
5784
5784
5785 if marks:
5785 if marks:
5786 current = repo._bookmarkcurrent
5786 current = repo._bookmarkcurrent
5787 # i18n: column positioning for "hg summary"
5787 # i18n: column positioning for "hg summary"
5788 ui.write(_('bookmarks:'), label='log.bookmark')
5788 ui.write(_('bookmarks:'), label='log.bookmark')
5789 if current is not None:
5789 if current is not None:
5790 if current in marks:
5790 if current in marks:
5791 ui.write(' *' + current, label='bookmarks.current')
5791 ui.write(' *' + current, label='bookmarks.current')
5792 marks.remove(current)
5792 marks.remove(current)
5793 else:
5793 else:
5794 ui.write(' [%s]' % current, label='bookmarks.current')
5794 ui.write(' [%s]' % current, label='bookmarks.current')
5795 for m in marks:
5795 for m in marks:
5796 ui.write(' ' + m, label='log.bookmark')
5796 ui.write(' ' + m, label='log.bookmark')
5797 ui.write('\n', label='log.bookmark')
5797 ui.write('\n', label='log.bookmark')
5798
5798
5799 status = repo.status(unknown=True)
5799 status = repo.status(unknown=True)
5800
5800
5801 c = repo.dirstate.copies()
5801 c = repo.dirstate.copies()
5802 copied, renamed = [], []
5802 copied, renamed = [], []
5803 for d, s in c.iteritems():
5803 for d, s in c.iteritems():
5804 if s in status.removed:
5804 if s in status.removed:
5805 status.removed.remove(s)
5805 status.removed.remove(s)
5806 renamed.append(d)
5806 renamed.append(d)
5807 else:
5807 else:
5808 copied.append(d)
5808 copied.append(d)
5809 if d in status.added:
5809 if d in status.added:
5810 status.added.remove(d)
5810 status.added.remove(d)
5811
5811
5812 ms = mergemod.mergestate(repo)
5812 ms = mergemod.mergestate(repo)
5813 unresolved = [f for f in ms if ms[f] == 'u']
5813 unresolved = [f for f in ms if ms[f] == 'u']
5814
5814
5815 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5815 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5816
5816
5817 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5817 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5818 (ui.label(_('%d added'), 'status.added'), status.added),
5818 (ui.label(_('%d added'), 'status.added'), status.added),
5819 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5819 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5820 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5820 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5821 (ui.label(_('%d copied'), 'status.copied'), copied),
5821 (ui.label(_('%d copied'), 'status.copied'), copied),
5822 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5822 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5823 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5823 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5824 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5824 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5825 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5825 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5826 t = []
5826 t = []
5827 for l, s in labels:
5827 for l, s in labels:
5828 if s:
5828 if s:
5829 t.append(l % len(s))
5829 t.append(l % len(s))
5830
5830
5831 t = ', '.join(t)
5831 t = ', '.join(t)
5832 cleanworkdir = False
5832 cleanworkdir = False
5833
5833
5834 if repo.vfs.exists('updatestate'):
5834 if repo.vfs.exists('updatestate'):
5835 t += _(' (interrupted update)')
5835 t += _(' (interrupted update)')
5836 elif len(parents) > 1:
5836 elif len(parents) > 1:
5837 t += _(' (merge)')
5837 t += _(' (merge)')
5838 elif branch != parents[0].branch():
5838 elif branch != parents[0].branch():
5839 t += _(' (new branch)')
5839 t += _(' (new branch)')
5840 elif (parents[0].closesbranch() and
5840 elif (parents[0].closesbranch() and
5841 pnode in repo.branchheads(branch, closed=True)):
5841 pnode in repo.branchheads(branch, closed=True)):
5842 t += _(' (head closed)')
5842 t += _(' (head closed)')
5843 elif not (status.modified or status.added or status.removed or renamed or
5843 elif not (status.modified or status.added or status.removed or renamed or
5844 copied or subs):
5844 copied or subs):
5845 t += _(' (clean)')
5845 t += _(' (clean)')
5846 cleanworkdir = True
5846 cleanworkdir = True
5847 elif pnode not in bheads:
5847 elif pnode not in bheads:
5848 t += _(' (new branch head)')
5848 t += _(' (new branch head)')
5849
5849
5850 if cleanworkdir:
5850 if cleanworkdir:
5851 # i18n: column positioning for "hg summary"
5851 # i18n: column positioning for "hg summary"
5852 ui.status(_('commit: %s\n') % t.strip())
5852 ui.status(_('commit: %s\n') % t.strip())
5853 else:
5853 else:
5854 # i18n: column positioning for "hg summary"
5854 # i18n: column positioning for "hg summary"
5855 ui.write(_('commit: %s\n') % t.strip())
5855 ui.write(_('commit: %s\n') % t.strip())
5856
5856
5857 # all ancestors of branch heads - all ancestors of parent = new csets
5857 # all ancestors of branch heads - all ancestors of parent = new csets
5858 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5858 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5859 bheads))
5859 bheads))
5860
5860
5861 if new == 0:
5861 if new == 0:
5862 # i18n: column positioning for "hg summary"
5862 # i18n: column positioning for "hg summary"
5863 ui.status(_('update: (current)\n'))
5863 ui.status(_('update: (current)\n'))
5864 elif pnode not in bheads:
5864 elif pnode not in bheads:
5865 # i18n: column positioning for "hg summary"
5865 # i18n: column positioning for "hg summary"
5866 ui.write(_('update: %d new changesets (update)\n') % new)
5866 ui.write(_('update: %d new changesets (update)\n') % new)
5867 else:
5867 else:
5868 # i18n: column positioning for "hg summary"
5868 # i18n: column positioning for "hg summary"
5869 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5869 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5870 (new, len(bheads)))
5870 (new, len(bheads)))
5871
5871
5872 cmdutil.summaryhooks(ui, repo)
5872 cmdutil.summaryhooks(ui, repo)
5873
5873
5874 if opts.get('remote'):
5874 if opts.get('remote'):
5875 needsincoming, needsoutgoing = True, True
5875 needsincoming, needsoutgoing = True, True
5876 else:
5876 else:
5877 needsincoming, needsoutgoing = False, False
5877 needsincoming, needsoutgoing = False, False
5878 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5878 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5879 if i:
5879 if i:
5880 needsincoming = True
5880 needsincoming = True
5881 if o:
5881 if o:
5882 needsoutgoing = True
5882 needsoutgoing = True
5883 if not needsincoming and not needsoutgoing:
5883 if not needsincoming and not needsoutgoing:
5884 return
5884 return
5885
5885
5886 def getincoming():
5886 def getincoming():
5887 source, branches = hg.parseurl(ui.expandpath('default'))
5887 source, branches = hg.parseurl(ui.expandpath('default'))
5888 sbranch = branches[0]
5888 sbranch = branches[0]
5889 try:
5889 try:
5890 other = hg.peer(repo, {}, source)
5890 other = hg.peer(repo, {}, source)
5891 except error.RepoError:
5891 except error.RepoError:
5892 if opts.get('remote'):
5892 if opts.get('remote'):
5893 raise
5893 raise
5894 return source, sbranch, None, None, None
5894 return source, sbranch, None, None, None
5895 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5895 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5896 if revs:
5896 if revs:
5897 revs = [other.lookup(rev) for rev in revs]
5897 revs = [other.lookup(rev) for rev in revs]
5898 ui.debug('comparing with %s\n' % util.hidepassword(source))
5898 ui.debug('comparing with %s\n' % util.hidepassword(source))
5899 repo.ui.pushbuffer()
5899 repo.ui.pushbuffer()
5900 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5900 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5901 repo.ui.popbuffer()
5901 repo.ui.popbuffer()
5902 return source, sbranch, other, commoninc, commoninc[1]
5902 return source, sbranch, other, commoninc, commoninc[1]
5903
5903
5904 if needsincoming:
5904 if needsincoming:
5905 source, sbranch, sother, commoninc, incoming = getincoming()
5905 source, sbranch, sother, commoninc, incoming = getincoming()
5906 else:
5906 else:
5907 source = sbranch = sother = commoninc = incoming = None
5907 source = sbranch = sother = commoninc = incoming = None
5908
5908
5909 def getoutgoing():
5909 def getoutgoing():
5910 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5910 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5911 dbranch = branches[0]
5911 dbranch = branches[0]
5912 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5912 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5913 if source != dest:
5913 if source != dest:
5914 try:
5914 try:
5915 dother = hg.peer(repo, {}, dest)
5915 dother = hg.peer(repo, {}, dest)
5916 except error.RepoError:
5916 except error.RepoError:
5917 if opts.get('remote'):
5917 if opts.get('remote'):
5918 raise
5918 raise
5919 return dest, dbranch, None, None
5919 return dest, dbranch, None, None
5920 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5920 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5921 elif sother is None:
5921 elif sother is None:
5922 # there is no explicit destination peer, but source one is invalid
5922 # there is no explicit destination peer, but source one is invalid
5923 return dest, dbranch, None, None
5923 return dest, dbranch, None, None
5924 else:
5924 else:
5925 dother = sother
5925 dother = sother
5926 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5926 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5927 common = None
5927 common = None
5928 else:
5928 else:
5929 common = commoninc
5929 common = commoninc
5930 if revs:
5930 if revs:
5931 revs = [repo.lookup(rev) for rev in revs]
5931 revs = [repo.lookup(rev) for rev in revs]
5932 repo.ui.pushbuffer()
5932 repo.ui.pushbuffer()
5933 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5933 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5934 commoninc=common)
5934 commoninc=common)
5935 repo.ui.popbuffer()
5935 repo.ui.popbuffer()
5936 return dest, dbranch, dother, outgoing
5936 return dest, dbranch, dother, outgoing
5937
5937
5938 if needsoutgoing:
5938 if needsoutgoing:
5939 dest, dbranch, dother, outgoing = getoutgoing()
5939 dest, dbranch, dother, outgoing = getoutgoing()
5940 else:
5940 else:
5941 dest = dbranch = dother = outgoing = None
5941 dest = dbranch = dother = outgoing = None
5942
5942
5943 if opts.get('remote'):
5943 if opts.get('remote'):
5944 t = []
5944 t = []
5945 if incoming:
5945 if incoming:
5946 t.append(_('1 or more incoming'))
5946 t.append(_('1 or more incoming'))
5947 o = outgoing.missing
5947 o = outgoing.missing
5948 if o:
5948 if o:
5949 t.append(_('%d outgoing') % len(o))
5949 t.append(_('%d outgoing') % len(o))
5950 other = dother or sother
5950 other = dother or sother
5951 if 'bookmarks' in other.listkeys('namespaces'):
5951 if 'bookmarks' in other.listkeys('namespaces'):
5952 lmarks = repo.listkeys('bookmarks')
5952 lmarks = repo.listkeys('bookmarks')
5953 rmarks = other.listkeys('bookmarks')
5953 rmarks = other.listkeys('bookmarks')
5954 diff = set(rmarks) - set(lmarks)
5954 diff = set(rmarks) - set(lmarks)
5955 if len(diff) > 0:
5955 if len(diff) > 0:
5956 t.append(_('%d incoming bookmarks') % len(diff))
5956 t.append(_('%d incoming bookmarks') % len(diff))
5957 diff = set(lmarks) - set(rmarks)
5957 diff = set(lmarks) - set(rmarks)
5958 if len(diff) > 0:
5958 if len(diff) > 0:
5959 t.append(_('%d outgoing bookmarks') % len(diff))
5959 t.append(_('%d outgoing bookmarks') % len(diff))
5960
5960
5961 if t:
5961 if t:
5962 # i18n: column positioning for "hg summary"
5962 # i18n: column positioning for "hg summary"
5963 ui.write(_('remote: %s\n') % (', '.join(t)))
5963 ui.write(_('remote: %s\n') % (', '.join(t)))
5964 else:
5964 else:
5965 # i18n: column positioning for "hg summary"
5965 # i18n: column positioning for "hg summary"
5966 ui.status(_('remote: (synced)\n'))
5966 ui.status(_('remote: (synced)\n'))
5967
5967
5968 cmdutil.summaryremotehooks(ui, repo, opts,
5968 cmdutil.summaryremotehooks(ui, repo, opts,
5969 ((source, sbranch, sother, commoninc),
5969 ((source, sbranch, sother, commoninc),
5970 (dest, dbranch, dother, outgoing)))
5970 (dest, dbranch, dother, outgoing)))
5971
5971
5972 @command('tag',
5972 @command('tag',
5973 [('f', 'force', None, _('force tag')),
5973 [('f', 'force', None, _('force tag')),
5974 ('l', 'local', None, _('make the tag local')),
5974 ('l', 'local', None, _('make the tag local')),
5975 ('r', 'rev', '', _('revision to tag'), _('REV')),
5975 ('r', 'rev', '', _('revision to tag'), _('REV')),
5976 ('', 'remove', None, _('remove a tag')),
5976 ('', 'remove', None, _('remove a tag')),
5977 # -l/--local is already there, commitopts cannot be used
5977 # -l/--local is already there, commitopts cannot be used
5978 ('e', 'edit', None, _('invoke editor on commit messages')),
5978 ('e', 'edit', None, _('invoke editor on commit messages')),
5979 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5979 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5980 ] + commitopts2,
5980 ] + commitopts2,
5981 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5981 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5982 def tag(ui, repo, name1, *names, **opts):
5982 def tag(ui, repo, name1, *names, **opts):
5983 """add one or more tags for the current or given revision
5983 """add one or more tags for the current or given revision
5984
5984
5985 Name a particular revision using <name>.
5985 Name a particular revision using <name>.
5986
5986
5987 Tags are used to name particular revisions of the repository and are
5987 Tags are used to name particular revisions of the repository and are
5988 very useful to compare different revisions, to go back to significant
5988 very useful to compare different revisions, to go back to significant
5989 earlier versions or to mark branch points as releases, etc. Changing
5989 earlier versions or to mark branch points as releases, etc. Changing
5990 an existing tag is normally disallowed; use -f/--force to override.
5990 an existing tag is normally disallowed; use -f/--force to override.
5991
5991
5992 If no revision is given, the parent of the working directory is
5992 If no revision is given, the parent of the working directory is
5993 used.
5993 used.
5994
5994
5995 To facilitate version control, distribution, and merging of tags,
5995 To facilitate version control, distribution, and merging of tags,
5996 they are stored as a file named ".hgtags" which is managed similarly
5996 they are stored as a file named ".hgtags" which is managed similarly
5997 to other project files and can be hand-edited if necessary. This
5997 to other project files and can be hand-edited if necessary. This
5998 also means that tagging creates a new commit. The file
5998 also means that tagging creates a new commit. The file
5999 ".hg/localtags" is used for local tags (not shared among
5999 ".hg/localtags" is used for local tags (not shared among
6000 repositories).
6000 repositories).
6001
6001
6002 Tag commits are usually made at the head of a branch. If the parent
6002 Tag commits are usually made at the head of a branch. If the parent
6003 of the working directory is not a branch head, :hg:`tag` aborts; use
6003 of the working directory is not a branch head, :hg:`tag` aborts; use
6004 -f/--force to force the tag commit to be based on a non-head
6004 -f/--force to force the tag commit to be based on a non-head
6005 changeset.
6005 changeset.
6006
6006
6007 See :hg:`help dates` for a list of formats valid for -d/--date.
6007 See :hg:`help dates` for a list of formats valid for -d/--date.
6008
6008
6009 Since tag names have priority over branch names during revision
6009 Since tag names have priority over branch names during revision
6010 lookup, using an existing branch name as a tag name is discouraged.
6010 lookup, using an existing branch name as a tag name is discouraged.
6011
6011
6012 Returns 0 on success.
6012 Returns 0 on success.
6013 """
6013 """
6014 wlock = lock = None
6014 wlock = lock = None
6015 try:
6015 try:
6016 wlock = repo.wlock()
6016 wlock = repo.wlock()
6017 lock = repo.lock()
6017 lock = repo.lock()
6018 rev_ = "."
6018 rev_ = "."
6019 names = [t.strip() for t in (name1,) + names]
6019 names = [t.strip() for t in (name1,) + names]
6020 if len(names) != len(set(names)):
6020 if len(names) != len(set(names)):
6021 raise util.Abort(_('tag names must be unique'))
6021 raise util.Abort(_('tag names must be unique'))
6022 for n in names:
6022 for n in names:
6023 scmutil.checknewlabel(repo, n, 'tag')
6023 scmutil.checknewlabel(repo, n, 'tag')
6024 if not n:
6024 if not n:
6025 raise util.Abort(_('tag names cannot consist entirely of '
6025 raise util.Abort(_('tag names cannot consist entirely of '
6026 'whitespace'))
6026 'whitespace'))
6027 if opts.get('rev') and opts.get('remove'):
6027 if opts.get('rev') and opts.get('remove'):
6028 raise util.Abort(_("--rev and --remove are incompatible"))
6028 raise util.Abort(_("--rev and --remove are incompatible"))
6029 if opts.get('rev'):
6029 if opts.get('rev'):
6030 rev_ = opts['rev']
6030 rev_ = opts['rev']
6031 message = opts.get('message')
6031 message = opts.get('message')
6032 if opts.get('remove'):
6032 if opts.get('remove'):
6033 expectedtype = opts.get('local') and 'local' or 'global'
6033 expectedtype = opts.get('local') and 'local' or 'global'
6034 for n in names:
6034 for n in names:
6035 if not repo.tagtype(n):
6035 if not repo.tagtype(n):
6036 raise util.Abort(_("tag '%s' does not exist") % n)
6036 raise util.Abort(_("tag '%s' does not exist") % n)
6037 if repo.tagtype(n) != expectedtype:
6037 if repo.tagtype(n) != expectedtype:
6038 if expectedtype == 'global':
6038 if expectedtype == 'global':
6039 raise util.Abort(_("tag '%s' is not a global tag") % n)
6039 raise util.Abort(_("tag '%s' is not a global tag") % n)
6040 else:
6040 else:
6041 raise util.Abort(_("tag '%s' is not a local tag") % n)
6041 raise util.Abort(_("tag '%s' is not a local tag") % n)
6042 rev_ = nullid
6042 rev_ = nullid
6043 if not message:
6043 if not message:
6044 # we don't translate commit messages
6044 # we don't translate commit messages
6045 message = 'Removed tag %s' % ', '.join(names)
6045 message = 'Removed tag %s' % ', '.join(names)
6046 elif not opts.get('force'):
6046 elif not opts.get('force'):
6047 for n in names:
6047 for n in names:
6048 if n in repo.tags():
6048 if n in repo.tags():
6049 raise util.Abort(_("tag '%s' already exists "
6049 raise util.Abort(_("tag '%s' already exists "
6050 "(use -f to force)") % n)
6050 "(use -f to force)") % n)
6051 if not opts.get('local'):
6051 if not opts.get('local'):
6052 p1, p2 = repo.dirstate.parents()
6052 p1, p2 = repo.dirstate.parents()
6053 if p2 != nullid:
6053 if p2 != nullid:
6054 raise util.Abort(_('uncommitted merge'))
6054 raise util.Abort(_('uncommitted merge'))
6055 bheads = repo.branchheads()
6055 bheads = repo.branchheads()
6056 if not opts.get('force') and bheads and p1 not in bheads:
6056 if not opts.get('force') and bheads and p1 not in bheads:
6057 raise util.Abort(_('not at a branch head (use -f to force)'))
6057 raise util.Abort(_('not at a branch head (use -f to force)'))
6058 r = scmutil.revsingle(repo, rev_).node()
6058 r = scmutil.revsingle(repo, rev_).node()
6059
6059
6060 if not message:
6060 if not message:
6061 # we don't translate commit messages
6061 # we don't translate commit messages
6062 message = ('Added tag %s for changeset %s' %
6062 message = ('Added tag %s for changeset %s' %
6063 (', '.join(names), short(r)))
6063 (', '.join(names), short(r)))
6064
6064
6065 date = opts.get('date')
6065 date = opts.get('date')
6066 if date:
6066 if date:
6067 date = util.parsedate(date)
6067 date = util.parsedate(date)
6068
6068
6069 if opts.get('remove'):
6069 if opts.get('remove'):
6070 editform = 'tag.remove'
6070 editform = 'tag.remove'
6071 else:
6071 else:
6072 editform = 'tag.add'
6072 editform = 'tag.add'
6073 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6073 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6074
6074
6075 # don't allow tagging the null rev
6075 # don't allow tagging the null rev
6076 if (not opts.get('remove') and
6076 if (not opts.get('remove') and
6077 scmutil.revsingle(repo, rev_).rev() == nullrev):
6077 scmutil.revsingle(repo, rev_).rev() == nullrev):
6078 raise util.Abort(_("cannot tag null revision"))
6078 raise util.Abort(_("cannot tag null revision"))
6079
6079
6080 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6080 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6081 editor=editor)
6081 editor=editor)
6082 finally:
6082 finally:
6083 release(lock, wlock)
6083 release(lock, wlock)
6084
6084
6085 @command('tags', formatteropts, '')
6085 @command('tags', formatteropts, '')
6086 def tags(ui, repo, **opts):
6086 def tags(ui, repo, **opts):
6087 """list repository tags
6087 """list repository tags
6088
6088
6089 This lists both regular and local tags. When the -v/--verbose
6089 This lists both regular and local tags. When the -v/--verbose
6090 switch is used, a third column "local" is printed for local tags.
6090 switch is used, a third column "local" is printed for local tags.
6091
6091
6092 Returns 0 on success.
6092 Returns 0 on success.
6093 """
6093 """
6094
6094
6095 fm = ui.formatter('tags', opts)
6095 fm = ui.formatter('tags', opts)
6096 hexfunc = fm.hexfunc
6096 hexfunc = fm.hexfunc
6097 tagtype = ""
6097 tagtype = ""
6098
6098
6099 for t, n in reversed(repo.tagslist()):
6099 for t, n in reversed(repo.tagslist()):
6100 hn = hexfunc(n)
6100 hn = hexfunc(n)
6101 label = 'tags.normal'
6101 label = 'tags.normal'
6102 tagtype = ''
6102 tagtype = ''
6103 if repo.tagtype(t) == 'local':
6103 if repo.tagtype(t) == 'local':
6104 label = 'tags.local'
6104 label = 'tags.local'
6105 tagtype = 'local'
6105 tagtype = 'local'
6106
6106
6107 fm.startitem()
6107 fm.startitem()
6108 fm.write('tag', '%s', t, label=label)
6108 fm.write('tag', '%s', t, label=label)
6109 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6109 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6110 fm.condwrite(not ui.quiet, 'rev node', fmt,
6110 fm.condwrite(not ui.quiet, 'rev node', fmt,
6111 repo.changelog.rev(n), hn, label=label)
6111 repo.changelog.rev(n), hn, label=label)
6112 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6112 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6113 tagtype, label=label)
6113 tagtype, label=label)
6114 fm.plain('\n')
6114 fm.plain('\n')
6115 fm.end()
6115 fm.end()
6116
6116
6117 @command('tip',
6117 @command('tip',
6118 [('p', 'patch', None, _('show patch')),
6118 [('p', 'patch', None, _('show patch')),
6119 ('g', 'git', None, _('use git extended diff format')),
6119 ('g', 'git', None, _('use git extended diff format')),
6120 ] + templateopts,
6120 ] + templateopts,
6121 _('[-p] [-g]'))
6121 _('[-p] [-g]'))
6122 def tip(ui, repo, **opts):
6122 def tip(ui, repo, **opts):
6123 """show the tip revision (DEPRECATED)
6123 """show the tip revision (DEPRECATED)
6124
6124
6125 The tip revision (usually just called the tip) is the changeset
6125 The tip revision (usually just called the tip) is the changeset
6126 most recently added to the repository (and therefore the most
6126 most recently added to the repository (and therefore the most
6127 recently changed head).
6127 recently changed head).
6128
6128
6129 If you have just made a commit, that commit will be the tip. If
6129 If you have just made a commit, that commit will be the tip. If
6130 you have just pulled changes from another repository, the tip of
6130 you have just pulled changes from another repository, the tip of
6131 that repository becomes the current tip. The "tip" tag is special
6131 that repository becomes the current tip. The "tip" tag is special
6132 and cannot be renamed or assigned to a different changeset.
6132 and cannot be renamed or assigned to a different changeset.
6133
6133
6134 This command is deprecated, please use :hg:`heads` instead.
6134 This command is deprecated, please use :hg:`heads` instead.
6135
6135
6136 Returns 0 on success.
6136 Returns 0 on success.
6137 """
6137 """
6138 displayer = cmdutil.show_changeset(ui, repo, opts)
6138 displayer = cmdutil.show_changeset(ui, repo, opts)
6139 displayer.show(repo['tip'])
6139 displayer.show(repo['tip'])
6140 displayer.close()
6140 displayer.close()
6141
6141
6142 @command('unbundle',
6142 @command('unbundle',
6143 [('u', 'update', None,
6143 [('u', 'update', None,
6144 _('update to new branch head if changesets were unbundled'))],
6144 _('update to new branch head if changesets were unbundled'))],
6145 _('[-u] FILE...'))
6145 _('[-u] FILE...'))
6146 def unbundle(ui, repo, fname1, *fnames, **opts):
6146 def unbundle(ui, repo, fname1, *fnames, **opts):
6147 """apply one or more changegroup files
6147 """apply one or more changegroup files
6148
6148
6149 Apply one or more compressed changegroup files generated by the
6149 Apply one or more compressed changegroup files generated by the
6150 bundle command.
6150 bundle command.
6151
6151
6152 Returns 0 on success, 1 if an update has unresolved files.
6152 Returns 0 on success, 1 if an update has unresolved files.
6153 """
6153 """
6154 fnames = (fname1,) + fnames
6154 fnames = (fname1,) + fnames
6155
6155
6156 lock = repo.lock()
6156 lock = repo.lock()
6157 try:
6157 try:
6158 for fname in fnames:
6158 for fname in fnames:
6159 f = hg.openpath(ui, fname)
6159 f = hg.openpath(ui, fname)
6160 gen = exchange.readbundle(ui, f, fname)
6160 gen = exchange.readbundle(ui, f, fname)
6161 if isinstance(gen, bundle2.unbundle20):
6161 if isinstance(gen, bundle2.unbundle20):
6162 tr = repo.transaction('unbundle')
6162 tr = repo.transaction('unbundle')
6163 try:
6163 try:
6164 op = bundle2.processbundle(repo, gen, lambda: tr)
6164 op = bundle2.processbundle(repo, gen, lambda: tr)
6165 tr.close()
6165 tr.close()
6166 finally:
6166 finally:
6167 if tr:
6167 if tr:
6168 tr.release()
6168 tr.release()
6169 changes = [r.get('result', 0)
6169 changes = [r.get('result', 0)
6170 for r in op.records['changegroup']]
6170 for r in op.records['changegroup']]
6171 modheads = changegroup.combineresults(changes)
6171 modheads = changegroup.combineresults(changes)
6172 else:
6172 else:
6173 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6173 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6174 'bundle:' + fname)
6174 'bundle:' + fname)
6175 finally:
6175 finally:
6176 lock.release()
6176 lock.release()
6177
6177
6178 return postincoming(ui, repo, modheads, opts.get('update'), None)
6178 return postincoming(ui, repo, modheads, opts.get('update'), None)
6179
6179
6180 @command('^update|up|checkout|co',
6180 @command('^update|up|checkout|co',
6181 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6181 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6182 ('c', 'check', None,
6182 ('c', 'check', None,
6183 _('update across branches if no uncommitted changes')),
6183 _('update across branches if no uncommitted changes')),
6184 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6184 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6185 ('r', 'rev', '', _('revision'), _('REV'))
6185 ('r', 'rev', '', _('revision'), _('REV'))
6186 ] + mergetoolopts,
6186 ] + mergetoolopts,
6187 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6187 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6188 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6188 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6189 tool=None):
6189 tool=None):
6190 """update working directory (or switch revisions)
6190 """update working directory (or switch revisions)
6191
6191
6192 Update the repository's working directory to the specified
6192 Update the repository's working directory to the specified
6193 changeset. If no changeset is specified, update to the tip of the
6193 changeset. If no changeset is specified, update to the tip of the
6194 current named branch and move the current bookmark (see :hg:`help
6194 current named branch and move the current bookmark (see :hg:`help
6195 bookmarks`).
6195 bookmarks`).
6196
6196
6197 Update sets the working directory's parent revision to the specified
6197 Update sets the working directory's parent revision to the specified
6198 changeset (see :hg:`help parents`).
6198 changeset (see :hg:`help parents`).
6199
6199
6200 If the changeset is not a descendant or ancestor of the working
6200 If the changeset is not a descendant or ancestor of the working
6201 directory's parent, the update is aborted. With the -c/--check
6201 directory's parent, the update is aborted. With the -c/--check
6202 option, the working directory is checked for uncommitted changes; if
6202 option, the working directory is checked for uncommitted changes; if
6203 none are found, the working directory is updated to the specified
6203 none are found, the working directory is updated to the specified
6204 changeset.
6204 changeset.
6205
6205
6206 .. container:: verbose
6206 .. container:: verbose
6207
6207
6208 The following rules apply when the working directory contains
6208 The following rules apply when the working directory contains
6209 uncommitted changes:
6209 uncommitted changes:
6210
6210
6211 1. If neither -c/--check nor -C/--clean is specified, and if
6211 1. If neither -c/--check nor -C/--clean is specified, and if
6212 the requested changeset is an ancestor or descendant of
6212 the requested changeset is an ancestor or descendant of
6213 the working directory's parent, the uncommitted changes
6213 the working directory's parent, the uncommitted changes
6214 are merged into the requested changeset and the merged
6214 are merged into the requested changeset and the merged
6215 result is left uncommitted. If the requested changeset is
6215 result is left uncommitted. If the requested changeset is
6216 not an ancestor or descendant (that is, it is on another
6216 not an ancestor or descendant (that is, it is on another
6217 branch), the update is aborted and the uncommitted changes
6217 branch), the update is aborted and the uncommitted changes
6218 are preserved.
6218 are preserved.
6219
6219
6220 2. With the -c/--check option, the update is aborted and the
6220 2. With the -c/--check option, the update is aborted and the
6221 uncommitted changes are preserved.
6221 uncommitted changes are preserved.
6222
6222
6223 3. With the -C/--clean option, uncommitted changes are discarded and
6223 3. With the -C/--clean option, uncommitted changes are discarded and
6224 the working directory is updated to the requested changeset.
6224 the working directory is updated to the requested changeset.
6225
6225
6226 To cancel an uncommitted merge (and lose your changes), use
6226 To cancel an uncommitted merge (and lose your changes), use
6227 :hg:`update --clean .`.
6227 :hg:`update --clean .`.
6228
6228
6229 Use null as the changeset to remove the working directory (like
6229 Use null as the changeset to remove the working directory (like
6230 :hg:`clone -U`).
6230 :hg:`clone -U`).
6231
6231
6232 If you want to revert just one file to an older revision, use
6232 If you want to revert just one file to an older revision, use
6233 :hg:`revert [-r REV] NAME`.
6233 :hg:`revert [-r REV] NAME`.
6234
6234
6235 See :hg:`help dates` for a list of formats valid for -d/--date.
6235 See :hg:`help dates` for a list of formats valid for -d/--date.
6236
6236
6237 Returns 0 on success, 1 if there are unresolved files.
6237 Returns 0 on success, 1 if there are unresolved files.
6238 """
6238 """
6239 if rev and node:
6239 if rev and node:
6240 raise util.Abort(_("please specify just one revision"))
6240 raise util.Abort(_("please specify just one revision"))
6241
6241
6242 if rev is None or rev == '':
6242 if rev is None or rev == '':
6243 rev = node
6243 rev = node
6244
6244
6245 cmdutil.clearunfinished(repo)
6245 cmdutil.clearunfinished(repo)
6246
6246
6247 # with no argument, we also move the current bookmark, if any
6247 # with no argument, we also move the current bookmark, if any
6248 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6248 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6249
6249
6250 # if we defined a bookmark, we have to remember the original bookmark name
6250 # if we defined a bookmark, we have to remember the original bookmark name
6251 brev = rev
6251 brev = rev
6252 rev = scmutil.revsingle(repo, rev, rev).rev()
6252 rev = scmutil.revsingle(repo, rev, rev).rev()
6253
6253
6254 if check and clean:
6254 if check and clean:
6255 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6255 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6256
6256
6257 if date:
6257 if date:
6258 if rev is not None:
6258 if rev is not None:
6259 raise util.Abort(_("you can't specify a revision and a date"))
6259 raise util.Abort(_("you can't specify a revision and a date"))
6260 rev = cmdutil.finddate(ui, repo, date)
6260 rev = cmdutil.finddate(ui, repo, date)
6261
6261
6262 if check:
6262 if check:
6263 c = repo[None]
6263 c = repo[None]
6264 if c.dirty(merge=False, branch=False, missing=True):
6264 if c.dirty(merge=False, branch=False, missing=True):
6265 raise util.Abort(_("uncommitted changes"))
6265 raise util.Abort(_("uncommitted changes"))
6266 if rev is None:
6266 if rev is None:
6267 rev = repo[repo[None].branch()].rev()
6267 rev = repo[repo[None].branch()].rev()
6268
6268
6269 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6269 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6270
6270
6271 if clean:
6271 if clean:
6272 ret = hg.clean(repo, rev)
6272 ret = hg.clean(repo, rev)
6273 else:
6273 else:
6274 ret = hg.update(repo, rev)
6274 ret = hg.update(repo, rev)
6275
6275
6276 if not ret and movemarkfrom:
6276 if not ret and movemarkfrom:
6277 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6277 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6278 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6278 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6279 elif brev in repo._bookmarks:
6279 elif brev in repo._bookmarks:
6280 bookmarks.setcurrent(repo, brev)
6280 bookmarks.setcurrent(repo, brev)
6281 ui.status(_("(activating bookmark %s)\n") % brev)
6281 ui.status(_("(activating bookmark %s)\n") % brev)
6282 elif brev:
6282 elif brev:
6283 if repo._bookmarkcurrent:
6283 if repo._bookmarkcurrent:
6284 ui.status(_("(leaving bookmark %s)\n") %
6284 ui.status(_("(leaving bookmark %s)\n") %
6285 repo._bookmarkcurrent)
6285 repo._bookmarkcurrent)
6286 bookmarks.unsetcurrent(repo)
6286 bookmarks.unsetcurrent(repo)
6287
6287
6288 return ret
6288 return ret
6289
6289
6290 @command('verify', [])
6290 @command('verify', [])
6291 def verify(ui, repo):
6291 def verify(ui, repo):
6292 """verify the integrity of the repository
6292 """verify the integrity of the repository
6293
6293
6294 Verify the integrity of the current repository.
6294 Verify the integrity of the current repository.
6295
6295
6296 This will perform an extensive check of the repository's
6296 This will perform an extensive check of the repository's
6297 integrity, validating the hashes and checksums of each entry in
6297 integrity, validating the hashes and checksums of each entry in
6298 the changelog, manifest, and tracked files, as well as the
6298 the changelog, manifest, and tracked files, as well as the
6299 integrity of their crosslinks and indices.
6299 integrity of their crosslinks and indices.
6300
6300
6301 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6301 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6302 for more information about recovery from corruption of the
6302 for more information about recovery from corruption of the
6303 repository.
6303 repository.
6304
6304
6305 Returns 0 on success, 1 if errors are encountered.
6305 Returns 0 on success, 1 if errors are encountered.
6306 """
6306 """
6307 return hg.verify(repo)
6307 return hg.verify(repo)
6308
6308
6309 @command('version', [], norepo=True)
6309 @command('version', [], norepo=True)
6310 def version_(ui):
6310 def version_(ui):
6311 """output version and copyright information"""
6311 """output version and copyright information"""
6312 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6312 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6313 % util.version())
6313 % util.version())
6314 ui.status(_(
6314 ui.status(_(
6315 "(see http://mercurial.selenic.com for more information)\n"
6315 "(see http://mercurial.selenic.com for more information)\n"
6316 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6316 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6317 "This is free software; see the source for copying conditions. "
6317 "This is free software; see the source for copying conditions. "
6318 "There is NO\nwarranty; "
6318 "There is NO\nwarranty; "
6319 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6319 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6320 ))
6320 ))
6321
6321
6322 ui.note(_("\nEnabled extensions:\n\n"))
6322 ui.note(_("\nEnabled extensions:\n\n"))
6323 if ui.verbose:
6323 if ui.verbose:
6324 # format names and versions into columns
6324 # format names and versions into columns
6325 names = []
6325 names = []
6326 vers = []
6326 vers = []
6327 for name, module in extensions.extensions():
6327 for name, module in extensions.extensions():
6328 names.append(name)
6328 names.append(name)
6329 vers.append(extensions.moduleversion(module))
6329 vers.append(extensions.moduleversion(module))
6330 if names:
6330 if names:
6331 maxnamelen = max(len(n) for n in names)
6331 maxnamelen = max(len(n) for n in names)
6332 for i, name in enumerate(names):
6332 for i, name in enumerate(names):
6333 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6333 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now