##// END OF EJS Templates
debugnamecomplete: use new name api...
Sean Farley -
r23763:7ad155e1 default
parent child Browse files
Show More
@@ -1,6284 +1,6287 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
24 import phases, obsolete, exchange
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, opts.get('dry_run'),
202 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
203 opts.get('subrepos'), prefix="", explicitonly=False)
203 opts.get('subrepos'), prefix="", explicitonly=False)
204 return rejected and 1 or 0
204 return rejected and 1 or 0
205
205
206 @command('addremove',
206 @command('addremove',
207 similarityopts + subrepoopts + walkopts + dryrunopts,
207 similarityopts + subrepoopts + walkopts + dryrunopts,
208 _('[OPTION]... [FILE]...'),
208 _('[OPTION]... [FILE]...'),
209 inferrepo=True)
209 inferrepo=True)
210 def addremove(ui, repo, *pats, **opts):
210 def addremove(ui, repo, *pats, **opts):
211 """add all new files, delete all missing files
211 """add all new files, delete all missing files
212
212
213 Add all new files and remove all missing files from the
213 Add all new files and remove all missing files from the
214 repository.
214 repository.
215
215
216 New files are ignored if they match any of the patterns in
216 New files are ignored if they match any of the patterns in
217 ``.hgignore``. As with add, these changes take effect at the next
217 ``.hgignore``. As with add, these changes take effect at the next
218 commit.
218 commit.
219
219
220 Use the -s/--similarity option to detect renamed files. This
220 Use the -s/--similarity option to detect renamed files. This
221 option takes a percentage between 0 (disabled) and 100 (files must
221 option takes a percentage between 0 (disabled) and 100 (files must
222 be identical) as its parameter. With a parameter greater than 0,
222 be identical) as its parameter. With a parameter greater than 0,
223 this compares every removed file with every added file and records
223 this compares every removed file with every added file and records
224 those similar enough as renames. Detecting renamed files this way
224 those similar enough as renames. Detecting renamed files this way
225 can be expensive. After using this option, :hg:`status -C` can be
225 can be expensive. After using this option, :hg:`status -C` can be
226 used to check which files were identified as moved or renamed. If
226 used to check which files were identified as moved or renamed. If
227 not specified, -s/--similarity defaults to 100 and only renames of
227 not specified, -s/--similarity defaults to 100 and only renames of
228 identical files are detected.
228 identical files are detected.
229
229
230 Returns 0 if all files are successfully added.
230 Returns 0 if all files are successfully added.
231 """
231 """
232 try:
232 try:
233 sim = float(opts.get('similarity') or 100)
233 sim = float(opts.get('similarity') or 100)
234 except ValueError:
234 except ValueError:
235 raise util.Abort(_('similarity must be a number'))
235 raise util.Abort(_('similarity must be a number'))
236 if sim < 0 or sim > 100:
236 if sim < 0 or sim > 100:
237 raise util.Abort(_('similarity must be between 0 and 100'))
237 raise util.Abort(_('similarity must be between 0 and 100'))
238 matcher = scmutil.match(repo[None], pats, opts)
238 matcher = scmutil.match(repo[None], pats, opts)
239 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
239 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
240
240
241 @command('^annotate|blame',
241 @command('^annotate|blame',
242 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
242 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
243 ('', 'follow', None,
243 ('', 'follow', None,
244 _('follow copies/renames and list the filename (DEPRECATED)')),
244 _('follow copies/renames and list the filename (DEPRECATED)')),
245 ('', 'no-follow', None, _("don't follow copies and renames")),
245 ('', 'no-follow', None, _("don't follow copies and renames")),
246 ('a', 'text', None, _('treat all files as text')),
246 ('a', 'text', None, _('treat all files as text')),
247 ('u', 'user', None, _('list the author (long with -v)')),
247 ('u', 'user', None, _('list the author (long with -v)')),
248 ('f', 'file', None, _('list the filename')),
248 ('f', 'file', None, _('list the filename')),
249 ('d', 'date', None, _('list the date (short with -q)')),
249 ('d', 'date', None, _('list the date (short with -q)')),
250 ('n', 'number', None, _('list the revision number (default)')),
250 ('n', 'number', None, _('list the revision number (default)')),
251 ('c', 'changeset', None, _('list the changeset')),
251 ('c', 'changeset', None, _('list the changeset')),
252 ('l', 'line-number', None, _('show line number at the first appearance'))
252 ('l', 'line-number', None, _('show line number at the first appearance'))
253 ] + diffwsopts + walkopts + formatteropts,
253 ] + diffwsopts + walkopts + formatteropts,
254 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
254 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
255 inferrepo=True)
255 inferrepo=True)
256 def annotate(ui, repo, *pats, **opts):
256 def annotate(ui, repo, *pats, **opts):
257 """show changeset information by line for each file
257 """show changeset information by line for each file
258
258
259 List changes in files, showing the revision id responsible for
259 List changes in files, showing the revision id responsible for
260 each line
260 each line
261
261
262 This command is useful for discovering when a change was made and
262 This command is useful for discovering when a change was made and
263 by whom.
263 by whom.
264
264
265 Without the -a/--text option, annotate will avoid processing files
265 Without the -a/--text option, annotate will avoid processing files
266 it detects as binary. With -a, annotate will annotate the file
266 it detects as binary. With -a, annotate will annotate the file
267 anyway, although the results will probably be neither useful
267 anyway, although the results will probably be neither useful
268 nor desirable.
268 nor desirable.
269
269
270 Returns 0 on success.
270 Returns 0 on success.
271 """
271 """
272 if not pats:
272 if not pats:
273 raise util.Abort(_('at least one filename or pattern is required'))
273 raise util.Abort(_('at least one filename or pattern is required'))
274
274
275 if opts.get('follow'):
275 if opts.get('follow'):
276 # --follow is deprecated and now just an alias for -f/--file
276 # --follow is deprecated and now just an alias for -f/--file
277 # to mimic the behavior of Mercurial before version 1.5
277 # to mimic the behavior of Mercurial before version 1.5
278 opts['file'] = True
278 opts['file'] = True
279
279
280 fm = ui.formatter('annotate', opts)
280 fm = ui.formatter('annotate', opts)
281 datefunc = ui.quiet and util.shortdate or util.datestr
281 datefunc = ui.quiet and util.shortdate or util.datestr
282 hexfn = fm.hexfunc
282 hexfn = fm.hexfunc
283
283
284 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
284 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
285 ('number', ' ', lambda x: x[0].rev(), str),
285 ('number', ' ', lambda x: x[0].rev(), str),
286 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
286 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
287 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
287 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
288 ('file', ' ', lambda x: x[0].path(), str),
288 ('file', ' ', lambda x: x[0].path(), str),
289 ('line_number', ':', lambda x: x[1], str),
289 ('line_number', ':', lambda x: x[1], str),
290 ]
290 ]
291 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
291 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
292
292
293 if (not opts.get('user') and not opts.get('changeset')
293 if (not opts.get('user') and not opts.get('changeset')
294 and not opts.get('date') and not opts.get('file')):
294 and not opts.get('date') and not opts.get('file')):
295 opts['number'] = True
295 opts['number'] = True
296
296
297 linenumber = opts.get('line_number') is not None
297 linenumber = opts.get('line_number') is not None
298 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
298 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
299 raise util.Abort(_('at least one of -n/-c is required for -l'))
299 raise util.Abort(_('at least one of -n/-c is required for -l'))
300
300
301 if fm:
301 if fm:
302 def makefunc(get, fmt):
302 def makefunc(get, fmt):
303 return get
303 return get
304 else:
304 else:
305 def makefunc(get, fmt):
305 def makefunc(get, fmt):
306 return lambda x: fmt(get(x))
306 return lambda x: fmt(get(x))
307 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
307 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
308 if opts.get(op)]
308 if opts.get(op)]
309 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
309 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
310 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
310 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
311 if opts.get(op))
311 if opts.get(op))
312
312
313 def bad(x, y):
313 def bad(x, y):
314 raise util.Abort("%s: %s" % (x, y))
314 raise util.Abort("%s: %s" % (x, y))
315
315
316 ctx = scmutil.revsingle(repo, opts.get('rev'))
316 ctx = scmutil.revsingle(repo, opts.get('rev'))
317 m = scmutil.match(ctx, pats, opts)
317 m = scmutil.match(ctx, pats, opts)
318 m.bad = bad
318 m.bad = bad
319 follow = not opts.get('no_follow')
319 follow = not opts.get('no_follow')
320 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
320 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
321 whitespace=True)
321 whitespace=True)
322 for abs in ctx.walk(m):
322 for abs in ctx.walk(m):
323 fctx = ctx[abs]
323 fctx = ctx[abs]
324 if not opts.get('text') and util.binary(fctx.data()):
324 if not opts.get('text') and util.binary(fctx.data()):
325 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
325 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
326 continue
326 continue
327
327
328 lines = fctx.annotate(follow=follow, linenumber=linenumber,
328 lines = fctx.annotate(follow=follow, linenumber=linenumber,
329 diffopts=diffopts)
329 diffopts=diffopts)
330 formats = []
330 formats = []
331 pieces = []
331 pieces = []
332
332
333 for f, sep in funcmap:
333 for f, sep in funcmap:
334 l = [f(n) for n, dummy in lines]
334 l = [f(n) for n, dummy in lines]
335 if l:
335 if l:
336 if fm:
336 if fm:
337 formats.append(['%s' for x in l])
337 formats.append(['%s' for x in l])
338 else:
338 else:
339 sizes = [encoding.colwidth(x) for x in l]
339 sizes = [encoding.colwidth(x) for x in l]
340 ml = max(sizes)
340 ml = max(sizes)
341 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
341 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
342 pieces.append(l)
342 pieces.append(l)
343
343
344 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
344 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
345 fm.startitem()
345 fm.startitem()
346 fm.write(fields, "".join(f), *p)
346 fm.write(fields, "".join(f), *p)
347 fm.write('line', ": %s", l[1])
347 fm.write('line', ": %s", l[1])
348
348
349 if lines and not lines[-1][1].endswith('\n'):
349 if lines and not lines[-1][1].endswith('\n'):
350 fm.plain('\n')
350 fm.plain('\n')
351
351
352 fm.end()
352 fm.end()
353
353
354 @command('archive',
354 @command('archive',
355 [('', 'no-decode', None, _('do not pass files through decoders')),
355 [('', 'no-decode', None, _('do not pass files through decoders')),
356 ('p', 'prefix', '', _('directory prefix for files in archive'),
356 ('p', 'prefix', '', _('directory prefix for files in archive'),
357 _('PREFIX')),
357 _('PREFIX')),
358 ('r', 'rev', '', _('revision to distribute'), _('REV')),
358 ('r', 'rev', '', _('revision to distribute'), _('REV')),
359 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
359 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
360 ] + subrepoopts + walkopts,
360 ] + subrepoopts + walkopts,
361 _('[OPTION]... DEST'))
361 _('[OPTION]... DEST'))
362 def archive(ui, repo, dest, **opts):
362 def archive(ui, repo, dest, **opts):
363 '''create an unversioned archive of a repository revision
363 '''create an unversioned archive of a repository revision
364
364
365 By default, the revision used is the parent of the working
365 By default, the revision used is the parent of the working
366 directory; use -r/--rev to specify a different revision.
366 directory; use -r/--rev to specify a different revision.
367
367
368 The archive type is automatically detected based on file
368 The archive type is automatically detected based on file
369 extension (or override using -t/--type).
369 extension (or override using -t/--type).
370
370
371 .. container:: verbose
371 .. container:: verbose
372
372
373 Examples:
373 Examples:
374
374
375 - create a zip file containing the 1.0 release::
375 - create a zip file containing the 1.0 release::
376
376
377 hg archive -r 1.0 project-1.0.zip
377 hg archive -r 1.0 project-1.0.zip
378
378
379 - create a tarball excluding .hg files::
379 - create a tarball excluding .hg files::
380
380
381 hg archive project.tar.gz -X ".hg*"
381 hg archive project.tar.gz -X ".hg*"
382
382
383 Valid types are:
383 Valid types are:
384
384
385 :``files``: a directory full of files (default)
385 :``files``: a directory full of files (default)
386 :``tar``: tar archive, uncompressed
386 :``tar``: tar archive, uncompressed
387 :``tbz2``: tar archive, compressed using bzip2
387 :``tbz2``: tar archive, compressed using bzip2
388 :``tgz``: tar archive, compressed using gzip
388 :``tgz``: tar archive, compressed using gzip
389 :``uzip``: zip archive, uncompressed
389 :``uzip``: zip archive, uncompressed
390 :``zip``: zip archive, compressed using deflate
390 :``zip``: zip archive, compressed using deflate
391
391
392 The exact name of the destination archive or directory is given
392 The exact name of the destination archive or directory is given
393 using a format string; see :hg:`help export` for details.
393 using a format string; see :hg:`help export` for details.
394
394
395 Each member added to an archive file has a directory prefix
395 Each member added to an archive file has a directory prefix
396 prepended. Use -p/--prefix to specify a format string for the
396 prepended. Use -p/--prefix to specify a format string for the
397 prefix. The default is the basename of the archive, with suffixes
397 prefix. The default is the basename of the archive, with suffixes
398 removed.
398 removed.
399
399
400 Returns 0 on success.
400 Returns 0 on success.
401 '''
401 '''
402
402
403 ctx = scmutil.revsingle(repo, opts.get('rev'))
403 ctx = scmutil.revsingle(repo, opts.get('rev'))
404 if not ctx:
404 if not ctx:
405 raise util.Abort(_('no working directory: please specify a revision'))
405 raise util.Abort(_('no working directory: please specify a revision'))
406 node = ctx.node()
406 node = ctx.node()
407 dest = cmdutil.makefilename(repo, dest, node)
407 dest = cmdutil.makefilename(repo, dest, node)
408 if os.path.realpath(dest) == repo.root:
408 if os.path.realpath(dest) == repo.root:
409 raise util.Abort(_('repository root cannot be destination'))
409 raise util.Abort(_('repository root cannot be destination'))
410
410
411 kind = opts.get('type') or archival.guesskind(dest) or 'files'
411 kind = opts.get('type') or archival.guesskind(dest) or 'files'
412 prefix = opts.get('prefix')
412 prefix = opts.get('prefix')
413
413
414 if dest == '-':
414 if dest == '-':
415 if kind == 'files':
415 if kind == 'files':
416 raise util.Abort(_('cannot archive plain files to stdout'))
416 raise util.Abort(_('cannot archive plain files to stdout'))
417 dest = cmdutil.makefileobj(repo, dest)
417 dest = cmdutil.makefileobj(repo, dest)
418 if not prefix:
418 if not prefix:
419 prefix = os.path.basename(repo.root) + '-%h'
419 prefix = os.path.basename(repo.root) + '-%h'
420
420
421 prefix = cmdutil.makefilename(repo, prefix, node)
421 prefix = cmdutil.makefilename(repo, prefix, node)
422 matchfn = scmutil.match(ctx, [], opts)
422 matchfn = scmutil.match(ctx, [], opts)
423 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
423 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
424 matchfn, prefix, subrepos=opts.get('subrepos'))
424 matchfn, prefix, subrepos=opts.get('subrepos'))
425
425
426 @command('backout',
426 @command('backout',
427 [('', 'merge', None, _('merge with old dirstate parent after backout')),
427 [('', 'merge', None, _('merge with old dirstate parent after backout')),
428 ('', 'commit', None, _('commit if no conflicts were encountered')),
428 ('', 'commit', None, _('commit if no conflicts were encountered')),
429 ('', 'parent', '',
429 ('', 'parent', '',
430 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
430 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
431 ('r', 'rev', '', _('revision to backout'), _('REV')),
431 ('r', 'rev', '', _('revision to backout'), _('REV')),
432 ('e', 'edit', False, _('invoke editor on commit messages')),
432 ('e', 'edit', False, _('invoke editor on commit messages')),
433 ] + mergetoolopts + walkopts + commitopts + commitopts2,
433 ] + mergetoolopts + walkopts + commitopts + commitopts2,
434 _('[OPTION]... [-r] REV'))
434 _('[OPTION]... [-r] REV'))
435 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
435 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
436 '''reverse effect of earlier changeset
436 '''reverse effect of earlier changeset
437
437
438 Prepare a new changeset with the effect of REV undone in the
438 Prepare a new changeset with the effect of REV undone in the
439 current working directory.
439 current working directory.
440
440
441 If REV is the parent of the working directory, then this new changeset
441 If REV is the parent of the working directory, then this new changeset
442 is committed automatically. Otherwise, hg needs to merge the
442 is committed automatically. Otherwise, hg needs to merge the
443 changes and the merged result is left uncommitted.
443 changes and the merged result is left uncommitted.
444
444
445 .. note::
445 .. note::
446
446
447 backout cannot be used to fix either an unwanted or
447 backout cannot be used to fix either an unwanted or
448 incorrect merge.
448 incorrect merge.
449
449
450 .. container:: verbose
450 .. container:: verbose
451
451
452 By default, the pending changeset will have one parent,
452 By default, the pending changeset will have one parent,
453 maintaining a linear history. With --merge, the pending
453 maintaining a linear history. With --merge, the pending
454 changeset will instead have two parents: the old parent of the
454 changeset will instead have two parents: the old parent of the
455 working directory and a new child of REV that simply undoes REV.
455 working directory and a new child of REV that simply undoes REV.
456
456
457 Before version 1.7, the behavior without --merge was equivalent
457 Before version 1.7, the behavior without --merge was equivalent
458 to specifying --merge followed by :hg:`update --clean .` to
458 to specifying --merge followed by :hg:`update --clean .` to
459 cancel the merge and leave the child of REV as a head to be
459 cancel the merge and leave the child of REV as a head to be
460 merged separately.
460 merged separately.
461
461
462 See :hg:`help dates` for a list of formats valid for -d/--date.
462 See :hg:`help dates` for a list of formats valid for -d/--date.
463
463
464 Returns 0 on success, 1 if nothing to backout or there are unresolved
464 Returns 0 on success, 1 if nothing to backout or there are unresolved
465 files.
465 files.
466 '''
466 '''
467 if rev and node:
467 if rev and node:
468 raise util.Abort(_("please specify just one revision"))
468 raise util.Abort(_("please specify just one revision"))
469
469
470 if not rev:
470 if not rev:
471 rev = node
471 rev = node
472
472
473 if not rev:
473 if not rev:
474 raise util.Abort(_("please specify a revision to backout"))
474 raise util.Abort(_("please specify a revision to backout"))
475
475
476 date = opts.get('date')
476 date = opts.get('date')
477 if date:
477 if date:
478 opts['date'] = util.parsedate(date)
478 opts['date'] = util.parsedate(date)
479
479
480 cmdutil.checkunfinished(repo)
480 cmdutil.checkunfinished(repo)
481 cmdutil.bailifchanged(repo)
481 cmdutil.bailifchanged(repo)
482 node = scmutil.revsingle(repo, rev).node()
482 node = scmutil.revsingle(repo, rev).node()
483
483
484 op1, op2 = repo.dirstate.parents()
484 op1, op2 = repo.dirstate.parents()
485 if not repo.changelog.isancestor(node, op1):
485 if not repo.changelog.isancestor(node, op1):
486 raise util.Abort(_('cannot backout change that is not an ancestor'))
486 raise util.Abort(_('cannot backout change that is not an ancestor'))
487
487
488 p1, p2 = repo.changelog.parents(node)
488 p1, p2 = repo.changelog.parents(node)
489 if p1 == nullid:
489 if p1 == nullid:
490 raise util.Abort(_('cannot backout a change with no parents'))
490 raise util.Abort(_('cannot backout a change with no parents'))
491 if p2 != nullid:
491 if p2 != nullid:
492 if not opts.get('parent'):
492 if not opts.get('parent'):
493 raise util.Abort(_('cannot backout a merge changeset'))
493 raise util.Abort(_('cannot backout a merge changeset'))
494 p = repo.lookup(opts['parent'])
494 p = repo.lookup(opts['parent'])
495 if p not in (p1, p2):
495 if p not in (p1, p2):
496 raise util.Abort(_('%s is not a parent of %s') %
496 raise util.Abort(_('%s is not a parent of %s') %
497 (short(p), short(node)))
497 (short(p), short(node)))
498 parent = p
498 parent = p
499 else:
499 else:
500 if opts.get('parent'):
500 if opts.get('parent'):
501 raise util.Abort(_('cannot use --parent on non-merge changeset'))
501 raise util.Abort(_('cannot use --parent on non-merge changeset'))
502 parent = p1
502 parent = p1
503
503
504 # the backout should appear on the same branch
504 # the backout should appear on the same branch
505 wlock = repo.wlock()
505 wlock = repo.wlock()
506 try:
506 try:
507 branch = repo.dirstate.branch()
507 branch = repo.dirstate.branch()
508 bheads = repo.branchheads(branch)
508 bheads = repo.branchheads(branch)
509 rctx = scmutil.revsingle(repo, hex(parent))
509 rctx = scmutil.revsingle(repo, hex(parent))
510 if not opts.get('merge') and op1 != node:
510 if not opts.get('merge') and op1 != node:
511 try:
511 try:
512 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
512 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
513 'backout')
513 'backout')
514 repo.dirstate.beginparentchange()
514 repo.dirstate.beginparentchange()
515 stats = mergemod.update(repo, parent, True, True, False,
515 stats = mergemod.update(repo, parent, True, True, False,
516 node, False)
516 node, False)
517 repo.setparents(op1, op2)
517 repo.setparents(op1, op2)
518 repo.dirstate.endparentchange()
518 repo.dirstate.endparentchange()
519 hg._showstats(repo, stats)
519 hg._showstats(repo, stats)
520 if stats[3]:
520 if stats[3]:
521 repo.ui.status(_("use 'hg resolve' to retry unresolved "
521 repo.ui.status(_("use 'hg resolve' to retry unresolved "
522 "file merges\n"))
522 "file merges\n"))
523 return 1
523 return 1
524 elif not commit:
524 elif not commit:
525 msg = _("changeset %s backed out, "
525 msg = _("changeset %s backed out, "
526 "don't forget to commit.\n")
526 "don't forget to commit.\n")
527 ui.status(msg % short(node))
527 ui.status(msg % short(node))
528 return 0
528 return 0
529 finally:
529 finally:
530 ui.setconfig('ui', 'forcemerge', '', '')
530 ui.setconfig('ui', 'forcemerge', '', '')
531 else:
531 else:
532 hg.clean(repo, node, show_stats=False)
532 hg.clean(repo, node, show_stats=False)
533 repo.dirstate.setbranch(branch)
533 repo.dirstate.setbranch(branch)
534 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
534 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
535
535
536
536
537 def commitfunc(ui, repo, message, match, opts):
537 def commitfunc(ui, repo, message, match, opts):
538 editform = 'backout'
538 editform = 'backout'
539 e = cmdutil.getcommiteditor(editform=editform, **opts)
539 e = cmdutil.getcommiteditor(editform=editform, **opts)
540 if not message:
540 if not message:
541 # we don't translate commit messages
541 # we don't translate commit messages
542 message = "Backed out changeset %s" % short(node)
542 message = "Backed out changeset %s" % short(node)
543 e = cmdutil.getcommiteditor(edit=True, editform=editform)
543 e = cmdutil.getcommiteditor(edit=True, editform=editform)
544 return repo.commit(message, opts.get('user'), opts.get('date'),
544 return repo.commit(message, opts.get('user'), opts.get('date'),
545 match, editor=e)
545 match, editor=e)
546 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
546 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
547 if not newnode:
547 if not newnode:
548 ui.status(_("nothing changed\n"))
548 ui.status(_("nothing changed\n"))
549 return 1
549 return 1
550 cmdutil.commitstatus(repo, newnode, branch, bheads)
550 cmdutil.commitstatus(repo, newnode, branch, bheads)
551
551
552 def nice(node):
552 def nice(node):
553 return '%d:%s' % (repo.changelog.rev(node), short(node))
553 return '%d:%s' % (repo.changelog.rev(node), short(node))
554 ui.status(_('changeset %s backs out changeset %s\n') %
554 ui.status(_('changeset %s backs out changeset %s\n') %
555 (nice(repo.changelog.tip()), nice(node)))
555 (nice(repo.changelog.tip()), nice(node)))
556 if opts.get('merge') and op1 != node:
556 if opts.get('merge') and op1 != node:
557 hg.clean(repo, op1, show_stats=False)
557 hg.clean(repo, op1, show_stats=False)
558 ui.status(_('merging with changeset %s\n')
558 ui.status(_('merging with changeset %s\n')
559 % nice(repo.changelog.tip()))
559 % nice(repo.changelog.tip()))
560 try:
560 try:
561 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
561 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
562 'backout')
562 'backout')
563 return hg.merge(repo, hex(repo.changelog.tip()))
563 return hg.merge(repo, hex(repo.changelog.tip()))
564 finally:
564 finally:
565 ui.setconfig('ui', 'forcemerge', '', '')
565 ui.setconfig('ui', 'forcemerge', '', '')
566 finally:
566 finally:
567 wlock.release()
567 wlock.release()
568 return 0
568 return 0
569
569
570 @command('bisect',
570 @command('bisect',
571 [('r', 'reset', False, _('reset bisect state')),
571 [('r', 'reset', False, _('reset bisect state')),
572 ('g', 'good', False, _('mark changeset good')),
572 ('g', 'good', False, _('mark changeset good')),
573 ('b', 'bad', False, _('mark changeset bad')),
573 ('b', 'bad', False, _('mark changeset bad')),
574 ('s', 'skip', False, _('skip testing changeset')),
574 ('s', 'skip', False, _('skip testing changeset')),
575 ('e', 'extend', False, _('extend the bisect range')),
575 ('e', 'extend', False, _('extend the bisect range')),
576 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
576 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
577 ('U', 'noupdate', False, _('do not update to target'))],
577 ('U', 'noupdate', False, _('do not update to target'))],
578 _("[-gbsr] [-U] [-c CMD] [REV]"))
578 _("[-gbsr] [-U] [-c CMD] [REV]"))
579 def bisect(ui, repo, rev=None, extra=None, command=None,
579 def bisect(ui, repo, rev=None, extra=None, command=None,
580 reset=None, good=None, bad=None, skip=None, extend=None,
580 reset=None, good=None, bad=None, skip=None, extend=None,
581 noupdate=None):
581 noupdate=None):
582 """subdivision search of changesets
582 """subdivision search of changesets
583
583
584 This command helps to find changesets which introduce problems. To
584 This command helps to find changesets which introduce problems. To
585 use, mark the earliest changeset you know exhibits the problem as
585 use, mark the earliest changeset you know exhibits the problem as
586 bad, then mark the latest changeset which is free from the problem
586 bad, then mark the latest changeset which is free from the problem
587 as good. Bisect will update your working directory to a revision
587 as good. Bisect will update your working directory to a revision
588 for testing (unless the -U/--noupdate option is specified). Once
588 for testing (unless the -U/--noupdate option is specified). Once
589 you have performed tests, mark the working directory as good or
589 you have performed tests, mark the working directory as good or
590 bad, and bisect will either update to another candidate changeset
590 bad, and bisect will either update to another candidate changeset
591 or announce that it has found the bad revision.
591 or announce that it has found the bad revision.
592
592
593 As a shortcut, you can also use the revision argument to mark a
593 As a shortcut, you can also use the revision argument to mark a
594 revision as good or bad without checking it out first.
594 revision as good or bad without checking it out first.
595
595
596 If you supply a command, it will be used for automatic bisection.
596 If you supply a command, it will be used for automatic bisection.
597 The environment variable HG_NODE will contain the ID of the
597 The environment variable HG_NODE will contain the ID of the
598 changeset being tested. The exit status of the command will be
598 changeset being tested. The exit status of the command will be
599 used to mark revisions as good or bad: status 0 means good, 125
599 used to mark revisions as good or bad: status 0 means good, 125
600 means to skip the revision, 127 (command not found) will abort the
600 means to skip the revision, 127 (command not found) will abort the
601 bisection, and any other non-zero exit status means the revision
601 bisection, and any other non-zero exit status means the revision
602 is bad.
602 is bad.
603
603
604 .. container:: verbose
604 .. container:: verbose
605
605
606 Some examples:
606 Some examples:
607
607
608 - start a bisection with known bad revision 34, and good revision 12::
608 - start a bisection with known bad revision 34, and good revision 12::
609
609
610 hg bisect --bad 34
610 hg bisect --bad 34
611 hg bisect --good 12
611 hg bisect --good 12
612
612
613 - advance the current bisection by marking current revision as good or
613 - advance the current bisection by marking current revision as good or
614 bad::
614 bad::
615
615
616 hg bisect --good
616 hg bisect --good
617 hg bisect --bad
617 hg bisect --bad
618
618
619 - mark the current revision, or a known revision, to be skipped (e.g. if
619 - mark the current revision, or a known revision, to be skipped (e.g. if
620 that revision is not usable because of another issue)::
620 that revision is not usable because of another issue)::
621
621
622 hg bisect --skip
622 hg bisect --skip
623 hg bisect --skip 23
623 hg bisect --skip 23
624
624
625 - skip all revisions that do not touch directories ``foo`` or ``bar``::
625 - skip all revisions that do not touch directories ``foo`` or ``bar``::
626
626
627 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
627 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
628
628
629 - forget the current bisection::
629 - forget the current bisection::
630
630
631 hg bisect --reset
631 hg bisect --reset
632
632
633 - use 'make && make tests' to automatically find the first broken
633 - use 'make && make tests' to automatically find the first broken
634 revision::
634 revision::
635
635
636 hg bisect --reset
636 hg bisect --reset
637 hg bisect --bad 34
637 hg bisect --bad 34
638 hg bisect --good 12
638 hg bisect --good 12
639 hg bisect --command "make && make tests"
639 hg bisect --command "make && make tests"
640
640
641 - see all changesets whose states are already known in the current
641 - see all changesets whose states are already known in the current
642 bisection::
642 bisection::
643
643
644 hg log -r "bisect(pruned)"
644 hg log -r "bisect(pruned)"
645
645
646 - see the changeset currently being bisected (especially useful
646 - see the changeset currently being bisected (especially useful
647 if running with -U/--noupdate)::
647 if running with -U/--noupdate)::
648
648
649 hg log -r "bisect(current)"
649 hg log -r "bisect(current)"
650
650
651 - see all changesets that took part in the current bisection::
651 - see all changesets that took part in the current bisection::
652
652
653 hg log -r "bisect(range)"
653 hg log -r "bisect(range)"
654
654
655 - you can even get a nice graph::
655 - you can even get a nice graph::
656
656
657 hg log --graph -r "bisect(range)"
657 hg log --graph -r "bisect(range)"
658
658
659 See :hg:`help revsets` for more about the `bisect()` keyword.
659 See :hg:`help revsets` for more about the `bisect()` keyword.
660
660
661 Returns 0 on success.
661 Returns 0 on success.
662 """
662 """
663 def extendbisectrange(nodes, good):
663 def extendbisectrange(nodes, good):
664 # bisect is incomplete when it ends on a merge node and
664 # bisect is incomplete when it ends on a merge node and
665 # one of the parent was not checked.
665 # one of the parent was not checked.
666 parents = repo[nodes[0]].parents()
666 parents = repo[nodes[0]].parents()
667 if len(parents) > 1:
667 if len(parents) > 1:
668 side = good and state['bad'] or state['good']
668 side = good and state['bad'] or state['good']
669 num = len(set(i.node() for i in parents) & set(side))
669 num = len(set(i.node() for i in parents) & set(side))
670 if num == 1:
670 if num == 1:
671 return parents[0].ancestor(parents[1])
671 return parents[0].ancestor(parents[1])
672 return None
672 return None
673
673
674 def print_result(nodes, good):
674 def print_result(nodes, good):
675 displayer = cmdutil.show_changeset(ui, repo, {})
675 displayer = cmdutil.show_changeset(ui, repo, {})
676 if len(nodes) == 1:
676 if len(nodes) == 1:
677 # narrowed it down to a single revision
677 # narrowed it down to a single revision
678 if good:
678 if good:
679 ui.write(_("The first good revision is:\n"))
679 ui.write(_("The first good revision is:\n"))
680 else:
680 else:
681 ui.write(_("The first bad revision is:\n"))
681 ui.write(_("The first bad revision is:\n"))
682 displayer.show(repo[nodes[0]])
682 displayer.show(repo[nodes[0]])
683 extendnode = extendbisectrange(nodes, good)
683 extendnode = extendbisectrange(nodes, good)
684 if extendnode is not None:
684 if extendnode is not None:
685 ui.write(_('Not all ancestors of this changeset have been'
685 ui.write(_('Not all ancestors of this changeset have been'
686 ' checked.\nUse bisect --extend to continue the '
686 ' checked.\nUse bisect --extend to continue the '
687 'bisection from\nthe common ancestor, %s.\n')
687 'bisection from\nthe common ancestor, %s.\n')
688 % extendnode)
688 % extendnode)
689 else:
689 else:
690 # multiple possible revisions
690 # multiple possible revisions
691 if good:
691 if good:
692 ui.write(_("Due to skipped revisions, the first "
692 ui.write(_("Due to skipped revisions, the first "
693 "good revision could be any of:\n"))
693 "good revision could be any of:\n"))
694 else:
694 else:
695 ui.write(_("Due to skipped revisions, the first "
695 ui.write(_("Due to skipped revisions, the first "
696 "bad revision could be any of:\n"))
696 "bad revision could be any of:\n"))
697 for n in nodes:
697 for n in nodes:
698 displayer.show(repo[n])
698 displayer.show(repo[n])
699 displayer.close()
699 displayer.close()
700
700
701 def check_state(state, interactive=True):
701 def check_state(state, interactive=True):
702 if not state['good'] or not state['bad']:
702 if not state['good'] or not state['bad']:
703 if (good or bad or skip or reset) and interactive:
703 if (good or bad or skip or reset) and interactive:
704 return
704 return
705 if not state['good']:
705 if not state['good']:
706 raise util.Abort(_('cannot bisect (no known good revisions)'))
706 raise util.Abort(_('cannot bisect (no known good revisions)'))
707 else:
707 else:
708 raise util.Abort(_('cannot bisect (no known bad revisions)'))
708 raise util.Abort(_('cannot bisect (no known bad revisions)'))
709 return True
709 return True
710
710
711 # backward compatibility
711 # backward compatibility
712 if rev in "good bad reset init".split():
712 if rev in "good bad reset init".split():
713 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
713 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
714 cmd, rev, extra = rev, extra, None
714 cmd, rev, extra = rev, extra, None
715 if cmd == "good":
715 if cmd == "good":
716 good = True
716 good = True
717 elif cmd == "bad":
717 elif cmd == "bad":
718 bad = True
718 bad = True
719 else:
719 else:
720 reset = True
720 reset = True
721 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
721 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
722 raise util.Abort(_('incompatible arguments'))
722 raise util.Abort(_('incompatible arguments'))
723
723
724 cmdutil.checkunfinished(repo)
724 cmdutil.checkunfinished(repo)
725
725
726 if reset:
726 if reset:
727 p = repo.join("bisect.state")
727 p = repo.join("bisect.state")
728 if os.path.exists(p):
728 if os.path.exists(p):
729 os.unlink(p)
729 os.unlink(p)
730 return
730 return
731
731
732 state = hbisect.load_state(repo)
732 state = hbisect.load_state(repo)
733
733
734 if command:
734 if command:
735 changesets = 1
735 changesets = 1
736 if noupdate:
736 if noupdate:
737 try:
737 try:
738 node = state['current'][0]
738 node = state['current'][0]
739 except LookupError:
739 except LookupError:
740 raise util.Abort(_('current bisect revision is unknown - '
740 raise util.Abort(_('current bisect revision is unknown - '
741 'start a new bisect to fix'))
741 'start a new bisect to fix'))
742 else:
742 else:
743 node, p2 = repo.dirstate.parents()
743 node, p2 = repo.dirstate.parents()
744 if p2 != nullid:
744 if p2 != nullid:
745 raise util.Abort(_('current bisect revision is a merge'))
745 raise util.Abort(_('current bisect revision is a merge'))
746 try:
746 try:
747 while changesets:
747 while changesets:
748 # update state
748 # update state
749 state['current'] = [node]
749 state['current'] = [node]
750 hbisect.save_state(repo, state)
750 hbisect.save_state(repo, state)
751 status = ui.system(command, environ={'HG_NODE': hex(node)})
751 status = ui.system(command, environ={'HG_NODE': hex(node)})
752 if status == 125:
752 if status == 125:
753 transition = "skip"
753 transition = "skip"
754 elif status == 0:
754 elif status == 0:
755 transition = "good"
755 transition = "good"
756 # status < 0 means process was killed
756 # status < 0 means process was killed
757 elif status == 127:
757 elif status == 127:
758 raise util.Abort(_("failed to execute %s") % command)
758 raise util.Abort(_("failed to execute %s") % command)
759 elif status < 0:
759 elif status < 0:
760 raise util.Abort(_("%s killed") % command)
760 raise util.Abort(_("%s killed") % command)
761 else:
761 else:
762 transition = "bad"
762 transition = "bad"
763 ctx = scmutil.revsingle(repo, rev, node)
763 ctx = scmutil.revsingle(repo, rev, node)
764 rev = None # clear for future iterations
764 rev = None # clear for future iterations
765 state[transition].append(ctx.node())
765 state[transition].append(ctx.node())
766 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
766 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
767 check_state(state, interactive=False)
767 check_state(state, interactive=False)
768 # bisect
768 # bisect
769 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
769 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
770 # update to next check
770 # update to next check
771 node = nodes[0]
771 node = nodes[0]
772 if not noupdate:
772 if not noupdate:
773 cmdutil.bailifchanged(repo)
773 cmdutil.bailifchanged(repo)
774 hg.clean(repo, node, show_stats=False)
774 hg.clean(repo, node, show_stats=False)
775 finally:
775 finally:
776 state['current'] = [node]
776 state['current'] = [node]
777 hbisect.save_state(repo, state)
777 hbisect.save_state(repo, state)
778 print_result(nodes, bgood)
778 print_result(nodes, bgood)
779 return
779 return
780
780
781 # update state
781 # update state
782
782
783 if rev:
783 if rev:
784 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
784 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
785 else:
785 else:
786 nodes = [repo.lookup('.')]
786 nodes = [repo.lookup('.')]
787
787
788 if good or bad or skip:
788 if good or bad or skip:
789 if good:
789 if good:
790 state['good'] += nodes
790 state['good'] += nodes
791 elif bad:
791 elif bad:
792 state['bad'] += nodes
792 state['bad'] += nodes
793 elif skip:
793 elif skip:
794 state['skip'] += nodes
794 state['skip'] += nodes
795 hbisect.save_state(repo, state)
795 hbisect.save_state(repo, state)
796
796
797 if not check_state(state):
797 if not check_state(state):
798 return
798 return
799
799
800 # actually bisect
800 # actually bisect
801 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
801 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
802 if extend:
802 if extend:
803 if not changesets:
803 if not changesets:
804 extendnode = extendbisectrange(nodes, good)
804 extendnode = extendbisectrange(nodes, good)
805 if extendnode is not None:
805 if extendnode is not None:
806 ui.write(_("Extending search to changeset %d:%s\n")
806 ui.write(_("Extending search to changeset %d:%s\n")
807 % (extendnode.rev(), extendnode))
807 % (extendnode.rev(), extendnode))
808 state['current'] = [extendnode.node()]
808 state['current'] = [extendnode.node()]
809 hbisect.save_state(repo, state)
809 hbisect.save_state(repo, state)
810 if noupdate:
810 if noupdate:
811 return
811 return
812 cmdutil.bailifchanged(repo)
812 cmdutil.bailifchanged(repo)
813 return hg.clean(repo, extendnode.node())
813 return hg.clean(repo, extendnode.node())
814 raise util.Abort(_("nothing to extend"))
814 raise util.Abort(_("nothing to extend"))
815
815
816 if changesets == 0:
816 if changesets == 0:
817 print_result(nodes, good)
817 print_result(nodes, good)
818 else:
818 else:
819 assert len(nodes) == 1 # only a single node can be tested next
819 assert len(nodes) == 1 # only a single node can be tested next
820 node = nodes[0]
820 node = nodes[0]
821 # compute the approximate number of remaining tests
821 # compute the approximate number of remaining tests
822 tests, size = 0, 2
822 tests, size = 0, 2
823 while size <= changesets:
823 while size <= changesets:
824 tests, size = tests + 1, size * 2
824 tests, size = tests + 1, size * 2
825 rev = repo.changelog.rev(node)
825 rev = repo.changelog.rev(node)
826 ui.write(_("Testing changeset %d:%s "
826 ui.write(_("Testing changeset %d:%s "
827 "(%d changesets remaining, ~%d tests)\n")
827 "(%d changesets remaining, ~%d tests)\n")
828 % (rev, short(node), changesets, tests))
828 % (rev, short(node), changesets, tests))
829 state['current'] = [node]
829 state['current'] = [node]
830 hbisect.save_state(repo, state)
830 hbisect.save_state(repo, state)
831 if not noupdate:
831 if not noupdate:
832 cmdutil.bailifchanged(repo)
832 cmdutil.bailifchanged(repo)
833 return hg.clean(repo, node)
833 return hg.clean(repo, node)
834
834
835 @command('bookmarks|bookmark',
835 @command('bookmarks|bookmark',
836 [('f', 'force', False, _('force')),
836 [('f', 'force', False, _('force')),
837 ('r', 'rev', '', _('revision'), _('REV')),
837 ('r', 'rev', '', _('revision'), _('REV')),
838 ('d', 'delete', False, _('delete a given bookmark')),
838 ('d', 'delete', False, _('delete a given bookmark')),
839 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
839 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
840 ('i', 'inactive', False, _('mark a bookmark inactive')),
840 ('i', 'inactive', False, _('mark a bookmark inactive')),
841 ] + formatteropts,
841 ] + formatteropts,
842 _('hg bookmarks [OPTIONS]... [NAME]...'))
842 _('hg bookmarks [OPTIONS]... [NAME]...'))
843 def bookmark(ui, repo, *names, **opts):
843 def bookmark(ui, repo, *names, **opts):
844 '''create a new bookmark or list existing bookmarks
844 '''create a new bookmark or list existing bookmarks
845
845
846 Bookmarks are labels on changesets to help track lines of development.
846 Bookmarks are labels on changesets to help track lines of development.
847 Bookmarks are unversioned and can be moved, renamed and deleted.
847 Bookmarks are unversioned and can be moved, renamed and deleted.
848 Deleting or moving a bookmark has no effect on the associated changesets.
848 Deleting or moving a bookmark has no effect on the associated changesets.
849
849
850 Creating or updating to a bookmark causes it to be marked as 'active'.
850 Creating or updating to a bookmark causes it to be marked as 'active'.
851 The active bookmark is indicated with a '*'.
851 The active bookmark is indicated with a '*'.
852 When a commit is made, the active bookmark will advance to the new commit.
852 When a commit is made, the active bookmark will advance to the new commit.
853 A plain :hg:`update` will also advance an active bookmark, if possible.
853 A plain :hg:`update` will also advance an active bookmark, if possible.
854 Updating away from a bookmark will cause it to be deactivated.
854 Updating away from a bookmark will cause it to be deactivated.
855
855
856 Bookmarks can be pushed and pulled between repositories (see
856 Bookmarks can be pushed and pulled between repositories (see
857 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
857 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
858 diverged, a new 'divergent bookmark' of the form 'name@path' will
858 diverged, a new 'divergent bookmark' of the form 'name@path' will
859 be created. Using :hg:`merge` will resolve the divergence.
859 be created. Using :hg:`merge` will resolve the divergence.
860
860
861 A bookmark named '@' has the special property that :hg:`clone` will
861 A bookmark named '@' has the special property that :hg:`clone` will
862 check it out by default if it exists.
862 check it out by default if it exists.
863
863
864 .. container:: verbose
864 .. container:: verbose
865
865
866 Examples:
866 Examples:
867
867
868 - create an active bookmark for a new line of development::
868 - create an active bookmark for a new line of development::
869
869
870 hg book new-feature
870 hg book new-feature
871
871
872 - create an inactive bookmark as a place marker::
872 - create an inactive bookmark as a place marker::
873
873
874 hg book -i reviewed
874 hg book -i reviewed
875
875
876 - create an inactive bookmark on another changeset::
876 - create an inactive bookmark on another changeset::
877
877
878 hg book -r .^ tested
878 hg book -r .^ tested
879
879
880 - move the '@' bookmark from another branch::
880 - move the '@' bookmark from another branch::
881
881
882 hg book -f @
882 hg book -f @
883 '''
883 '''
884 force = opts.get('force')
884 force = opts.get('force')
885 rev = opts.get('rev')
885 rev = opts.get('rev')
886 delete = opts.get('delete')
886 delete = opts.get('delete')
887 rename = opts.get('rename')
887 rename = opts.get('rename')
888 inactive = opts.get('inactive')
888 inactive = opts.get('inactive')
889
889
890 def checkformat(mark):
890 def checkformat(mark):
891 mark = mark.strip()
891 mark = mark.strip()
892 if not mark:
892 if not mark:
893 raise util.Abort(_("bookmark names cannot consist entirely of "
893 raise util.Abort(_("bookmark names cannot consist entirely of "
894 "whitespace"))
894 "whitespace"))
895 scmutil.checknewlabel(repo, mark, 'bookmark')
895 scmutil.checknewlabel(repo, mark, 'bookmark')
896 return mark
896 return mark
897
897
898 def checkconflict(repo, mark, cur, force=False, target=None):
898 def checkconflict(repo, mark, cur, force=False, target=None):
899 if mark in marks and not force:
899 if mark in marks and not force:
900 if target:
900 if target:
901 if marks[mark] == target and target == cur:
901 if marks[mark] == target and target == cur:
902 # re-activating a bookmark
902 # re-activating a bookmark
903 return
903 return
904 anc = repo.changelog.ancestors([repo[target].rev()])
904 anc = repo.changelog.ancestors([repo[target].rev()])
905 bmctx = repo[marks[mark]]
905 bmctx = repo[marks[mark]]
906 divs = [repo[b].node() for b in marks
906 divs = [repo[b].node() for b in marks
907 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
907 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
908
908
909 # allow resolving a single divergent bookmark even if moving
909 # allow resolving a single divergent bookmark even if moving
910 # the bookmark across branches when a revision is specified
910 # the bookmark across branches when a revision is specified
911 # that contains a divergent bookmark
911 # that contains a divergent bookmark
912 if bmctx.rev() not in anc and target in divs:
912 if bmctx.rev() not in anc and target in divs:
913 bookmarks.deletedivergent(repo, [target], mark)
913 bookmarks.deletedivergent(repo, [target], mark)
914 return
914 return
915
915
916 deletefrom = [b for b in divs
916 deletefrom = [b for b in divs
917 if repo[b].rev() in anc or b == target]
917 if repo[b].rev() in anc or b == target]
918 bookmarks.deletedivergent(repo, deletefrom, mark)
918 bookmarks.deletedivergent(repo, deletefrom, mark)
919 if bookmarks.validdest(repo, bmctx, repo[target]):
919 if bookmarks.validdest(repo, bmctx, repo[target]):
920 ui.status(_("moving bookmark '%s' forward from %s\n") %
920 ui.status(_("moving bookmark '%s' forward from %s\n") %
921 (mark, short(bmctx.node())))
921 (mark, short(bmctx.node())))
922 return
922 return
923 raise util.Abort(_("bookmark '%s' already exists "
923 raise util.Abort(_("bookmark '%s' already exists "
924 "(use -f to force)") % mark)
924 "(use -f to force)") % mark)
925 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
925 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
926 and not force):
926 and not force):
927 raise util.Abort(
927 raise util.Abort(
928 _("a bookmark cannot have the name of an existing branch"))
928 _("a bookmark cannot have the name of an existing branch"))
929
929
930 if delete and rename:
930 if delete and rename:
931 raise util.Abort(_("--delete and --rename are incompatible"))
931 raise util.Abort(_("--delete and --rename are incompatible"))
932 if delete and rev:
932 if delete and rev:
933 raise util.Abort(_("--rev is incompatible with --delete"))
933 raise util.Abort(_("--rev is incompatible with --delete"))
934 if rename and rev:
934 if rename and rev:
935 raise util.Abort(_("--rev is incompatible with --rename"))
935 raise util.Abort(_("--rev is incompatible with --rename"))
936 if not names and (delete or rev):
936 if not names and (delete or rev):
937 raise util.Abort(_("bookmark name required"))
937 raise util.Abort(_("bookmark name required"))
938
938
939 if delete or rename or names or inactive:
939 if delete or rename or names or inactive:
940 wlock = repo.wlock()
940 wlock = repo.wlock()
941 try:
941 try:
942 cur = repo.changectx('.').node()
942 cur = repo.changectx('.').node()
943 marks = repo._bookmarks
943 marks = repo._bookmarks
944 if delete:
944 if delete:
945 for mark in names:
945 for mark in names:
946 if mark not in marks:
946 if mark not in marks:
947 raise util.Abort(_("bookmark '%s' does not exist") %
947 raise util.Abort(_("bookmark '%s' does not exist") %
948 mark)
948 mark)
949 if mark == repo._bookmarkcurrent:
949 if mark == repo._bookmarkcurrent:
950 bookmarks.unsetcurrent(repo)
950 bookmarks.unsetcurrent(repo)
951 del marks[mark]
951 del marks[mark]
952 marks.write()
952 marks.write()
953
953
954 elif rename:
954 elif rename:
955 if not names:
955 if not names:
956 raise util.Abort(_("new bookmark name required"))
956 raise util.Abort(_("new bookmark name required"))
957 elif len(names) > 1:
957 elif len(names) > 1:
958 raise util.Abort(_("only one new bookmark name allowed"))
958 raise util.Abort(_("only one new bookmark name allowed"))
959 mark = checkformat(names[0])
959 mark = checkformat(names[0])
960 if rename not in marks:
960 if rename not in marks:
961 raise util.Abort(_("bookmark '%s' does not exist") % rename)
961 raise util.Abort(_("bookmark '%s' does not exist") % rename)
962 checkconflict(repo, mark, cur, force)
962 checkconflict(repo, mark, cur, force)
963 marks[mark] = marks[rename]
963 marks[mark] = marks[rename]
964 if repo._bookmarkcurrent == rename and not inactive:
964 if repo._bookmarkcurrent == rename and not inactive:
965 bookmarks.setcurrent(repo, mark)
965 bookmarks.setcurrent(repo, mark)
966 del marks[rename]
966 del marks[rename]
967 marks.write()
967 marks.write()
968
968
969 elif names:
969 elif names:
970 newact = None
970 newact = None
971 for mark in names:
971 for mark in names:
972 mark = checkformat(mark)
972 mark = checkformat(mark)
973 if newact is None:
973 if newact is None:
974 newact = mark
974 newact = mark
975 if inactive and mark == repo._bookmarkcurrent:
975 if inactive and mark == repo._bookmarkcurrent:
976 bookmarks.unsetcurrent(repo)
976 bookmarks.unsetcurrent(repo)
977 return
977 return
978 tgt = cur
978 tgt = cur
979 if rev:
979 if rev:
980 tgt = scmutil.revsingle(repo, rev).node()
980 tgt = scmutil.revsingle(repo, rev).node()
981 checkconflict(repo, mark, cur, force, tgt)
981 checkconflict(repo, mark, cur, force, tgt)
982 marks[mark] = tgt
982 marks[mark] = tgt
983 if not inactive and cur == marks[newact] and not rev:
983 if not inactive and cur == marks[newact] and not rev:
984 bookmarks.setcurrent(repo, newact)
984 bookmarks.setcurrent(repo, newact)
985 elif cur != tgt and newact == repo._bookmarkcurrent:
985 elif cur != tgt and newact == repo._bookmarkcurrent:
986 bookmarks.unsetcurrent(repo)
986 bookmarks.unsetcurrent(repo)
987 marks.write()
987 marks.write()
988
988
989 elif inactive:
989 elif inactive:
990 if len(marks) == 0:
990 if len(marks) == 0:
991 ui.status(_("no bookmarks set\n"))
991 ui.status(_("no bookmarks set\n"))
992 elif not repo._bookmarkcurrent:
992 elif not repo._bookmarkcurrent:
993 ui.status(_("no active bookmark\n"))
993 ui.status(_("no active bookmark\n"))
994 else:
994 else:
995 bookmarks.unsetcurrent(repo)
995 bookmarks.unsetcurrent(repo)
996 finally:
996 finally:
997 wlock.release()
997 wlock.release()
998 else: # show bookmarks
998 else: # show bookmarks
999 fm = ui.formatter('bookmarks', opts)
999 fm = ui.formatter('bookmarks', opts)
1000 hexfn = fm.hexfunc
1000 hexfn = fm.hexfunc
1001 marks = repo._bookmarks
1001 marks = repo._bookmarks
1002 if len(marks) == 0 and not fm:
1002 if len(marks) == 0 and not fm:
1003 ui.status(_("no bookmarks set\n"))
1003 ui.status(_("no bookmarks set\n"))
1004 for bmark, n in sorted(marks.iteritems()):
1004 for bmark, n in sorted(marks.iteritems()):
1005 current = repo._bookmarkcurrent
1005 current = repo._bookmarkcurrent
1006 if bmark == current:
1006 if bmark == current:
1007 prefix, label = '*', 'bookmarks.current'
1007 prefix, label = '*', 'bookmarks.current'
1008 else:
1008 else:
1009 prefix, label = ' ', ''
1009 prefix, label = ' ', ''
1010
1010
1011 fm.startitem()
1011 fm.startitem()
1012 if not ui.quiet:
1012 if not ui.quiet:
1013 fm.plain(' %s ' % prefix, label=label)
1013 fm.plain(' %s ' % prefix, label=label)
1014 fm.write('bookmark', '%s', bmark, label=label)
1014 fm.write('bookmark', '%s', bmark, label=label)
1015 pad = " " * (25 - encoding.colwidth(bmark))
1015 pad = " " * (25 - encoding.colwidth(bmark))
1016 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1016 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1017 repo.changelog.rev(n), hexfn(n), label=label)
1017 repo.changelog.rev(n), hexfn(n), label=label)
1018 fm.data(active=(bmark == current))
1018 fm.data(active=(bmark == current))
1019 fm.plain('\n')
1019 fm.plain('\n')
1020 fm.end()
1020 fm.end()
1021
1021
1022 @command('branch',
1022 @command('branch',
1023 [('f', 'force', None,
1023 [('f', 'force', None,
1024 _('set branch name even if it shadows an existing branch')),
1024 _('set branch name even if it shadows an existing branch')),
1025 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1025 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1026 _('[-fC] [NAME]'))
1026 _('[-fC] [NAME]'))
1027 def branch(ui, repo, label=None, **opts):
1027 def branch(ui, repo, label=None, **opts):
1028 """set or show the current branch name
1028 """set or show the current branch name
1029
1029
1030 .. note::
1030 .. note::
1031
1031
1032 Branch names are permanent and global. Use :hg:`bookmark` to create a
1032 Branch names are permanent and global. Use :hg:`bookmark` to create a
1033 light-weight bookmark instead. See :hg:`help glossary` for more
1033 light-weight bookmark instead. See :hg:`help glossary` for more
1034 information about named branches and bookmarks.
1034 information about named branches and bookmarks.
1035
1035
1036 With no argument, show the current branch name. With one argument,
1036 With no argument, show the current branch name. With one argument,
1037 set the working directory branch name (the branch will not exist
1037 set the working directory branch name (the branch will not exist
1038 in the repository until the next commit). Standard practice
1038 in the repository until the next commit). Standard practice
1039 recommends that primary development take place on the 'default'
1039 recommends that primary development take place on the 'default'
1040 branch.
1040 branch.
1041
1041
1042 Unless -f/--force is specified, branch will not let you set a
1042 Unless -f/--force is specified, branch will not let you set a
1043 branch name that already exists.
1043 branch name that already exists.
1044
1044
1045 Use -C/--clean to reset the working directory branch to that of
1045 Use -C/--clean to reset the working directory branch to that of
1046 the parent of the working directory, negating a previous branch
1046 the parent of the working directory, negating a previous branch
1047 change.
1047 change.
1048
1048
1049 Use the command :hg:`update` to switch to an existing branch. Use
1049 Use the command :hg:`update` to switch to an existing branch. Use
1050 :hg:`commit --close-branch` to mark this branch as closed.
1050 :hg:`commit --close-branch` to mark this branch as closed.
1051
1051
1052 Returns 0 on success.
1052 Returns 0 on success.
1053 """
1053 """
1054 if label:
1054 if label:
1055 label = label.strip()
1055 label = label.strip()
1056
1056
1057 if not opts.get('clean') and not label:
1057 if not opts.get('clean') and not label:
1058 ui.write("%s\n" % repo.dirstate.branch())
1058 ui.write("%s\n" % repo.dirstate.branch())
1059 return
1059 return
1060
1060
1061 wlock = repo.wlock()
1061 wlock = repo.wlock()
1062 try:
1062 try:
1063 if opts.get('clean'):
1063 if opts.get('clean'):
1064 label = repo[None].p1().branch()
1064 label = repo[None].p1().branch()
1065 repo.dirstate.setbranch(label)
1065 repo.dirstate.setbranch(label)
1066 ui.status(_('reset working directory to branch %s\n') % label)
1066 ui.status(_('reset working directory to branch %s\n') % label)
1067 elif label:
1067 elif label:
1068 if not opts.get('force') and label in repo.branchmap():
1068 if not opts.get('force') and label in repo.branchmap():
1069 if label not in [p.branch() for p in repo.parents()]:
1069 if label not in [p.branch() for p in repo.parents()]:
1070 raise util.Abort(_('a branch of the same name already'
1070 raise util.Abort(_('a branch of the same name already'
1071 ' exists'),
1071 ' exists'),
1072 # i18n: "it" refers to an existing branch
1072 # i18n: "it" refers to an existing branch
1073 hint=_("use 'hg update' to switch to it"))
1073 hint=_("use 'hg update' to switch to it"))
1074 scmutil.checknewlabel(repo, label, 'branch')
1074 scmutil.checknewlabel(repo, label, 'branch')
1075 repo.dirstate.setbranch(label)
1075 repo.dirstate.setbranch(label)
1076 ui.status(_('marked working directory as branch %s\n') % label)
1076 ui.status(_('marked working directory as branch %s\n') % label)
1077 ui.status(_('(branches are permanent and global, '
1077 ui.status(_('(branches are permanent and global, '
1078 'did you want a bookmark?)\n'))
1078 'did you want a bookmark?)\n'))
1079 finally:
1079 finally:
1080 wlock.release()
1080 wlock.release()
1081
1081
1082 @command('branches',
1082 @command('branches',
1083 [('a', 'active', False,
1083 [('a', 'active', False,
1084 _('show only branches that have unmerged heads (DEPRECATED)')),
1084 _('show only branches that have unmerged heads (DEPRECATED)')),
1085 ('c', 'closed', False, _('show normal and closed branches')),
1085 ('c', 'closed', False, _('show normal and closed branches')),
1086 ] + formatteropts,
1086 ] + formatteropts,
1087 _('[-ac]'))
1087 _('[-ac]'))
1088 def branches(ui, repo, active=False, closed=False, **opts):
1088 def branches(ui, repo, active=False, closed=False, **opts):
1089 """list repository named branches
1089 """list repository named branches
1090
1090
1091 List the repository's named branches, indicating which ones are
1091 List the repository's named branches, indicating which ones are
1092 inactive. If -c/--closed is specified, also list branches which have
1092 inactive. If -c/--closed is specified, also list branches which have
1093 been marked closed (see :hg:`commit --close-branch`).
1093 been marked closed (see :hg:`commit --close-branch`).
1094
1094
1095 Use the command :hg:`update` to switch to an existing branch.
1095 Use the command :hg:`update` to switch to an existing branch.
1096
1096
1097 Returns 0.
1097 Returns 0.
1098 """
1098 """
1099
1099
1100 fm = ui.formatter('branches', opts)
1100 fm = ui.formatter('branches', opts)
1101 hexfunc = fm.hexfunc
1101 hexfunc = fm.hexfunc
1102
1102
1103 allheads = set(repo.heads())
1103 allheads = set(repo.heads())
1104 branches = []
1104 branches = []
1105 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1105 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1106 isactive = not isclosed and bool(set(heads) & allheads)
1106 isactive = not isclosed and bool(set(heads) & allheads)
1107 branches.append((tag, repo[tip], isactive, not isclosed))
1107 branches.append((tag, repo[tip], isactive, not isclosed))
1108 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1108 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1109 reverse=True)
1109 reverse=True)
1110
1110
1111 for tag, ctx, isactive, isopen in branches:
1111 for tag, ctx, isactive, isopen in branches:
1112 if active and not isactive:
1112 if active and not isactive:
1113 continue
1113 continue
1114 if isactive:
1114 if isactive:
1115 label = 'branches.active'
1115 label = 'branches.active'
1116 notice = ''
1116 notice = ''
1117 elif not isopen:
1117 elif not isopen:
1118 if not closed:
1118 if not closed:
1119 continue
1119 continue
1120 label = 'branches.closed'
1120 label = 'branches.closed'
1121 notice = _(' (closed)')
1121 notice = _(' (closed)')
1122 else:
1122 else:
1123 label = 'branches.inactive'
1123 label = 'branches.inactive'
1124 notice = _(' (inactive)')
1124 notice = _(' (inactive)')
1125 current = (tag == repo.dirstate.branch())
1125 current = (tag == repo.dirstate.branch())
1126 if current:
1126 if current:
1127 label = 'branches.current'
1127 label = 'branches.current'
1128
1128
1129 fm.startitem()
1129 fm.startitem()
1130 fm.write('branch', '%s', tag, label=label)
1130 fm.write('branch', '%s', tag, label=label)
1131 rev = ctx.rev()
1131 rev = ctx.rev()
1132 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1132 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1133 fmt = ' ' * padsize + ' %d:%s'
1133 fmt = ' ' * padsize + ' %d:%s'
1134 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1134 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1135 label='log.changeset changeset.%s' % ctx.phasestr())
1135 label='log.changeset changeset.%s' % ctx.phasestr())
1136 fm.data(active=isactive, closed=not isopen, current=current)
1136 fm.data(active=isactive, closed=not isopen, current=current)
1137 if not ui.quiet:
1137 if not ui.quiet:
1138 fm.plain(notice)
1138 fm.plain(notice)
1139 fm.plain('\n')
1139 fm.plain('\n')
1140 fm.end()
1140 fm.end()
1141
1141
1142 @command('bundle',
1142 @command('bundle',
1143 [('f', 'force', None, _('run even when the destination is unrelated')),
1143 [('f', 'force', None, _('run even when the destination is unrelated')),
1144 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1144 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1145 _('REV')),
1145 _('REV')),
1146 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1146 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1147 _('BRANCH')),
1147 _('BRANCH')),
1148 ('', 'base', [],
1148 ('', 'base', [],
1149 _('a base changeset assumed to be available at the destination'),
1149 _('a base changeset assumed to be available at the destination'),
1150 _('REV')),
1150 _('REV')),
1151 ('a', 'all', None, _('bundle all changesets in the repository')),
1151 ('a', 'all', None, _('bundle all changesets in the repository')),
1152 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1152 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1153 ] + remoteopts,
1153 ] + remoteopts,
1154 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1154 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1155 def bundle(ui, repo, fname, dest=None, **opts):
1155 def bundle(ui, repo, fname, dest=None, **opts):
1156 """create a changegroup file
1156 """create a changegroup file
1157
1157
1158 Generate a compressed changegroup file collecting changesets not
1158 Generate a compressed changegroup file collecting changesets not
1159 known to be in another repository.
1159 known to be in another repository.
1160
1160
1161 If you omit the destination repository, then hg assumes the
1161 If you omit the destination repository, then hg assumes the
1162 destination will have all the nodes you specify with --base
1162 destination will have all the nodes you specify with --base
1163 parameters. To create a bundle containing all changesets, use
1163 parameters. To create a bundle containing all changesets, use
1164 -a/--all (or --base null).
1164 -a/--all (or --base null).
1165
1165
1166 You can change compression method with the -t/--type option.
1166 You can change compression method with the -t/--type option.
1167 The available compression methods are: none, bzip2, and
1167 The available compression methods are: none, bzip2, and
1168 gzip (by default, bundles are compressed using bzip2).
1168 gzip (by default, bundles are compressed using bzip2).
1169
1169
1170 The bundle file can then be transferred using conventional means
1170 The bundle file can then be transferred using conventional means
1171 and applied to another repository with the unbundle or pull
1171 and applied to another repository with the unbundle or pull
1172 command. This is useful when direct push and pull are not
1172 command. This is useful when direct push and pull are not
1173 available or when exporting an entire repository is undesirable.
1173 available or when exporting an entire repository is undesirable.
1174
1174
1175 Applying bundles preserves all changeset contents including
1175 Applying bundles preserves all changeset contents including
1176 permissions, copy/rename information, and revision history.
1176 permissions, copy/rename information, and revision history.
1177
1177
1178 Returns 0 on success, 1 if no changes found.
1178 Returns 0 on success, 1 if no changes found.
1179 """
1179 """
1180 revs = None
1180 revs = None
1181 if 'rev' in opts:
1181 if 'rev' in opts:
1182 revs = scmutil.revrange(repo, opts['rev'])
1182 revs = scmutil.revrange(repo, opts['rev'])
1183
1183
1184 bundletype = opts.get('type', 'bzip2').lower()
1184 bundletype = opts.get('type', 'bzip2').lower()
1185 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1185 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1186 bundletype = btypes.get(bundletype)
1186 bundletype = btypes.get(bundletype)
1187 if bundletype not in changegroup.bundletypes:
1187 if bundletype not in changegroup.bundletypes:
1188 raise util.Abort(_('unknown bundle type specified with --type'))
1188 raise util.Abort(_('unknown bundle type specified with --type'))
1189
1189
1190 if opts.get('all'):
1190 if opts.get('all'):
1191 base = ['null']
1191 base = ['null']
1192 else:
1192 else:
1193 base = scmutil.revrange(repo, opts.get('base'))
1193 base = scmutil.revrange(repo, opts.get('base'))
1194 # TODO: get desired bundlecaps from command line.
1194 # TODO: get desired bundlecaps from command line.
1195 bundlecaps = None
1195 bundlecaps = None
1196 if base:
1196 if base:
1197 if dest:
1197 if dest:
1198 raise util.Abort(_("--base is incompatible with specifying "
1198 raise util.Abort(_("--base is incompatible with specifying "
1199 "a destination"))
1199 "a destination"))
1200 common = [repo.lookup(rev) for rev in base]
1200 common = [repo.lookup(rev) for rev in base]
1201 heads = revs and map(repo.lookup, revs) or revs
1201 heads = revs and map(repo.lookup, revs) or revs
1202 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1202 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1203 common=common, bundlecaps=bundlecaps)
1203 common=common, bundlecaps=bundlecaps)
1204 outgoing = None
1204 outgoing = None
1205 else:
1205 else:
1206 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1206 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1207 dest, branches = hg.parseurl(dest, opts.get('branch'))
1207 dest, branches = hg.parseurl(dest, opts.get('branch'))
1208 other = hg.peer(repo, opts, dest)
1208 other = hg.peer(repo, opts, dest)
1209 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1209 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1210 heads = revs and map(repo.lookup, revs) or revs
1210 heads = revs and map(repo.lookup, revs) or revs
1211 outgoing = discovery.findcommonoutgoing(repo, other,
1211 outgoing = discovery.findcommonoutgoing(repo, other,
1212 onlyheads=heads,
1212 onlyheads=heads,
1213 force=opts.get('force'),
1213 force=opts.get('force'),
1214 portable=True)
1214 portable=True)
1215 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1215 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1216 bundlecaps)
1216 bundlecaps)
1217 if not cg:
1217 if not cg:
1218 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1218 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1219 return 1
1219 return 1
1220
1220
1221 changegroup.writebundle(cg, fname, bundletype)
1221 changegroup.writebundle(cg, fname, bundletype)
1222
1222
1223 @command('cat',
1223 @command('cat',
1224 [('o', 'output', '',
1224 [('o', 'output', '',
1225 _('print output to file with formatted name'), _('FORMAT')),
1225 _('print output to file with formatted name'), _('FORMAT')),
1226 ('r', 'rev', '', _('print the given revision'), _('REV')),
1226 ('r', 'rev', '', _('print the given revision'), _('REV')),
1227 ('', 'decode', None, _('apply any matching decode filter')),
1227 ('', 'decode', None, _('apply any matching decode filter')),
1228 ] + walkopts,
1228 ] + walkopts,
1229 _('[OPTION]... FILE...'),
1229 _('[OPTION]... FILE...'),
1230 inferrepo=True)
1230 inferrepo=True)
1231 def cat(ui, repo, file1, *pats, **opts):
1231 def cat(ui, repo, file1, *pats, **opts):
1232 """output the current or given revision of files
1232 """output the current or given revision of files
1233
1233
1234 Print the specified files as they were at the given revision. If
1234 Print the specified files as they were at the given revision. If
1235 no revision is given, the parent of the working directory is used.
1235 no revision is given, the parent of the working directory is used.
1236
1236
1237 Output may be to a file, in which case the name of the file is
1237 Output may be to a file, in which case the name of the file is
1238 given using a format string. The formatting rules as follows:
1238 given using a format string. The formatting rules as follows:
1239
1239
1240 :``%%``: literal "%" character
1240 :``%%``: literal "%" character
1241 :``%s``: basename of file being printed
1241 :``%s``: basename of file being printed
1242 :``%d``: dirname of file being printed, or '.' if in repository root
1242 :``%d``: dirname of file being printed, or '.' if in repository root
1243 :``%p``: root-relative path name of file being printed
1243 :``%p``: root-relative path name of file being printed
1244 :``%H``: changeset hash (40 hexadecimal digits)
1244 :``%H``: changeset hash (40 hexadecimal digits)
1245 :``%R``: changeset revision number
1245 :``%R``: changeset revision number
1246 :``%h``: short-form changeset hash (12 hexadecimal digits)
1246 :``%h``: short-form changeset hash (12 hexadecimal digits)
1247 :``%r``: zero-padded changeset revision number
1247 :``%r``: zero-padded changeset revision number
1248 :``%b``: basename of the exporting repository
1248 :``%b``: basename of the exporting repository
1249
1249
1250 Returns 0 on success.
1250 Returns 0 on success.
1251 """
1251 """
1252 ctx = scmutil.revsingle(repo, opts.get('rev'))
1252 ctx = scmutil.revsingle(repo, opts.get('rev'))
1253 m = scmutil.match(ctx, (file1,) + pats, opts)
1253 m = scmutil.match(ctx, (file1,) + pats, opts)
1254
1254
1255 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1255 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1256
1256
1257 @command('^clone',
1257 @command('^clone',
1258 [('U', 'noupdate', None,
1258 [('U', 'noupdate', None,
1259 _('the clone will include an empty working copy (only a repository)')),
1259 _('the clone will include an empty working copy (only a repository)')),
1260 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1260 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1261 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1261 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1262 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1262 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1263 ('', 'pull', None, _('use pull protocol to copy metadata')),
1263 ('', 'pull', None, _('use pull protocol to copy metadata')),
1264 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1264 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1265 ] + remoteopts,
1265 ] + remoteopts,
1266 _('[OPTION]... SOURCE [DEST]'),
1266 _('[OPTION]... SOURCE [DEST]'),
1267 norepo=True)
1267 norepo=True)
1268 def clone(ui, source, dest=None, **opts):
1268 def clone(ui, source, dest=None, **opts):
1269 """make a copy of an existing repository
1269 """make a copy of an existing repository
1270
1270
1271 Create a copy of an existing repository in a new directory.
1271 Create a copy of an existing repository in a new directory.
1272
1272
1273 If no destination directory name is specified, it defaults to the
1273 If no destination directory name is specified, it defaults to the
1274 basename of the source.
1274 basename of the source.
1275
1275
1276 The location of the source is added to the new repository's
1276 The location of the source is added to the new repository's
1277 ``.hg/hgrc`` file, as the default to be used for future pulls.
1277 ``.hg/hgrc`` file, as the default to be used for future pulls.
1278
1278
1279 Only local paths and ``ssh://`` URLs are supported as
1279 Only local paths and ``ssh://`` URLs are supported as
1280 destinations. For ``ssh://`` destinations, no working directory or
1280 destinations. For ``ssh://`` destinations, no working directory or
1281 ``.hg/hgrc`` will be created on the remote side.
1281 ``.hg/hgrc`` will be created on the remote side.
1282
1282
1283 To pull only a subset of changesets, specify one or more revisions
1283 To pull only a subset of changesets, specify one or more revisions
1284 identifiers with -r/--rev or branches with -b/--branch. The
1284 identifiers with -r/--rev or branches with -b/--branch. The
1285 resulting clone will contain only the specified changesets and
1285 resulting clone will contain only the specified changesets and
1286 their ancestors. These options (or 'clone src#rev dest') imply
1286 their ancestors. These options (or 'clone src#rev dest') imply
1287 --pull, even for local source repositories. Note that specifying a
1287 --pull, even for local source repositories. Note that specifying a
1288 tag will include the tagged changeset but not the changeset
1288 tag will include the tagged changeset but not the changeset
1289 containing the tag.
1289 containing the tag.
1290
1290
1291 If the source repository has a bookmark called '@' set, that
1291 If the source repository has a bookmark called '@' set, that
1292 revision will be checked out in the new repository by default.
1292 revision will be checked out in the new repository by default.
1293
1293
1294 To check out a particular version, use -u/--update, or
1294 To check out a particular version, use -u/--update, or
1295 -U/--noupdate to create a clone with no working directory.
1295 -U/--noupdate to create a clone with no working directory.
1296
1296
1297 .. container:: verbose
1297 .. container:: verbose
1298
1298
1299 For efficiency, hardlinks are used for cloning whenever the
1299 For efficiency, hardlinks are used for cloning whenever the
1300 source and destination are on the same filesystem (note this
1300 source and destination are on the same filesystem (note this
1301 applies only to the repository data, not to the working
1301 applies only to the repository data, not to the working
1302 directory). Some filesystems, such as AFS, implement hardlinking
1302 directory). Some filesystems, such as AFS, implement hardlinking
1303 incorrectly, but do not report errors. In these cases, use the
1303 incorrectly, but do not report errors. In these cases, use the
1304 --pull option to avoid hardlinking.
1304 --pull option to avoid hardlinking.
1305
1305
1306 In some cases, you can clone repositories and the working
1306 In some cases, you can clone repositories and the working
1307 directory using full hardlinks with ::
1307 directory using full hardlinks with ::
1308
1308
1309 $ cp -al REPO REPOCLONE
1309 $ cp -al REPO REPOCLONE
1310
1310
1311 This is the fastest way to clone, but it is not always safe. The
1311 This is the fastest way to clone, but it is not always safe. The
1312 operation is not atomic (making sure REPO is not modified during
1312 operation is not atomic (making sure REPO is not modified during
1313 the operation is up to you) and you have to make sure your
1313 the operation is up to you) and you have to make sure your
1314 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1314 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1315 so). Also, this is not compatible with certain extensions that
1315 so). Also, this is not compatible with certain extensions that
1316 place their metadata under the .hg directory, such as mq.
1316 place their metadata under the .hg directory, such as mq.
1317
1317
1318 Mercurial will update the working directory to the first applicable
1318 Mercurial will update the working directory to the first applicable
1319 revision from this list:
1319 revision from this list:
1320
1320
1321 a) null if -U or the source repository has no changesets
1321 a) null if -U or the source repository has no changesets
1322 b) if -u . and the source repository is local, the first parent of
1322 b) if -u . and the source repository is local, the first parent of
1323 the source repository's working directory
1323 the source repository's working directory
1324 c) the changeset specified with -u (if a branch name, this means the
1324 c) the changeset specified with -u (if a branch name, this means the
1325 latest head of that branch)
1325 latest head of that branch)
1326 d) the changeset specified with -r
1326 d) the changeset specified with -r
1327 e) the tipmost head specified with -b
1327 e) the tipmost head specified with -b
1328 f) the tipmost head specified with the url#branch source syntax
1328 f) the tipmost head specified with the url#branch source syntax
1329 g) the revision marked with the '@' bookmark, if present
1329 g) the revision marked with the '@' bookmark, if present
1330 h) the tipmost head of the default branch
1330 h) the tipmost head of the default branch
1331 i) tip
1331 i) tip
1332
1332
1333 Examples:
1333 Examples:
1334
1334
1335 - clone a remote repository to a new directory named hg/::
1335 - clone a remote repository to a new directory named hg/::
1336
1336
1337 hg clone http://selenic.com/hg
1337 hg clone http://selenic.com/hg
1338
1338
1339 - create a lightweight local clone::
1339 - create a lightweight local clone::
1340
1340
1341 hg clone project/ project-feature/
1341 hg clone project/ project-feature/
1342
1342
1343 - clone from an absolute path on an ssh server (note double-slash)::
1343 - clone from an absolute path on an ssh server (note double-slash)::
1344
1344
1345 hg clone ssh://user@server//home/projects/alpha/
1345 hg clone ssh://user@server//home/projects/alpha/
1346
1346
1347 - do a high-speed clone over a LAN while checking out a
1347 - do a high-speed clone over a LAN while checking out a
1348 specified version::
1348 specified version::
1349
1349
1350 hg clone --uncompressed http://server/repo -u 1.5
1350 hg clone --uncompressed http://server/repo -u 1.5
1351
1351
1352 - create a repository without changesets after a particular revision::
1352 - create a repository without changesets after a particular revision::
1353
1353
1354 hg clone -r 04e544 experimental/ good/
1354 hg clone -r 04e544 experimental/ good/
1355
1355
1356 - clone (and track) a particular named branch::
1356 - clone (and track) a particular named branch::
1357
1357
1358 hg clone http://selenic.com/hg#stable
1358 hg clone http://selenic.com/hg#stable
1359
1359
1360 See :hg:`help urls` for details on specifying URLs.
1360 See :hg:`help urls` for details on specifying URLs.
1361
1361
1362 Returns 0 on success.
1362 Returns 0 on success.
1363 """
1363 """
1364 if opts.get('noupdate') and opts.get('updaterev'):
1364 if opts.get('noupdate') and opts.get('updaterev'):
1365 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1365 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1366
1366
1367 r = hg.clone(ui, opts, source, dest,
1367 r = hg.clone(ui, opts, source, dest,
1368 pull=opts.get('pull'),
1368 pull=opts.get('pull'),
1369 stream=opts.get('uncompressed'),
1369 stream=opts.get('uncompressed'),
1370 rev=opts.get('rev'),
1370 rev=opts.get('rev'),
1371 update=opts.get('updaterev') or not opts.get('noupdate'),
1371 update=opts.get('updaterev') or not opts.get('noupdate'),
1372 branch=opts.get('branch'))
1372 branch=opts.get('branch'))
1373
1373
1374 return r is None
1374 return r is None
1375
1375
1376 @command('^commit|ci',
1376 @command('^commit|ci',
1377 [('A', 'addremove', None,
1377 [('A', 'addremove', None,
1378 _('mark new/missing files as added/removed before committing')),
1378 _('mark new/missing files as added/removed before committing')),
1379 ('', 'close-branch', None,
1379 ('', 'close-branch', None,
1380 _('mark a branch as closed, hiding it from the branch list')),
1380 _('mark a branch as closed, hiding it from the branch list')),
1381 ('', 'amend', None, _('amend the parent of the working dir')),
1381 ('', 'amend', None, _('amend the parent of the working dir')),
1382 ('s', 'secret', None, _('use the secret phase for committing')),
1382 ('s', 'secret', None, _('use the secret phase for committing')),
1383 ('e', 'edit', None, _('invoke editor on commit messages')),
1383 ('e', 'edit', None, _('invoke editor on commit messages')),
1384 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1384 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1385 _('[OPTION]... [FILE]...'),
1385 _('[OPTION]... [FILE]...'),
1386 inferrepo=True)
1386 inferrepo=True)
1387 def commit(ui, repo, *pats, **opts):
1387 def commit(ui, repo, *pats, **opts):
1388 """commit the specified files or all outstanding changes
1388 """commit the specified files or all outstanding changes
1389
1389
1390 Commit changes to the given files into the repository. Unlike a
1390 Commit changes to the given files into the repository. Unlike a
1391 centralized SCM, this operation is a local operation. See
1391 centralized SCM, this operation is a local operation. See
1392 :hg:`push` for a way to actively distribute your changes.
1392 :hg:`push` for a way to actively distribute your changes.
1393
1393
1394 If a list of files is omitted, all changes reported by :hg:`status`
1394 If a list of files is omitted, all changes reported by :hg:`status`
1395 will be committed.
1395 will be committed.
1396
1396
1397 If you are committing the result of a merge, do not provide any
1397 If you are committing the result of a merge, do not provide any
1398 filenames or -I/-X filters.
1398 filenames or -I/-X filters.
1399
1399
1400 If no commit message is specified, Mercurial starts your
1400 If no commit message is specified, Mercurial starts your
1401 configured editor where you can enter a message. In case your
1401 configured editor where you can enter a message. In case your
1402 commit fails, you will find a backup of your message in
1402 commit fails, you will find a backup of your message in
1403 ``.hg/last-message.txt``.
1403 ``.hg/last-message.txt``.
1404
1404
1405 The --amend flag can be used to amend the parent of the
1405 The --amend flag can be used to amend the parent of the
1406 working directory with a new commit that contains the changes
1406 working directory with a new commit that contains the changes
1407 in the parent in addition to those currently reported by :hg:`status`,
1407 in the parent in addition to those currently reported by :hg:`status`,
1408 if there are any. The old commit is stored in a backup bundle in
1408 if there are any. The old commit is stored in a backup bundle in
1409 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1409 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1410 on how to restore it).
1410 on how to restore it).
1411
1411
1412 Message, user and date are taken from the amended commit unless
1412 Message, user and date are taken from the amended commit unless
1413 specified. When a message isn't specified on the command line,
1413 specified. When a message isn't specified on the command line,
1414 the editor will open with the message of the amended commit.
1414 the editor will open with the message of the amended commit.
1415
1415
1416 It is not possible to amend public changesets (see :hg:`help phases`)
1416 It is not possible to amend public changesets (see :hg:`help phases`)
1417 or changesets that have children.
1417 or changesets that have children.
1418
1418
1419 See :hg:`help dates` for a list of formats valid for -d/--date.
1419 See :hg:`help dates` for a list of formats valid for -d/--date.
1420
1420
1421 Returns 0 on success, 1 if nothing changed.
1421 Returns 0 on success, 1 if nothing changed.
1422 """
1422 """
1423 if opts.get('subrepos'):
1423 if opts.get('subrepos'):
1424 if opts.get('amend'):
1424 if opts.get('amend'):
1425 raise util.Abort(_('cannot amend with --subrepos'))
1425 raise util.Abort(_('cannot amend with --subrepos'))
1426 # Let --subrepos on the command line override config setting.
1426 # Let --subrepos on the command line override config setting.
1427 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1427 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1428
1428
1429 cmdutil.checkunfinished(repo, commit=True)
1429 cmdutil.checkunfinished(repo, commit=True)
1430
1430
1431 branch = repo[None].branch()
1431 branch = repo[None].branch()
1432 bheads = repo.branchheads(branch)
1432 bheads = repo.branchheads(branch)
1433
1433
1434 extra = {}
1434 extra = {}
1435 if opts.get('close_branch'):
1435 if opts.get('close_branch'):
1436 extra['close'] = 1
1436 extra['close'] = 1
1437
1437
1438 if not bheads:
1438 if not bheads:
1439 raise util.Abort(_('can only close branch heads'))
1439 raise util.Abort(_('can only close branch heads'))
1440 elif opts.get('amend'):
1440 elif opts.get('amend'):
1441 if repo.parents()[0].p1().branch() != branch and \
1441 if repo.parents()[0].p1().branch() != branch and \
1442 repo.parents()[0].p2().branch() != branch:
1442 repo.parents()[0].p2().branch() != branch:
1443 raise util.Abort(_('can only close branch heads'))
1443 raise util.Abort(_('can only close branch heads'))
1444
1444
1445 if opts.get('amend'):
1445 if opts.get('amend'):
1446 if ui.configbool('ui', 'commitsubrepos'):
1446 if ui.configbool('ui', 'commitsubrepos'):
1447 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1447 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1448
1448
1449 old = repo['.']
1449 old = repo['.']
1450 if not old.mutable():
1450 if not old.mutable():
1451 raise util.Abort(_('cannot amend public changesets'))
1451 raise util.Abort(_('cannot amend public changesets'))
1452 if len(repo[None].parents()) > 1:
1452 if len(repo[None].parents()) > 1:
1453 raise util.Abort(_('cannot amend while merging'))
1453 raise util.Abort(_('cannot amend while merging'))
1454 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1454 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1455 if not allowunstable and old.children():
1455 if not allowunstable and old.children():
1456 raise util.Abort(_('cannot amend changeset with children'))
1456 raise util.Abort(_('cannot amend changeset with children'))
1457
1457
1458 # commitfunc is used only for temporary amend commit by cmdutil.amend
1458 # commitfunc is used only for temporary amend commit by cmdutil.amend
1459 def commitfunc(ui, repo, message, match, opts):
1459 def commitfunc(ui, repo, message, match, opts):
1460 return repo.commit(message,
1460 return repo.commit(message,
1461 opts.get('user') or old.user(),
1461 opts.get('user') or old.user(),
1462 opts.get('date') or old.date(),
1462 opts.get('date') or old.date(),
1463 match,
1463 match,
1464 extra=extra)
1464 extra=extra)
1465
1465
1466 current = repo._bookmarkcurrent
1466 current = repo._bookmarkcurrent
1467 marks = old.bookmarks()
1467 marks = old.bookmarks()
1468 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1468 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1469 if node == old.node():
1469 if node == old.node():
1470 ui.status(_("nothing changed\n"))
1470 ui.status(_("nothing changed\n"))
1471 return 1
1471 return 1
1472 elif marks:
1472 elif marks:
1473 ui.debug('moving bookmarks %r from %s to %s\n' %
1473 ui.debug('moving bookmarks %r from %s to %s\n' %
1474 (marks, old.hex(), hex(node)))
1474 (marks, old.hex(), hex(node)))
1475 newmarks = repo._bookmarks
1475 newmarks = repo._bookmarks
1476 for bm in marks:
1476 for bm in marks:
1477 newmarks[bm] = node
1477 newmarks[bm] = node
1478 if bm == current:
1478 if bm == current:
1479 bookmarks.setcurrent(repo, bm)
1479 bookmarks.setcurrent(repo, bm)
1480 newmarks.write()
1480 newmarks.write()
1481 else:
1481 else:
1482 def commitfunc(ui, repo, message, match, opts):
1482 def commitfunc(ui, repo, message, match, opts):
1483 backup = ui.backupconfig('phases', 'new-commit')
1483 backup = ui.backupconfig('phases', 'new-commit')
1484 baseui = repo.baseui
1484 baseui = repo.baseui
1485 basebackup = baseui.backupconfig('phases', 'new-commit')
1485 basebackup = baseui.backupconfig('phases', 'new-commit')
1486 try:
1486 try:
1487 if opts.get('secret'):
1487 if opts.get('secret'):
1488 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1488 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1489 # Propagate to subrepos
1489 # Propagate to subrepos
1490 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1490 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1491
1491
1492 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1492 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1493 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1493 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1494 return repo.commit(message, opts.get('user'), opts.get('date'),
1494 return repo.commit(message, opts.get('user'), opts.get('date'),
1495 match,
1495 match,
1496 editor=editor,
1496 editor=editor,
1497 extra=extra)
1497 extra=extra)
1498 finally:
1498 finally:
1499 ui.restoreconfig(backup)
1499 ui.restoreconfig(backup)
1500 repo.baseui.restoreconfig(basebackup)
1500 repo.baseui.restoreconfig(basebackup)
1501
1501
1502
1502
1503 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1503 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1504
1504
1505 if not node:
1505 if not node:
1506 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1506 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1507 if stat[3]:
1507 if stat[3]:
1508 ui.status(_("nothing changed (%d missing files, see "
1508 ui.status(_("nothing changed (%d missing files, see "
1509 "'hg status')\n") % len(stat[3]))
1509 "'hg status')\n") % len(stat[3]))
1510 else:
1510 else:
1511 ui.status(_("nothing changed\n"))
1511 ui.status(_("nothing changed\n"))
1512 return 1
1512 return 1
1513
1513
1514 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1514 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1515
1515
1516 @command('config|showconfig|debugconfig',
1516 @command('config|showconfig|debugconfig',
1517 [('u', 'untrusted', None, _('show untrusted configuration options')),
1517 [('u', 'untrusted', None, _('show untrusted configuration options')),
1518 ('e', 'edit', None, _('edit user config')),
1518 ('e', 'edit', None, _('edit user config')),
1519 ('l', 'local', None, _('edit repository config')),
1519 ('l', 'local', None, _('edit repository config')),
1520 ('g', 'global', None, _('edit global config'))],
1520 ('g', 'global', None, _('edit global config'))],
1521 _('[-u] [NAME]...'),
1521 _('[-u] [NAME]...'),
1522 optionalrepo=True)
1522 optionalrepo=True)
1523 def config(ui, repo, *values, **opts):
1523 def config(ui, repo, *values, **opts):
1524 """show combined config settings from all hgrc files
1524 """show combined config settings from all hgrc files
1525
1525
1526 With no arguments, print names and values of all config items.
1526 With no arguments, print names and values of all config items.
1527
1527
1528 With one argument of the form section.name, print just the value
1528 With one argument of the form section.name, print just the value
1529 of that config item.
1529 of that config item.
1530
1530
1531 With multiple arguments, print names and values of all config
1531 With multiple arguments, print names and values of all config
1532 items with matching section names.
1532 items with matching section names.
1533
1533
1534 With --edit, start an editor on the user-level config file. With
1534 With --edit, start an editor on the user-level config file. With
1535 --global, edit the system-wide config file. With --local, edit the
1535 --global, edit the system-wide config file. With --local, edit the
1536 repository-level config file.
1536 repository-level config file.
1537
1537
1538 With --debug, the source (filename and line number) is printed
1538 With --debug, the source (filename and line number) is printed
1539 for each config item.
1539 for each config item.
1540
1540
1541 See :hg:`help config` for more information about config files.
1541 See :hg:`help config` for more information about config files.
1542
1542
1543 Returns 0 on success, 1 if NAME does not exist.
1543 Returns 0 on success, 1 if NAME does not exist.
1544
1544
1545 """
1545 """
1546
1546
1547 if opts.get('edit') or opts.get('local') or opts.get('global'):
1547 if opts.get('edit') or opts.get('local') or opts.get('global'):
1548 if opts.get('local') and opts.get('global'):
1548 if opts.get('local') and opts.get('global'):
1549 raise util.Abort(_("can't use --local and --global together"))
1549 raise util.Abort(_("can't use --local and --global together"))
1550
1550
1551 if opts.get('local'):
1551 if opts.get('local'):
1552 if not repo:
1552 if not repo:
1553 raise util.Abort(_("can't use --local outside a repository"))
1553 raise util.Abort(_("can't use --local outside a repository"))
1554 paths = [repo.join('hgrc')]
1554 paths = [repo.join('hgrc')]
1555 elif opts.get('global'):
1555 elif opts.get('global'):
1556 paths = scmutil.systemrcpath()
1556 paths = scmutil.systemrcpath()
1557 else:
1557 else:
1558 paths = scmutil.userrcpath()
1558 paths = scmutil.userrcpath()
1559
1559
1560 for f in paths:
1560 for f in paths:
1561 if os.path.exists(f):
1561 if os.path.exists(f):
1562 break
1562 break
1563 else:
1563 else:
1564 if opts.get('global'):
1564 if opts.get('global'):
1565 samplehgrc = uimod.samplehgrcs['global']
1565 samplehgrc = uimod.samplehgrcs['global']
1566 elif opts.get('local'):
1566 elif opts.get('local'):
1567 samplehgrc = uimod.samplehgrcs['local']
1567 samplehgrc = uimod.samplehgrcs['local']
1568 else:
1568 else:
1569 samplehgrc = uimod.samplehgrcs['user']
1569 samplehgrc = uimod.samplehgrcs['user']
1570
1570
1571 f = paths[0]
1571 f = paths[0]
1572 fp = open(f, "w")
1572 fp = open(f, "w")
1573 fp.write(samplehgrc)
1573 fp.write(samplehgrc)
1574 fp.close()
1574 fp.close()
1575
1575
1576 editor = ui.geteditor()
1576 editor = ui.geteditor()
1577 ui.system("%s \"%s\"" % (editor, f),
1577 ui.system("%s \"%s\"" % (editor, f),
1578 onerr=util.Abort, errprefix=_("edit failed"))
1578 onerr=util.Abort, errprefix=_("edit failed"))
1579 return
1579 return
1580
1580
1581 for f in scmutil.rcpath():
1581 for f in scmutil.rcpath():
1582 ui.debug('read config from: %s\n' % f)
1582 ui.debug('read config from: %s\n' % f)
1583 untrusted = bool(opts.get('untrusted'))
1583 untrusted = bool(opts.get('untrusted'))
1584 if values:
1584 if values:
1585 sections = [v for v in values if '.' not in v]
1585 sections = [v for v in values if '.' not in v]
1586 items = [v for v in values if '.' in v]
1586 items = [v for v in values if '.' in v]
1587 if len(items) > 1 or items and sections:
1587 if len(items) > 1 or items and sections:
1588 raise util.Abort(_('only one config item permitted'))
1588 raise util.Abort(_('only one config item permitted'))
1589 matched = False
1589 matched = False
1590 for section, name, value in ui.walkconfig(untrusted=untrusted):
1590 for section, name, value in ui.walkconfig(untrusted=untrusted):
1591 value = str(value).replace('\n', '\\n')
1591 value = str(value).replace('\n', '\\n')
1592 sectname = section + '.' + name
1592 sectname = section + '.' + name
1593 if values:
1593 if values:
1594 for v in values:
1594 for v in values:
1595 if v == section:
1595 if v == section:
1596 ui.debug('%s: ' %
1596 ui.debug('%s: ' %
1597 ui.configsource(section, name, untrusted))
1597 ui.configsource(section, name, untrusted))
1598 ui.write('%s=%s\n' % (sectname, value))
1598 ui.write('%s=%s\n' % (sectname, value))
1599 matched = True
1599 matched = True
1600 elif v == sectname:
1600 elif v == sectname:
1601 ui.debug('%s: ' %
1601 ui.debug('%s: ' %
1602 ui.configsource(section, name, untrusted))
1602 ui.configsource(section, name, untrusted))
1603 ui.write(value, '\n')
1603 ui.write(value, '\n')
1604 matched = True
1604 matched = True
1605 else:
1605 else:
1606 ui.debug('%s: ' %
1606 ui.debug('%s: ' %
1607 ui.configsource(section, name, untrusted))
1607 ui.configsource(section, name, untrusted))
1608 ui.write('%s=%s\n' % (sectname, value))
1608 ui.write('%s=%s\n' % (sectname, value))
1609 matched = True
1609 matched = True
1610 if matched:
1610 if matched:
1611 return 0
1611 return 0
1612 return 1
1612 return 1
1613
1613
1614 @command('copy|cp',
1614 @command('copy|cp',
1615 [('A', 'after', None, _('record a copy that has already occurred')),
1615 [('A', 'after', None, _('record a copy that has already occurred')),
1616 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1616 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1617 ] + walkopts + dryrunopts,
1617 ] + walkopts + dryrunopts,
1618 _('[OPTION]... [SOURCE]... DEST'))
1618 _('[OPTION]... [SOURCE]... DEST'))
1619 def copy(ui, repo, *pats, **opts):
1619 def copy(ui, repo, *pats, **opts):
1620 """mark files as copied for the next commit
1620 """mark files as copied for the next commit
1621
1621
1622 Mark dest as having copies of source files. If dest is a
1622 Mark dest as having copies of source files. If dest is a
1623 directory, copies are put in that directory. If dest is a file,
1623 directory, copies are put in that directory. If dest is a file,
1624 the source must be a single file.
1624 the source must be a single file.
1625
1625
1626 By default, this command copies the contents of files as they
1626 By default, this command copies the contents of files as they
1627 exist in the working directory. If invoked with -A/--after, the
1627 exist in the working directory. If invoked with -A/--after, the
1628 operation is recorded, but no copying is performed.
1628 operation is recorded, but no copying is performed.
1629
1629
1630 This command takes effect with the next commit. To undo a copy
1630 This command takes effect with the next commit. To undo a copy
1631 before that, see :hg:`revert`.
1631 before that, see :hg:`revert`.
1632
1632
1633 Returns 0 on success, 1 if errors are encountered.
1633 Returns 0 on success, 1 if errors are encountered.
1634 """
1634 """
1635 wlock = repo.wlock(False)
1635 wlock = repo.wlock(False)
1636 try:
1636 try:
1637 return cmdutil.copy(ui, repo, pats, opts)
1637 return cmdutil.copy(ui, repo, pats, opts)
1638 finally:
1638 finally:
1639 wlock.release()
1639 wlock.release()
1640
1640
1641 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1641 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1642 def debugancestor(ui, repo, *args):
1642 def debugancestor(ui, repo, *args):
1643 """find the ancestor revision of two revisions in a given index"""
1643 """find the ancestor revision of two revisions in a given index"""
1644 if len(args) == 3:
1644 if len(args) == 3:
1645 index, rev1, rev2 = args
1645 index, rev1, rev2 = args
1646 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1646 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1647 lookup = r.lookup
1647 lookup = r.lookup
1648 elif len(args) == 2:
1648 elif len(args) == 2:
1649 if not repo:
1649 if not repo:
1650 raise util.Abort(_("there is no Mercurial repository here "
1650 raise util.Abort(_("there is no Mercurial repository here "
1651 "(.hg not found)"))
1651 "(.hg not found)"))
1652 rev1, rev2 = args
1652 rev1, rev2 = args
1653 r = repo.changelog
1653 r = repo.changelog
1654 lookup = repo.lookup
1654 lookup = repo.lookup
1655 else:
1655 else:
1656 raise util.Abort(_('either two or three arguments required'))
1656 raise util.Abort(_('either two or three arguments required'))
1657 a = r.ancestor(lookup(rev1), lookup(rev2))
1657 a = r.ancestor(lookup(rev1), lookup(rev2))
1658 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1658 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1659
1659
1660 @command('debugbuilddag',
1660 @command('debugbuilddag',
1661 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1661 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1662 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1662 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1663 ('n', 'new-file', None, _('add new file at each rev'))],
1663 ('n', 'new-file', None, _('add new file at each rev'))],
1664 _('[OPTION]... [TEXT]'))
1664 _('[OPTION]... [TEXT]'))
1665 def debugbuilddag(ui, repo, text=None,
1665 def debugbuilddag(ui, repo, text=None,
1666 mergeable_file=False,
1666 mergeable_file=False,
1667 overwritten_file=False,
1667 overwritten_file=False,
1668 new_file=False):
1668 new_file=False):
1669 """builds a repo with a given DAG from scratch in the current empty repo
1669 """builds a repo with a given DAG from scratch in the current empty repo
1670
1670
1671 The description of the DAG is read from stdin if not given on the
1671 The description of the DAG is read from stdin if not given on the
1672 command line.
1672 command line.
1673
1673
1674 Elements:
1674 Elements:
1675
1675
1676 - "+n" is a linear run of n nodes based on the current default parent
1676 - "+n" is a linear run of n nodes based on the current default parent
1677 - "." is a single node based on the current default parent
1677 - "." is a single node based on the current default parent
1678 - "$" resets the default parent to null (implied at the start);
1678 - "$" resets the default parent to null (implied at the start);
1679 otherwise the default parent is always the last node created
1679 otherwise the default parent is always the last node created
1680 - "<p" sets the default parent to the backref p
1680 - "<p" sets the default parent to the backref p
1681 - "*p" is a fork at parent p, which is a backref
1681 - "*p" is a fork at parent p, which is a backref
1682 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1682 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1683 - "/p2" is a merge of the preceding node and p2
1683 - "/p2" is a merge of the preceding node and p2
1684 - ":tag" defines a local tag for the preceding node
1684 - ":tag" defines a local tag for the preceding node
1685 - "@branch" sets the named branch for subsequent nodes
1685 - "@branch" sets the named branch for subsequent nodes
1686 - "#...\\n" is a comment up to the end of the line
1686 - "#...\\n" is a comment up to the end of the line
1687
1687
1688 Whitespace between the above elements is ignored.
1688 Whitespace between the above elements is ignored.
1689
1689
1690 A backref is either
1690 A backref is either
1691
1691
1692 - a number n, which references the node curr-n, where curr is the current
1692 - a number n, which references the node curr-n, where curr is the current
1693 node, or
1693 node, or
1694 - the name of a local tag you placed earlier using ":tag", or
1694 - the name of a local tag you placed earlier using ":tag", or
1695 - empty to denote the default parent.
1695 - empty to denote the default parent.
1696
1696
1697 All string valued-elements are either strictly alphanumeric, or must
1697 All string valued-elements are either strictly alphanumeric, or must
1698 be enclosed in double quotes ("..."), with "\\" as escape character.
1698 be enclosed in double quotes ("..."), with "\\" as escape character.
1699 """
1699 """
1700
1700
1701 if text is None:
1701 if text is None:
1702 ui.status(_("reading DAG from stdin\n"))
1702 ui.status(_("reading DAG from stdin\n"))
1703 text = ui.fin.read()
1703 text = ui.fin.read()
1704
1704
1705 cl = repo.changelog
1705 cl = repo.changelog
1706 if len(cl) > 0:
1706 if len(cl) > 0:
1707 raise util.Abort(_('repository is not empty'))
1707 raise util.Abort(_('repository is not empty'))
1708
1708
1709 # determine number of revs in DAG
1709 # determine number of revs in DAG
1710 total = 0
1710 total = 0
1711 for type, data in dagparser.parsedag(text):
1711 for type, data in dagparser.parsedag(text):
1712 if type == 'n':
1712 if type == 'n':
1713 total += 1
1713 total += 1
1714
1714
1715 if mergeable_file:
1715 if mergeable_file:
1716 linesperrev = 2
1716 linesperrev = 2
1717 # make a file with k lines per rev
1717 # make a file with k lines per rev
1718 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1718 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1719 initialmergedlines.append("")
1719 initialmergedlines.append("")
1720
1720
1721 tags = []
1721 tags = []
1722
1722
1723 lock = tr = None
1723 lock = tr = None
1724 try:
1724 try:
1725 lock = repo.lock()
1725 lock = repo.lock()
1726 tr = repo.transaction("builddag")
1726 tr = repo.transaction("builddag")
1727
1727
1728 at = -1
1728 at = -1
1729 atbranch = 'default'
1729 atbranch = 'default'
1730 nodeids = []
1730 nodeids = []
1731 id = 0
1731 id = 0
1732 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1732 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1733 for type, data in dagparser.parsedag(text):
1733 for type, data in dagparser.parsedag(text):
1734 if type == 'n':
1734 if type == 'n':
1735 ui.note(('node %s\n' % str(data)))
1735 ui.note(('node %s\n' % str(data)))
1736 id, ps = data
1736 id, ps = data
1737
1737
1738 files = []
1738 files = []
1739 fctxs = {}
1739 fctxs = {}
1740
1740
1741 p2 = None
1741 p2 = None
1742 if mergeable_file:
1742 if mergeable_file:
1743 fn = "mf"
1743 fn = "mf"
1744 p1 = repo[ps[0]]
1744 p1 = repo[ps[0]]
1745 if len(ps) > 1:
1745 if len(ps) > 1:
1746 p2 = repo[ps[1]]
1746 p2 = repo[ps[1]]
1747 pa = p1.ancestor(p2)
1747 pa = p1.ancestor(p2)
1748 base, local, other = [x[fn].data() for x in (pa, p1,
1748 base, local, other = [x[fn].data() for x in (pa, p1,
1749 p2)]
1749 p2)]
1750 m3 = simplemerge.Merge3Text(base, local, other)
1750 m3 = simplemerge.Merge3Text(base, local, other)
1751 ml = [l.strip() for l in m3.merge_lines()]
1751 ml = [l.strip() for l in m3.merge_lines()]
1752 ml.append("")
1752 ml.append("")
1753 elif at > 0:
1753 elif at > 0:
1754 ml = p1[fn].data().split("\n")
1754 ml = p1[fn].data().split("\n")
1755 else:
1755 else:
1756 ml = initialmergedlines
1756 ml = initialmergedlines
1757 ml[id * linesperrev] += " r%i" % id
1757 ml[id * linesperrev] += " r%i" % id
1758 mergedtext = "\n".join(ml)
1758 mergedtext = "\n".join(ml)
1759 files.append(fn)
1759 files.append(fn)
1760 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1760 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1761
1761
1762 if overwritten_file:
1762 if overwritten_file:
1763 fn = "of"
1763 fn = "of"
1764 files.append(fn)
1764 files.append(fn)
1765 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1765 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1766
1766
1767 if new_file:
1767 if new_file:
1768 fn = "nf%i" % id
1768 fn = "nf%i" % id
1769 files.append(fn)
1769 files.append(fn)
1770 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1770 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1771 if len(ps) > 1:
1771 if len(ps) > 1:
1772 if not p2:
1772 if not p2:
1773 p2 = repo[ps[1]]
1773 p2 = repo[ps[1]]
1774 for fn in p2:
1774 for fn in p2:
1775 if fn.startswith("nf"):
1775 if fn.startswith("nf"):
1776 files.append(fn)
1776 files.append(fn)
1777 fctxs[fn] = p2[fn]
1777 fctxs[fn] = p2[fn]
1778
1778
1779 def fctxfn(repo, cx, path):
1779 def fctxfn(repo, cx, path):
1780 return fctxs.get(path)
1780 return fctxs.get(path)
1781
1781
1782 if len(ps) == 0 or ps[0] < 0:
1782 if len(ps) == 0 or ps[0] < 0:
1783 pars = [None, None]
1783 pars = [None, None]
1784 elif len(ps) == 1:
1784 elif len(ps) == 1:
1785 pars = [nodeids[ps[0]], None]
1785 pars = [nodeids[ps[0]], None]
1786 else:
1786 else:
1787 pars = [nodeids[p] for p in ps]
1787 pars = [nodeids[p] for p in ps]
1788 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1788 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1789 date=(id, 0),
1789 date=(id, 0),
1790 user="debugbuilddag",
1790 user="debugbuilddag",
1791 extra={'branch': atbranch})
1791 extra={'branch': atbranch})
1792 nodeid = repo.commitctx(cx)
1792 nodeid = repo.commitctx(cx)
1793 nodeids.append(nodeid)
1793 nodeids.append(nodeid)
1794 at = id
1794 at = id
1795 elif type == 'l':
1795 elif type == 'l':
1796 id, name = data
1796 id, name = data
1797 ui.note(('tag %s\n' % name))
1797 ui.note(('tag %s\n' % name))
1798 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1798 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1799 elif type == 'a':
1799 elif type == 'a':
1800 ui.note(('branch %s\n' % data))
1800 ui.note(('branch %s\n' % data))
1801 atbranch = data
1801 atbranch = data
1802 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1802 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1803 tr.close()
1803 tr.close()
1804
1804
1805 if tags:
1805 if tags:
1806 repo.opener.write("localtags", "".join(tags))
1806 repo.opener.write("localtags", "".join(tags))
1807 finally:
1807 finally:
1808 ui.progress(_('building'), None)
1808 ui.progress(_('building'), None)
1809 release(tr, lock)
1809 release(tr, lock)
1810
1810
1811 @command('debugbundle',
1811 @command('debugbundle',
1812 [('a', 'all', None, _('show all details'))],
1812 [('a', 'all', None, _('show all details'))],
1813 _('FILE'),
1813 _('FILE'),
1814 norepo=True)
1814 norepo=True)
1815 def debugbundle(ui, bundlepath, all=None, **opts):
1815 def debugbundle(ui, bundlepath, all=None, **opts):
1816 """lists the contents of a bundle"""
1816 """lists the contents of a bundle"""
1817 f = hg.openpath(ui, bundlepath)
1817 f = hg.openpath(ui, bundlepath)
1818 try:
1818 try:
1819 gen = exchange.readbundle(ui, f, bundlepath)
1819 gen = exchange.readbundle(ui, f, bundlepath)
1820 if all:
1820 if all:
1821 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1821 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1822
1822
1823 def showchunks(named):
1823 def showchunks(named):
1824 ui.write("\n%s\n" % named)
1824 ui.write("\n%s\n" % named)
1825 chain = None
1825 chain = None
1826 while True:
1826 while True:
1827 chunkdata = gen.deltachunk(chain)
1827 chunkdata = gen.deltachunk(chain)
1828 if not chunkdata:
1828 if not chunkdata:
1829 break
1829 break
1830 node = chunkdata['node']
1830 node = chunkdata['node']
1831 p1 = chunkdata['p1']
1831 p1 = chunkdata['p1']
1832 p2 = chunkdata['p2']
1832 p2 = chunkdata['p2']
1833 cs = chunkdata['cs']
1833 cs = chunkdata['cs']
1834 deltabase = chunkdata['deltabase']
1834 deltabase = chunkdata['deltabase']
1835 delta = chunkdata['delta']
1835 delta = chunkdata['delta']
1836 ui.write("%s %s %s %s %s %s\n" %
1836 ui.write("%s %s %s %s %s %s\n" %
1837 (hex(node), hex(p1), hex(p2),
1837 (hex(node), hex(p1), hex(p2),
1838 hex(cs), hex(deltabase), len(delta)))
1838 hex(cs), hex(deltabase), len(delta)))
1839 chain = node
1839 chain = node
1840
1840
1841 chunkdata = gen.changelogheader()
1841 chunkdata = gen.changelogheader()
1842 showchunks("changelog")
1842 showchunks("changelog")
1843 chunkdata = gen.manifestheader()
1843 chunkdata = gen.manifestheader()
1844 showchunks("manifest")
1844 showchunks("manifest")
1845 while True:
1845 while True:
1846 chunkdata = gen.filelogheader()
1846 chunkdata = gen.filelogheader()
1847 if not chunkdata:
1847 if not chunkdata:
1848 break
1848 break
1849 fname = chunkdata['filename']
1849 fname = chunkdata['filename']
1850 showchunks(fname)
1850 showchunks(fname)
1851 else:
1851 else:
1852 chunkdata = gen.changelogheader()
1852 chunkdata = gen.changelogheader()
1853 chain = None
1853 chain = None
1854 while True:
1854 while True:
1855 chunkdata = gen.deltachunk(chain)
1855 chunkdata = gen.deltachunk(chain)
1856 if not chunkdata:
1856 if not chunkdata:
1857 break
1857 break
1858 node = chunkdata['node']
1858 node = chunkdata['node']
1859 ui.write("%s\n" % hex(node))
1859 ui.write("%s\n" % hex(node))
1860 chain = node
1860 chain = node
1861 finally:
1861 finally:
1862 f.close()
1862 f.close()
1863
1863
1864 @command('debugcheckstate', [], '')
1864 @command('debugcheckstate', [], '')
1865 def debugcheckstate(ui, repo):
1865 def debugcheckstate(ui, repo):
1866 """validate the correctness of the current dirstate"""
1866 """validate the correctness of the current dirstate"""
1867 parent1, parent2 = repo.dirstate.parents()
1867 parent1, parent2 = repo.dirstate.parents()
1868 m1 = repo[parent1].manifest()
1868 m1 = repo[parent1].manifest()
1869 m2 = repo[parent2].manifest()
1869 m2 = repo[parent2].manifest()
1870 errors = 0
1870 errors = 0
1871 for f in repo.dirstate:
1871 for f in repo.dirstate:
1872 state = repo.dirstate[f]
1872 state = repo.dirstate[f]
1873 if state in "nr" and f not in m1:
1873 if state in "nr" and f not in m1:
1874 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1874 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1875 errors += 1
1875 errors += 1
1876 if state in "a" and f in m1:
1876 if state in "a" and f in m1:
1877 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1877 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1878 errors += 1
1878 errors += 1
1879 if state in "m" and f not in m1 and f not in m2:
1879 if state in "m" and f not in m1 and f not in m2:
1880 ui.warn(_("%s in state %s, but not in either manifest\n") %
1880 ui.warn(_("%s in state %s, but not in either manifest\n") %
1881 (f, state))
1881 (f, state))
1882 errors += 1
1882 errors += 1
1883 for f in m1:
1883 for f in m1:
1884 state = repo.dirstate[f]
1884 state = repo.dirstate[f]
1885 if state not in "nrm":
1885 if state not in "nrm":
1886 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1886 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1887 errors += 1
1887 errors += 1
1888 if errors:
1888 if errors:
1889 error = _(".hg/dirstate inconsistent with current parent's manifest")
1889 error = _(".hg/dirstate inconsistent with current parent's manifest")
1890 raise util.Abort(error)
1890 raise util.Abort(error)
1891
1891
1892 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1892 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1893 def debugcommands(ui, cmd='', *args):
1893 def debugcommands(ui, cmd='', *args):
1894 """list all available commands and options"""
1894 """list all available commands and options"""
1895 for cmd, vals in sorted(table.iteritems()):
1895 for cmd, vals in sorted(table.iteritems()):
1896 cmd = cmd.split('|')[0].strip('^')
1896 cmd = cmd.split('|')[0].strip('^')
1897 opts = ', '.join([i[1] for i in vals[1]])
1897 opts = ', '.join([i[1] for i in vals[1]])
1898 ui.write('%s: %s\n' % (cmd, opts))
1898 ui.write('%s: %s\n' % (cmd, opts))
1899
1899
1900 @command('debugcomplete',
1900 @command('debugcomplete',
1901 [('o', 'options', None, _('show the command options'))],
1901 [('o', 'options', None, _('show the command options'))],
1902 _('[-o] CMD'),
1902 _('[-o] CMD'),
1903 norepo=True)
1903 norepo=True)
1904 def debugcomplete(ui, cmd='', **opts):
1904 def debugcomplete(ui, cmd='', **opts):
1905 """returns the completion list associated with the given command"""
1905 """returns the completion list associated with the given command"""
1906
1906
1907 if opts.get('options'):
1907 if opts.get('options'):
1908 options = []
1908 options = []
1909 otables = [globalopts]
1909 otables = [globalopts]
1910 if cmd:
1910 if cmd:
1911 aliases, entry = cmdutil.findcmd(cmd, table, False)
1911 aliases, entry = cmdutil.findcmd(cmd, table, False)
1912 otables.append(entry[1])
1912 otables.append(entry[1])
1913 for t in otables:
1913 for t in otables:
1914 for o in t:
1914 for o in t:
1915 if "(DEPRECATED)" in o[3]:
1915 if "(DEPRECATED)" in o[3]:
1916 continue
1916 continue
1917 if o[0]:
1917 if o[0]:
1918 options.append('-%s' % o[0])
1918 options.append('-%s' % o[0])
1919 options.append('--%s' % o[1])
1919 options.append('--%s' % o[1])
1920 ui.write("%s\n" % "\n".join(options))
1920 ui.write("%s\n" % "\n".join(options))
1921 return
1921 return
1922
1922
1923 cmdlist = cmdutil.findpossible(cmd, table)
1923 cmdlist = cmdutil.findpossible(cmd, table)
1924 if ui.verbose:
1924 if ui.verbose:
1925 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1925 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1926 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1926 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1927
1927
1928 @command('debugdag',
1928 @command('debugdag',
1929 [('t', 'tags', None, _('use tags as labels')),
1929 [('t', 'tags', None, _('use tags as labels')),
1930 ('b', 'branches', None, _('annotate with branch names')),
1930 ('b', 'branches', None, _('annotate with branch names')),
1931 ('', 'dots', None, _('use dots for runs')),
1931 ('', 'dots', None, _('use dots for runs')),
1932 ('s', 'spaces', None, _('separate elements by spaces'))],
1932 ('s', 'spaces', None, _('separate elements by spaces'))],
1933 _('[OPTION]... [FILE [REV]...]'),
1933 _('[OPTION]... [FILE [REV]...]'),
1934 optionalrepo=True)
1934 optionalrepo=True)
1935 def debugdag(ui, repo, file_=None, *revs, **opts):
1935 def debugdag(ui, repo, file_=None, *revs, **opts):
1936 """format the changelog or an index DAG as a concise textual description
1936 """format the changelog or an index DAG as a concise textual description
1937
1937
1938 If you pass a revlog index, the revlog's DAG is emitted. If you list
1938 If you pass a revlog index, the revlog's DAG is emitted. If you list
1939 revision numbers, they get labeled in the output as rN.
1939 revision numbers, they get labeled in the output as rN.
1940
1940
1941 Otherwise, the changelog DAG of the current repo is emitted.
1941 Otherwise, the changelog DAG of the current repo is emitted.
1942 """
1942 """
1943 spaces = opts.get('spaces')
1943 spaces = opts.get('spaces')
1944 dots = opts.get('dots')
1944 dots = opts.get('dots')
1945 if file_:
1945 if file_:
1946 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1946 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1947 revs = set((int(r) for r in revs))
1947 revs = set((int(r) for r in revs))
1948 def events():
1948 def events():
1949 for r in rlog:
1949 for r in rlog:
1950 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1950 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1951 if p != -1))
1951 if p != -1))
1952 if r in revs:
1952 if r in revs:
1953 yield 'l', (r, "r%i" % r)
1953 yield 'l', (r, "r%i" % r)
1954 elif repo:
1954 elif repo:
1955 cl = repo.changelog
1955 cl = repo.changelog
1956 tags = opts.get('tags')
1956 tags = opts.get('tags')
1957 branches = opts.get('branches')
1957 branches = opts.get('branches')
1958 if tags:
1958 if tags:
1959 labels = {}
1959 labels = {}
1960 for l, n in repo.tags().items():
1960 for l, n in repo.tags().items():
1961 labels.setdefault(cl.rev(n), []).append(l)
1961 labels.setdefault(cl.rev(n), []).append(l)
1962 def events():
1962 def events():
1963 b = "default"
1963 b = "default"
1964 for r in cl:
1964 for r in cl:
1965 if branches:
1965 if branches:
1966 newb = cl.read(cl.node(r))[5]['branch']
1966 newb = cl.read(cl.node(r))[5]['branch']
1967 if newb != b:
1967 if newb != b:
1968 yield 'a', newb
1968 yield 'a', newb
1969 b = newb
1969 b = newb
1970 yield 'n', (r, list(p for p in cl.parentrevs(r)
1970 yield 'n', (r, list(p for p in cl.parentrevs(r)
1971 if p != -1))
1971 if p != -1))
1972 if tags:
1972 if tags:
1973 ls = labels.get(r)
1973 ls = labels.get(r)
1974 if ls:
1974 if ls:
1975 for l in ls:
1975 for l in ls:
1976 yield 'l', (r, l)
1976 yield 'l', (r, l)
1977 else:
1977 else:
1978 raise util.Abort(_('need repo for changelog dag'))
1978 raise util.Abort(_('need repo for changelog dag'))
1979
1979
1980 for line in dagparser.dagtextlines(events(),
1980 for line in dagparser.dagtextlines(events(),
1981 addspaces=spaces,
1981 addspaces=spaces,
1982 wraplabels=True,
1982 wraplabels=True,
1983 wrapannotations=True,
1983 wrapannotations=True,
1984 wrapnonlinear=dots,
1984 wrapnonlinear=dots,
1985 usedots=dots,
1985 usedots=dots,
1986 maxlinewidth=70):
1986 maxlinewidth=70):
1987 ui.write(line)
1987 ui.write(line)
1988 ui.write("\n")
1988 ui.write("\n")
1989
1989
1990 @command('debugdata',
1990 @command('debugdata',
1991 [('c', 'changelog', False, _('open changelog')),
1991 [('c', 'changelog', False, _('open changelog')),
1992 ('m', 'manifest', False, _('open manifest'))],
1992 ('m', 'manifest', False, _('open manifest'))],
1993 _('-c|-m|FILE REV'))
1993 _('-c|-m|FILE REV'))
1994 def debugdata(ui, repo, file_, rev=None, **opts):
1994 def debugdata(ui, repo, file_, rev=None, **opts):
1995 """dump the contents of a data file revision"""
1995 """dump the contents of a data file revision"""
1996 if opts.get('changelog') or opts.get('manifest'):
1996 if opts.get('changelog') or opts.get('manifest'):
1997 file_, rev = None, file_
1997 file_, rev = None, file_
1998 elif rev is None:
1998 elif rev is None:
1999 raise error.CommandError('debugdata', _('invalid arguments'))
1999 raise error.CommandError('debugdata', _('invalid arguments'))
2000 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2000 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2001 try:
2001 try:
2002 ui.write(r.revision(r.lookup(rev)))
2002 ui.write(r.revision(r.lookup(rev)))
2003 except KeyError:
2003 except KeyError:
2004 raise util.Abort(_('invalid revision identifier %s') % rev)
2004 raise util.Abort(_('invalid revision identifier %s') % rev)
2005
2005
2006 @command('debugdate',
2006 @command('debugdate',
2007 [('e', 'extended', None, _('try extended date formats'))],
2007 [('e', 'extended', None, _('try extended date formats'))],
2008 _('[-e] DATE [RANGE]'),
2008 _('[-e] DATE [RANGE]'),
2009 norepo=True, optionalrepo=True)
2009 norepo=True, optionalrepo=True)
2010 def debugdate(ui, date, range=None, **opts):
2010 def debugdate(ui, date, range=None, **opts):
2011 """parse and display a date"""
2011 """parse and display a date"""
2012 if opts["extended"]:
2012 if opts["extended"]:
2013 d = util.parsedate(date, util.extendeddateformats)
2013 d = util.parsedate(date, util.extendeddateformats)
2014 else:
2014 else:
2015 d = util.parsedate(date)
2015 d = util.parsedate(date)
2016 ui.write(("internal: %s %s\n") % d)
2016 ui.write(("internal: %s %s\n") % d)
2017 ui.write(("standard: %s\n") % util.datestr(d))
2017 ui.write(("standard: %s\n") % util.datestr(d))
2018 if range:
2018 if range:
2019 m = util.matchdate(range)
2019 m = util.matchdate(range)
2020 ui.write(("match: %s\n") % m(d[0]))
2020 ui.write(("match: %s\n") % m(d[0]))
2021
2021
2022 @command('debugdiscovery',
2022 @command('debugdiscovery',
2023 [('', 'old', None, _('use old-style discovery')),
2023 [('', 'old', None, _('use old-style discovery')),
2024 ('', 'nonheads', None,
2024 ('', 'nonheads', None,
2025 _('use old-style discovery with non-heads included')),
2025 _('use old-style discovery with non-heads included')),
2026 ] + remoteopts,
2026 ] + remoteopts,
2027 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2027 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2028 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2028 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2029 """runs the changeset discovery protocol in isolation"""
2029 """runs the changeset discovery protocol in isolation"""
2030 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2030 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2031 opts.get('branch'))
2031 opts.get('branch'))
2032 remote = hg.peer(repo, opts, remoteurl)
2032 remote = hg.peer(repo, opts, remoteurl)
2033 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2033 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2034
2034
2035 # make sure tests are repeatable
2035 # make sure tests are repeatable
2036 random.seed(12323)
2036 random.seed(12323)
2037
2037
2038 def doit(localheads, remoteheads, remote=remote):
2038 def doit(localheads, remoteheads, remote=remote):
2039 if opts.get('old'):
2039 if opts.get('old'):
2040 if localheads:
2040 if localheads:
2041 raise util.Abort('cannot use localheads with old style '
2041 raise util.Abort('cannot use localheads with old style '
2042 'discovery')
2042 'discovery')
2043 if not util.safehasattr(remote, 'branches'):
2043 if not util.safehasattr(remote, 'branches'):
2044 # enable in-client legacy support
2044 # enable in-client legacy support
2045 remote = localrepo.locallegacypeer(remote.local())
2045 remote = localrepo.locallegacypeer(remote.local())
2046 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2046 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2047 force=True)
2047 force=True)
2048 common = set(common)
2048 common = set(common)
2049 if not opts.get('nonheads'):
2049 if not opts.get('nonheads'):
2050 ui.write(("unpruned common: %s\n") %
2050 ui.write(("unpruned common: %s\n") %
2051 " ".join(sorted(short(n) for n in common)))
2051 " ".join(sorted(short(n) for n in common)))
2052 dag = dagutil.revlogdag(repo.changelog)
2052 dag = dagutil.revlogdag(repo.changelog)
2053 all = dag.ancestorset(dag.internalizeall(common))
2053 all = dag.ancestorset(dag.internalizeall(common))
2054 common = dag.externalizeall(dag.headsetofconnecteds(all))
2054 common = dag.externalizeall(dag.headsetofconnecteds(all))
2055 else:
2055 else:
2056 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2056 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2057 common = set(common)
2057 common = set(common)
2058 rheads = set(hds)
2058 rheads = set(hds)
2059 lheads = set(repo.heads())
2059 lheads = set(repo.heads())
2060 ui.write(("common heads: %s\n") %
2060 ui.write(("common heads: %s\n") %
2061 " ".join(sorted(short(n) for n in common)))
2061 " ".join(sorted(short(n) for n in common)))
2062 if lheads <= common:
2062 if lheads <= common:
2063 ui.write(("local is subset\n"))
2063 ui.write(("local is subset\n"))
2064 elif rheads <= common:
2064 elif rheads <= common:
2065 ui.write(("remote is subset\n"))
2065 ui.write(("remote is subset\n"))
2066
2066
2067 serverlogs = opts.get('serverlog')
2067 serverlogs = opts.get('serverlog')
2068 if serverlogs:
2068 if serverlogs:
2069 for filename in serverlogs:
2069 for filename in serverlogs:
2070 logfile = open(filename, 'r')
2070 logfile = open(filename, 'r')
2071 try:
2071 try:
2072 line = logfile.readline()
2072 line = logfile.readline()
2073 while line:
2073 while line:
2074 parts = line.strip().split(';')
2074 parts = line.strip().split(';')
2075 op = parts[1]
2075 op = parts[1]
2076 if op == 'cg':
2076 if op == 'cg':
2077 pass
2077 pass
2078 elif op == 'cgss':
2078 elif op == 'cgss':
2079 doit(parts[2].split(' '), parts[3].split(' '))
2079 doit(parts[2].split(' '), parts[3].split(' '))
2080 elif op == 'unb':
2080 elif op == 'unb':
2081 doit(parts[3].split(' '), parts[2].split(' '))
2081 doit(parts[3].split(' '), parts[2].split(' '))
2082 line = logfile.readline()
2082 line = logfile.readline()
2083 finally:
2083 finally:
2084 logfile.close()
2084 logfile.close()
2085
2085
2086 else:
2086 else:
2087 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2087 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2088 opts.get('remote_head'))
2088 opts.get('remote_head'))
2089 localrevs = opts.get('local_head')
2089 localrevs = opts.get('local_head')
2090 doit(localrevs, remoterevs)
2090 doit(localrevs, remoterevs)
2091
2091
2092 @command('debugfileset',
2092 @command('debugfileset',
2093 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2093 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2094 _('[-r REV] FILESPEC'))
2094 _('[-r REV] FILESPEC'))
2095 def debugfileset(ui, repo, expr, **opts):
2095 def debugfileset(ui, repo, expr, **opts):
2096 '''parse and apply a fileset specification'''
2096 '''parse and apply a fileset specification'''
2097 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2097 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2098 if ui.verbose:
2098 if ui.verbose:
2099 tree = fileset.parse(expr)[0]
2099 tree = fileset.parse(expr)[0]
2100 ui.note(tree, "\n")
2100 ui.note(tree, "\n")
2101
2101
2102 for f in ctx.getfileset(expr):
2102 for f in ctx.getfileset(expr):
2103 ui.write("%s\n" % f)
2103 ui.write("%s\n" % f)
2104
2104
2105 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2105 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2106 def debugfsinfo(ui, path="."):
2106 def debugfsinfo(ui, path="."):
2107 """show information detected about current filesystem"""
2107 """show information detected about current filesystem"""
2108 util.writefile('.debugfsinfo', '')
2108 util.writefile('.debugfsinfo', '')
2109 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2109 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2110 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2110 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2111 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2111 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2112 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2112 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2113 and 'yes' or 'no'))
2113 and 'yes' or 'no'))
2114 os.unlink('.debugfsinfo')
2114 os.unlink('.debugfsinfo')
2115
2115
2116 @command('debuggetbundle',
2116 @command('debuggetbundle',
2117 [('H', 'head', [], _('id of head node'), _('ID')),
2117 [('H', 'head', [], _('id of head node'), _('ID')),
2118 ('C', 'common', [], _('id of common node'), _('ID')),
2118 ('C', 'common', [], _('id of common node'), _('ID')),
2119 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2119 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2120 _('REPO FILE [-H|-C ID]...'),
2120 _('REPO FILE [-H|-C ID]...'),
2121 norepo=True)
2121 norepo=True)
2122 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2122 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2123 """retrieves a bundle from a repo
2123 """retrieves a bundle from a repo
2124
2124
2125 Every ID must be a full-length hex node id string. Saves the bundle to the
2125 Every ID must be a full-length hex node id string. Saves the bundle to the
2126 given file.
2126 given file.
2127 """
2127 """
2128 repo = hg.peer(ui, opts, repopath)
2128 repo = hg.peer(ui, opts, repopath)
2129 if not repo.capable('getbundle'):
2129 if not repo.capable('getbundle'):
2130 raise util.Abort("getbundle() not supported by target repository")
2130 raise util.Abort("getbundle() not supported by target repository")
2131 args = {}
2131 args = {}
2132 if common:
2132 if common:
2133 args['common'] = [bin(s) for s in common]
2133 args['common'] = [bin(s) for s in common]
2134 if head:
2134 if head:
2135 args['heads'] = [bin(s) for s in head]
2135 args['heads'] = [bin(s) for s in head]
2136 # TODO: get desired bundlecaps from command line.
2136 # TODO: get desired bundlecaps from command line.
2137 args['bundlecaps'] = None
2137 args['bundlecaps'] = None
2138 bundle = repo.getbundle('debug', **args)
2138 bundle = repo.getbundle('debug', **args)
2139
2139
2140 bundletype = opts.get('type', 'bzip2').lower()
2140 bundletype = opts.get('type', 'bzip2').lower()
2141 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2141 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2142 bundletype = btypes.get(bundletype)
2142 bundletype = btypes.get(bundletype)
2143 if bundletype not in changegroup.bundletypes:
2143 if bundletype not in changegroup.bundletypes:
2144 raise util.Abort(_('unknown bundle type specified with --type'))
2144 raise util.Abort(_('unknown bundle type specified with --type'))
2145 changegroup.writebundle(bundle, bundlepath, bundletype)
2145 changegroup.writebundle(bundle, bundlepath, bundletype)
2146
2146
2147 @command('debugignore', [], '')
2147 @command('debugignore', [], '')
2148 def debugignore(ui, repo, *values, **opts):
2148 def debugignore(ui, repo, *values, **opts):
2149 """display the combined ignore pattern"""
2149 """display the combined ignore pattern"""
2150 ignore = repo.dirstate._ignore
2150 ignore = repo.dirstate._ignore
2151 includepat = getattr(ignore, 'includepat', None)
2151 includepat = getattr(ignore, 'includepat', None)
2152 if includepat is not None:
2152 if includepat is not None:
2153 ui.write("%s\n" % includepat)
2153 ui.write("%s\n" % includepat)
2154 else:
2154 else:
2155 raise util.Abort(_("no ignore patterns found"))
2155 raise util.Abort(_("no ignore patterns found"))
2156
2156
2157 @command('debugindex',
2157 @command('debugindex',
2158 [('c', 'changelog', False, _('open changelog')),
2158 [('c', 'changelog', False, _('open changelog')),
2159 ('m', 'manifest', False, _('open manifest')),
2159 ('m', 'manifest', False, _('open manifest')),
2160 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2160 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2161 _('[-f FORMAT] -c|-m|FILE'),
2161 _('[-f FORMAT] -c|-m|FILE'),
2162 optionalrepo=True)
2162 optionalrepo=True)
2163 def debugindex(ui, repo, file_=None, **opts):
2163 def debugindex(ui, repo, file_=None, **opts):
2164 """dump the contents of an index file"""
2164 """dump the contents of an index file"""
2165 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2165 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2166 format = opts.get('format', 0)
2166 format = opts.get('format', 0)
2167 if format not in (0, 1):
2167 if format not in (0, 1):
2168 raise util.Abort(_("unknown format %d") % format)
2168 raise util.Abort(_("unknown format %d") % format)
2169
2169
2170 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2170 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2171 if generaldelta:
2171 if generaldelta:
2172 basehdr = ' delta'
2172 basehdr = ' delta'
2173 else:
2173 else:
2174 basehdr = ' base'
2174 basehdr = ' base'
2175
2175
2176 if ui.debugflag:
2176 if ui.debugflag:
2177 shortfn = hex
2177 shortfn = hex
2178 else:
2178 else:
2179 shortfn = short
2179 shortfn = short
2180
2180
2181 # There might not be anything in r, so have a sane default
2181 # There might not be anything in r, so have a sane default
2182 idlen = 12
2182 idlen = 12
2183 for i in r:
2183 for i in r:
2184 idlen = len(shortfn(r.node(i)))
2184 idlen = len(shortfn(r.node(i)))
2185 break
2185 break
2186
2186
2187 if format == 0:
2187 if format == 0:
2188 ui.write(" rev offset length " + basehdr + " linkrev"
2188 ui.write(" rev offset length " + basehdr + " linkrev"
2189 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2189 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2190 elif format == 1:
2190 elif format == 1:
2191 ui.write(" rev flag offset length"
2191 ui.write(" rev flag offset length"
2192 " size " + basehdr + " link p1 p2"
2192 " size " + basehdr + " link p1 p2"
2193 " %s\n" % "nodeid".rjust(idlen))
2193 " %s\n" % "nodeid".rjust(idlen))
2194
2194
2195 for i in r:
2195 for i in r:
2196 node = r.node(i)
2196 node = r.node(i)
2197 if generaldelta:
2197 if generaldelta:
2198 base = r.deltaparent(i)
2198 base = r.deltaparent(i)
2199 else:
2199 else:
2200 base = r.chainbase(i)
2200 base = r.chainbase(i)
2201 if format == 0:
2201 if format == 0:
2202 try:
2202 try:
2203 pp = r.parents(node)
2203 pp = r.parents(node)
2204 except Exception:
2204 except Exception:
2205 pp = [nullid, nullid]
2205 pp = [nullid, nullid]
2206 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2206 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2207 i, r.start(i), r.length(i), base, r.linkrev(i),
2207 i, r.start(i), r.length(i), base, r.linkrev(i),
2208 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2208 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2209 elif format == 1:
2209 elif format == 1:
2210 pr = r.parentrevs(i)
2210 pr = r.parentrevs(i)
2211 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2211 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2212 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2212 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2213 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2213 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2214
2214
2215 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2215 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2216 def debugindexdot(ui, repo, file_):
2216 def debugindexdot(ui, repo, file_):
2217 """dump an index DAG as a graphviz dot file"""
2217 """dump an index DAG as a graphviz dot file"""
2218 r = None
2218 r = None
2219 if repo:
2219 if repo:
2220 filelog = repo.file(file_)
2220 filelog = repo.file(file_)
2221 if len(filelog):
2221 if len(filelog):
2222 r = filelog
2222 r = filelog
2223 if not r:
2223 if not r:
2224 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2224 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2225 ui.write(("digraph G {\n"))
2225 ui.write(("digraph G {\n"))
2226 for i in r:
2226 for i in r:
2227 node = r.node(i)
2227 node = r.node(i)
2228 pp = r.parents(node)
2228 pp = r.parents(node)
2229 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2229 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2230 if pp[1] != nullid:
2230 if pp[1] != nullid:
2231 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2231 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2232 ui.write("}\n")
2232 ui.write("}\n")
2233
2233
2234 @command('debuginstall', [], '', norepo=True)
2234 @command('debuginstall', [], '', norepo=True)
2235 def debuginstall(ui):
2235 def debuginstall(ui):
2236 '''test Mercurial installation
2236 '''test Mercurial installation
2237
2237
2238 Returns 0 on success.
2238 Returns 0 on success.
2239 '''
2239 '''
2240
2240
2241 def writetemp(contents):
2241 def writetemp(contents):
2242 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2242 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2243 f = os.fdopen(fd, "wb")
2243 f = os.fdopen(fd, "wb")
2244 f.write(contents)
2244 f.write(contents)
2245 f.close()
2245 f.close()
2246 return name
2246 return name
2247
2247
2248 problems = 0
2248 problems = 0
2249
2249
2250 # encoding
2250 # encoding
2251 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2251 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2252 try:
2252 try:
2253 encoding.fromlocal("test")
2253 encoding.fromlocal("test")
2254 except util.Abort, inst:
2254 except util.Abort, inst:
2255 ui.write(" %s\n" % inst)
2255 ui.write(" %s\n" % inst)
2256 ui.write(_(" (check that your locale is properly set)\n"))
2256 ui.write(_(" (check that your locale is properly set)\n"))
2257 problems += 1
2257 problems += 1
2258
2258
2259 # Python
2259 # Python
2260 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2260 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2261 ui.status(_("checking Python version (%s)\n")
2261 ui.status(_("checking Python version (%s)\n")
2262 % ("%s.%s.%s" % sys.version_info[:3]))
2262 % ("%s.%s.%s" % sys.version_info[:3]))
2263 ui.status(_("checking Python lib (%s)...\n")
2263 ui.status(_("checking Python lib (%s)...\n")
2264 % os.path.dirname(os.__file__))
2264 % os.path.dirname(os.__file__))
2265
2265
2266 # compiled modules
2266 # compiled modules
2267 ui.status(_("checking installed modules (%s)...\n")
2267 ui.status(_("checking installed modules (%s)...\n")
2268 % os.path.dirname(__file__))
2268 % os.path.dirname(__file__))
2269 try:
2269 try:
2270 import bdiff, mpatch, base85, osutil
2270 import bdiff, mpatch, base85, osutil
2271 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2271 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2272 except Exception, inst:
2272 except Exception, inst:
2273 ui.write(" %s\n" % inst)
2273 ui.write(" %s\n" % inst)
2274 ui.write(_(" One or more extensions could not be found"))
2274 ui.write(_(" One or more extensions could not be found"))
2275 ui.write(_(" (check that you compiled the extensions)\n"))
2275 ui.write(_(" (check that you compiled the extensions)\n"))
2276 problems += 1
2276 problems += 1
2277
2277
2278 # templates
2278 # templates
2279 import templater
2279 import templater
2280 p = templater.templatepaths()
2280 p = templater.templatepaths()
2281 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2281 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2282 if p:
2282 if p:
2283 m = templater.templatepath("map-cmdline.default")
2283 m = templater.templatepath("map-cmdline.default")
2284 if m:
2284 if m:
2285 # template found, check if it is working
2285 # template found, check if it is working
2286 try:
2286 try:
2287 templater.templater(m)
2287 templater.templater(m)
2288 except Exception, inst:
2288 except Exception, inst:
2289 ui.write(" %s\n" % inst)
2289 ui.write(" %s\n" % inst)
2290 p = None
2290 p = None
2291 else:
2291 else:
2292 ui.write(_(" template 'default' not found\n"))
2292 ui.write(_(" template 'default' not found\n"))
2293 p = None
2293 p = None
2294 else:
2294 else:
2295 ui.write(_(" no template directories found\n"))
2295 ui.write(_(" no template directories found\n"))
2296 if not p:
2296 if not p:
2297 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2297 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2298 problems += 1
2298 problems += 1
2299
2299
2300 # editor
2300 # editor
2301 ui.status(_("checking commit editor...\n"))
2301 ui.status(_("checking commit editor...\n"))
2302 editor = ui.geteditor()
2302 editor = ui.geteditor()
2303 cmdpath = util.findexe(shlex.split(editor)[0])
2303 cmdpath = util.findexe(shlex.split(editor)[0])
2304 if not cmdpath:
2304 if not cmdpath:
2305 if editor == 'vi':
2305 if editor == 'vi':
2306 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2306 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2307 ui.write(_(" (specify a commit editor in your configuration"
2307 ui.write(_(" (specify a commit editor in your configuration"
2308 " file)\n"))
2308 " file)\n"))
2309 else:
2309 else:
2310 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2310 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2311 ui.write(_(" (specify a commit editor in your configuration"
2311 ui.write(_(" (specify a commit editor in your configuration"
2312 " file)\n"))
2312 " file)\n"))
2313 problems += 1
2313 problems += 1
2314
2314
2315 # check username
2315 # check username
2316 ui.status(_("checking username...\n"))
2316 ui.status(_("checking username...\n"))
2317 try:
2317 try:
2318 ui.username()
2318 ui.username()
2319 except util.Abort, e:
2319 except util.Abort, e:
2320 ui.write(" %s\n" % e)
2320 ui.write(" %s\n" % e)
2321 ui.write(_(" (specify a username in your configuration file)\n"))
2321 ui.write(_(" (specify a username in your configuration file)\n"))
2322 problems += 1
2322 problems += 1
2323
2323
2324 if not problems:
2324 if not problems:
2325 ui.status(_("no problems detected\n"))
2325 ui.status(_("no problems detected\n"))
2326 else:
2326 else:
2327 ui.write(_("%s problems detected,"
2327 ui.write(_("%s problems detected,"
2328 " please check your install!\n") % problems)
2328 " please check your install!\n") % problems)
2329
2329
2330 return problems
2330 return problems
2331
2331
2332 @command('debugknown', [], _('REPO ID...'), norepo=True)
2332 @command('debugknown', [], _('REPO ID...'), norepo=True)
2333 def debugknown(ui, repopath, *ids, **opts):
2333 def debugknown(ui, repopath, *ids, **opts):
2334 """test whether node ids are known to a repo
2334 """test whether node ids are known to a repo
2335
2335
2336 Every ID must be a full-length hex node id string. Returns a list of 0s
2336 Every ID must be a full-length hex node id string. Returns a list of 0s
2337 and 1s indicating unknown/known.
2337 and 1s indicating unknown/known.
2338 """
2338 """
2339 repo = hg.peer(ui, opts, repopath)
2339 repo = hg.peer(ui, opts, repopath)
2340 if not repo.capable('known'):
2340 if not repo.capable('known'):
2341 raise util.Abort("known() not supported by target repository")
2341 raise util.Abort("known() not supported by target repository")
2342 flags = repo.known([bin(s) for s in ids])
2342 flags = repo.known([bin(s) for s in ids])
2343 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2343 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2344
2344
2345 @command('debuglabelcomplete', [], _('LABEL...'))
2345 @command('debuglabelcomplete', [], _('LABEL...'))
2346 def debuglabelcomplete(ui, repo, *args):
2346 def debuglabelcomplete(ui, repo, *args):
2347 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2347 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2348 debugnamecomplete(ui, repo, *args)
2348 debugnamecomplete(ui, repo, *args)
2349
2349
2350 @command('debugnamecomplete', [], _('NAME...'))
2350 @command('debugnamecomplete', [], _('NAME...'))
2351 def debugnamecomplete(ui, repo, *args):
2351 def debugnamecomplete(ui, repo, *args):
2352 '''complete "names" - tags, open branch names, bookmark names'''
2352 '''complete "names" - tags, open branch names, bookmark names'''
2353
2353
2354 names = set()
2354 names = set()
2355 names.update(t[0] for t in repo.tagslist())
2355 # since we previously only listed open branches, we will handle that
2356 names.update(repo._bookmarks.keys())
2356 # specially (after this for loop)
2357 for name, ns in repo.names.iteritems():
2358 if name != 'branches':
2359 names.update(ns.listnames(repo))
2357 names.update(tag for (tag, heads, tip, closed)
2360 names.update(tag for (tag, heads, tip, closed)
2358 in repo.branchmap().iterbranches() if not closed)
2361 in repo.branchmap().iterbranches() if not closed)
2359 completions = set()
2362 completions = set()
2360 if not args:
2363 if not args:
2361 args = ['']
2364 args = ['']
2362 for a in args:
2365 for a in args:
2363 completions.update(n for n in names if n.startswith(a))
2366 completions.update(n for n in names if n.startswith(a))
2364 ui.write('\n'.join(sorted(completions)))
2367 ui.write('\n'.join(sorted(completions)))
2365 ui.write('\n')
2368 ui.write('\n')
2366
2369
2367 @command('debuglocks',
2370 @command('debuglocks',
2368 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2371 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2369 ('W', 'force-wlock', None,
2372 ('W', 'force-wlock', None,
2370 _('free the working state lock (DANGEROUS)'))],
2373 _('free the working state lock (DANGEROUS)'))],
2371 _('[OPTION]...'))
2374 _('[OPTION]...'))
2372 def debuglocks(ui, repo, **opts):
2375 def debuglocks(ui, repo, **opts):
2373 """show or modify state of locks
2376 """show or modify state of locks
2374
2377
2375 By default, this command will show which locks are held. This
2378 By default, this command will show which locks are held. This
2376 includes the user and process holding the lock, the amount of time
2379 includes the user and process holding the lock, the amount of time
2377 the lock has been held, and the machine name where the process is
2380 the lock has been held, and the machine name where the process is
2378 running if it's not local.
2381 running if it's not local.
2379
2382
2380 Locks protect the integrity of Mercurial's data, so should be
2383 Locks protect the integrity of Mercurial's data, so should be
2381 treated with care. System crashes or other interruptions may cause
2384 treated with care. System crashes or other interruptions may cause
2382 locks to not be properly released, though Mercurial will usually
2385 locks to not be properly released, though Mercurial will usually
2383 detect and remove such stale locks automatically.
2386 detect and remove such stale locks automatically.
2384
2387
2385 However, detecting stale locks may not always be possible (for
2388 However, detecting stale locks may not always be possible (for
2386 instance, on a shared filesystem). Removing locks may also be
2389 instance, on a shared filesystem). Removing locks may also be
2387 blocked by filesystem permissions.
2390 blocked by filesystem permissions.
2388
2391
2389 Returns 0 if no locks are held.
2392 Returns 0 if no locks are held.
2390
2393
2391 """
2394 """
2392
2395
2393 if opts.get('force_lock'):
2396 if opts.get('force_lock'):
2394 repo.svfs.unlink('lock')
2397 repo.svfs.unlink('lock')
2395 if opts.get('force_wlock'):
2398 if opts.get('force_wlock'):
2396 repo.vfs.unlink('wlock')
2399 repo.vfs.unlink('wlock')
2397 if opts.get('force_lock') or opts.get('force_lock'):
2400 if opts.get('force_lock') or opts.get('force_lock'):
2398 return 0
2401 return 0
2399
2402
2400 now = time.time()
2403 now = time.time()
2401 held = 0
2404 held = 0
2402
2405
2403 def report(vfs, name, method):
2406 def report(vfs, name, method):
2404 # this causes stale locks to get reaped for more accurate reporting
2407 # this causes stale locks to get reaped for more accurate reporting
2405 try:
2408 try:
2406 l = method(False)
2409 l = method(False)
2407 except error.LockHeld:
2410 except error.LockHeld:
2408 l = None
2411 l = None
2409
2412
2410 if l:
2413 if l:
2411 l.release()
2414 l.release()
2412 else:
2415 else:
2413 try:
2416 try:
2414 stat = repo.svfs.lstat(name)
2417 stat = repo.svfs.lstat(name)
2415 age = now - stat.st_mtime
2418 age = now - stat.st_mtime
2416 user = util.username(stat.st_uid)
2419 user = util.username(stat.st_uid)
2417 locker = vfs.readlock(name)
2420 locker = vfs.readlock(name)
2418 if ":" in locker:
2421 if ":" in locker:
2419 host, pid = locker.split(':')
2422 host, pid = locker.split(':')
2420 if host == socket.gethostname():
2423 if host == socket.gethostname():
2421 locker = 'user %s, process %s' % (user, pid)
2424 locker = 'user %s, process %s' % (user, pid)
2422 else:
2425 else:
2423 locker = 'user %s, process %s, host %s' \
2426 locker = 'user %s, process %s, host %s' \
2424 % (user, pid, host)
2427 % (user, pid, host)
2425 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2428 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2426 return 1
2429 return 1
2427 except OSError, e:
2430 except OSError, e:
2428 if e.errno != errno.ENOENT:
2431 if e.errno != errno.ENOENT:
2429 raise
2432 raise
2430
2433
2431 ui.write("%-6s free\n" % (name + ":"))
2434 ui.write("%-6s free\n" % (name + ":"))
2432 return 0
2435 return 0
2433
2436
2434 held += report(repo.svfs, "lock", repo.lock)
2437 held += report(repo.svfs, "lock", repo.lock)
2435 held += report(repo.vfs, "wlock", repo.wlock)
2438 held += report(repo.vfs, "wlock", repo.wlock)
2436
2439
2437 return held
2440 return held
2438
2441
2439 @command('debugobsolete',
2442 @command('debugobsolete',
2440 [('', 'flags', 0, _('markers flag')),
2443 [('', 'flags', 0, _('markers flag')),
2441 ('', 'record-parents', False,
2444 ('', 'record-parents', False,
2442 _('record parent information for the precursor')),
2445 _('record parent information for the precursor')),
2443 ('r', 'rev', [], _('display markers relevant to REV')),
2446 ('r', 'rev', [], _('display markers relevant to REV')),
2444 ] + commitopts2,
2447 ] + commitopts2,
2445 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2448 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2446 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2449 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2447 """create arbitrary obsolete marker
2450 """create arbitrary obsolete marker
2448
2451
2449 With no arguments, displays the list of obsolescence markers."""
2452 With no arguments, displays the list of obsolescence markers."""
2450
2453
2451 def parsenodeid(s):
2454 def parsenodeid(s):
2452 try:
2455 try:
2453 # We do not use revsingle/revrange functions here to accept
2456 # We do not use revsingle/revrange functions here to accept
2454 # arbitrary node identifiers, possibly not present in the
2457 # arbitrary node identifiers, possibly not present in the
2455 # local repository.
2458 # local repository.
2456 n = bin(s)
2459 n = bin(s)
2457 if len(n) != len(nullid):
2460 if len(n) != len(nullid):
2458 raise TypeError()
2461 raise TypeError()
2459 return n
2462 return n
2460 except TypeError:
2463 except TypeError:
2461 raise util.Abort('changeset references must be full hexadecimal '
2464 raise util.Abort('changeset references must be full hexadecimal '
2462 'node identifiers')
2465 'node identifiers')
2463
2466
2464 if precursor is not None:
2467 if precursor is not None:
2465 if opts['rev']:
2468 if opts['rev']:
2466 raise util.Abort('cannot select revision when creating marker')
2469 raise util.Abort('cannot select revision when creating marker')
2467 metadata = {}
2470 metadata = {}
2468 metadata['user'] = opts['user'] or ui.username()
2471 metadata['user'] = opts['user'] or ui.username()
2469 succs = tuple(parsenodeid(succ) for succ in successors)
2472 succs = tuple(parsenodeid(succ) for succ in successors)
2470 l = repo.lock()
2473 l = repo.lock()
2471 try:
2474 try:
2472 tr = repo.transaction('debugobsolete')
2475 tr = repo.transaction('debugobsolete')
2473 try:
2476 try:
2474 try:
2477 try:
2475 date = opts.get('date')
2478 date = opts.get('date')
2476 if date:
2479 if date:
2477 date = util.parsedate(date)
2480 date = util.parsedate(date)
2478 else:
2481 else:
2479 date = None
2482 date = None
2480 prec = parsenodeid(precursor)
2483 prec = parsenodeid(precursor)
2481 parents = None
2484 parents = None
2482 if opts['record_parents']:
2485 if opts['record_parents']:
2483 if prec not in repo.unfiltered():
2486 if prec not in repo.unfiltered():
2484 raise util.Abort('cannot used --record-parents on '
2487 raise util.Abort('cannot used --record-parents on '
2485 'unknown changesets')
2488 'unknown changesets')
2486 parents = repo.unfiltered()[prec].parents()
2489 parents = repo.unfiltered()[prec].parents()
2487 parents = tuple(p.node() for p in parents)
2490 parents = tuple(p.node() for p in parents)
2488 repo.obsstore.create(tr, prec, succs, opts['flags'],
2491 repo.obsstore.create(tr, prec, succs, opts['flags'],
2489 parents=parents, date=date,
2492 parents=parents, date=date,
2490 metadata=metadata)
2493 metadata=metadata)
2491 tr.close()
2494 tr.close()
2492 except ValueError, exc:
2495 except ValueError, exc:
2493 raise util.Abort(_('bad obsmarker input: %s') % exc)
2496 raise util.Abort(_('bad obsmarker input: %s') % exc)
2494 finally:
2497 finally:
2495 tr.release()
2498 tr.release()
2496 finally:
2499 finally:
2497 l.release()
2500 l.release()
2498 else:
2501 else:
2499 if opts['rev']:
2502 if opts['rev']:
2500 revs = scmutil.revrange(repo, opts['rev'])
2503 revs = scmutil.revrange(repo, opts['rev'])
2501 nodes = [repo[r].node() for r in revs]
2504 nodes = [repo[r].node() for r in revs]
2502 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2505 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2503 markers.sort(key=lambda x: x._data)
2506 markers.sort(key=lambda x: x._data)
2504 else:
2507 else:
2505 markers = obsolete.getmarkers(repo)
2508 markers = obsolete.getmarkers(repo)
2506
2509
2507 for m in markers:
2510 for m in markers:
2508 cmdutil.showmarker(ui, m)
2511 cmdutil.showmarker(ui, m)
2509
2512
2510 @command('debugpathcomplete',
2513 @command('debugpathcomplete',
2511 [('f', 'full', None, _('complete an entire path')),
2514 [('f', 'full', None, _('complete an entire path')),
2512 ('n', 'normal', None, _('show only normal files')),
2515 ('n', 'normal', None, _('show only normal files')),
2513 ('a', 'added', None, _('show only added files')),
2516 ('a', 'added', None, _('show only added files')),
2514 ('r', 'removed', None, _('show only removed files'))],
2517 ('r', 'removed', None, _('show only removed files'))],
2515 _('FILESPEC...'))
2518 _('FILESPEC...'))
2516 def debugpathcomplete(ui, repo, *specs, **opts):
2519 def debugpathcomplete(ui, repo, *specs, **opts):
2517 '''complete part or all of a tracked path
2520 '''complete part or all of a tracked path
2518
2521
2519 This command supports shells that offer path name completion. It
2522 This command supports shells that offer path name completion. It
2520 currently completes only files already known to the dirstate.
2523 currently completes only files already known to the dirstate.
2521
2524
2522 Completion extends only to the next path segment unless
2525 Completion extends only to the next path segment unless
2523 --full is specified, in which case entire paths are used.'''
2526 --full is specified, in which case entire paths are used.'''
2524
2527
2525 def complete(path, acceptable):
2528 def complete(path, acceptable):
2526 dirstate = repo.dirstate
2529 dirstate = repo.dirstate
2527 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2530 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2528 rootdir = repo.root + os.sep
2531 rootdir = repo.root + os.sep
2529 if spec != repo.root and not spec.startswith(rootdir):
2532 if spec != repo.root and not spec.startswith(rootdir):
2530 return [], []
2533 return [], []
2531 if os.path.isdir(spec):
2534 if os.path.isdir(spec):
2532 spec += '/'
2535 spec += '/'
2533 spec = spec[len(rootdir):]
2536 spec = spec[len(rootdir):]
2534 fixpaths = os.sep != '/'
2537 fixpaths = os.sep != '/'
2535 if fixpaths:
2538 if fixpaths:
2536 spec = spec.replace(os.sep, '/')
2539 spec = spec.replace(os.sep, '/')
2537 speclen = len(spec)
2540 speclen = len(spec)
2538 fullpaths = opts['full']
2541 fullpaths = opts['full']
2539 files, dirs = set(), set()
2542 files, dirs = set(), set()
2540 adddir, addfile = dirs.add, files.add
2543 adddir, addfile = dirs.add, files.add
2541 for f, st in dirstate.iteritems():
2544 for f, st in dirstate.iteritems():
2542 if f.startswith(spec) and st[0] in acceptable:
2545 if f.startswith(spec) and st[0] in acceptable:
2543 if fixpaths:
2546 if fixpaths:
2544 f = f.replace('/', os.sep)
2547 f = f.replace('/', os.sep)
2545 if fullpaths:
2548 if fullpaths:
2546 addfile(f)
2549 addfile(f)
2547 continue
2550 continue
2548 s = f.find(os.sep, speclen)
2551 s = f.find(os.sep, speclen)
2549 if s >= 0:
2552 if s >= 0:
2550 adddir(f[:s])
2553 adddir(f[:s])
2551 else:
2554 else:
2552 addfile(f)
2555 addfile(f)
2553 return files, dirs
2556 return files, dirs
2554
2557
2555 acceptable = ''
2558 acceptable = ''
2556 if opts['normal']:
2559 if opts['normal']:
2557 acceptable += 'nm'
2560 acceptable += 'nm'
2558 if opts['added']:
2561 if opts['added']:
2559 acceptable += 'a'
2562 acceptable += 'a'
2560 if opts['removed']:
2563 if opts['removed']:
2561 acceptable += 'r'
2564 acceptable += 'r'
2562 cwd = repo.getcwd()
2565 cwd = repo.getcwd()
2563 if not specs:
2566 if not specs:
2564 specs = ['.']
2567 specs = ['.']
2565
2568
2566 files, dirs = set(), set()
2569 files, dirs = set(), set()
2567 for spec in specs:
2570 for spec in specs:
2568 f, d = complete(spec, acceptable or 'nmar')
2571 f, d = complete(spec, acceptable or 'nmar')
2569 files.update(f)
2572 files.update(f)
2570 dirs.update(d)
2573 dirs.update(d)
2571 files.update(dirs)
2574 files.update(dirs)
2572 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2575 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2573 ui.write('\n')
2576 ui.write('\n')
2574
2577
2575 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2578 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2576 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2579 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2577 '''access the pushkey key/value protocol
2580 '''access the pushkey key/value protocol
2578
2581
2579 With two args, list the keys in the given namespace.
2582 With two args, list the keys in the given namespace.
2580
2583
2581 With five args, set a key to new if it currently is set to old.
2584 With five args, set a key to new if it currently is set to old.
2582 Reports success or failure.
2585 Reports success or failure.
2583 '''
2586 '''
2584
2587
2585 target = hg.peer(ui, {}, repopath)
2588 target = hg.peer(ui, {}, repopath)
2586 if keyinfo:
2589 if keyinfo:
2587 key, old, new = keyinfo
2590 key, old, new = keyinfo
2588 r = target.pushkey(namespace, key, old, new)
2591 r = target.pushkey(namespace, key, old, new)
2589 ui.status(str(r) + '\n')
2592 ui.status(str(r) + '\n')
2590 return not r
2593 return not r
2591 else:
2594 else:
2592 for k, v in sorted(target.listkeys(namespace).iteritems()):
2595 for k, v in sorted(target.listkeys(namespace).iteritems()):
2593 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2596 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2594 v.encode('string-escape')))
2597 v.encode('string-escape')))
2595
2598
2596 @command('debugpvec', [], _('A B'))
2599 @command('debugpvec', [], _('A B'))
2597 def debugpvec(ui, repo, a, b=None):
2600 def debugpvec(ui, repo, a, b=None):
2598 ca = scmutil.revsingle(repo, a)
2601 ca = scmutil.revsingle(repo, a)
2599 cb = scmutil.revsingle(repo, b)
2602 cb = scmutil.revsingle(repo, b)
2600 pa = pvec.ctxpvec(ca)
2603 pa = pvec.ctxpvec(ca)
2601 pb = pvec.ctxpvec(cb)
2604 pb = pvec.ctxpvec(cb)
2602 if pa == pb:
2605 if pa == pb:
2603 rel = "="
2606 rel = "="
2604 elif pa > pb:
2607 elif pa > pb:
2605 rel = ">"
2608 rel = ">"
2606 elif pa < pb:
2609 elif pa < pb:
2607 rel = "<"
2610 rel = "<"
2608 elif pa | pb:
2611 elif pa | pb:
2609 rel = "|"
2612 rel = "|"
2610 ui.write(_("a: %s\n") % pa)
2613 ui.write(_("a: %s\n") % pa)
2611 ui.write(_("b: %s\n") % pb)
2614 ui.write(_("b: %s\n") % pb)
2612 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2615 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2613 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2616 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2614 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2617 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2615 pa.distance(pb), rel))
2618 pa.distance(pb), rel))
2616
2619
2617 @command('debugrebuilddirstate|debugrebuildstate',
2620 @command('debugrebuilddirstate|debugrebuildstate',
2618 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2621 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2619 _('[-r REV]'))
2622 _('[-r REV]'))
2620 def debugrebuilddirstate(ui, repo, rev):
2623 def debugrebuilddirstate(ui, repo, rev):
2621 """rebuild the dirstate as it would look like for the given revision
2624 """rebuild the dirstate as it would look like for the given revision
2622
2625
2623 If no revision is specified the first current parent will be used.
2626 If no revision is specified the first current parent will be used.
2624
2627
2625 The dirstate will be set to the files of the given revision.
2628 The dirstate will be set to the files of the given revision.
2626 The actual working directory content or existing dirstate
2629 The actual working directory content or existing dirstate
2627 information such as adds or removes is not considered.
2630 information such as adds or removes is not considered.
2628
2631
2629 One use of this command is to make the next :hg:`status` invocation
2632 One use of this command is to make the next :hg:`status` invocation
2630 check the actual file content.
2633 check the actual file content.
2631 """
2634 """
2632 ctx = scmutil.revsingle(repo, rev)
2635 ctx = scmutil.revsingle(repo, rev)
2633 wlock = repo.wlock()
2636 wlock = repo.wlock()
2634 try:
2637 try:
2635 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2638 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2636 finally:
2639 finally:
2637 wlock.release()
2640 wlock.release()
2638
2641
2639 @command('debugrename',
2642 @command('debugrename',
2640 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2643 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2641 _('[-r REV] FILE'))
2644 _('[-r REV] FILE'))
2642 def debugrename(ui, repo, file1, *pats, **opts):
2645 def debugrename(ui, repo, file1, *pats, **opts):
2643 """dump rename information"""
2646 """dump rename information"""
2644
2647
2645 ctx = scmutil.revsingle(repo, opts.get('rev'))
2648 ctx = scmutil.revsingle(repo, opts.get('rev'))
2646 m = scmutil.match(ctx, (file1,) + pats, opts)
2649 m = scmutil.match(ctx, (file1,) + pats, opts)
2647 for abs in ctx.walk(m):
2650 for abs in ctx.walk(m):
2648 fctx = ctx[abs]
2651 fctx = ctx[abs]
2649 o = fctx.filelog().renamed(fctx.filenode())
2652 o = fctx.filelog().renamed(fctx.filenode())
2650 rel = m.rel(abs)
2653 rel = m.rel(abs)
2651 if o:
2654 if o:
2652 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2655 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2653 else:
2656 else:
2654 ui.write(_("%s not renamed\n") % rel)
2657 ui.write(_("%s not renamed\n") % rel)
2655
2658
2656 @command('debugrevlog',
2659 @command('debugrevlog',
2657 [('c', 'changelog', False, _('open changelog')),
2660 [('c', 'changelog', False, _('open changelog')),
2658 ('m', 'manifest', False, _('open manifest')),
2661 ('m', 'manifest', False, _('open manifest')),
2659 ('d', 'dump', False, _('dump index data'))],
2662 ('d', 'dump', False, _('dump index data'))],
2660 _('-c|-m|FILE'),
2663 _('-c|-m|FILE'),
2661 optionalrepo=True)
2664 optionalrepo=True)
2662 def debugrevlog(ui, repo, file_=None, **opts):
2665 def debugrevlog(ui, repo, file_=None, **opts):
2663 """show data and statistics about a revlog"""
2666 """show data and statistics about a revlog"""
2664 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2667 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2665
2668
2666 if opts.get("dump"):
2669 if opts.get("dump"):
2667 numrevs = len(r)
2670 numrevs = len(r)
2668 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2671 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2669 " rawsize totalsize compression heads chainlen\n")
2672 " rawsize totalsize compression heads chainlen\n")
2670 ts = 0
2673 ts = 0
2671 heads = set()
2674 heads = set()
2672
2675
2673 for rev in xrange(numrevs):
2676 for rev in xrange(numrevs):
2674 dbase = r.deltaparent(rev)
2677 dbase = r.deltaparent(rev)
2675 if dbase == -1:
2678 if dbase == -1:
2676 dbase = rev
2679 dbase = rev
2677 cbase = r.chainbase(rev)
2680 cbase = r.chainbase(rev)
2678 clen = r.chainlen(rev)
2681 clen = r.chainlen(rev)
2679 p1, p2 = r.parentrevs(rev)
2682 p1, p2 = r.parentrevs(rev)
2680 rs = r.rawsize(rev)
2683 rs = r.rawsize(rev)
2681 ts = ts + rs
2684 ts = ts + rs
2682 heads -= set(r.parentrevs(rev))
2685 heads -= set(r.parentrevs(rev))
2683 heads.add(rev)
2686 heads.add(rev)
2684 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2687 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2685 "%11d %5d %8d\n" %
2688 "%11d %5d %8d\n" %
2686 (rev, p1, p2, r.start(rev), r.end(rev),
2689 (rev, p1, p2, r.start(rev), r.end(rev),
2687 r.start(dbase), r.start(cbase),
2690 r.start(dbase), r.start(cbase),
2688 r.start(p1), r.start(p2),
2691 r.start(p1), r.start(p2),
2689 rs, ts, ts / r.end(rev), len(heads), clen))
2692 rs, ts, ts / r.end(rev), len(heads), clen))
2690 return 0
2693 return 0
2691
2694
2692 v = r.version
2695 v = r.version
2693 format = v & 0xFFFF
2696 format = v & 0xFFFF
2694 flags = []
2697 flags = []
2695 gdelta = False
2698 gdelta = False
2696 if v & revlog.REVLOGNGINLINEDATA:
2699 if v & revlog.REVLOGNGINLINEDATA:
2697 flags.append('inline')
2700 flags.append('inline')
2698 if v & revlog.REVLOGGENERALDELTA:
2701 if v & revlog.REVLOGGENERALDELTA:
2699 gdelta = True
2702 gdelta = True
2700 flags.append('generaldelta')
2703 flags.append('generaldelta')
2701 if not flags:
2704 if not flags:
2702 flags = ['(none)']
2705 flags = ['(none)']
2703
2706
2704 nummerges = 0
2707 nummerges = 0
2705 numfull = 0
2708 numfull = 0
2706 numprev = 0
2709 numprev = 0
2707 nump1 = 0
2710 nump1 = 0
2708 nump2 = 0
2711 nump2 = 0
2709 numother = 0
2712 numother = 0
2710 nump1prev = 0
2713 nump1prev = 0
2711 nump2prev = 0
2714 nump2prev = 0
2712 chainlengths = []
2715 chainlengths = []
2713
2716
2714 datasize = [None, 0, 0L]
2717 datasize = [None, 0, 0L]
2715 fullsize = [None, 0, 0L]
2718 fullsize = [None, 0, 0L]
2716 deltasize = [None, 0, 0L]
2719 deltasize = [None, 0, 0L]
2717
2720
2718 def addsize(size, l):
2721 def addsize(size, l):
2719 if l[0] is None or size < l[0]:
2722 if l[0] is None or size < l[0]:
2720 l[0] = size
2723 l[0] = size
2721 if size > l[1]:
2724 if size > l[1]:
2722 l[1] = size
2725 l[1] = size
2723 l[2] += size
2726 l[2] += size
2724
2727
2725 numrevs = len(r)
2728 numrevs = len(r)
2726 for rev in xrange(numrevs):
2729 for rev in xrange(numrevs):
2727 p1, p2 = r.parentrevs(rev)
2730 p1, p2 = r.parentrevs(rev)
2728 delta = r.deltaparent(rev)
2731 delta = r.deltaparent(rev)
2729 if format > 0:
2732 if format > 0:
2730 addsize(r.rawsize(rev), datasize)
2733 addsize(r.rawsize(rev), datasize)
2731 if p2 != nullrev:
2734 if p2 != nullrev:
2732 nummerges += 1
2735 nummerges += 1
2733 size = r.length(rev)
2736 size = r.length(rev)
2734 if delta == nullrev:
2737 if delta == nullrev:
2735 chainlengths.append(0)
2738 chainlengths.append(0)
2736 numfull += 1
2739 numfull += 1
2737 addsize(size, fullsize)
2740 addsize(size, fullsize)
2738 else:
2741 else:
2739 chainlengths.append(chainlengths[delta] + 1)
2742 chainlengths.append(chainlengths[delta] + 1)
2740 addsize(size, deltasize)
2743 addsize(size, deltasize)
2741 if delta == rev - 1:
2744 if delta == rev - 1:
2742 numprev += 1
2745 numprev += 1
2743 if delta == p1:
2746 if delta == p1:
2744 nump1prev += 1
2747 nump1prev += 1
2745 elif delta == p2:
2748 elif delta == p2:
2746 nump2prev += 1
2749 nump2prev += 1
2747 elif delta == p1:
2750 elif delta == p1:
2748 nump1 += 1
2751 nump1 += 1
2749 elif delta == p2:
2752 elif delta == p2:
2750 nump2 += 1
2753 nump2 += 1
2751 elif delta != nullrev:
2754 elif delta != nullrev:
2752 numother += 1
2755 numother += 1
2753
2756
2754 # Adjust size min value for empty cases
2757 # Adjust size min value for empty cases
2755 for size in (datasize, fullsize, deltasize):
2758 for size in (datasize, fullsize, deltasize):
2756 if size[0] is None:
2759 if size[0] is None:
2757 size[0] = 0
2760 size[0] = 0
2758
2761
2759 numdeltas = numrevs - numfull
2762 numdeltas = numrevs - numfull
2760 numoprev = numprev - nump1prev - nump2prev
2763 numoprev = numprev - nump1prev - nump2prev
2761 totalrawsize = datasize[2]
2764 totalrawsize = datasize[2]
2762 datasize[2] /= numrevs
2765 datasize[2] /= numrevs
2763 fulltotal = fullsize[2]
2766 fulltotal = fullsize[2]
2764 fullsize[2] /= numfull
2767 fullsize[2] /= numfull
2765 deltatotal = deltasize[2]
2768 deltatotal = deltasize[2]
2766 if numrevs - numfull > 0:
2769 if numrevs - numfull > 0:
2767 deltasize[2] /= numrevs - numfull
2770 deltasize[2] /= numrevs - numfull
2768 totalsize = fulltotal + deltatotal
2771 totalsize = fulltotal + deltatotal
2769 avgchainlen = sum(chainlengths) / numrevs
2772 avgchainlen = sum(chainlengths) / numrevs
2770 compratio = totalrawsize / totalsize
2773 compratio = totalrawsize / totalsize
2771
2774
2772 basedfmtstr = '%%%dd\n'
2775 basedfmtstr = '%%%dd\n'
2773 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2776 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2774
2777
2775 def dfmtstr(max):
2778 def dfmtstr(max):
2776 return basedfmtstr % len(str(max))
2779 return basedfmtstr % len(str(max))
2777 def pcfmtstr(max, padding=0):
2780 def pcfmtstr(max, padding=0):
2778 return basepcfmtstr % (len(str(max)), ' ' * padding)
2781 return basepcfmtstr % (len(str(max)), ' ' * padding)
2779
2782
2780 def pcfmt(value, total):
2783 def pcfmt(value, total):
2781 return (value, 100 * float(value) / total)
2784 return (value, 100 * float(value) / total)
2782
2785
2783 ui.write(('format : %d\n') % format)
2786 ui.write(('format : %d\n') % format)
2784 ui.write(('flags : %s\n') % ', '.join(flags))
2787 ui.write(('flags : %s\n') % ', '.join(flags))
2785
2788
2786 ui.write('\n')
2789 ui.write('\n')
2787 fmt = pcfmtstr(totalsize)
2790 fmt = pcfmtstr(totalsize)
2788 fmt2 = dfmtstr(totalsize)
2791 fmt2 = dfmtstr(totalsize)
2789 ui.write(('revisions : ') + fmt2 % numrevs)
2792 ui.write(('revisions : ') + fmt2 % numrevs)
2790 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2793 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2791 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2794 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2792 ui.write(('revisions : ') + fmt2 % numrevs)
2795 ui.write(('revisions : ') + fmt2 % numrevs)
2793 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2796 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2794 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2797 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2795 ui.write(('revision size : ') + fmt2 % totalsize)
2798 ui.write(('revision size : ') + fmt2 % totalsize)
2796 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2799 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2797 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2800 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2798
2801
2799 ui.write('\n')
2802 ui.write('\n')
2800 fmt = dfmtstr(max(avgchainlen, compratio))
2803 fmt = dfmtstr(max(avgchainlen, compratio))
2801 ui.write(('avg chain length : ') + fmt % avgchainlen)
2804 ui.write(('avg chain length : ') + fmt % avgchainlen)
2802 ui.write(('compression ratio : ') + fmt % compratio)
2805 ui.write(('compression ratio : ') + fmt % compratio)
2803
2806
2804 if format > 0:
2807 if format > 0:
2805 ui.write('\n')
2808 ui.write('\n')
2806 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2809 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2807 % tuple(datasize))
2810 % tuple(datasize))
2808 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2811 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2809 % tuple(fullsize))
2812 % tuple(fullsize))
2810 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2813 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2811 % tuple(deltasize))
2814 % tuple(deltasize))
2812
2815
2813 if numdeltas > 0:
2816 if numdeltas > 0:
2814 ui.write('\n')
2817 ui.write('\n')
2815 fmt = pcfmtstr(numdeltas)
2818 fmt = pcfmtstr(numdeltas)
2816 fmt2 = pcfmtstr(numdeltas, 4)
2819 fmt2 = pcfmtstr(numdeltas, 4)
2817 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2820 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2818 if numprev > 0:
2821 if numprev > 0:
2819 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2822 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2820 numprev))
2823 numprev))
2821 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2824 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2822 numprev))
2825 numprev))
2823 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2826 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2824 numprev))
2827 numprev))
2825 if gdelta:
2828 if gdelta:
2826 ui.write(('deltas against p1 : ')
2829 ui.write(('deltas against p1 : ')
2827 + fmt % pcfmt(nump1, numdeltas))
2830 + fmt % pcfmt(nump1, numdeltas))
2828 ui.write(('deltas against p2 : ')
2831 ui.write(('deltas against p2 : ')
2829 + fmt % pcfmt(nump2, numdeltas))
2832 + fmt % pcfmt(nump2, numdeltas))
2830 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2833 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2831 numdeltas))
2834 numdeltas))
2832
2835
2833 @command('debugrevspec',
2836 @command('debugrevspec',
2834 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2837 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2835 ('REVSPEC'))
2838 ('REVSPEC'))
2836 def debugrevspec(ui, repo, expr, **opts):
2839 def debugrevspec(ui, repo, expr, **opts):
2837 """parse and apply a revision specification
2840 """parse and apply a revision specification
2838
2841
2839 Use --verbose to print the parsed tree before and after aliases
2842 Use --verbose to print the parsed tree before and after aliases
2840 expansion.
2843 expansion.
2841 """
2844 """
2842 if ui.verbose:
2845 if ui.verbose:
2843 tree = revset.parse(expr)[0]
2846 tree = revset.parse(expr)[0]
2844 ui.note(revset.prettyformat(tree), "\n")
2847 ui.note(revset.prettyformat(tree), "\n")
2845 newtree = revset.findaliases(ui, tree)
2848 newtree = revset.findaliases(ui, tree)
2846 if newtree != tree:
2849 if newtree != tree:
2847 ui.note(revset.prettyformat(newtree), "\n")
2850 ui.note(revset.prettyformat(newtree), "\n")
2848 tree = newtree
2851 tree = newtree
2849 newtree = revset.foldconcat(tree)
2852 newtree = revset.foldconcat(tree)
2850 if newtree != tree:
2853 if newtree != tree:
2851 ui.note(revset.prettyformat(newtree), "\n")
2854 ui.note(revset.prettyformat(newtree), "\n")
2852 if opts["optimize"]:
2855 if opts["optimize"]:
2853 weight, optimizedtree = revset.optimize(newtree, True)
2856 weight, optimizedtree = revset.optimize(newtree, True)
2854 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2857 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2855 func = revset.match(ui, expr)
2858 func = revset.match(ui, expr)
2856 for c in func(repo, revset.spanset(repo)):
2859 for c in func(repo, revset.spanset(repo)):
2857 ui.write("%s\n" % c)
2860 ui.write("%s\n" % c)
2858
2861
2859 @command('debugsetparents', [], _('REV1 [REV2]'))
2862 @command('debugsetparents', [], _('REV1 [REV2]'))
2860 def debugsetparents(ui, repo, rev1, rev2=None):
2863 def debugsetparents(ui, repo, rev1, rev2=None):
2861 """manually set the parents of the current working directory
2864 """manually set the parents of the current working directory
2862
2865
2863 This is useful for writing repository conversion tools, but should
2866 This is useful for writing repository conversion tools, but should
2864 be used with care.
2867 be used with care.
2865
2868
2866 Returns 0 on success.
2869 Returns 0 on success.
2867 """
2870 """
2868
2871
2869 r1 = scmutil.revsingle(repo, rev1).node()
2872 r1 = scmutil.revsingle(repo, rev1).node()
2870 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2873 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2871
2874
2872 wlock = repo.wlock()
2875 wlock = repo.wlock()
2873 try:
2876 try:
2874 repo.dirstate.beginparentchange()
2877 repo.dirstate.beginparentchange()
2875 repo.setparents(r1, r2)
2878 repo.setparents(r1, r2)
2876 repo.dirstate.endparentchange()
2879 repo.dirstate.endparentchange()
2877 finally:
2880 finally:
2878 wlock.release()
2881 wlock.release()
2879
2882
2880 @command('debugdirstate|debugstate',
2883 @command('debugdirstate|debugstate',
2881 [('', 'nodates', None, _('do not display the saved mtime')),
2884 [('', 'nodates', None, _('do not display the saved mtime')),
2882 ('', 'datesort', None, _('sort by saved mtime'))],
2885 ('', 'datesort', None, _('sort by saved mtime'))],
2883 _('[OPTION]...'))
2886 _('[OPTION]...'))
2884 def debugstate(ui, repo, nodates=None, datesort=None):
2887 def debugstate(ui, repo, nodates=None, datesort=None):
2885 """show the contents of the current dirstate"""
2888 """show the contents of the current dirstate"""
2886 timestr = ""
2889 timestr = ""
2887 showdate = not nodates
2890 showdate = not nodates
2888 if datesort:
2891 if datesort:
2889 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2892 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2890 else:
2893 else:
2891 keyfunc = None # sort by filename
2894 keyfunc = None # sort by filename
2892 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2895 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2893 if showdate:
2896 if showdate:
2894 if ent[3] == -1:
2897 if ent[3] == -1:
2895 # Pad or slice to locale representation
2898 # Pad or slice to locale representation
2896 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2899 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2897 time.localtime(0)))
2900 time.localtime(0)))
2898 timestr = 'unset'
2901 timestr = 'unset'
2899 timestr = (timestr[:locale_len] +
2902 timestr = (timestr[:locale_len] +
2900 ' ' * (locale_len - len(timestr)))
2903 ' ' * (locale_len - len(timestr)))
2901 else:
2904 else:
2902 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2905 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2903 time.localtime(ent[3]))
2906 time.localtime(ent[3]))
2904 if ent[1] & 020000:
2907 if ent[1] & 020000:
2905 mode = 'lnk'
2908 mode = 'lnk'
2906 else:
2909 else:
2907 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2910 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2908 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2911 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2909 for f in repo.dirstate.copies():
2912 for f in repo.dirstate.copies():
2910 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2913 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2911
2914
2912 @command('debugsub',
2915 @command('debugsub',
2913 [('r', 'rev', '',
2916 [('r', 'rev', '',
2914 _('revision to check'), _('REV'))],
2917 _('revision to check'), _('REV'))],
2915 _('[-r REV] [REV]'))
2918 _('[-r REV] [REV]'))
2916 def debugsub(ui, repo, rev=None):
2919 def debugsub(ui, repo, rev=None):
2917 ctx = scmutil.revsingle(repo, rev, None)
2920 ctx = scmutil.revsingle(repo, rev, None)
2918 for k, v in sorted(ctx.substate.items()):
2921 for k, v in sorted(ctx.substate.items()):
2919 ui.write(('path %s\n') % k)
2922 ui.write(('path %s\n') % k)
2920 ui.write((' source %s\n') % v[0])
2923 ui.write((' source %s\n') % v[0])
2921 ui.write((' revision %s\n') % v[1])
2924 ui.write((' revision %s\n') % v[1])
2922
2925
2923 @command('debugsuccessorssets',
2926 @command('debugsuccessorssets',
2924 [],
2927 [],
2925 _('[REV]'))
2928 _('[REV]'))
2926 def debugsuccessorssets(ui, repo, *revs):
2929 def debugsuccessorssets(ui, repo, *revs):
2927 """show set of successors for revision
2930 """show set of successors for revision
2928
2931
2929 A successors set of changeset A is a consistent group of revisions that
2932 A successors set of changeset A is a consistent group of revisions that
2930 succeed A. It contains non-obsolete changesets only.
2933 succeed A. It contains non-obsolete changesets only.
2931
2934
2932 In most cases a changeset A has a single successors set containing a single
2935 In most cases a changeset A has a single successors set containing a single
2933 successor (changeset A replaced by A').
2936 successor (changeset A replaced by A').
2934
2937
2935 A changeset that is made obsolete with no successors are called "pruned".
2938 A changeset that is made obsolete with no successors are called "pruned".
2936 Such changesets have no successors sets at all.
2939 Such changesets have no successors sets at all.
2937
2940
2938 A changeset that has been "split" will have a successors set containing
2941 A changeset that has been "split" will have a successors set containing
2939 more than one successor.
2942 more than one successor.
2940
2943
2941 A changeset that has been rewritten in multiple different ways is called
2944 A changeset that has been rewritten in multiple different ways is called
2942 "divergent". Such changesets have multiple successor sets (each of which
2945 "divergent". Such changesets have multiple successor sets (each of which
2943 may also be split, i.e. have multiple successors).
2946 may also be split, i.e. have multiple successors).
2944
2947
2945 Results are displayed as follows::
2948 Results are displayed as follows::
2946
2949
2947 <rev1>
2950 <rev1>
2948 <successors-1A>
2951 <successors-1A>
2949 <rev2>
2952 <rev2>
2950 <successors-2A>
2953 <successors-2A>
2951 <successors-2B1> <successors-2B2> <successors-2B3>
2954 <successors-2B1> <successors-2B2> <successors-2B3>
2952
2955
2953 Here rev2 has two possible (i.e. divergent) successors sets. The first
2956 Here rev2 has two possible (i.e. divergent) successors sets. The first
2954 holds one element, whereas the second holds three (i.e. the changeset has
2957 holds one element, whereas the second holds three (i.e. the changeset has
2955 been split).
2958 been split).
2956 """
2959 """
2957 # passed to successorssets caching computation from one call to another
2960 # passed to successorssets caching computation from one call to another
2958 cache = {}
2961 cache = {}
2959 ctx2str = str
2962 ctx2str = str
2960 node2str = short
2963 node2str = short
2961 if ui.debug():
2964 if ui.debug():
2962 def ctx2str(ctx):
2965 def ctx2str(ctx):
2963 return ctx.hex()
2966 return ctx.hex()
2964 node2str = hex
2967 node2str = hex
2965 for rev in scmutil.revrange(repo, revs):
2968 for rev in scmutil.revrange(repo, revs):
2966 ctx = repo[rev]
2969 ctx = repo[rev]
2967 ui.write('%s\n'% ctx2str(ctx))
2970 ui.write('%s\n'% ctx2str(ctx))
2968 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2971 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2969 if succsset:
2972 if succsset:
2970 ui.write(' ')
2973 ui.write(' ')
2971 ui.write(node2str(succsset[0]))
2974 ui.write(node2str(succsset[0]))
2972 for node in succsset[1:]:
2975 for node in succsset[1:]:
2973 ui.write(' ')
2976 ui.write(' ')
2974 ui.write(node2str(node))
2977 ui.write(node2str(node))
2975 ui.write('\n')
2978 ui.write('\n')
2976
2979
2977 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2980 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2978 def debugwalk(ui, repo, *pats, **opts):
2981 def debugwalk(ui, repo, *pats, **opts):
2979 """show how files match on given patterns"""
2982 """show how files match on given patterns"""
2980 m = scmutil.match(repo[None], pats, opts)
2983 m = scmutil.match(repo[None], pats, opts)
2981 items = list(repo.walk(m))
2984 items = list(repo.walk(m))
2982 if not items:
2985 if not items:
2983 return
2986 return
2984 f = lambda fn: fn
2987 f = lambda fn: fn
2985 if ui.configbool('ui', 'slash') and os.sep != '/':
2988 if ui.configbool('ui', 'slash') and os.sep != '/':
2986 f = lambda fn: util.normpath(fn)
2989 f = lambda fn: util.normpath(fn)
2987 fmt = 'f %%-%ds %%-%ds %%s' % (
2990 fmt = 'f %%-%ds %%-%ds %%s' % (
2988 max([len(abs) for abs in items]),
2991 max([len(abs) for abs in items]),
2989 max([len(m.rel(abs)) for abs in items]))
2992 max([len(m.rel(abs)) for abs in items]))
2990 for abs in items:
2993 for abs in items:
2991 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2994 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2992 ui.write("%s\n" % line.rstrip())
2995 ui.write("%s\n" % line.rstrip())
2993
2996
2994 @command('debugwireargs',
2997 @command('debugwireargs',
2995 [('', 'three', '', 'three'),
2998 [('', 'three', '', 'three'),
2996 ('', 'four', '', 'four'),
2999 ('', 'four', '', 'four'),
2997 ('', 'five', '', 'five'),
3000 ('', 'five', '', 'five'),
2998 ] + remoteopts,
3001 ] + remoteopts,
2999 _('REPO [OPTIONS]... [ONE [TWO]]'),
3002 _('REPO [OPTIONS]... [ONE [TWO]]'),
3000 norepo=True)
3003 norepo=True)
3001 def debugwireargs(ui, repopath, *vals, **opts):
3004 def debugwireargs(ui, repopath, *vals, **opts):
3002 repo = hg.peer(ui, opts, repopath)
3005 repo = hg.peer(ui, opts, repopath)
3003 for opt in remoteopts:
3006 for opt in remoteopts:
3004 del opts[opt[1]]
3007 del opts[opt[1]]
3005 args = {}
3008 args = {}
3006 for k, v in opts.iteritems():
3009 for k, v in opts.iteritems():
3007 if v:
3010 if v:
3008 args[k] = v
3011 args[k] = v
3009 # run twice to check that we don't mess up the stream for the next command
3012 # run twice to check that we don't mess up the stream for the next command
3010 res1 = repo.debugwireargs(*vals, **args)
3013 res1 = repo.debugwireargs(*vals, **args)
3011 res2 = repo.debugwireargs(*vals, **args)
3014 res2 = repo.debugwireargs(*vals, **args)
3012 ui.write("%s\n" % res1)
3015 ui.write("%s\n" % res1)
3013 if res1 != res2:
3016 if res1 != res2:
3014 ui.warn("%s\n" % res2)
3017 ui.warn("%s\n" % res2)
3015
3018
3016 @command('^diff',
3019 @command('^diff',
3017 [('r', 'rev', [], _('revision'), _('REV')),
3020 [('r', 'rev', [], _('revision'), _('REV')),
3018 ('c', 'change', '', _('change made by revision'), _('REV'))
3021 ('c', 'change', '', _('change made by revision'), _('REV'))
3019 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3022 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3020 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3023 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3021 inferrepo=True)
3024 inferrepo=True)
3022 def diff(ui, repo, *pats, **opts):
3025 def diff(ui, repo, *pats, **opts):
3023 """diff repository (or selected files)
3026 """diff repository (or selected files)
3024
3027
3025 Show differences between revisions for the specified files.
3028 Show differences between revisions for the specified files.
3026
3029
3027 Differences between files are shown using the unified diff format.
3030 Differences between files are shown using the unified diff format.
3028
3031
3029 .. note::
3032 .. note::
3030
3033
3031 diff may generate unexpected results for merges, as it will
3034 diff may generate unexpected results for merges, as it will
3032 default to comparing against the working directory's first
3035 default to comparing against the working directory's first
3033 parent changeset if no revisions are specified.
3036 parent changeset if no revisions are specified.
3034
3037
3035 When two revision arguments are given, then changes are shown
3038 When two revision arguments are given, then changes are shown
3036 between those revisions. If only one revision is specified then
3039 between those revisions. If only one revision is specified then
3037 that revision is compared to the working directory, and, when no
3040 that revision is compared to the working directory, and, when no
3038 revisions are specified, the working directory files are compared
3041 revisions are specified, the working directory files are compared
3039 to its parent.
3042 to its parent.
3040
3043
3041 Alternatively you can specify -c/--change with a revision to see
3044 Alternatively you can specify -c/--change with a revision to see
3042 the changes in that changeset relative to its first parent.
3045 the changes in that changeset relative to its first parent.
3043
3046
3044 Without the -a/--text option, diff will avoid generating diffs of
3047 Without the -a/--text option, diff will avoid generating diffs of
3045 files it detects as binary. With -a, diff will generate a diff
3048 files it detects as binary. With -a, diff will generate a diff
3046 anyway, probably with undesirable results.
3049 anyway, probably with undesirable results.
3047
3050
3048 Use the -g/--git option to generate diffs in the git extended diff
3051 Use the -g/--git option to generate diffs in the git extended diff
3049 format. For more information, read :hg:`help diffs`.
3052 format. For more information, read :hg:`help diffs`.
3050
3053
3051 .. container:: verbose
3054 .. container:: verbose
3052
3055
3053 Examples:
3056 Examples:
3054
3057
3055 - compare a file in the current working directory to its parent::
3058 - compare a file in the current working directory to its parent::
3056
3059
3057 hg diff foo.c
3060 hg diff foo.c
3058
3061
3059 - compare two historical versions of a directory, with rename info::
3062 - compare two historical versions of a directory, with rename info::
3060
3063
3061 hg diff --git -r 1.0:1.2 lib/
3064 hg diff --git -r 1.0:1.2 lib/
3062
3065
3063 - get change stats relative to the last change on some date::
3066 - get change stats relative to the last change on some date::
3064
3067
3065 hg diff --stat -r "date('may 2')"
3068 hg diff --stat -r "date('may 2')"
3066
3069
3067 - diff all newly-added files that contain a keyword::
3070 - diff all newly-added files that contain a keyword::
3068
3071
3069 hg diff "set:added() and grep(GNU)"
3072 hg diff "set:added() and grep(GNU)"
3070
3073
3071 - compare a revision and its parents::
3074 - compare a revision and its parents::
3072
3075
3073 hg diff -c 9353 # compare against first parent
3076 hg diff -c 9353 # compare against first parent
3074 hg diff -r 9353^:9353 # same using revset syntax
3077 hg diff -r 9353^:9353 # same using revset syntax
3075 hg diff -r 9353^2:9353 # compare against the second parent
3078 hg diff -r 9353^2:9353 # compare against the second parent
3076
3079
3077 Returns 0 on success.
3080 Returns 0 on success.
3078 """
3081 """
3079
3082
3080 revs = opts.get('rev')
3083 revs = opts.get('rev')
3081 change = opts.get('change')
3084 change = opts.get('change')
3082 stat = opts.get('stat')
3085 stat = opts.get('stat')
3083 reverse = opts.get('reverse')
3086 reverse = opts.get('reverse')
3084
3087
3085 if revs and change:
3088 if revs and change:
3086 msg = _('cannot specify --rev and --change at the same time')
3089 msg = _('cannot specify --rev and --change at the same time')
3087 raise util.Abort(msg)
3090 raise util.Abort(msg)
3088 elif change:
3091 elif change:
3089 node2 = scmutil.revsingle(repo, change, None).node()
3092 node2 = scmutil.revsingle(repo, change, None).node()
3090 node1 = repo[node2].p1().node()
3093 node1 = repo[node2].p1().node()
3091 else:
3094 else:
3092 node1, node2 = scmutil.revpair(repo, revs)
3095 node1, node2 = scmutil.revpair(repo, revs)
3093
3096
3094 if reverse:
3097 if reverse:
3095 node1, node2 = node2, node1
3098 node1, node2 = node2, node1
3096
3099
3097 diffopts = patch.diffallopts(ui, opts)
3100 diffopts = patch.diffallopts(ui, opts)
3098 m = scmutil.match(repo[node2], pats, opts)
3101 m = scmutil.match(repo[node2], pats, opts)
3099 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3102 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3100 listsubrepos=opts.get('subrepos'))
3103 listsubrepos=opts.get('subrepos'))
3101
3104
3102 @command('^export',
3105 @command('^export',
3103 [('o', 'output', '',
3106 [('o', 'output', '',
3104 _('print output to file with formatted name'), _('FORMAT')),
3107 _('print output to file with formatted name'), _('FORMAT')),
3105 ('', 'switch-parent', None, _('diff against the second parent')),
3108 ('', 'switch-parent', None, _('diff against the second parent')),
3106 ('r', 'rev', [], _('revisions to export'), _('REV')),
3109 ('r', 'rev', [], _('revisions to export'), _('REV')),
3107 ] + diffopts,
3110 ] + diffopts,
3108 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3111 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3109 def export(ui, repo, *changesets, **opts):
3112 def export(ui, repo, *changesets, **opts):
3110 """dump the header and diffs for one or more changesets
3113 """dump the header and diffs for one or more changesets
3111
3114
3112 Print the changeset header and diffs for one or more revisions.
3115 Print the changeset header and diffs for one or more revisions.
3113 If no revision is given, the parent of the working directory is used.
3116 If no revision is given, the parent of the working directory is used.
3114
3117
3115 The information shown in the changeset header is: author, date,
3118 The information shown in the changeset header is: author, date,
3116 branch name (if non-default), changeset hash, parent(s) and commit
3119 branch name (if non-default), changeset hash, parent(s) and commit
3117 comment.
3120 comment.
3118
3121
3119 .. note::
3122 .. note::
3120
3123
3121 export may generate unexpected diff output for merge
3124 export may generate unexpected diff output for merge
3122 changesets, as it will compare the merge changeset against its
3125 changesets, as it will compare the merge changeset against its
3123 first parent only.
3126 first parent only.
3124
3127
3125 Output may be to a file, in which case the name of the file is
3128 Output may be to a file, in which case the name of the file is
3126 given using a format string. The formatting rules are as follows:
3129 given using a format string. The formatting rules are as follows:
3127
3130
3128 :``%%``: literal "%" character
3131 :``%%``: literal "%" character
3129 :``%H``: changeset hash (40 hexadecimal digits)
3132 :``%H``: changeset hash (40 hexadecimal digits)
3130 :``%N``: number of patches being generated
3133 :``%N``: number of patches being generated
3131 :``%R``: changeset revision number
3134 :``%R``: changeset revision number
3132 :``%b``: basename of the exporting repository
3135 :``%b``: basename of the exporting repository
3133 :``%h``: short-form changeset hash (12 hexadecimal digits)
3136 :``%h``: short-form changeset hash (12 hexadecimal digits)
3134 :``%m``: first line of the commit message (only alphanumeric characters)
3137 :``%m``: first line of the commit message (only alphanumeric characters)
3135 :``%n``: zero-padded sequence number, starting at 1
3138 :``%n``: zero-padded sequence number, starting at 1
3136 :``%r``: zero-padded changeset revision number
3139 :``%r``: zero-padded changeset revision number
3137
3140
3138 Without the -a/--text option, export will avoid generating diffs
3141 Without the -a/--text option, export will avoid generating diffs
3139 of files it detects as binary. With -a, export will generate a
3142 of files it detects as binary. With -a, export will generate a
3140 diff anyway, probably with undesirable results.
3143 diff anyway, probably with undesirable results.
3141
3144
3142 Use the -g/--git option to generate diffs in the git extended diff
3145 Use the -g/--git option to generate diffs in the git extended diff
3143 format. See :hg:`help diffs` for more information.
3146 format. See :hg:`help diffs` for more information.
3144
3147
3145 With the --switch-parent option, the diff will be against the
3148 With the --switch-parent option, the diff will be against the
3146 second parent. It can be useful to review a merge.
3149 second parent. It can be useful to review a merge.
3147
3150
3148 .. container:: verbose
3151 .. container:: verbose
3149
3152
3150 Examples:
3153 Examples:
3151
3154
3152 - use export and import to transplant a bugfix to the current
3155 - use export and import to transplant a bugfix to the current
3153 branch::
3156 branch::
3154
3157
3155 hg export -r 9353 | hg import -
3158 hg export -r 9353 | hg import -
3156
3159
3157 - export all the changesets between two revisions to a file with
3160 - export all the changesets between two revisions to a file with
3158 rename information::
3161 rename information::
3159
3162
3160 hg export --git -r 123:150 > changes.txt
3163 hg export --git -r 123:150 > changes.txt
3161
3164
3162 - split outgoing changes into a series of patches with
3165 - split outgoing changes into a series of patches with
3163 descriptive names::
3166 descriptive names::
3164
3167
3165 hg export -r "outgoing()" -o "%n-%m.patch"
3168 hg export -r "outgoing()" -o "%n-%m.patch"
3166
3169
3167 Returns 0 on success.
3170 Returns 0 on success.
3168 """
3171 """
3169 changesets += tuple(opts.get('rev', []))
3172 changesets += tuple(opts.get('rev', []))
3170 if not changesets:
3173 if not changesets:
3171 changesets = ['.']
3174 changesets = ['.']
3172 revs = scmutil.revrange(repo, changesets)
3175 revs = scmutil.revrange(repo, changesets)
3173 if not revs:
3176 if not revs:
3174 raise util.Abort(_("export requires at least one changeset"))
3177 raise util.Abort(_("export requires at least one changeset"))
3175 if len(revs) > 1:
3178 if len(revs) > 1:
3176 ui.note(_('exporting patches:\n'))
3179 ui.note(_('exporting patches:\n'))
3177 else:
3180 else:
3178 ui.note(_('exporting patch:\n'))
3181 ui.note(_('exporting patch:\n'))
3179 cmdutil.export(repo, revs, template=opts.get('output'),
3182 cmdutil.export(repo, revs, template=opts.get('output'),
3180 switch_parent=opts.get('switch_parent'),
3183 switch_parent=opts.get('switch_parent'),
3181 opts=patch.diffallopts(ui, opts))
3184 opts=patch.diffallopts(ui, opts))
3182
3185
3183 @command('files',
3186 @command('files',
3184 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3187 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3185 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3188 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3186 ] + walkopts + formatteropts,
3189 ] + walkopts + formatteropts,
3187 _('[OPTION]... [PATTERN]...'))
3190 _('[OPTION]... [PATTERN]...'))
3188 def files(ui, repo, *pats, **opts):
3191 def files(ui, repo, *pats, **opts):
3189 """list tracked files
3192 """list tracked files
3190
3193
3191 Print files under Mercurial control in the working directory or
3194 Print files under Mercurial control in the working directory or
3192 specified revision whose names match the given patterns (excluding
3195 specified revision whose names match the given patterns (excluding
3193 removed files).
3196 removed files).
3194
3197
3195 If no patterns are given to match, this command prints the names
3198 If no patterns are given to match, this command prints the names
3196 of all files under Mercurial control in the working copy.
3199 of all files under Mercurial control in the working copy.
3197
3200
3198 .. container:: verbose
3201 .. container:: verbose
3199
3202
3200 Examples:
3203 Examples:
3201
3204
3202 - list all files under the current directory::
3205 - list all files under the current directory::
3203
3206
3204 hg files .
3207 hg files .
3205
3208
3206 - shows sizes and flags for current revision::
3209 - shows sizes and flags for current revision::
3207
3210
3208 hg files -vr .
3211 hg files -vr .
3209
3212
3210 - list all files named README::
3213 - list all files named README::
3211
3214
3212 hg files -I "**/README"
3215 hg files -I "**/README"
3213
3216
3214 - list all binary files::
3217 - list all binary files::
3215
3218
3216 hg files "set:binary()"
3219 hg files "set:binary()"
3217
3220
3218 - find files containing a regular expression::
3221 - find files containing a regular expression::
3219
3222
3220 hg files "set:grep('bob')"
3223 hg files "set:grep('bob')"
3221
3224
3222 - search tracked file contents with xargs and grep::
3225 - search tracked file contents with xargs and grep::
3223
3226
3224 hg files -0 | xargs -0 grep foo
3227 hg files -0 | xargs -0 grep foo
3225
3228
3226 See :hg:`help patterns` and :hg:`help filesets` for more information
3229 See :hg:`help patterns` and :hg:`help filesets` for more information
3227 on specifying file patterns.
3230 on specifying file patterns.
3228
3231
3229 Returns 0 if a match is found, 1 otherwise.
3232 Returns 0 if a match is found, 1 otherwise.
3230
3233
3231 """
3234 """
3232 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3235 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3233 rev = ctx.rev()
3236 rev = ctx.rev()
3234 ret = 1
3237 ret = 1
3235
3238
3236 end = '\n'
3239 end = '\n'
3237 if opts.get('print0'):
3240 if opts.get('print0'):
3238 end = '\0'
3241 end = '\0'
3239 fm = ui.formatter('files', opts)
3242 fm = ui.formatter('files', opts)
3240 fmt = '%s' + end
3243 fmt = '%s' + end
3241
3244
3242 m = scmutil.match(ctx, pats, opts)
3245 m = scmutil.match(ctx, pats, opts)
3243 ds = repo.dirstate
3246 ds = repo.dirstate
3244 for f in ctx.matches(m):
3247 for f in ctx.matches(m):
3245 if rev is None and ds[f] == 'r':
3248 if rev is None and ds[f] == 'r':
3246 continue
3249 continue
3247 fm.startitem()
3250 fm.startitem()
3248 if ui.verbose:
3251 if ui.verbose:
3249 fc = ctx[f]
3252 fc = ctx[f]
3250 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3253 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3251 fm.data(abspath=f)
3254 fm.data(abspath=f)
3252 fm.write('path', fmt, m.rel(f))
3255 fm.write('path', fmt, m.rel(f))
3253 ret = 0
3256 ret = 0
3254
3257
3255 fm.end()
3258 fm.end()
3256
3259
3257 return ret
3260 return ret
3258
3261
3259 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3262 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3260 def forget(ui, repo, *pats, **opts):
3263 def forget(ui, repo, *pats, **opts):
3261 """forget the specified files on the next commit
3264 """forget the specified files on the next commit
3262
3265
3263 Mark the specified files so they will no longer be tracked
3266 Mark the specified files so they will no longer be tracked
3264 after the next commit.
3267 after the next commit.
3265
3268
3266 This only removes files from the current branch, not from the
3269 This only removes files from the current branch, not from the
3267 entire project history, and it does not delete them from the
3270 entire project history, and it does not delete them from the
3268 working directory.
3271 working directory.
3269
3272
3270 To undo a forget before the next commit, see :hg:`add`.
3273 To undo a forget before the next commit, see :hg:`add`.
3271
3274
3272 .. container:: verbose
3275 .. container:: verbose
3273
3276
3274 Examples:
3277 Examples:
3275
3278
3276 - forget newly-added binary files::
3279 - forget newly-added binary files::
3277
3280
3278 hg forget "set:added() and binary()"
3281 hg forget "set:added() and binary()"
3279
3282
3280 - forget files that would be excluded by .hgignore::
3283 - forget files that would be excluded by .hgignore::
3281
3284
3282 hg forget "set:hgignore()"
3285 hg forget "set:hgignore()"
3283
3286
3284 Returns 0 on success.
3287 Returns 0 on success.
3285 """
3288 """
3286
3289
3287 if not pats:
3290 if not pats:
3288 raise util.Abort(_('no files specified'))
3291 raise util.Abort(_('no files specified'))
3289
3292
3290 m = scmutil.match(repo[None], pats, opts)
3293 m = scmutil.match(repo[None], pats, opts)
3291 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3294 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3292 return rejected and 1 or 0
3295 return rejected and 1 or 0
3293
3296
3294 @command(
3297 @command(
3295 'graft',
3298 'graft',
3296 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3299 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3297 ('c', 'continue', False, _('resume interrupted graft')),
3300 ('c', 'continue', False, _('resume interrupted graft')),
3298 ('e', 'edit', False, _('invoke editor on commit messages')),
3301 ('e', 'edit', False, _('invoke editor on commit messages')),
3299 ('', 'log', None, _('append graft info to log message')),
3302 ('', 'log', None, _('append graft info to log message')),
3300 ('f', 'force', False, _('force graft')),
3303 ('f', 'force', False, _('force graft')),
3301 ('D', 'currentdate', False,
3304 ('D', 'currentdate', False,
3302 _('record the current date as commit date')),
3305 _('record the current date as commit date')),
3303 ('U', 'currentuser', False,
3306 ('U', 'currentuser', False,
3304 _('record the current user as committer'), _('DATE'))]
3307 _('record the current user as committer'), _('DATE'))]
3305 + commitopts2 + mergetoolopts + dryrunopts,
3308 + commitopts2 + mergetoolopts + dryrunopts,
3306 _('[OPTION]... [-r] REV...'))
3309 _('[OPTION]... [-r] REV...'))
3307 def graft(ui, repo, *revs, **opts):
3310 def graft(ui, repo, *revs, **opts):
3308 '''copy changes from other branches onto the current branch
3311 '''copy changes from other branches onto the current branch
3309
3312
3310 This command uses Mercurial's merge logic to copy individual
3313 This command uses Mercurial's merge logic to copy individual
3311 changes from other branches without merging branches in the
3314 changes from other branches without merging branches in the
3312 history graph. This is sometimes known as 'backporting' or
3315 history graph. This is sometimes known as 'backporting' or
3313 'cherry-picking'. By default, graft will copy user, date, and
3316 'cherry-picking'. By default, graft will copy user, date, and
3314 description from the source changesets.
3317 description from the source changesets.
3315
3318
3316 Changesets that are ancestors of the current revision, that have
3319 Changesets that are ancestors of the current revision, that have
3317 already been grafted, or that are merges will be skipped.
3320 already been grafted, or that are merges will be skipped.
3318
3321
3319 If --log is specified, log messages will have a comment appended
3322 If --log is specified, log messages will have a comment appended
3320 of the form::
3323 of the form::
3321
3324
3322 (grafted from CHANGESETHASH)
3325 (grafted from CHANGESETHASH)
3323
3326
3324 If --force is specified, revisions will be grafted even if they
3327 If --force is specified, revisions will be grafted even if they
3325 are already ancestors of or have been grafted to the destination.
3328 are already ancestors of or have been grafted to the destination.
3326 This is useful when the revisions have since been backed out.
3329 This is useful when the revisions have since been backed out.
3327
3330
3328 If a graft merge results in conflicts, the graft process is
3331 If a graft merge results in conflicts, the graft process is
3329 interrupted so that the current merge can be manually resolved.
3332 interrupted so that the current merge can be manually resolved.
3330 Once all conflicts are addressed, the graft process can be
3333 Once all conflicts are addressed, the graft process can be
3331 continued with the -c/--continue option.
3334 continued with the -c/--continue option.
3332
3335
3333 .. note::
3336 .. note::
3334
3337
3335 The -c/--continue option does not reapply earlier options, except
3338 The -c/--continue option does not reapply earlier options, except
3336 for --force.
3339 for --force.
3337
3340
3338 .. container:: verbose
3341 .. container:: verbose
3339
3342
3340 Examples:
3343 Examples:
3341
3344
3342 - copy a single change to the stable branch and edit its description::
3345 - copy a single change to the stable branch and edit its description::
3343
3346
3344 hg update stable
3347 hg update stable
3345 hg graft --edit 9393
3348 hg graft --edit 9393
3346
3349
3347 - graft a range of changesets with one exception, updating dates::
3350 - graft a range of changesets with one exception, updating dates::
3348
3351
3349 hg graft -D "2085::2093 and not 2091"
3352 hg graft -D "2085::2093 and not 2091"
3350
3353
3351 - continue a graft after resolving conflicts::
3354 - continue a graft after resolving conflicts::
3352
3355
3353 hg graft -c
3356 hg graft -c
3354
3357
3355 - show the source of a grafted changeset::
3358 - show the source of a grafted changeset::
3356
3359
3357 hg log --debug -r .
3360 hg log --debug -r .
3358
3361
3359 See :hg:`help revisions` and :hg:`help revsets` for more about
3362 See :hg:`help revisions` and :hg:`help revsets` for more about
3360 specifying revisions.
3363 specifying revisions.
3361
3364
3362 Returns 0 on successful completion.
3365 Returns 0 on successful completion.
3363 '''
3366 '''
3364
3367
3365 revs = list(revs)
3368 revs = list(revs)
3366 revs.extend(opts['rev'])
3369 revs.extend(opts['rev'])
3367
3370
3368 if not opts.get('user') and opts.get('currentuser'):
3371 if not opts.get('user') and opts.get('currentuser'):
3369 opts['user'] = ui.username()
3372 opts['user'] = ui.username()
3370 if not opts.get('date') and opts.get('currentdate'):
3373 if not opts.get('date') and opts.get('currentdate'):
3371 opts['date'] = "%d %d" % util.makedate()
3374 opts['date'] = "%d %d" % util.makedate()
3372
3375
3373 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3376 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3374
3377
3375 cont = False
3378 cont = False
3376 if opts['continue']:
3379 if opts['continue']:
3377 cont = True
3380 cont = True
3378 if revs:
3381 if revs:
3379 raise util.Abort(_("can't specify --continue and revisions"))
3382 raise util.Abort(_("can't specify --continue and revisions"))
3380 # read in unfinished revisions
3383 # read in unfinished revisions
3381 try:
3384 try:
3382 nodes = repo.opener.read('graftstate').splitlines()
3385 nodes = repo.opener.read('graftstate').splitlines()
3383 revs = [repo[node].rev() for node in nodes]
3386 revs = [repo[node].rev() for node in nodes]
3384 except IOError, inst:
3387 except IOError, inst:
3385 if inst.errno != errno.ENOENT:
3388 if inst.errno != errno.ENOENT:
3386 raise
3389 raise
3387 raise util.Abort(_("no graft state found, can't continue"))
3390 raise util.Abort(_("no graft state found, can't continue"))
3388 else:
3391 else:
3389 cmdutil.checkunfinished(repo)
3392 cmdutil.checkunfinished(repo)
3390 cmdutil.bailifchanged(repo)
3393 cmdutil.bailifchanged(repo)
3391 if not revs:
3394 if not revs:
3392 raise util.Abort(_('no revisions specified'))
3395 raise util.Abort(_('no revisions specified'))
3393 revs = scmutil.revrange(repo, revs)
3396 revs = scmutil.revrange(repo, revs)
3394
3397
3395 skipped = set()
3398 skipped = set()
3396 # check for merges
3399 # check for merges
3397 for rev in repo.revs('%ld and merge()', revs):
3400 for rev in repo.revs('%ld and merge()', revs):
3398 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3401 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3399 skipped.add(rev)
3402 skipped.add(rev)
3400 revs = [r for r in revs if r not in skipped]
3403 revs = [r for r in revs if r not in skipped]
3401 if not revs:
3404 if not revs:
3402 return -1
3405 return -1
3403
3406
3404 # Don't check in the --continue case, in effect retaining --force across
3407 # Don't check in the --continue case, in effect retaining --force across
3405 # --continues. That's because without --force, any revisions we decided to
3408 # --continues. That's because without --force, any revisions we decided to
3406 # skip would have been filtered out here, so they wouldn't have made their
3409 # skip would have been filtered out here, so they wouldn't have made their
3407 # way to the graftstate. With --force, any revisions we would have otherwise
3410 # way to the graftstate. With --force, any revisions we would have otherwise
3408 # skipped would not have been filtered out, and if they hadn't been applied
3411 # skipped would not have been filtered out, and if they hadn't been applied
3409 # already, they'd have been in the graftstate.
3412 # already, they'd have been in the graftstate.
3410 if not (cont or opts.get('force')):
3413 if not (cont or opts.get('force')):
3411 # check for ancestors of dest branch
3414 # check for ancestors of dest branch
3412 crev = repo['.'].rev()
3415 crev = repo['.'].rev()
3413 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3416 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3414 # Cannot use x.remove(y) on smart set, this has to be a list.
3417 # Cannot use x.remove(y) on smart set, this has to be a list.
3415 # XXX make this lazy in the future
3418 # XXX make this lazy in the future
3416 revs = list(revs)
3419 revs = list(revs)
3417 # don't mutate while iterating, create a copy
3420 # don't mutate while iterating, create a copy
3418 for rev in list(revs):
3421 for rev in list(revs):
3419 if rev in ancestors:
3422 if rev in ancestors:
3420 ui.warn(_('skipping ancestor revision %d:%s\n') %
3423 ui.warn(_('skipping ancestor revision %d:%s\n') %
3421 (rev, repo[rev]))
3424 (rev, repo[rev]))
3422 # XXX remove on list is slow
3425 # XXX remove on list is slow
3423 revs.remove(rev)
3426 revs.remove(rev)
3424 if not revs:
3427 if not revs:
3425 return -1
3428 return -1
3426
3429
3427 # analyze revs for earlier grafts
3430 # analyze revs for earlier grafts
3428 ids = {}
3431 ids = {}
3429 for ctx in repo.set("%ld", revs):
3432 for ctx in repo.set("%ld", revs):
3430 ids[ctx.hex()] = ctx.rev()
3433 ids[ctx.hex()] = ctx.rev()
3431 n = ctx.extra().get('source')
3434 n = ctx.extra().get('source')
3432 if n:
3435 if n:
3433 ids[n] = ctx.rev()
3436 ids[n] = ctx.rev()
3434
3437
3435 # check ancestors for earlier grafts
3438 # check ancestors for earlier grafts
3436 ui.debug('scanning for duplicate grafts\n')
3439 ui.debug('scanning for duplicate grafts\n')
3437
3440
3438 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3441 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3439 ctx = repo[rev]
3442 ctx = repo[rev]
3440 n = ctx.extra().get('source')
3443 n = ctx.extra().get('source')
3441 if n in ids:
3444 if n in ids:
3442 try:
3445 try:
3443 r = repo[n].rev()
3446 r = repo[n].rev()
3444 except error.RepoLookupError:
3447 except error.RepoLookupError:
3445 r = None
3448 r = None
3446 if r in revs:
3449 if r in revs:
3447 ui.warn(_('skipping revision %d:%s '
3450 ui.warn(_('skipping revision %d:%s '
3448 '(already grafted to %d:%s)\n')
3451 '(already grafted to %d:%s)\n')
3449 % (r, repo[r], rev, ctx))
3452 % (r, repo[r], rev, ctx))
3450 revs.remove(r)
3453 revs.remove(r)
3451 elif ids[n] in revs:
3454 elif ids[n] in revs:
3452 if r is None:
3455 if r is None:
3453 ui.warn(_('skipping already grafted revision %d:%s '
3456 ui.warn(_('skipping already grafted revision %d:%s '
3454 '(%d:%s also has unknown origin %s)\n')
3457 '(%d:%s also has unknown origin %s)\n')
3455 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3458 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3456 else:
3459 else:
3457 ui.warn(_('skipping already grafted revision %d:%s '
3460 ui.warn(_('skipping already grafted revision %d:%s '
3458 '(%d:%s also has origin %d:%s)\n')
3461 '(%d:%s also has origin %d:%s)\n')
3459 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3462 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3460 revs.remove(ids[n])
3463 revs.remove(ids[n])
3461 elif ctx.hex() in ids:
3464 elif ctx.hex() in ids:
3462 r = ids[ctx.hex()]
3465 r = ids[ctx.hex()]
3463 ui.warn(_('skipping already grafted revision %d:%s '
3466 ui.warn(_('skipping already grafted revision %d:%s '
3464 '(was grafted from %d:%s)\n') %
3467 '(was grafted from %d:%s)\n') %
3465 (r, repo[r], rev, ctx))
3468 (r, repo[r], rev, ctx))
3466 revs.remove(r)
3469 revs.remove(r)
3467 if not revs:
3470 if not revs:
3468 return -1
3471 return -1
3469
3472
3470 wlock = repo.wlock()
3473 wlock = repo.wlock()
3471 try:
3474 try:
3472 for pos, ctx in enumerate(repo.set("%ld", revs)):
3475 for pos, ctx in enumerate(repo.set("%ld", revs)):
3473 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3476 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3474 ctx.description().split('\n', 1)[0])
3477 ctx.description().split('\n', 1)[0])
3475 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3478 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3476 if names:
3479 if names:
3477 desc += ' (%s)' % ' '.join(names)
3480 desc += ' (%s)' % ' '.join(names)
3478 ui.status(_('grafting %s\n') % desc)
3481 ui.status(_('grafting %s\n') % desc)
3479 if opts.get('dry_run'):
3482 if opts.get('dry_run'):
3480 continue
3483 continue
3481
3484
3482 source = ctx.extra().get('source')
3485 source = ctx.extra().get('source')
3483 if not source:
3486 if not source:
3484 source = ctx.hex()
3487 source = ctx.hex()
3485 extra = {'source': source}
3488 extra = {'source': source}
3486 user = ctx.user()
3489 user = ctx.user()
3487 if opts.get('user'):
3490 if opts.get('user'):
3488 user = opts['user']
3491 user = opts['user']
3489 date = ctx.date()
3492 date = ctx.date()
3490 if opts.get('date'):
3493 if opts.get('date'):
3491 date = opts['date']
3494 date = opts['date']
3492 message = ctx.description()
3495 message = ctx.description()
3493 if opts.get('log'):
3496 if opts.get('log'):
3494 message += '\n(grafted from %s)' % ctx.hex()
3497 message += '\n(grafted from %s)' % ctx.hex()
3495
3498
3496 # we don't merge the first commit when continuing
3499 # we don't merge the first commit when continuing
3497 if not cont:
3500 if not cont:
3498 # perform the graft merge with p1(rev) as 'ancestor'
3501 # perform the graft merge with p1(rev) as 'ancestor'
3499 try:
3502 try:
3500 # ui.forcemerge is an internal variable, do not document
3503 # ui.forcemerge is an internal variable, do not document
3501 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3504 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3502 'graft')
3505 'graft')
3503 stats = mergemod.graft(repo, ctx, ctx.p1(),
3506 stats = mergemod.graft(repo, ctx, ctx.p1(),
3504 ['local', 'graft'])
3507 ['local', 'graft'])
3505 finally:
3508 finally:
3506 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3509 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3507 # report any conflicts
3510 # report any conflicts
3508 if stats and stats[3] > 0:
3511 if stats and stats[3] > 0:
3509 # write out state for --continue
3512 # write out state for --continue
3510 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3513 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3511 repo.opener.write('graftstate', ''.join(nodelines))
3514 repo.opener.write('graftstate', ''.join(nodelines))
3512 raise util.Abort(
3515 raise util.Abort(
3513 _("unresolved conflicts, can't continue"),
3516 _("unresolved conflicts, can't continue"),
3514 hint=_('use hg resolve and hg graft --continue'))
3517 hint=_('use hg resolve and hg graft --continue'))
3515 else:
3518 else:
3516 cont = False
3519 cont = False
3517
3520
3518 # commit
3521 # commit
3519 node = repo.commit(text=message, user=user,
3522 node = repo.commit(text=message, user=user,
3520 date=date, extra=extra, editor=editor)
3523 date=date, extra=extra, editor=editor)
3521 if node is None:
3524 if node is None:
3522 ui.warn(
3525 ui.warn(
3523 _('note: graft of %d:%s created no changes to commit\n') %
3526 _('note: graft of %d:%s created no changes to commit\n') %
3524 (ctx.rev(), ctx))
3527 (ctx.rev(), ctx))
3525 finally:
3528 finally:
3526 wlock.release()
3529 wlock.release()
3527
3530
3528 # remove state when we complete successfully
3531 # remove state when we complete successfully
3529 if not opts.get('dry_run'):
3532 if not opts.get('dry_run'):
3530 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3533 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3531
3534
3532 return 0
3535 return 0
3533
3536
3534 @command('grep',
3537 @command('grep',
3535 [('0', 'print0', None, _('end fields with NUL')),
3538 [('0', 'print0', None, _('end fields with NUL')),
3536 ('', 'all', None, _('print all revisions that match')),
3539 ('', 'all', None, _('print all revisions that match')),
3537 ('a', 'text', None, _('treat all files as text')),
3540 ('a', 'text', None, _('treat all files as text')),
3538 ('f', 'follow', None,
3541 ('f', 'follow', None,
3539 _('follow changeset history,'
3542 _('follow changeset history,'
3540 ' or file history across copies and renames')),
3543 ' or file history across copies and renames')),
3541 ('i', 'ignore-case', None, _('ignore case when matching')),
3544 ('i', 'ignore-case', None, _('ignore case when matching')),
3542 ('l', 'files-with-matches', None,
3545 ('l', 'files-with-matches', None,
3543 _('print only filenames and revisions that match')),
3546 _('print only filenames and revisions that match')),
3544 ('n', 'line-number', None, _('print matching line numbers')),
3547 ('n', 'line-number', None, _('print matching line numbers')),
3545 ('r', 'rev', [],
3548 ('r', 'rev', [],
3546 _('only search files changed within revision range'), _('REV')),
3549 _('only search files changed within revision range'), _('REV')),
3547 ('u', 'user', None, _('list the author (long with -v)')),
3550 ('u', 'user', None, _('list the author (long with -v)')),
3548 ('d', 'date', None, _('list the date (short with -q)')),
3551 ('d', 'date', None, _('list the date (short with -q)')),
3549 ] + walkopts,
3552 ] + walkopts,
3550 _('[OPTION]... PATTERN [FILE]...'),
3553 _('[OPTION]... PATTERN [FILE]...'),
3551 inferrepo=True)
3554 inferrepo=True)
3552 def grep(ui, repo, pattern, *pats, **opts):
3555 def grep(ui, repo, pattern, *pats, **opts):
3553 """search for a pattern in specified files and revisions
3556 """search for a pattern in specified files and revisions
3554
3557
3555 Search revisions of files for a regular expression.
3558 Search revisions of files for a regular expression.
3556
3559
3557 This command behaves differently than Unix grep. It only accepts
3560 This command behaves differently than Unix grep. It only accepts
3558 Python/Perl regexps. It searches repository history, not the
3561 Python/Perl regexps. It searches repository history, not the
3559 working directory. It always prints the revision number in which a
3562 working directory. It always prints the revision number in which a
3560 match appears.
3563 match appears.
3561
3564
3562 By default, grep only prints output for the first revision of a
3565 By default, grep only prints output for the first revision of a
3563 file in which it finds a match. To get it to print every revision
3566 file in which it finds a match. To get it to print every revision
3564 that contains a change in match status ("-" for a match that
3567 that contains a change in match status ("-" for a match that
3565 becomes a non-match, or "+" for a non-match that becomes a match),
3568 becomes a non-match, or "+" for a non-match that becomes a match),
3566 use the --all flag.
3569 use the --all flag.
3567
3570
3568 Returns 0 if a match is found, 1 otherwise.
3571 Returns 0 if a match is found, 1 otherwise.
3569 """
3572 """
3570 reflags = re.M
3573 reflags = re.M
3571 if opts.get('ignore_case'):
3574 if opts.get('ignore_case'):
3572 reflags |= re.I
3575 reflags |= re.I
3573 try:
3576 try:
3574 regexp = util.re.compile(pattern, reflags)
3577 regexp = util.re.compile(pattern, reflags)
3575 except re.error, inst:
3578 except re.error, inst:
3576 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3579 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3577 return 1
3580 return 1
3578 sep, eol = ':', '\n'
3581 sep, eol = ':', '\n'
3579 if opts.get('print0'):
3582 if opts.get('print0'):
3580 sep = eol = '\0'
3583 sep = eol = '\0'
3581
3584
3582 getfile = util.lrucachefunc(repo.file)
3585 getfile = util.lrucachefunc(repo.file)
3583
3586
3584 def matchlines(body):
3587 def matchlines(body):
3585 begin = 0
3588 begin = 0
3586 linenum = 0
3589 linenum = 0
3587 while begin < len(body):
3590 while begin < len(body):
3588 match = regexp.search(body, begin)
3591 match = regexp.search(body, begin)
3589 if not match:
3592 if not match:
3590 break
3593 break
3591 mstart, mend = match.span()
3594 mstart, mend = match.span()
3592 linenum += body.count('\n', begin, mstart) + 1
3595 linenum += body.count('\n', begin, mstart) + 1
3593 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3596 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3594 begin = body.find('\n', mend) + 1 or len(body) + 1
3597 begin = body.find('\n', mend) + 1 or len(body) + 1
3595 lend = begin - 1
3598 lend = begin - 1
3596 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3599 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3597
3600
3598 class linestate(object):
3601 class linestate(object):
3599 def __init__(self, line, linenum, colstart, colend):
3602 def __init__(self, line, linenum, colstart, colend):
3600 self.line = line
3603 self.line = line
3601 self.linenum = linenum
3604 self.linenum = linenum
3602 self.colstart = colstart
3605 self.colstart = colstart
3603 self.colend = colend
3606 self.colend = colend
3604
3607
3605 def __hash__(self):
3608 def __hash__(self):
3606 return hash((self.linenum, self.line))
3609 return hash((self.linenum, self.line))
3607
3610
3608 def __eq__(self, other):
3611 def __eq__(self, other):
3609 return self.line == other.line
3612 return self.line == other.line
3610
3613
3611 def __iter__(self):
3614 def __iter__(self):
3612 yield (self.line[:self.colstart], '')
3615 yield (self.line[:self.colstart], '')
3613 yield (self.line[self.colstart:self.colend], 'grep.match')
3616 yield (self.line[self.colstart:self.colend], 'grep.match')
3614 rest = self.line[self.colend:]
3617 rest = self.line[self.colend:]
3615 while rest != '':
3618 while rest != '':
3616 match = regexp.search(rest)
3619 match = regexp.search(rest)
3617 if not match:
3620 if not match:
3618 yield (rest, '')
3621 yield (rest, '')
3619 break
3622 break
3620 mstart, mend = match.span()
3623 mstart, mend = match.span()
3621 yield (rest[:mstart], '')
3624 yield (rest[:mstart], '')
3622 yield (rest[mstart:mend], 'grep.match')
3625 yield (rest[mstart:mend], 'grep.match')
3623 rest = rest[mend:]
3626 rest = rest[mend:]
3624
3627
3625 matches = {}
3628 matches = {}
3626 copies = {}
3629 copies = {}
3627 def grepbody(fn, rev, body):
3630 def grepbody(fn, rev, body):
3628 matches[rev].setdefault(fn, [])
3631 matches[rev].setdefault(fn, [])
3629 m = matches[rev][fn]
3632 m = matches[rev][fn]
3630 for lnum, cstart, cend, line in matchlines(body):
3633 for lnum, cstart, cend, line in matchlines(body):
3631 s = linestate(line, lnum, cstart, cend)
3634 s = linestate(line, lnum, cstart, cend)
3632 m.append(s)
3635 m.append(s)
3633
3636
3634 def difflinestates(a, b):
3637 def difflinestates(a, b):
3635 sm = difflib.SequenceMatcher(None, a, b)
3638 sm = difflib.SequenceMatcher(None, a, b)
3636 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3639 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3637 if tag == 'insert':
3640 if tag == 'insert':
3638 for i in xrange(blo, bhi):
3641 for i in xrange(blo, bhi):
3639 yield ('+', b[i])
3642 yield ('+', b[i])
3640 elif tag == 'delete':
3643 elif tag == 'delete':
3641 for i in xrange(alo, ahi):
3644 for i in xrange(alo, ahi):
3642 yield ('-', a[i])
3645 yield ('-', a[i])
3643 elif tag == 'replace':
3646 elif tag == 'replace':
3644 for i in xrange(alo, ahi):
3647 for i in xrange(alo, ahi):
3645 yield ('-', a[i])
3648 yield ('-', a[i])
3646 for i in xrange(blo, bhi):
3649 for i in xrange(blo, bhi):
3647 yield ('+', b[i])
3650 yield ('+', b[i])
3648
3651
3649 def display(fn, ctx, pstates, states):
3652 def display(fn, ctx, pstates, states):
3650 rev = ctx.rev()
3653 rev = ctx.rev()
3651 datefunc = ui.quiet and util.shortdate or util.datestr
3654 datefunc = ui.quiet and util.shortdate or util.datestr
3652 found = False
3655 found = False
3653 @util.cachefunc
3656 @util.cachefunc
3654 def binary():
3657 def binary():
3655 flog = getfile(fn)
3658 flog = getfile(fn)
3656 return util.binary(flog.read(ctx.filenode(fn)))
3659 return util.binary(flog.read(ctx.filenode(fn)))
3657
3660
3658 if opts.get('all'):
3661 if opts.get('all'):
3659 iter = difflinestates(pstates, states)
3662 iter = difflinestates(pstates, states)
3660 else:
3663 else:
3661 iter = [('', l) for l in states]
3664 iter = [('', l) for l in states]
3662 for change, l in iter:
3665 for change, l in iter:
3663 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3666 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3664
3667
3665 if opts.get('line_number'):
3668 if opts.get('line_number'):
3666 cols.append((str(l.linenum), 'grep.linenumber'))
3669 cols.append((str(l.linenum), 'grep.linenumber'))
3667 if opts.get('all'):
3670 if opts.get('all'):
3668 cols.append((change, 'grep.change'))
3671 cols.append((change, 'grep.change'))
3669 if opts.get('user'):
3672 if opts.get('user'):
3670 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3673 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3671 if opts.get('date'):
3674 if opts.get('date'):
3672 cols.append((datefunc(ctx.date()), 'grep.date'))
3675 cols.append((datefunc(ctx.date()), 'grep.date'))
3673 for col, label in cols[:-1]:
3676 for col, label in cols[:-1]:
3674 ui.write(col, label=label)
3677 ui.write(col, label=label)
3675 ui.write(sep, label='grep.sep')
3678 ui.write(sep, label='grep.sep')
3676 ui.write(cols[-1][0], label=cols[-1][1])
3679 ui.write(cols[-1][0], label=cols[-1][1])
3677 if not opts.get('files_with_matches'):
3680 if not opts.get('files_with_matches'):
3678 ui.write(sep, label='grep.sep')
3681 ui.write(sep, label='grep.sep')
3679 if not opts.get('text') and binary():
3682 if not opts.get('text') and binary():
3680 ui.write(" Binary file matches")
3683 ui.write(" Binary file matches")
3681 else:
3684 else:
3682 for s, label in l:
3685 for s, label in l:
3683 ui.write(s, label=label)
3686 ui.write(s, label=label)
3684 ui.write(eol)
3687 ui.write(eol)
3685 found = True
3688 found = True
3686 if opts.get('files_with_matches'):
3689 if opts.get('files_with_matches'):
3687 break
3690 break
3688 return found
3691 return found
3689
3692
3690 skip = {}
3693 skip = {}
3691 revfiles = {}
3694 revfiles = {}
3692 matchfn = scmutil.match(repo[None], pats, opts)
3695 matchfn = scmutil.match(repo[None], pats, opts)
3693 found = False
3696 found = False
3694 follow = opts.get('follow')
3697 follow = opts.get('follow')
3695
3698
3696 def prep(ctx, fns):
3699 def prep(ctx, fns):
3697 rev = ctx.rev()
3700 rev = ctx.rev()
3698 pctx = ctx.p1()
3701 pctx = ctx.p1()
3699 parent = pctx.rev()
3702 parent = pctx.rev()
3700 matches.setdefault(rev, {})
3703 matches.setdefault(rev, {})
3701 matches.setdefault(parent, {})
3704 matches.setdefault(parent, {})
3702 files = revfiles.setdefault(rev, [])
3705 files = revfiles.setdefault(rev, [])
3703 for fn in fns:
3706 for fn in fns:
3704 flog = getfile(fn)
3707 flog = getfile(fn)
3705 try:
3708 try:
3706 fnode = ctx.filenode(fn)
3709 fnode = ctx.filenode(fn)
3707 except error.LookupError:
3710 except error.LookupError:
3708 continue
3711 continue
3709
3712
3710 copied = flog.renamed(fnode)
3713 copied = flog.renamed(fnode)
3711 copy = follow and copied and copied[0]
3714 copy = follow and copied and copied[0]
3712 if copy:
3715 if copy:
3713 copies.setdefault(rev, {})[fn] = copy
3716 copies.setdefault(rev, {})[fn] = copy
3714 if fn in skip:
3717 if fn in skip:
3715 if copy:
3718 if copy:
3716 skip[copy] = True
3719 skip[copy] = True
3717 continue
3720 continue
3718 files.append(fn)
3721 files.append(fn)
3719
3722
3720 if fn not in matches[rev]:
3723 if fn not in matches[rev]:
3721 grepbody(fn, rev, flog.read(fnode))
3724 grepbody(fn, rev, flog.read(fnode))
3722
3725
3723 pfn = copy or fn
3726 pfn = copy or fn
3724 if pfn not in matches[parent]:
3727 if pfn not in matches[parent]:
3725 try:
3728 try:
3726 fnode = pctx.filenode(pfn)
3729 fnode = pctx.filenode(pfn)
3727 grepbody(pfn, parent, flog.read(fnode))
3730 grepbody(pfn, parent, flog.read(fnode))
3728 except error.LookupError:
3731 except error.LookupError:
3729 pass
3732 pass
3730
3733
3731 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3734 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3732 rev = ctx.rev()
3735 rev = ctx.rev()
3733 parent = ctx.p1().rev()
3736 parent = ctx.p1().rev()
3734 for fn in sorted(revfiles.get(rev, [])):
3737 for fn in sorted(revfiles.get(rev, [])):
3735 states = matches[rev][fn]
3738 states = matches[rev][fn]
3736 copy = copies.get(rev, {}).get(fn)
3739 copy = copies.get(rev, {}).get(fn)
3737 if fn in skip:
3740 if fn in skip:
3738 if copy:
3741 if copy:
3739 skip[copy] = True
3742 skip[copy] = True
3740 continue
3743 continue
3741 pstates = matches.get(parent, {}).get(copy or fn, [])
3744 pstates = matches.get(parent, {}).get(copy or fn, [])
3742 if pstates or states:
3745 if pstates or states:
3743 r = display(fn, ctx, pstates, states)
3746 r = display(fn, ctx, pstates, states)
3744 found = found or r
3747 found = found or r
3745 if r and not opts.get('all'):
3748 if r and not opts.get('all'):
3746 skip[fn] = True
3749 skip[fn] = True
3747 if copy:
3750 if copy:
3748 skip[copy] = True
3751 skip[copy] = True
3749 del matches[rev]
3752 del matches[rev]
3750 del revfiles[rev]
3753 del revfiles[rev]
3751
3754
3752 return not found
3755 return not found
3753
3756
3754 @command('heads',
3757 @command('heads',
3755 [('r', 'rev', '',
3758 [('r', 'rev', '',
3756 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3759 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3757 ('t', 'topo', False, _('show topological heads only')),
3760 ('t', 'topo', False, _('show topological heads only')),
3758 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3761 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3759 ('c', 'closed', False, _('show normal and closed branch heads')),
3762 ('c', 'closed', False, _('show normal and closed branch heads')),
3760 ] + templateopts,
3763 ] + templateopts,
3761 _('[-ct] [-r STARTREV] [REV]...'))
3764 _('[-ct] [-r STARTREV] [REV]...'))
3762 def heads(ui, repo, *branchrevs, **opts):
3765 def heads(ui, repo, *branchrevs, **opts):
3763 """show branch heads
3766 """show branch heads
3764
3767
3765 With no arguments, show all open branch heads in the repository.
3768 With no arguments, show all open branch heads in the repository.
3766 Branch heads are changesets that have no descendants on the
3769 Branch heads are changesets that have no descendants on the
3767 same branch. They are where development generally takes place and
3770 same branch. They are where development generally takes place and
3768 are the usual targets for update and merge operations.
3771 are the usual targets for update and merge operations.
3769
3772
3770 If one or more REVs are given, only open branch heads on the
3773 If one or more REVs are given, only open branch heads on the
3771 branches associated with the specified changesets are shown. This
3774 branches associated with the specified changesets are shown. This
3772 means that you can use :hg:`heads .` to see the heads on the
3775 means that you can use :hg:`heads .` to see the heads on the
3773 currently checked-out branch.
3776 currently checked-out branch.
3774
3777
3775 If -c/--closed is specified, also show branch heads marked closed
3778 If -c/--closed is specified, also show branch heads marked closed
3776 (see :hg:`commit --close-branch`).
3779 (see :hg:`commit --close-branch`).
3777
3780
3778 If STARTREV is specified, only those heads that are descendants of
3781 If STARTREV is specified, only those heads that are descendants of
3779 STARTREV will be displayed.
3782 STARTREV will be displayed.
3780
3783
3781 If -t/--topo is specified, named branch mechanics will be ignored and only
3784 If -t/--topo is specified, named branch mechanics will be ignored and only
3782 topological heads (changesets with no children) will be shown.
3785 topological heads (changesets with no children) will be shown.
3783
3786
3784 Returns 0 if matching heads are found, 1 if not.
3787 Returns 0 if matching heads are found, 1 if not.
3785 """
3788 """
3786
3789
3787 start = None
3790 start = None
3788 if 'rev' in opts:
3791 if 'rev' in opts:
3789 start = scmutil.revsingle(repo, opts['rev'], None).node()
3792 start = scmutil.revsingle(repo, opts['rev'], None).node()
3790
3793
3791 if opts.get('topo'):
3794 if opts.get('topo'):
3792 heads = [repo[h] for h in repo.heads(start)]
3795 heads = [repo[h] for h in repo.heads(start)]
3793 else:
3796 else:
3794 heads = []
3797 heads = []
3795 for branch in repo.branchmap():
3798 for branch in repo.branchmap():
3796 heads += repo.branchheads(branch, start, opts.get('closed'))
3799 heads += repo.branchheads(branch, start, opts.get('closed'))
3797 heads = [repo[h] for h in heads]
3800 heads = [repo[h] for h in heads]
3798
3801
3799 if branchrevs:
3802 if branchrevs:
3800 branches = set(repo[br].branch() for br in branchrevs)
3803 branches = set(repo[br].branch() for br in branchrevs)
3801 heads = [h for h in heads if h.branch() in branches]
3804 heads = [h for h in heads if h.branch() in branches]
3802
3805
3803 if opts.get('active') and branchrevs:
3806 if opts.get('active') and branchrevs:
3804 dagheads = repo.heads(start)
3807 dagheads = repo.heads(start)
3805 heads = [h for h in heads if h.node() in dagheads]
3808 heads = [h for h in heads if h.node() in dagheads]
3806
3809
3807 if branchrevs:
3810 if branchrevs:
3808 haveheads = set(h.branch() for h in heads)
3811 haveheads = set(h.branch() for h in heads)
3809 if branches - haveheads:
3812 if branches - haveheads:
3810 headless = ', '.join(b for b in branches - haveheads)
3813 headless = ', '.join(b for b in branches - haveheads)
3811 msg = _('no open branch heads found on branches %s')
3814 msg = _('no open branch heads found on branches %s')
3812 if opts.get('rev'):
3815 if opts.get('rev'):
3813 msg += _(' (started at %s)') % opts['rev']
3816 msg += _(' (started at %s)') % opts['rev']
3814 ui.warn((msg + '\n') % headless)
3817 ui.warn((msg + '\n') % headless)
3815
3818
3816 if not heads:
3819 if not heads:
3817 return 1
3820 return 1
3818
3821
3819 heads = sorted(heads, key=lambda x: -x.rev())
3822 heads = sorted(heads, key=lambda x: -x.rev())
3820 displayer = cmdutil.show_changeset(ui, repo, opts)
3823 displayer = cmdutil.show_changeset(ui, repo, opts)
3821 for ctx in heads:
3824 for ctx in heads:
3822 displayer.show(ctx)
3825 displayer.show(ctx)
3823 displayer.close()
3826 displayer.close()
3824
3827
3825 @command('help',
3828 @command('help',
3826 [('e', 'extension', None, _('show only help for extensions')),
3829 [('e', 'extension', None, _('show only help for extensions')),
3827 ('c', 'command', None, _('show only help for commands')),
3830 ('c', 'command', None, _('show only help for commands')),
3828 ('k', 'keyword', '', _('show topics matching keyword')),
3831 ('k', 'keyword', '', _('show topics matching keyword')),
3829 ],
3832 ],
3830 _('[-ec] [TOPIC]'),
3833 _('[-ec] [TOPIC]'),
3831 norepo=True)
3834 norepo=True)
3832 def help_(ui, name=None, **opts):
3835 def help_(ui, name=None, **opts):
3833 """show help for a given topic or a help overview
3836 """show help for a given topic or a help overview
3834
3837
3835 With no arguments, print a list of commands with short help messages.
3838 With no arguments, print a list of commands with short help messages.
3836
3839
3837 Given a topic, extension, or command name, print help for that
3840 Given a topic, extension, or command name, print help for that
3838 topic.
3841 topic.
3839
3842
3840 Returns 0 if successful.
3843 Returns 0 if successful.
3841 """
3844 """
3842
3845
3843 textwidth = min(ui.termwidth(), 80) - 2
3846 textwidth = min(ui.termwidth(), 80) - 2
3844
3847
3845 keep = []
3848 keep = []
3846 if ui.verbose:
3849 if ui.verbose:
3847 keep.append('verbose')
3850 keep.append('verbose')
3848 if sys.platform.startswith('win'):
3851 if sys.platform.startswith('win'):
3849 keep.append('windows')
3852 keep.append('windows')
3850 elif sys.platform == 'OpenVMS':
3853 elif sys.platform == 'OpenVMS':
3851 keep.append('vms')
3854 keep.append('vms')
3852 elif sys.platform == 'plan9':
3855 elif sys.platform == 'plan9':
3853 keep.append('plan9')
3856 keep.append('plan9')
3854 else:
3857 else:
3855 keep.append('unix')
3858 keep.append('unix')
3856 keep.append(sys.platform.lower())
3859 keep.append(sys.platform.lower())
3857
3860
3858 section = None
3861 section = None
3859 if name and '.' in name:
3862 if name and '.' in name:
3860 name, section = name.split('.', 1)
3863 name, section = name.split('.', 1)
3861
3864
3862 text = help.help_(ui, name, **opts)
3865 text = help.help_(ui, name, **opts)
3863
3866
3864 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3867 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3865 section=section)
3868 section=section)
3866 if section and not formatted:
3869 if section and not formatted:
3867 raise util.Abort(_("help section not found"))
3870 raise util.Abort(_("help section not found"))
3868
3871
3869 if 'verbose' in pruned:
3872 if 'verbose' in pruned:
3870 keep.append('omitted')
3873 keep.append('omitted')
3871 else:
3874 else:
3872 keep.append('notomitted')
3875 keep.append('notomitted')
3873 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3876 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3874 section=section)
3877 section=section)
3875 ui.write(formatted)
3878 ui.write(formatted)
3876
3879
3877
3880
3878 @command('identify|id',
3881 @command('identify|id',
3879 [('r', 'rev', '',
3882 [('r', 'rev', '',
3880 _('identify the specified revision'), _('REV')),
3883 _('identify the specified revision'), _('REV')),
3881 ('n', 'num', None, _('show local revision number')),
3884 ('n', 'num', None, _('show local revision number')),
3882 ('i', 'id', None, _('show global revision id')),
3885 ('i', 'id', None, _('show global revision id')),
3883 ('b', 'branch', None, _('show branch')),
3886 ('b', 'branch', None, _('show branch')),
3884 ('t', 'tags', None, _('show tags')),
3887 ('t', 'tags', None, _('show tags')),
3885 ('B', 'bookmarks', None, _('show bookmarks')),
3888 ('B', 'bookmarks', None, _('show bookmarks')),
3886 ] + remoteopts,
3889 ] + remoteopts,
3887 _('[-nibtB] [-r REV] [SOURCE]'),
3890 _('[-nibtB] [-r REV] [SOURCE]'),
3888 optionalrepo=True)
3891 optionalrepo=True)
3889 def identify(ui, repo, source=None, rev=None,
3892 def identify(ui, repo, source=None, rev=None,
3890 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3893 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3891 """identify the working copy or specified revision
3894 """identify the working copy or specified revision
3892
3895
3893 Print a summary identifying the repository state at REV using one or
3896 Print a summary identifying the repository state at REV using one or
3894 two parent hash identifiers, followed by a "+" if the working
3897 two parent hash identifiers, followed by a "+" if the working
3895 directory has uncommitted changes, the branch name (if not default),
3898 directory has uncommitted changes, the branch name (if not default),
3896 a list of tags, and a list of bookmarks.
3899 a list of tags, and a list of bookmarks.
3897
3900
3898 When REV is not given, print a summary of the current state of the
3901 When REV is not given, print a summary of the current state of the
3899 repository.
3902 repository.
3900
3903
3901 Specifying a path to a repository root or Mercurial bundle will
3904 Specifying a path to a repository root or Mercurial bundle will
3902 cause lookup to operate on that repository/bundle.
3905 cause lookup to operate on that repository/bundle.
3903
3906
3904 .. container:: verbose
3907 .. container:: verbose
3905
3908
3906 Examples:
3909 Examples:
3907
3910
3908 - generate a build identifier for the working directory::
3911 - generate a build identifier for the working directory::
3909
3912
3910 hg id --id > build-id.dat
3913 hg id --id > build-id.dat
3911
3914
3912 - find the revision corresponding to a tag::
3915 - find the revision corresponding to a tag::
3913
3916
3914 hg id -n -r 1.3
3917 hg id -n -r 1.3
3915
3918
3916 - check the most recent revision of a remote repository::
3919 - check the most recent revision of a remote repository::
3917
3920
3918 hg id -r tip http://selenic.com/hg/
3921 hg id -r tip http://selenic.com/hg/
3919
3922
3920 Returns 0 if successful.
3923 Returns 0 if successful.
3921 """
3924 """
3922
3925
3923 if not repo and not source:
3926 if not repo and not source:
3924 raise util.Abort(_("there is no Mercurial repository here "
3927 raise util.Abort(_("there is no Mercurial repository here "
3925 "(.hg not found)"))
3928 "(.hg not found)"))
3926
3929
3927 hexfunc = ui.debugflag and hex or short
3930 hexfunc = ui.debugflag and hex or short
3928 default = not (num or id or branch or tags or bookmarks)
3931 default = not (num or id or branch or tags or bookmarks)
3929 output = []
3932 output = []
3930 revs = []
3933 revs = []
3931
3934
3932 if source:
3935 if source:
3933 source, branches = hg.parseurl(ui.expandpath(source))
3936 source, branches = hg.parseurl(ui.expandpath(source))
3934 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3937 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3935 repo = peer.local()
3938 repo = peer.local()
3936 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3939 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3937
3940
3938 if not repo:
3941 if not repo:
3939 if num or branch or tags:
3942 if num or branch or tags:
3940 raise util.Abort(
3943 raise util.Abort(
3941 _("can't query remote revision number, branch, or tags"))
3944 _("can't query remote revision number, branch, or tags"))
3942 if not rev and revs:
3945 if not rev and revs:
3943 rev = revs[0]
3946 rev = revs[0]
3944 if not rev:
3947 if not rev:
3945 rev = "tip"
3948 rev = "tip"
3946
3949
3947 remoterev = peer.lookup(rev)
3950 remoterev = peer.lookup(rev)
3948 if default or id:
3951 if default or id:
3949 output = [hexfunc(remoterev)]
3952 output = [hexfunc(remoterev)]
3950
3953
3951 def getbms():
3954 def getbms():
3952 bms = []
3955 bms = []
3953
3956
3954 if 'bookmarks' in peer.listkeys('namespaces'):
3957 if 'bookmarks' in peer.listkeys('namespaces'):
3955 hexremoterev = hex(remoterev)
3958 hexremoterev = hex(remoterev)
3956 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3959 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3957 if bmr == hexremoterev]
3960 if bmr == hexremoterev]
3958
3961
3959 return sorted(bms)
3962 return sorted(bms)
3960
3963
3961 if bookmarks:
3964 if bookmarks:
3962 output.extend(getbms())
3965 output.extend(getbms())
3963 elif default and not ui.quiet:
3966 elif default and not ui.quiet:
3964 # multiple bookmarks for a single parent separated by '/'
3967 # multiple bookmarks for a single parent separated by '/'
3965 bm = '/'.join(getbms())
3968 bm = '/'.join(getbms())
3966 if bm:
3969 if bm:
3967 output.append(bm)
3970 output.append(bm)
3968 else:
3971 else:
3969 if not rev:
3972 if not rev:
3970 ctx = repo[None]
3973 ctx = repo[None]
3971 parents = ctx.parents()
3974 parents = ctx.parents()
3972 changed = ""
3975 changed = ""
3973 if default or id or num:
3976 if default or id or num:
3974 if (util.any(repo.status())
3977 if (util.any(repo.status())
3975 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3978 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3976 changed = '+'
3979 changed = '+'
3977 if default or id:
3980 if default or id:
3978 output = ["%s%s" %
3981 output = ["%s%s" %
3979 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3982 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3980 if num:
3983 if num:
3981 output.append("%s%s" %
3984 output.append("%s%s" %
3982 ('+'.join([str(p.rev()) for p in parents]), changed))
3985 ('+'.join([str(p.rev()) for p in parents]), changed))
3983 else:
3986 else:
3984 ctx = scmutil.revsingle(repo, rev)
3987 ctx = scmutil.revsingle(repo, rev)
3985 if default or id:
3988 if default or id:
3986 output = [hexfunc(ctx.node())]
3989 output = [hexfunc(ctx.node())]
3987 if num:
3990 if num:
3988 output.append(str(ctx.rev()))
3991 output.append(str(ctx.rev()))
3989
3992
3990 if default and not ui.quiet:
3993 if default and not ui.quiet:
3991 b = ctx.branch()
3994 b = ctx.branch()
3992 if b != 'default':
3995 if b != 'default':
3993 output.append("(%s)" % b)
3996 output.append("(%s)" % b)
3994
3997
3995 # multiple tags for a single parent separated by '/'
3998 # multiple tags for a single parent separated by '/'
3996 t = '/'.join(ctx.tags())
3999 t = '/'.join(ctx.tags())
3997 if t:
4000 if t:
3998 output.append(t)
4001 output.append(t)
3999
4002
4000 # multiple bookmarks for a single parent separated by '/'
4003 # multiple bookmarks for a single parent separated by '/'
4001 bm = '/'.join(ctx.bookmarks())
4004 bm = '/'.join(ctx.bookmarks())
4002 if bm:
4005 if bm:
4003 output.append(bm)
4006 output.append(bm)
4004 else:
4007 else:
4005 if branch:
4008 if branch:
4006 output.append(ctx.branch())
4009 output.append(ctx.branch())
4007
4010
4008 if tags:
4011 if tags:
4009 output.extend(ctx.tags())
4012 output.extend(ctx.tags())
4010
4013
4011 if bookmarks:
4014 if bookmarks:
4012 output.extend(ctx.bookmarks())
4015 output.extend(ctx.bookmarks())
4013
4016
4014 ui.write("%s\n" % ' '.join(output))
4017 ui.write("%s\n" % ' '.join(output))
4015
4018
4016 @command('import|patch',
4019 @command('import|patch',
4017 [('p', 'strip', 1,
4020 [('p', 'strip', 1,
4018 _('directory strip option for patch. This has the same '
4021 _('directory strip option for patch. This has the same '
4019 'meaning as the corresponding patch option'), _('NUM')),
4022 'meaning as the corresponding patch option'), _('NUM')),
4020 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4023 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4021 ('e', 'edit', False, _('invoke editor on commit messages')),
4024 ('e', 'edit', False, _('invoke editor on commit messages')),
4022 ('f', 'force', None,
4025 ('f', 'force', None,
4023 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4026 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4024 ('', 'no-commit', None,
4027 ('', 'no-commit', None,
4025 _("don't commit, just update the working directory")),
4028 _("don't commit, just update the working directory")),
4026 ('', 'bypass', None,
4029 ('', 'bypass', None,
4027 _("apply patch without touching the working directory")),
4030 _("apply patch without touching the working directory")),
4028 ('', 'partial', None,
4031 ('', 'partial', None,
4029 _('commit even if some hunks fail')),
4032 _('commit even if some hunks fail')),
4030 ('', 'exact', None,
4033 ('', 'exact', None,
4031 _('apply patch to the nodes from which it was generated')),
4034 _('apply patch to the nodes from which it was generated')),
4032 ('', 'import-branch', None,
4035 ('', 'import-branch', None,
4033 _('use any branch information in patch (implied by --exact)'))] +
4036 _('use any branch information in patch (implied by --exact)'))] +
4034 commitopts + commitopts2 + similarityopts,
4037 commitopts + commitopts2 + similarityopts,
4035 _('[OPTION]... PATCH...'))
4038 _('[OPTION]... PATCH...'))
4036 def import_(ui, repo, patch1=None, *patches, **opts):
4039 def import_(ui, repo, patch1=None, *patches, **opts):
4037 """import an ordered set of patches
4040 """import an ordered set of patches
4038
4041
4039 Import a list of patches and commit them individually (unless
4042 Import a list of patches and commit them individually (unless
4040 --no-commit is specified).
4043 --no-commit is specified).
4041
4044
4042 Because import first applies changes to the working directory,
4045 Because import first applies changes to the working directory,
4043 import will abort if there are outstanding changes.
4046 import will abort if there are outstanding changes.
4044
4047
4045 You can import a patch straight from a mail message. Even patches
4048 You can import a patch straight from a mail message. Even patches
4046 as attachments work (to use the body part, it must have type
4049 as attachments work (to use the body part, it must have type
4047 text/plain or text/x-patch). From and Subject headers of email
4050 text/plain or text/x-patch). From and Subject headers of email
4048 message are used as default committer and commit message. All
4051 message are used as default committer and commit message. All
4049 text/plain body parts before first diff are added to commit
4052 text/plain body parts before first diff are added to commit
4050 message.
4053 message.
4051
4054
4052 If the imported patch was generated by :hg:`export`, user and
4055 If the imported patch was generated by :hg:`export`, user and
4053 description from patch override values from message headers and
4056 description from patch override values from message headers and
4054 body. Values given on command line with -m/--message and -u/--user
4057 body. Values given on command line with -m/--message and -u/--user
4055 override these.
4058 override these.
4056
4059
4057 If --exact is specified, import will set the working directory to
4060 If --exact is specified, import will set the working directory to
4058 the parent of each patch before applying it, and will abort if the
4061 the parent of each patch before applying it, and will abort if the
4059 resulting changeset has a different ID than the one recorded in
4062 resulting changeset has a different ID than the one recorded in
4060 the patch. This may happen due to character set problems or other
4063 the patch. This may happen due to character set problems or other
4061 deficiencies in the text patch format.
4064 deficiencies in the text patch format.
4062
4065
4063 Use --bypass to apply and commit patches directly to the
4066 Use --bypass to apply and commit patches directly to the
4064 repository, not touching the working directory. Without --exact,
4067 repository, not touching the working directory. Without --exact,
4065 patches will be applied on top of the working directory parent
4068 patches will be applied on top of the working directory parent
4066 revision.
4069 revision.
4067
4070
4068 With -s/--similarity, hg will attempt to discover renames and
4071 With -s/--similarity, hg will attempt to discover renames and
4069 copies in the patch in the same way as :hg:`addremove`.
4072 copies in the patch in the same way as :hg:`addremove`.
4070
4073
4071 Use --partial to ensure a changeset will be created from the patch
4074 Use --partial to ensure a changeset will be created from the patch
4072 even if some hunks fail to apply. Hunks that fail to apply will be
4075 even if some hunks fail to apply. Hunks that fail to apply will be
4073 written to a <target-file>.rej file. Conflicts can then be resolved
4076 written to a <target-file>.rej file. Conflicts can then be resolved
4074 by hand before :hg:`commit --amend` is run to update the created
4077 by hand before :hg:`commit --amend` is run to update the created
4075 changeset. This flag exists to let people import patches that
4078 changeset. This flag exists to let people import patches that
4076 partially apply without losing the associated metadata (author,
4079 partially apply without losing the associated metadata (author,
4077 date, description, ...). Note that when none of the hunk applies
4080 date, description, ...). Note that when none of the hunk applies
4078 cleanly, :hg:`import --partial` will create an empty changeset,
4081 cleanly, :hg:`import --partial` will create an empty changeset,
4079 importing only the patch metadata.
4082 importing only the patch metadata.
4080
4083
4081 To read a patch from standard input, use "-" as the patch name. If
4084 To read a patch from standard input, use "-" as the patch name. If
4082 a URL is specified, the patch will be downloaded from it.
4085 a URL is specified, the patch will be downloaded from it.
4083 See :hg:`help dates` for a list of formats valid for -d/--date.
4086 See :hg:`help dates` for a list of formats valid for -d/--date.
4084
4087
4085 .. container:: verbose
4088 .. container:: verbose
4086
4089
4087 Examples:
4090 Examples:
4088
4091
4089 - import a traditional patch from a website and detect renames::
4092 - import a traditional patch from a website and detect renames::
4090
4093
4091 hg import -s 80 http://example.com/bugfix.patch
4094 hg import -s 80 http://example.com/bugfix.patch
4092
4095
4093 - import a changeset from an hgweb server::
4096 - import a changeset from an hgweb server::
4094
4097
4095 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4098 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4096
4099
4097 - import all the patches in an Unix-style mbox::
4100 - import all the patches in an Unix-style mbox::
4098
4101
4099 hg import incoming-patches.mbox
4102 hg import incoming-patches.mbox
4100
4103
4101 - attempt to exactly restore an exported changeset (not always
4104 - attempt to exactly restore an exported changeset (not always
4102 possible)::
4105 possible)::
4103
4106
4104 hg import --exact proposed-fix.patch
4107 hg import --exact proposed-fix.patch
4105
4108
4106 Returns 0 on success, 1 on partial success (see --partial).
4109 Returns 0 on success, 1 on partial success (see --partial).
4107 """
4110 """
4108
4111
4109 if not patch1:
4112 if not patch1:
4110 raise util.Abort(_('need at least one patch to import'))
4113 raise util.Abort(_('need at least one patch to import'))
4111
4114
4112 patches = (patch1,) + patches
4115 patches = (patch1,) + patches
4113
4116
4114 date = opts.get('date')
4117 date = opts.get('date')
4115 if date:
4118 if date:
4116 opts['date'] = util.parsedate(date)
4119 opts['date'] = util.parsedate(date)
4117
4120
4118 update = not opts.get('bypass')
4121 update = not opts.get('bypass')
4119 if not update and opts.get('no_commit'):
4122 if not update and opts.get('no_commit'):
4120 raise util.Abort(_('cannot use --no-commit with --bypass'))
4123 raise util.Abort(_('cannot use --no-commit with --bypass'))
4121 try:
4124 try:
4122 sim = float(opts.get('similarity') or 0)
4125 sim = float(opts.get('similarity') or 0)
4123 except ValueError:
4126 except ValueError:
4124 raise util.Abort(_('similarity must be a number'))
4127 raise util.Abort(_('similarity must be a number'))
4125 if sim < 0 or sim > 100:
4128 if sim < 0 or sim > 100:
4126 raise util.Abort(_('similarity must be between 0 and 100'))
4129 raise util.Abort(_('similarity must be between 0 and 100'))
4127 if sim and not update:
4130 if sim and not update:
4128 raise util.Abort(_('cannot use --similarity with --bypass'))
4131 raise util.Abort(_('cannot use --similarity with --bypass'))
4129 if opts.get('exact') and opts.get('edit'):
4132 if opts.get('exact') and opts.get('edit'):
4130 raise util.Abort(_('cannot use --exact with --edit'))
4133 raise util.Abort(_('cannot use --exact with --edit'))
4131
4134
4132 if update:
4135 if update:
4133 cmdutil.checkunfinished(repo)
4136 cmdutil.checkunfinished(repo)
4134 if (opts.get('exact') or not opts.get('force')) and update:
4137 if (opts.get('exact') or not opts.get('force')) and update:
4135 cmdutil.bailifchanged(repo)
4138 cmdutil.bailifchanged(repo)
4136
4139
4137 base = opts["base"]
4140 base = opts["base"]
4138 wlock = lock = tr = None
4141 wlock = lock = tr = None
4139 msgs = []
4142 msgs = []
4140 ret = 0
4143 ret = 0
4141
4144
4142
4145
4143 try:
4146 try:
4144 try:
4147 try:
4145 wlock = repo.wlock()
4148 wlock = repo.wlock()
4146 repo.dirstate.beginparentchange()
4149 repo.dirstate.beginparentchange()
4147 if not opts.get('no_commit'):
4150 if not opts.get('no_commit'):
4148 lock = repo.lock()
4151 lock = repo.lock()
4149 tr = repo.transaction('import')
4152 tr = repo.transaction('import')
4150 parents = repo.parents()
4153 parents = repo.parents()
4151 for patchurl in patches:
4154 for patchurl in patches:
4152 if patchurl == '-':
4155 if patchurl == '-':
4153 ui.status(_('applying patch from stdin\n'))
4156 ui.status(_('applying patch from stdin\n'))
4154 patchfile = ui.fin
4157 patchfile = ui.fin
4155 patchurl = 'stdin' # for error message
4158 patchurl = 'stdin' # for error message
4156 else:
4159 else:
4157 patchurl = os.path.join(base, patchurl)
4160 patchurl = os.path.join(base, patchurl)
4158 ui.status(_('applying %s\n') % patchurl)
4161 ui.status(_('applying %s\n') % patchurl)
4159 patchfile = hg.openpath(ui, patchurl)
4162 patchfile = hg.openpath(ui, patchurl)
4160
4163
4161 haspatch = False
4164 haspatch = False
4162 for hunk in patch.split(patchfile):
4165 for hunk in patch.split(patchfile):
4163 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4166 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4164 parents, opts,
4167 parents, opts,
4165 msgs, hg.clean)
4168 msgs, hg.clean)
4166 if msg:
4169 if msg:
4167 haspatch = True
4170 haspatch = True
4168 ui.note(msg + '\n')
4171 ui.note(msg + '\n')
4169 if update or opts.get('exact'):
4172 if update or opts.get('exact'):
4170 parents = repo.parents()
4173 parents = repo.parents()
4171 else:
4174 else:
4172 parents = [repo[node]]
4175 parents = [repo[node]]
4173 if rej:
4176 if rej:
4174 ui.write_err(_("patch applied partially\n"))
4177 ui.write_err(_("patch applied partially\n"))
4175 ui.write_err(_("(fix the .rej files and run "
4178 ui.write_err(_("(fix the .rej files and run "
4176 "`hg commit --amend`)\n"))
4179 "`hg commit --amend`)\n"))
4177 ret = 1
4180 ret = 1
4178 break
4181 break
4179
4182
4180 if not haspatch:
4183 if not haspatch:
4181 raise util.Abort(_('%s: no diffs found') % patchurl)
4184 raise util.Abort(_('%s: no diffs found') % patchurl)
4182
4185
4183 if tr:
4186 if tr:
4184 tr.close()
4187 tr.close()
4185 if msgs:
4188 if msgs:
4186 repo.savecommitmessage('\n* * *\n'.join(msgs))
4189 repo.savecommitmessage('\n* * *\n'.join(msgs))
4187 repo.dirstate.endparentchange()
4190 repo.dirstate.endparentchange()
4188 return ret
4191 return ret
4189 except: # re-raises
4192 except: # re-raises
4190 # wlock.release() indirectly calls dirstate.write(): since
4193 # wlock.release() indirectly calls dirstate.write(): since
4191 # we're crashing, we do not want to change the working dir
4194 # we're crashing, we do not want to change the working dir
4192 # parent after all, so make sure it writes nothing
4195 # parent after all, so make sure it writes nothing
4193 repo.dirstate.invalidate()
4196 repo.dirstate.invalidate()
4194 raise
4197 raise
4195 finally:
4198 finally:
4196 if tr:
4199 if tr:
4197 tr.release()
4200 tr.release()
4198 release(lock, wlock)
4201 release(lock, wlock)
4199
4202
4200 @command('incoming|in',
4203 @command('incoming|in',
4201 [('f', 'force', None,
4204 [('f', 'force', None,
4202 _('run even if remote repository is unrelated')),
4205 _('run even if remote repository is unrelated')),
4203 ('n', 'newest-first', None, _('show newest record first')),
4206 ('n', 'newest-first', None, _('show newest record first')),
4204 ('', 'bundle', '',
4207 ('', 'bundle', '',
4205 _('file to store the bundles into'), _('FILE')),
4208 _('file to store the bundles into'), _('FILE')),
4206 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4209 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4207 ('B', 'bookmarks', False, _("compare bookmarks")),
4210 ('B', 'bookmarks', False, _("compare bookmarks")),
4208 ('b', 'branch', [],
4211 ('b', 'branch', [],
4209 _('a specific branch you would like to pull'), _('BRANCH')),
4212 _('a specific branch you would like to pull'), _('BRANCH')),
4210 ] + logopts + remoteopts + subrepoopts,
4213 ] + logopts + remoteopts + subrepoopts,
4211 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4214 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4212 def incoming(ui, repo, source="default", **opts):
4215 def incoming(ui, repo, source="default", **opts):
4213 """show new changesets found in source
4216 """show new changesets found in source
4214
4217
4215 Show new changesets found in the specified path/URL or the default
4218 Show new changesets found in the specified path/URL or the default
4216 pull location. These are the changesets that would have been pulled
4219 pull location. These are the changesets that would have been pulled
4217 if a pull at the time you issued this command.
4220 if a pull at the time you issued this command.
4218
4221
4219 For remote repository, using --bundle avoids downloading the
4222 For remote repository, using --bundle avoids downloading the
4220 changesets twice if the incoming is followed by a pull.
4223 changesets twice if the incoming is followed by a pull.
4221
4224
4222 See pull for valid source format details.
4225 See pull for valid source format details.
4223
4226
4224 .. container:: verbose
4227 .. container:: verbose
4225
4228
4226 Examples:
4229 Examples:
4227
4230
4228 - show incoming changes with patches and full description::
4231 - show incoming changes with patches and full description::
4229
4232
4230 hg incoming -vp
4233 hg incoming -vp
4231
4234
4232 - show incoming changes excluding merges, store a bundle::
4235 - show incoming changes excluding merges, store a bundle::
4233
4236
4234 hg in -vpM --bundle incoming.hg
4237 hg in -vpM --bundle incoming.hg
4235 hg pull incoming.hg
4238 hg pull incoming.hg
4236
4239
4237 - briefly list changes inside a bundle::
4240 - briefly list changes inside a bundle::
4238
4241
4239 hg in changes.hg -T "{desc|firstline}\\n"
4242 hg in changes.hg -T "{desc|firstline}\\n"
4240
4243
4241 Returns 0 if there are incoming changes, 1 otherwise.
4244 Returns 0 if there are incoming changes, 1 otherwise.
4242 """
4245 """
4243 if opts.get('graph'):
4246 if opts.get('graph'):
4244 cmdutil.checkunsupportedgraphflags([], opts)
4247 cmdutil.checkunsupportedgraphflags([], opts)
4245 def display(other, chlist, displayer):
4248 def display(other, chlist, displayer):
4246 revdag = cmdutil.graphrevs(other, chlist, opts)
4249 revdag = cmdutil.graphrevs(other, chlist, opts)
4247 showparents = [ctx.node() for ctx in repo[None].parents()]
4250 showparents = [ctx.node() for ctx in repo[None].parents()]
4248 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4251 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4249 graphmod.asciiedges)
4252 graphmod.asciiedges)
4250
4253
4251 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4254 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4252 return 0
4255 return 0
4253
4256
4254 if opts.get('bundle') and opts.get('subrepos'):
4257 if opts.get('bundle') and opts.get('subrepos'):
4255 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4258 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4256
4259
4257 if opts.get('bookmarks'):
4260 if opts.get('bookmarks'):
4258 source, branches = hg.parseurl(ui.expandpath(source),
4261 source, branches = hg.parseurl(ui.expandpath(source),
4259 opts.get('branch'))
4262 opts.get('branch'))
4260 other = hg.peer(repo, opts, source)
4263 other = hg.peer(repo, opts, source)
4261 if 'bookmarks' not in other.listkeys('namespaces'):
4264 if 'bookmarks' not in other.listkeys('namespaces'):
4262 ui.warn(_("remote doesn't support bookmarks\n"))
4265 ui.warn(_("remote doesn't support bookmarks\n"))
4263 return 0
4266 return 0
4264 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4267 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4265 return bookmarks.diff(ui, repo, other)
4268 return bookmarks.diff(ui, repo, other)
4266
4269
4267 repo._subtoppath = ui.expandpath(source)
4270 repo._subtoppath = ui.expandpath(source)
4268 try:
4271 try:
4269 return hg.incoming(ui, repo, source, opts)
4272 return hg.incoming(ui, repo, source, opts)
4270 finally:
4273 finally:
4271 del repo._subtoppath
4274 del repo._subtoppath
4272
4275
4273
4276
4274 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4277 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4275 norepo=True)
4278 norepo=True)
4276 def init(ui, dest=".", **opts):
4279 def init(ui, dest=".", **opts):
4277 """create a new repository in the given directory
4280 """create a new repository in the given directory
4278
4281
4279 Initialize a new repository in the given directory. If the given
4282 Initialize a new repository in the given directory. If the given
4280 directory does not exist, it will be created.
4283 directory does not exist, it will be created.
4281
4284
4282 If no directory is given, the current directory is used.
4285 If no directory is given, the current directory is used.
4283
4286
4284 It is possible to specify an ``ssh://`` URL as the destination.
4287 It is possible to specify an ``ssh://`` URL as the destination.
4285 See :hg:`help urls` for more information.
4288 See :hg:`help urls` for more information.
4286
4289
4287 Returns 0 on success.
4290 Returns 0 on success.
4288 """
4291 """
4289 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4292 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4290
4293
4291 @command('locate',
4294 @command('locate',
4292 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4295 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4293 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4296 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4294 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4297 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4295 ] + walkopts,
4298 ] + walkopts,
4296 _('[OPTION]... [PATTERN]...'))
4299 _('[OPTION]... [PATTERN]...'))
4297 def locate(ui, repo, *pats, **opts):
4300 def locate(ui, repo, *pats, **opts):
4298 """locate files matching specific patterns (DEPRECATED)
4301 """locate files matching specific patterns (DEPRECATED)
4299
4302
4300 Print files under Mercurial control in the working directory whose
4303 Print files under Mercurial control in the working directory whose
4301 names match the given patterns.
4304 names match the given patterns.
4302
4305
4303 By default, this command searches all directories in the working
4306 By default, this command searches all directories in the working
4304 directory. To search just the current directory and its
4307 directory. To search just the current directory and its
4305 subdirectories, use "--include .".
4308 subdirectories, use "--include .".
4306
4309
4307 If no patterns are given to match, this command prints the names
4310 If no patterns are given to match, this command prints the names
4308 of all files under Mercurial control in the working directory.
4311 of all files under Mercurial control in the working directory.
4309
4312
4310 If you want to feed the output of this command into the "xargs"
4313 If you want to feed the output of this command into the "xargs"
4311 command, use the -0 option to both this command and "xargs". This
4314 command, use the -0 option to both this command and "xargs". This
4312 will avoid the problem of "xargs" treating single filenames that
4315 will avoid the problem of "xargs" treating single filenames that
4313 contain whitespace as multiple filenames.
4316 contain whitespace as multiple filenames.
4314
4317
4315 See :hg:`help files` for a more versatile command.
4318 See :hg:`help files` for a more versatile command.
4316
4319
4317 Returns 0 if a match is found, 1 otherwise.
4320 Returns 0 if a match is found, 1 otherwise.
4318 """
4321 """
4319 end = opts.get('print0') and '\0' or '\n'
4322 end = opts.get('print0') and '\0' or '\n'
4320 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4323 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4321
4324
4322 ret = 1
4325 ret = 1
4323 ctx = repo[rev]
4326 ctx = repo[rev]
4324 m = scmutil.match(ctx, pats, opts, default='relglob')
4327 m = scmutil.match(ctx, pats, opts, default='relglob')
4325 m.bad = lambda x, y: False
4328 m.bad = lambda x, y: False
4326
4329
4327 for abs in ctx.matches(m):
4330 for abs in ctx.matches(m):
4328 if opts.get('fullpath'):
4331 if opts.get('fullpath'):
4329 ui.write(repo.wjoin(abs), end)
4332 ui.write(repo.wjoin(abs), end)
4330 else:
4333 else:
4331 ui.write(((pats and m.rel(abs)) or abs), end)
4334 ui.write(((pats and m.rel(abs)) or abs), end)
4332 ret = 0
4335 ret = 0
4333
4336
4334 return ret
4337 return ret
4335
4338
4336 @command('^log|history',
4339 @command('^log|history',
4337 [('f', 'follow', None,
4340 [('f', 'follow', None,
4338 _('follow changeset history, or file history across copies and renames')),
4341 _('follow changeset history, or file history across copies and renames')),
4339 ('', 'follow-first', None,
4342 ('', 'follow-first', None,
4340 _('only follow the first parent of merge changesets (DEPRECATED)')),
4343 _('only follow the first parent of merge changesets (DEPRECATED)')),
4341 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4344 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4342 ('C', 'copies', None, _('show copied files')),
4345 ('C', 'copies', None, _('show copied files')),
4343 ('k', 'keyword', [],
4346 ('k', 'keyword', [],
4344 _('do case-insensitive search for a given text'), _('TEXT')),
4347 _('do case-insensitive search for a given text'), _('TEXT')),
4345 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4348 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4346 ('', 'removed', None, _('include revisions where files were removed')),
4349 ('', 'removed', None, _('include revisions where files were removed')),
4347 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4350 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4348 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4351 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4349 ('', 'only-branch', [],
4352 ('', 'only-branch', [],
4350 _('show only changesets within the given named branch (DEPRECATED)'),
4353 _('show only changesets within the given named branch (DEPRECATED)'),
4351 _('BRANCH')),
4354 _('BRANCH')),
4352 ('b', 'branch', [],
4355 ('b', 'branch', [],
4353 _('show changesets within the given named branch'), _('BRANCH')),
4356 _('show changesets within the given named branch'), _('BRANCH')),
4354 ('P', 'prune', [],
4357 ('P', 'prune', [],
4355 _('do not display revision or any of its ancestors'), _('REV')),
4358 _('do not display revision or any of its ancestors'), _('REV')),
4356 ] + logopts + walkopts,
4359 ] + logopts + walkopts,
4357 _('[OPTION]... [FILE]'),
4360 _('[OPTION]... [FILE]'),
4358 inferrepo=True)
4361 inferrepo=True)
4359 def log(ui, repo, *pats, **opts):
4362 def log(ui, repo, *pats, **opts):
4360 """show revision history of entire repository or files
4363 """show revision history of entire repository or files
4361
4364
4362 Print the revision history of the specified files or the entire
4365 Print the revision history of the specified files or the entire
4363 project.
4366 project.
4364
4367
4365 If no revision range is specified, the default is ``tip:0`` unless
4368 If no revision range is specified, the default is ``tip:0`` unless
4366 --follow is set, in which case the working directory parent is
4369 --follow is set, in which case the working directory parent is
4367 used as the starting revision.
4370 used as the starting revision.
4368
4371
4369 File history is shown without following rename or copy history of
4372 File history is shown without following rename or copy history of
4370 files. Use -f/--follow with a filename to follow history across
4373 files. Use -f/--follow with a filename to follow history across
4371 renames and copies. --follow without a filename will only show
4374 renames and copies. --follow without a filename will only show
4372 ancestors or descendants of the starting revision.
4375 ancestors or descendants of the starting revision.
4373
4376
4374 By default this command prints revision number and changeset id,
4377 By default this command prints revision number and changeset id,
4375 tags, non-trivial parents, user, date and time, and a summary for
4378 tags, non-trivial parents, user, date and time, and a summary for
4376 each commit. When the -v/--verbose switch is used, the list of
4379 each commit. When the -v/--verbose switch is used, the list of
4377 changed files and full commit message are shown.
4380 changed files and full commit message are shown.
4378
4381
4379 With --graph the revisions are shown as an ASCII art DAG with the most
4382 With --graph the revisions are shown as an ASCII art DAG with the most
4380 recent changeset at the top.
4383 recent changeset at the top.
4381 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4384 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4382 and '+' represents a fork where the changeset from the lines below is a
4385 and '+' represents a fork where the changeset from the lines below is a
4383 parent of the 'o' merge on the same line.
4386 parent of the 'o' merge on the same line.
4384
4387
4385 .. note::
4388 .. note::
4386
4389
4387 log -p/--patch may generate unexpected diff output for merge
4390 log -p/--patch may generate unexpected diff output for merge
4388 changesets, as it will only compare the merge changeset against
4391 changesets, as it will only compare the merge changeset against
4389 its first parent. Also, only files different from BOTH parents
4392 its first parent. Also, only files different from BOTH parents
4390 will appear in files:.
4393 will appear in files:.
4391
4394
4392 .. note::
4395 .. note::
4393
4396
4394 for performance reasons, log FILE may omit duplicate changes
4397 for performance reasons, log FILE may omit duplicate changes
4395 made on branches and will not show removals or mode changes. To
4398 made on branches and will not show removals or mode changes. To
4396 see all such changes, use the --removed switch.
4399 see all such changes, use the --removed switch.
4397
4400
4398 .. container:: verbose
4401 .. container:: verbose
4399
4402
4400 Some examples:
4403 Some examples:
4401
4404
4402 - changesets with full descriptions and file lists::
4405 - changesets with full descriptions and file lists::
4403
4406
4404 hg log -v
4407 hg log -v
4405
4408
4406 - changesets ancestral to the working directory::
4409 - changesets ancestral to the working directory::
4407
4410
4408 hg log -f
4411 hg log -f
4409
4412
4410 - last 10 commits on the current branch::
4413 - last 10 commits on the current branch::
4411
4414
4412 hg log -l 10 -b .
4415 hg log -l 10 -b .
4413
4416
4414 - changesets showing all modifications of a file, including removals::
4417 - changesets showing all modifications of a file, including removals::
4415
4418
4416 hg log --removed file.c
4419 hg log --removed file.c
4417
4420
4418 - all changesets that touch a directory, with diffs, excluding merges::
4421 - all changesets that touch a directory, with diffs, excluding merges::
4419
4422
4420 hg log -Mp lib/
4423 hg log -Mp lib/
4421
4424
4422 - all revision numbers that match a keyword::
4425 - all revision numbers that match a keyword::
4423
4426
4424 hg log -k bug --template "{rev}\\n"
4427 hg log -k bug --template "{rev}\\n"
4425
4428
4426 - list available log templates::
4429 - list available log templates::
4427
4430
4428 hg log -T list
4431 hg log -T list
4429
4432
4430 - check if a given changeset is included in a tagged release::
4433 - check if a given changeset is included in a tagged release::
4431
4434
4432 hg log -r "a21ccf and ancestor(1.9)"
4435 hg log -r "a21ccf and ancestor(1.9)"
4433
4436
4434 - find all changesets by some user in a date range::
4437 - find all changesets by some user in a date range::
4435
4438
4436 hg log -k alice -d "may 2008 to jul 2008"
4439 hg log -k alice -d "may 2008 to jul 2008"
4437
4440
4438 - summary of all changesets after the last tag::
4441 - summary of all changesets after the last tag::
4439
4442
4440 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4443 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4441
4444
4442 See :hg:`help dates` for a list of formats valid for -d/--date.
4445 See :hg:`help dates` for a list of formats valid for -d/--date.
4443
4446
4444 See :hg:`help revisions` and :hg:`help revsets` for more about
4447 See :hg:`help revisions` and :hg:`help revsets` for more about
4445 specifying revisions.
4448 specifying revisions.
4446
4449
4447 See :hg:`help templates` for more about pre-packaged styles and
4450 See :hg:`help templates` for more about pre-packaged styles and
4448 specifying custom templates.
4451 specifying custom templates.
4449
4452
4450 Returns 0 on success.
4453 Returns 0 on success.
4451
4454
4452 """
4455 """
4453 if opts.get('graph'):
4456 if opts.get('graph'):
4454 return cmdutil.graphlog(ui, repo, *pats, **opts)
4457 return cmdutil.graphlog(ui, repo, *pats, **opts)
4455
4458
4456 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4459 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4457 limit = cmdutil.loglimit(opts)
4460 limit = cmdutil.loglimit(opts)
4458 count = 0
4461 count = 0
4459
4462
4460 getrenamed = None
4463 getrenamed = None
4461 if opts.get('copies'):
4464 if opts.get('copies'):
4462 endrev = None
4465 endrev = None
4463 if opts.get('rev'):
4466 if opts.get('rev'):
4464 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4467 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4465 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4468 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4466
4469
4467 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4470 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4468 for rev in revs:
4471 for rev in revs:
4469 if count == limit:
4472 if count == limit:
4470 break
4473 break
4471 ctx = repo[rev]
4474 ctx = repo[rev]
4472 copies = None
4475 copies = None
4473 if getrenamed is not None and rev:
4476 if getrenamed is not None and rev:
4474 copies = []
4477 copies = []
4475 for fn in ctx.files():
4478 for fn in ctx.files():
4476 rename = getrenamed(fn, rev)
4479 rename = getrenamed(fn, rev)
4477 if rename:
4480 if rename:
4478 copies.append((fn, rename[0]))
4481 copies.append((fn, rename[0]))
4479 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4482 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4480 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4483 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4481 if displayer.flush(rev):
4484 if displayer.flush(rev):
4482 count += 1
4485 count += 1
4483
4486
4484 displayer.close()
4487 displayer.close()
4485
4488
4486 @command('manifest',
4489 @command('manifest',
4487 [('r', 'rev', '', _('revision to display'), _('REV')),
4490 [('r', 'rev', '', _('revision to display'), _('REV')),
4488 ('', 'all', False, _("list files from all revisions"))]
4491 ('', 'all', False, _("list files from all revisions"))]
4489 + formatteropts,
4492 + formatteropts,
4490 _('[-r REV]'))
4493 _('[-r REV]'))
4491 def manifest(ui, repo, node=None, rev=None, **opts):
4494 def manifest(ui, repo, node=None, rev=None, **opts):
4492 """output the current or given revision of the project manifest
4495 """output the current or given revision of the project manifest
4493
4496
4494 Print a list of version controlled files for the given revision.
4497 Print a list of version controlled files for the given revision.
4495 If no revision is given, the first parent of the working directory
4498 If no revision is given, the first parent of the working directory
4496 is used, or the null revision if no revision is checked out.
4499 is used, or the null revision if no revision is checked out.
4497
4500
4498 With -v, print file permissions, symlink and executable bits.
4501 With -v, print file permissions, symlink and executable bits.
4499 With --debug, print file revision hashes.
4502 With --debug, print file revision hashes.
4500
4503
4501 If option --all is specified, the list of all files from all revisions
4504 If option --all is specified, the list of all files from all revisions
4502 is printed. This includes deleted and renamed files.
4505 is printed. This includes deleted and renamed files.
4503
4506
4504 Returns 0 on success.
4507 Returns 0 on success.
4505 """
4508 """
4506
4509
4507 fm = ui.formatter('manifest', opts)
4510 fm = ui.formatter('manifest', opts)
4508
4511
4509 if opts.get('all'):
4512 if opts.get('all'):
4510 if rev or node:
4513 if rev or node:
4511 raise util.Abort(_("can't specify a revision with --all"))
4514 raise util.Abort(_("can't specify a revision with --all"))
4512
4515
4513 res = []
4516 res = []
4514 prefix = "data/"
4517 prefix = "data/"
4515 suffix = ".i"
4518 suffix = ".i"
4516 plen = len(prefix)
4519 plen = len(prefix)
4517 slen = len(suffix)
4520 slen = len(suffix)
4518 lock = repo.lock()
4521 lock = repo.lock()
4519 try:
4522 try:
4520 for fn, b, size in repo.store.datafiles():
4523 for fn, b, size in repo.store.datafiles():
4521 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4524 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4522 res.append(fn[plen:-slen])
4525 res.append(fn[plen:-slen])
4523 finally:
4526 finally:
4524 lock.release()
4527 lock.release()
4525 for f in res:
4528 for f in res:
4526 fm.startitem()
4529 fm.startitem()
4527 fm.write("path", '%s\n', f)
4530 fm.write("path", '%s\n', f)
4528 fm.end()
4531 fm.end()
4529 return
4532 return
4530
4533
4531 if rev and node:
4534 if rev and node:
4532 raise util.Abort(_("please specify just one revision"))
4535 raise util.Abort(_("please specify just one revision"))
4533
4536
4534 if not node:
4537 if not node:
4535 node = rev
4538 node = rev
4536
4539
4537 char = {'l': '@', 'x': '*', '': ''}
4540 char = {'l': '@', 'x': '*', '': ''}
4538 mode = {'l': '644', 'x': '755', '': '644'}
4541 mode = {'l': '644', 'x': '755', '': '644'}
4539 ctx = scmutil.revsingle(repo, node)
4542 ctx = scmutil.revsingle(repo, node)
4540 mf = ctx.manifest()
4543 mf = ctx.manifest()
4541 for f in ctx:
4544 for f in ctx:
4542 fm.startitem()
4545 fm.startitem()
4543 fl = ctx[f].flags()
4546 fl = ctx[f].flags()
4544 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4547 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4545 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4548 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4546 fm.write('path', '%s\n', f)
4549 fm.write('path', '%s\n', f)
4547 fm.end()
4550 fm.end()
4548
4551
4549 @command('^merge',
4552 @command('^merge',
4550 [('f', 'force', None,
4553 [('f', 'force', None,
4551 _('force a merge including outstanding changes (DEPRECATED)')),
4554 _('force a merge including outstanding changes (DEPRECATED)')),
4552 ('r', 'rev', '', _('revision to merge'), _('REV')),
4555 ('r', 'rev', '', _('revision to merge'), _('REV')),
4553 ('P', 'preview', None,
4556 ('P', 'preview', None,
4554 _('review revisions to merge (no merge is performed)'))
4557 _('review revisions to merge (no merge is performed)'))
4555 ] + mergetoolopts,
4558 ] + mergetoolopts,
4556 _('[-P] [-f] [[-r] REV]'))
4559 _('[-P] [-f] [[-r] REV]'))
4557 def merge(ui, repo, node=None, **opts):
4560 def merge(ui, repo, node=None, **opts):
4558 """merge another revision into working directory
4561 """merge another revision into working directory
4559
4562
4560 The current working directory is updated with all changes made in
4563 The current working directory is updated with all changes made in
4561 the requested revision since the last common predecessor revision.
4564 the requested revision since the last common predecessor revision.
4562
4565
4563 Files that changed between either parent are marked as changed for
4566 Files that changed between either parent are marked as changed for
4564 the next commit and a commit must be performed before any further
4567 the next commit and a commit must be performed before any further
4565 updates to the repository are allowed. The next commit will have
4568 updates to the repository are allowed. The next commit will have
4566 two parents.
4569 two parents.
4567
4570
4568 ``--tool`` can be used to specify the merge tool used for file
4571 ``--tool`` can be used to specify the merge tool used for file
4569 merges. It overrides the HGMERGE environment variable and your
4572 merges. It overrides the HGMERGE environment variable and your
4570 configuration files. See :hg:`help merge-tools` for options.
4573 configuration files. See :hg:`help merge-tools` for options.
4571
4574
4572 If no revision is specified, the working directory's parent is a
4575 If no revision is specified, the working directory's parent is a
4573 head revision, and the current branch contains exactly one other
4576 head revision, and the current branch contains exactly one other
4574 head, the other head is merged with by default. Otherwise, an
4577 head, the other head is merged with by default. Otherwise, an
4575 explicit revision with which to merge with must be provided.
4578 explicit revision with which to merge with must be provided.
4576
4579
4577 :hg:`resolve` must be used to resolve unresolved files.
4580 :hg:`resolve` must be used to resolve unresolved files.
4578
4581
4579 To undo an uncommitted merge, use :hg:`update --clean .` which
4582 To undo an uncommitted merge, use :hg:`update --clean .` which
4580 will check out a clean copy of the original merge parent, losing
4583 will check out a clean copy of the original merge parent, losing
4581 all changes.
4584 all changes.
4582
4585
4583 Returns 0 on success, 1 if there are unresolved files.
4586 Returns 0 on success, 1 if there are unresolved files.
4584 """
4587 """
4585
4588
4586 if opts.get('rev') and node:
4589 if opts.get('rev') and node:
4587 raise util.Abort(_("please specify just one revision"))
4590 raise util.Abort(_("please specify just one revision"))
4588 if not node:
4591 if not node:
4589 node = opts.get('rev')
4592 node = opts.get('rev')
4590
4593
4591 if node:
4594 if node:
4592 node = scmutil.revsingle(repo, node).node()
4595 node = scmutil.revsingle(repo, node).node()
4593
4596
4594 if not node and repo._bookmarkcurrent:
4597 if not node and repo._bookmarkcurrent:
4595 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4598 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4596 curhead = repo[repo._bookmarkcurrent].node()
4599 curhead = repo[repo._bookmarkcurrent].node()
4597 if len(bmheads) == 2:
4600 if len(bmheads) == 2:
4598 if curhead == bmheads[0]:
4601 if curhead == bmheads[0]:
4599 node = bmheads[1]
4602 node = bmheads[1]
4600 else:
4603 else:
4601 node = bmheads[0]
4604 node = bmheads[0]
4602 elif len(bmheads) > 2:
4605 elif len(bmheads) > 2:
4603 raise util.Abort(_("multiple matching bookmarks to merge - "
4606 raise util.Abort(_("multiple matching bookmarks to merge - "
4604 "please merge with an explicit rev or bookmark"),
4607 "please merge with an explicit rev or bookmark"),
4605 hint=_("run 'hg heads' to see all heads"))
4608 hint=_("run 'hg heads' to see all heads"))
4606 elif len(bmheads) <= 1:
4609 elif len(bmheads) <= 1:
4607 raise util.Abort(_("no matching bookmark to merge - "
4610 raise util.Abort(_("no matching bookmark to merge - "
4608 "please merge with an explicit rev or bookmark"),
4611 "please merge with an explicit rev or bookmark"),
4609 hint=_("run 'hg heads' to see all heads"))
4612 hint=_("run 'hg heads' to see all heads"))
4610
4613
4611 if not node and not repo._bookmarkcurrent:
4614 if not node and not repo._bookmarkcurrent:
4612 branch = repo[None].branch()
4615 branch = repo[None].branch()
4613 bheads = repo.branchheads(branch)
4616 bheads = repo.branchheads(branch)
4614 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4617 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4615
4618
4616 if len(nbhs) > 2:
4619 if len(nbhs) > 2:
4617 raise util.Abort(_("branch '%s' has %d heads - "
4620 raise util.Abort(_("branch '%s' has %d heads - "
4618 "please merge with an explicit rev")
4621 "please merge with an explicit rev")
4619 % (branch, len(bheads)),
4622 % (branch, len(bheads)),
4620 hint=_("run 'hg heads .' to see heads"))
4623 hint=_("run 'hg heads .' to see heads"))
4621
4624
4622 parent = repo.dirstate.p1()
4625 parent = repo.dirstate.p1()
4623 if len(nbhs) <= 1:
4626 if len(nbhs) <= 1:
4624 if len(bheads) > 1:
4627 if len(bheads) > 1:
4625 raise util.Abort(_("heads are bookmarked - "
4628 raise util.Abort(_("heads are bookmarked - "
4626 "please merge with an explicit rev"),
4629 "please merge with an explicit rev"),
4627 hint=_("run 'hg heads' to see all heads"))
4630 hint=_("run 'hg heads' to see all heads"))
4628 if len(repo.heads()) > 1:
4631 if len(repo.heads()) > 1:
4629 raise util.Abort(_("branch '%s' has one head - "
4632 raise util.Abort(_("branch '%s' has one head - "
4630 "please merge with an explicit rev")
4633 "please merge with an explicit rev")
4631 % branch,
4634 % branch,
4632 hint=_("run 'hg heads' to see all heads"))
4635 hint=_("run 'hg heads' to see all heads"))
4633 msg, hint = _('nothing to merge'), None
4636 msg, hint = _('nothing to merge'), None
4634 if parent != repo.lookup(branch):
4637 if parent != repo.lookup(branch):
4635 hint = _("use 'hg update' instead")
4638 hint = _("use 'hg update' instead")
4636 raise util.Abort(msg, hint=hint)
4639 raise util.Abort(msg, hint=hint)
4637
4640
4638 if parent not in bheads:
4641 if parent not in bheads:
4639 raise util.Abort(_('working directory not at a head revision'),
4642 raise util.Abort(_('working directory not at a head revision'),
4640 hint=_("use 'hg update' or merge with an "
4643 hint=_("use 'hg update' or merge with an "
4641 "explicit revision"))
4644 "explicit revision"))
4642 if parent == nbhs[0]:
4645 if parent == nbhs[0]:
4643 node = nbhs[-1]
4646 node = nbhs[-1]
4644 else:
4647 else:
4645 node = nbhs[0]
4648 node = nbhs[0]
4646
4649
4647 if opts.get('preview'):
4650 if opts.get('preview'):
4648 # find nodes that are ancestors of p2 but not of p1
4651 # find nodes that are ancestors of p2 but not of p1
4649 p1 = repo.lookup('.')
4652 p1 = repo.lookup('.')
4650 p2 = repo.lookup(node)
4653 p2 = repo.lookup(node)
4651 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4654 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4652
4655
4653 displayer = cmdutil.show_changeset(ui, repo, opts)
4656 displayer = cmdutil.show_changeset(ui, repo, opts)
4654 for node in nodes:
4657 for node in nodes:
4655 displayer.show(repo[node])
4658 displayer.show(repo[node])
4656 displayer.close()
4659 displayer.close()
4657 return 0
4660 return 0
4658
4661
4659 try:
4662 try:
4660 # ui.forcemerge is an internal variable, do not document
4663 # ui.forcemerge is an internal variable, do not document
4661 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4664 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4662 return hg.merge(repo, node, force=opts.get('force'))
4665 return hg.merge(repo, node, force=opts.get('force'))
4663 finally:
4666 finally:
4664 ui.setconfig('ui', 'forcemerge', '', 'merge')
4667 ui.setconfig('ui', 'forcemerge', '', 'merge')
4665
4668
4666 @command('outgoing|out',
4669 @command('outgoing|out',
4667 [('f', 'force', None, _('run even when the destination is unrelated')),
4670 [('f', 'force', None, _('run even when the destination is unrelated')),
4668 ('r', 'rev', [],
4671 ('r', 'rev', [],
4669 _('a changeset intended to be included in the destination'), _('REV')),
4672 _('a changeset intended to be included in the destination'), _('REV')),
4670 ('n', 'newest-first', None, _('show newest record first')),
4673 ('n', 'newest-first', None, _('show newest record first')),
4671 ('B', 'bookmarks', False, _('compare bookmarks')),
4674 ('B', 'bookmarks', False, _('compare bookmarks')),
4672 ('b', 'branch', [], _('a specific branch you would like to push'),
4675 ('b', 'branch', [], _('a specific branch you would like to push'),
4673 _('BRANCH')),
4676 _('BRANCH')),
4674 ] + logopts + remoteopts + subrepoopts,
4677 ] + logopts + remoteopts + subrepoopts,
4675 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4678 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4676 def outgoing(ui, repo, dest=None, **opts):
4679 def outgoing(ui, repo, dest=None, **opts):
4677 """show changesets not found in the destination
4680 """show changesets not found in the destination
4678
4681
4679 Show changesets not found in the specified destination repository
4682 Show changesets not found in the specified destination repository
4680 or the default push location. These are the changesets that would
4683 or the default push location. These are the changesets that would
4681 be pushed if a push was requested.
4684 be pushed if a push was requested.
4682
4685
4683 See pull for details of valid destination formats.
4686 See pull for details of valid destination formats.
4684
4687
4685 Returns 0 if there are outgoing changes, 1 otherwise.
4688 Returns 0 if there are outgoing changes, 1 otherwise.
4686 """
4689 """
4687 if opts.get('graph'):
4690 if opts.get('graph'):
4688 cmdutil.checkunsupportedgraphflags([], opts)
4691 cmdutil.checkunsupportedgraphflags([], opts)
4689 o, other = hg._outgoing(ui, repo, dest, opts)
4692 o, other = hg._outgoing(ui, repo, dest, opts)
4690 if not o:
4693 if not o:
4691 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4694 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4692 return
4695 return
4693
4696
4694 revdag = cmdutil.graphrevs(repo, o, opts)
4697 revdag = cmdutil.graphrevs(repo, o, opts)
4695 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4698 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4696 showparents = [ctx.node() for ctx in repo[None].parents()]
4699 showparents = [ctx.node() for ctx in repo[None].parents()]
4697 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4700 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4698 graphmod.asciiedges)
4701 graphmod.asciiedges)
4699 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4702 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4700 return 0
4703 return 0
4701
4704
4702 if opts.get('bookmarks'):
4705 if opts.get('bookmarks'):
4703 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4706 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4704 dest, branches = hg.parseurl(dest, opts.get('branch'))
4707 dest, branches = hg.parseurl(dest, opts.get('branch'))
4705 other = hg.peer(repo, opts, dest)
4708 other = hg.peer(repo, opts, dest)
4706 if 'bookmarks' not in other.listkeys('namespaces'):
4709 if 'bookmarks' not in other.listkeys('namespaces'):
4707 ui.warn(_("remote doesn't support bookmarks\n"))
4710 ui.warn(_("remote doesn't support bookmarks\n"))
4708 return 0
4711 return 0
4709 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4712 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4710 return bookmarks.diff(ui, other, repo)
4713 return bookmarks.diff(ui, other, repo)
4711
4714
4712 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4715 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4713 try:
4716 try:
4714 return hg.outgoing(ui, repo, dest, opts)
4717 return hg.outgoing(ui, repo, dest, opts)
4715 finally:
4718 finally:
4716 del repo._subtoppath
4719 del repo._subtoppath
4717
4720
4718 @command('parents',
4721 @command('parents',
4719 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4722 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4720 ] + templateopts,
4723 ] + templateopts,
4721 _('[-r REV] [FILE]'),
4724 _('[-r REV] [FILE]'),
4722 inferrepo=True)
4725 inferrepo=True)
4723 def parents(ui, repo, file_=None, **opts):
4726 def parents(ui, repo, file_=None, **opts):
4724 """show the parents of the working directory or revision (DEPRECATED)
4727 """show the parents of the working directory or revision (DEPRECATED)
4725
4728
4726 Print the working directory's parent revisions. If a revision is
4729 Print the working directory's parent revisions. If a revision is
4727 given via -r/--rev, the parent of that revision will be printed.
4730 given via -r/--rev, the parent of that revision will be printed.
4728 If a file argument is given, the revision in which the file was
4731 If a file argument is given, the revision in which the file was
4729 last changed (before the working directory revision or the
4732 last changed (before the working directory revision or the
4730 argument to --rev if given) is printed.
4733 argument to --rev if given) is printed.
4731
4734
4732 See :hg:`summary` and :hg:`help revsets` for related information.
4735 See :hg:`summary` and :hg:`help revsets` for related information.
4733
4736
4734 Returns 0 on success.
4737 Returns 0 on success.
4735 """
4738 """
4736
4739
4737 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4740 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4738
4741
4739 if file_:
4742 if file_:
4740 m = scmutil.match(ctx, (file_,), opts)
4743 m = scmutil.match(ctx, (file_,), opts)
4741 if m.anypats() or len(m.files()) != 1:
4744 if m.anypats() or len(m.files()) != 1:
4742 raise util.Abort(_('can only specify an explicit filename'))
4745 raise util.Abort(_('can only specify an explicit filename'))
4743 file_ = m.files()[0]
4746 file_ = m.files()[0]
4744 filenodes = []
4747 filenodes = []
4745 for cp in ctx.parents():
4748 for cp in ctx.parents():
4746 if not cp:
4749 if not cp:
4747 continue
4750 continue
4748 try:
4751 try:
4749 filenodes.append(cp.filenode(file_))
4752 filenodes.append(cp.filenode(file_))
4750 except error.LookupError:
4753 except error.LookupError:
4751 pass
4754 pass
4752 if not filenodes:
4755 if not filenodes:
4753 raise util.Abort(_("'%s' not found in manifest!") % file_)
4756 raise util.Abort(_("'%s' not found in manifest!") % file_)
4754 p = []
4757 p = []
4755 for fn in filenodes:
4758 for fn in filenodes:
4756 fctx = repo.filectx(file_, fileid=fn)
4759 fctx = repo.filectx(file_, fileid=fn)
4757 p.append(fctx.node())
4760 p.append(fctx.node())
4758 else:
4761 else:
4759 p = [cp.node() for cp in ctx.parents()]
4762 p = [cp.node() for cp in ctx.parents()]
4760
4763
4761 displayer = cmdutil.show_changeset(ui, repo, opts)
4764 displayer = cmdutil.show_changeset(ui, repo, opts)
4762 for n in p:
4765 for n in p:
4763 if n != nullid:
4766 if n != nullid:
4764 displayer.show(repo[n])
4767 displayer.show(repo[n])
4765 displayer.close()
4768 displayer.close()
4766
4769
4767 @command('paths', [], _('[NAME]'), optionalrepo=True)
4770 @command('paths', [], _('[NAME]'), optionalrepo=True)
4768 def paths(ui, repo, search=None):
4771 def paths(ui, repo, search=None):
4769 """show aliases for remote repositories
4772 """show aliases for remote repositories
4770
4773
4771 Show definition of symbolic path name NAME. If no name is given,
4774 Show definition of symbolic path name NAME. If no name is given,
4772 show definition of all available names.
4775 show definition of all available names.
4773
4776
4774 Option -q/--quiet suppresses all output when searching for NAME
4777 Option -q/--quiet suppresses all output when searching for NAME
4775 and shows only the path names when listing all definitions.
4778 and shows only the path names when listing all definitions.
4776
4779
4777 Path names are defined in the [paths] section of your
4780 Path names are defined in the [paths] section of your
4778 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4781 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4779 repository, ``.hg/hgrc`` is used, too.
4782 repository, ``.hg/hgrc`` is used, too.
4780
4783
4781 The path names ``default`` and ``default-push`` have a special
4784 The path names ``default`` and ``default-push`` have a special
4782 meaning. When performing a push or pull operation, they are used
4785 meaning. When performing a push or pull operation, they are used
4783 as fallbacks if no location is specified on the command-line.
4786 as fallbacks if no location is specified on the command-line.
4784 When ``default-push`` is set, it will be used for push and
4787 When ``default-push`` is set, it will be used for push and
4785 ``default`` will be used for pull; otherwise ``default`` is used
4788 ``default`` will be used for pull; otherwise ``default`` is used
4786 as the fallback for both. When cloning a repository, the clone
4789 as the fallback for both. When cloning a repository, the clone
4787 source is written as ``default`` in ``.hg/hgrc``. Note that
4790 source is written as ``default`` in ``.hg/hgrc``. Note that
4788 ``default`` and ``default-push`` apply to all inbound (e.g.
4791 ``default`` and ``default-push`` apply to all inbound (e.g.
4789 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4792 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4790 :hg:`bundle`) operations.
4793 :hg:`bundle`) operations.
4791
4794
4792 See :hg:`help urls` for more information.
4795 See :hg:`help urls` for more information.
4793
4796
4794 Returns 0 on success.
4797 Returns 0 on success.
4795 """
4798 """
4796 if search:
4799 if search:
4797 for name, path in ui.configitems("paths"):
4800 for name, path in ui.configitems("paths"):
4798 if name == search:
4801 if name == search:
4799 ui.status("%s\n" % util.hidepassword(path))
4802 ui.status("%s\n" % util.hidepassword(path))
4800 return
4803 return
4801 if not ui.quiet:
4804 if not ui.quiet:
4802 ui.warn(_("not found!\n"))
4805 ui.warn(_("not found!\n"))
4803 return 1
4806 return 1
4804 else:
4807 else:
4805 for name, path in ui.configitems("paths"):
4808 for name, path in ui.configitems("paths"):
4806 if ui.quiet:
4809 if ui.quiet:
4807 ui.write("%s\n" % name)
4810 ui.write("%s\n" % name)
4808 else:
4811 else:
4809 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4812 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4810
4813
4811 @command('phase',
4814 @command('phase',
4812 [('p', 'public', False, _('set changeset phase to public')),
4815 [('p', 'public', False, _('set changeset phase to public')),
4813 ('d', 'draft', False, _('set changeset phase to draft')),
4816 ('d', 'draft', False, _('set changeset phase to draft')),
4814 ('s', 'secret', False, _('set changeset phase to secret')),
4817 ('s', 'secret', False, _('set changeset phase to secret')),
4815 ('f', 'force', False, _('allow to move boundary backward')),
4818 ('f', 'force', False, _('allow to move boundary backward')),
4816 ('r', 'rev', [], _('target revision'), _('REV')),
4819 ('r', 'rev', [], _('target revision'), _('REV')),
4817 ],
4820 ],
4818 _('[-p|-d|-s] [-f] [-r] REV...'))
4821 _('[-p|-d|-s] [-f] [-r] REV...'))
4819 def phase(ui, repo, *revs, **opts):
4822 def phase(ui, repo, *revs, **opts):
4820 """set or show the current phase name
4823 """set or show the current phase name
4821
4824
4822 With no argument, show the phase name of specified revisions.
4825 With no argument, show the phase name of specified revisions.
4823
4826
4824 With one of -p/--public, -d/--draft or -s/--secret, change the
4827 With one of -p/--public, -d/--draft or -s/--secret, change the
4825 phase value of the specified revisions.
4828 phase value of the specified revisions.
4826
4829
4827 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4830 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4828 lower phase to an higher phase. Phases are ordered as follows::
4831 lower phase to an higher phase. Phases are ordered as follows::
4829
4832
4830 public < draft < secret
4833 public < draft < secret
4831
4834
4832 Returns 0 on success, 1 if no phases were changed or some could not
4835 Returns 0 on success, 1 if no phases were changed or some could not
4833 be changed.
4836 be changed.
4834 """
4837 """
4835 # search for a unique phase argument
4838 # search for a unique phase argument
4836 targetphase = None
4839 targetphase = None
4837 for idx, name in enumerate(phases.phasenames):
4840 for idx, name in enumerate(phases.phasenames):
4838 if opts[name]:
4841 if opts[name]:
4839 if targetphase is not None:
4842 if targetphase is not None:
4840 raise util.Abort(_('only one phase can be specified'))
4843 raise util.Abort(_('only one phase can be specified'))
4841 targetphase = idx
4844 targetphase = idx
4842
4845
4843 # look for specified revision
4846 # look for specified revision
4844 revs = list(revs)
4847 revs = list(revs)
4845 revs.extend(opts['rev'])
4848 revs.extend(opts['rev'])
4846 if not revs:
4849 if not revs:
4847 raise util.Abort(_('no revisions specified'))
4850 raise util.Abort(_('no revisions specified'))
4848
4851
4849 revs = scmutil.revrange(repo, revs)
4852 revs = scmutil.revrange(repo, revs)
4850
4853
4851 lock = None
4854 lock = None
4852 ret = 0
4855 ret = 0
4853 if targetphase is None:
4856 if targetphase is None:
4854 # display
4857 # display
4855 for r in revs:
4858 for r in revs:
4856 ctx = repo[r]
4859 ctx = repo[r]
4857 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4860 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4858 else:
4861 else:
4859 tr = None
4862 tr = None
4860 lock = repo.lock()
4863 lock = repo.lock()
4861 try:
4864 try:
4862 tr = repo.transaction("phase")
4865 tr = repo.transaction("phase")
4863 # set phase
4866 # set phase
4864 if not revs:
4867 if not revs:
4865 raise util.Abort(_('empty revision set'))
4868 raise util.Abort(_('empty revision set'))
4866 nodes = [repo[r].node() for r in revs]
4869 nodes = [repo[r].node() for r in revs]
4867 # moving revision from public to draft may hide them
4870 # moving revision from public to draft may hide them
4868 # We have to check result on an unfiltered repository
4871 # We have to check result on an unfiltered repository
4869 unfi = repo.unfiltered()
4872 unfi = repo.unfiltered()
4870 getphase = unfi._phasecache.phase
4873 getphase = unfi._phasecache.phase
4871 olddata = [getphase(unfi, r) for r in unfi]
4874 olddata = [getphase(unfi, r) for r in unfi]
4872 phases.advanceboundary(repo, tr, targetphase, nodes)
4875 phases.advanceboundary(repo, tr, targetphase, nodes)
4873 if opts['force']:
4876 if opts['force']:
4874 phases.retractboundary(repo, tr, targetphase, nodes)
4877 phases.retractboundary(repo, tr, targetphase, nodes)
4875 tr.close()
4878 tr.close()
4876 finally:
4879 finally:
4877 if tr is not None:
4880 if tr is not None:
4878 tr.release()
4881 tr.release()
4879 lock.release()
4882 lock.release()
4880 getphase = unfi._phasecache.phase
4883 getphase = unfi._phasecache.phase
4881 newdata = [getphase(unfi, r) for r in unfi]
4884 newdata = [getphase(unfi, r) for r in unfi]
4882 changes = sum(newdata[r] != olddata[r] for r in unfi)
4885 changes = sum(newdata[r] != olddata[r] for r in unfi)
4883 cl = unfi.changelog
4886 cl = unfi.changelog
4884 rejected = [n for n in nodes
4887 rejected = [n for n in nodes
4885 if newdata[cl.rev(n)] < targetphase]
4888 if newdata[cl.rev(n)] < targetphase]
4886 if rejected:
4889 if rejected:
4887 ui.warn(_('cannot move %i changesets to a higher '
4890 ui.warn(_('cannot move %i changesets to a higher '
4888 'phase, use --force\n') % len(rejected))
4891 'phase, use --force\n') % len(rejected))
4889 ret = 1
4892 ret = 1
4890 if changes:
4893 if changes:
4891 msg = _('phase changed for %i changesets\n') % changes
4894 msg = _('phase changed for %i changesets\n') % changes
4892 if ret:
4895 if ret:
4893 ui.status(msg)
4896 ui.status(msg)
4894 else:
4897 else:
4895 ui.note(msg)
4898 ui.note(msg)
4896 else:
4899 else:
4897 ui.warn(_('no phases changed\n'))
4900 ui.warn(_('no phases changed\n'))
4898 ret = 1
4901 ret = 1
4899 return ret
4902 return ret
4900
4903
4901 def postincoming(ui, repo, modheads, optupdate, checkout):
4904 def postincoming(ui, repo, modheads, optupdate, checkout):
4902 if modheads == 0:
4905 if modheads == 0:
4903 return
4906 return
4904 if optupdate:
4907 if optupdate:
4905 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4908 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4906 try:
4909 try:
4907 ret = hg.update(repo, checkout)
4910 ret = hg.update(repo, checkout)
4908 except util.Abort, inst:
4911 except util.Abort, inst:
4909 ui.warn(_("not updating: %s\n") % str(inst))
4912 ui.warn(_("not updating: %s\n") % str(inst))
4910 if inst.hint:
4913 if inst.hint:
4911 ui.warn(_("(%s)\n") % inst.hint)
4914 ui.warn(_("(%s)\n") % inst.hint)
4912 return 0
4915 return 0
4913 if not ret and not checkout:
4916 if not ret and not checkout:
4914 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4917 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4915 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4918 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4916 return ret
4919 return ret
4917 if modheads > 1:
4920 if modheads > 1:
4918 currentbranchheads = len(repo.branchheads())
4921 currentbranchheads = len(repo.branchheads())
4919 if currentbranchheads == modheads:
4922 if currentbranchheads == modheads:
4920 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4923 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4921 elif currentbranchheads > 1:
4924 elif currentbranchheads > 1:
4922 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4925 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4923 "merge)\n"))
4926 "merge)\n"))
4924 else:
4927 else:
4925 ui.status(_("(run 'hg heads' to see heads)\n"))
4928 ui.status(_("(run 'hg heads' to see heads)\n"))
4926 else:
4929 else:
4927 ui.status(_("(run 'hg update' to get a working copy)\n"))
4930 ui.status(_("(run 'hg update' to get a working copy)\n"))
4928
4931
4929 @command('^pull',
4932 @command('^pull',
4930 [('u', 'update', None,
4933 [('u', 'update', None,
4931 _('update to new branch head if changesets were pulled')),
4934 _('update to new branch head if changesets were pulled')),
4932 ('f', 'force', None, _('run even when remote repository is unrelated')),
4935 ('f', 'force', None, _('run even when remote repository is unrelated')),
4933 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4936 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4934 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4937 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4935 ('b', 'branch', [], _('a specific branch you would like to pull'),
4938 ('b', 'branch', [], _('a specific branch you would like to pull'),
4936 _('BRANCH')),
4939 _('BRANCH')),
4937 ] + remoteopts,
4940 ] + remoteopts,
4938 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4941 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4939 def pull(ui, repo, source="default", **opts):
4942 def pull(ui, repo, source="default", **opts):
4940 """pull changes from the specified source
4943 """pull changes from the specified source
4941
4944
4942 Pull changes from a remote repository to a local one.
4945 Pull changes from a remote repository to a local one.
4943
4946
4944 This finds all changes from the repository at the specified path
4947 This finds all changes from the repository at the specified path
4945 or URL and adds them to a local repository (the current one unless
4948 or URL and adds them to a local repository (the current one unless
4946 -R is specified). By default, this does not update the copy of the
4949 -R is specified). By default, this does not update the copy of the
4947 project in the working directory.
4950 project in the working directory.
4948
4951
4949 Use :hg:`incoming` if you want to see what would have been added
4952 Use :hg:`incoming` if you want to see what would have been added
4950 by a pull at the time you issued this command. If you then decide
4953 by a pull at the time you issued this command. If you then decide
4951 to add those changes to the repository, you should use :hg:`pull
4954 to add those changes to the repository, you should use :hg:`pull
4952 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4955 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4953
4956
4954 If SOURCE is omitted, the 'default' path will be used.
4957 If SOURCE is omitted, the 'default' path will be used.
4955 See :hg:`help urls` for more information.
4958 See :hg:`help urls` for more information.
4956
4959
4957 Returns 0 on success, 1 if an update had unresolved files.
4960 Returns 0 on success, 1 if an update had unresolved files.
4958 """
4961 """
4959 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4962 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4960 other = hg.peer(repo, opts, source)
4963 other = hg.peer(repo, opts, source)
4961 try:
4964 try:
4962 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4965 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4963 revs, checkout = hg.addbranchrevs(repo, other, branches,
4966 revs, checkout = hg.addbranchrevs(repo, other, branches,
4964 opts.get('rev'))
4967 opts.get('rev'))
4965
4968
4966 remotebookmarks = other.listkeys('bookmarks')
4969 remotebookmarks = other.listkeys('bookmarks')
4967
4970
4968 if opts.get('bookmark'):
4971 if opts.get('bookmark'):
4969 if not revs:
4972 if not revs:
4970 revs = []
4973 revs = []
4971 for b in opts['bookmark']:
4974 for b in opts['bookmark']:
4972 if b not in remotebookmarks:
4975 if b not in remotebookmarks:
4973 raise util.Abort(_('remote bookmark %s not found!') % b)
4976 raise util.Abort(_('remote bookmark %s not found!') % b)
4974 revs.append(remotebookmarks[b])
4977 revs.append(remotebookmarks[b])
4975
4978
4976 if revs:
4979 if revs:
4977 try:
4980 try:
4978 revs = [other.lookup(rev) for rev in revs]
4981 revs = [other.lookup(rev) for rev in revs]
4979 except error.CapabilityError:
4982 except error.CapabilityError:
4980 err = _("other repository doesn't support revision lookup, "
4983 err = _("other repository doesn't support revision lookup, "
4981 "so a rev cannot be specified.")
4984 "so a rev cannot be specified.")
4982 raise util.Abort(err)
4985 raise util.Abort(err)
4983
4986
4984 modheads = exchange.pull(repo, other, heads=revs,
4987 modheads = exchange.pull(repo, other, heads=revs,
4985 force=opts.get('force'),
4988 force=opts.get('force'),
4986 bookmarks=opts.get('bookmark', ())).cgresult
4989 bookmarks=opts.get('bookmark', ())).cgresult
4987 if checkout:
4990 if checkout:
4988 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4991 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4989 repo._subtoppath = source
4992 repo._subtoppath = source
4990 try:
4993 try:
4991 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4994 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4992
4995
4993 finally:
4996 finally:
4994 del repo._subtoppath
4997 del repo._subtoppath
4995
4998
4996 finally:
4999 finally:
4997 other.close()
5000 other.close()
4998 return ret
5001 return ret
4999
5002
5000 @command('^push',
5003 @command('^push',
5001 [('f', 'force', None, _('force push')),
5004 [('f', 'force', None, _('force push')),
5002 ('r', 'rev', [],
5005 ('r', 'rev', [],
5003 _('a changeset intended to be included in the destination'),
5006 _('a changeset intended to be included in the destination'),
5004 _('REV')),
5007 _('REV')),
5005 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5008 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5006 ('b', 'branch', [],
5009 ('b', 'branch', [],
5007 _('a specific branch you would like to push'), _('BRANCH')),
5010 _('a specific branch you would like to push'), _('BRANCH')),
5008 ('', 'new-branch', False, _('allow pushing a new branch')),
5011 ('', 'new-branch', False, _('allow pushing a new branch')),
5009 ] + remoteopts,
5012 ] + remoteopts,
5010 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5013 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5011 def push(ui, repo, dest=None, **opts):
5014 def push(ui, repo, dest=None, **opts):
5012 """push changes to the specified destination
5015 """push changes to the specified destination
5013
5016
5014 Push changesets from the local repository to the specified
5017 Push changesets from the local repository to the specified
5015 destination.
5018 destination.
5016
5019
5017 This operation is symmetrical to pull: it is identical to a pull
5020 This operation is symmetrical to pull: it is identical to a pull
5018 in the destination repository from the current one.
5021 in the destination repository from the current one.
5019
5022
5020 By default, push will not allow creation of new heads at the
5023 By default, push will not allow creation of new heads at the
5021 destination, since multiple heads would make it unclear which head
5024 destination, since multiple heads would make it unclear which head
5022 to use. In this situation, it is recommended to pull and merge
5025 to use. In this situation, it is recommended to pull and merge
5023 before pushing.
5026 before pushing.
5024
5027
5025 Use --new-branch if you want to allow push to create a new named
5028 Use --new-branch if you want to allow push to create a new named
5026 branch that is not present at the destination. This allows you to
5029 branch that is not present at the destination. This allows you to
5027 only create a new branch without forcing other changes.
5030 only create a new branch without forcing other changes.
5028
5031
5029 .. note::
5032 .. note::
5030
5033
5031 Extra care should be taken with the -f/--force option,
5034 Extra care should be taken with the -f/--force option,
5032 which will push all new heads on all branches, an action which will
5035 which will push all new heads on all branches, an action which will
5033 almost always cause confusion for collaborators.
5036 almost always cause confusion for collaborators.
5034
5037
5035 If -r/--rev is used, the specified revision and all its ancestors
5038 If -r/--rev is used, the specified revision and all its ancestors
5036 will be pushed to the remote repository.
5039 will be pushed to the remote repository.
5037
5040
5038 If -B/--bookmark is used, the specified bookmarked revision, its
5041 If -B/--bookmark is used, the specified bookmarked revision, its
5039 ancestors, and the bookmark will be pushed to the remote
5042 ancestors, and the bookmark will be pushed to the remote
5040 repository.
5043 repository.
5041
5044
5042 Please see :hg:`help urls` for important details about ``ssh://``
5045 Please see :hg:`help urls` for important details about ``ssh://``
5043 URLs. If DESTINATION is omitted, a default path will be used.
5046 URLs. If DESTINATION is omitted, a default path will be used.
5044
5047
5045 Returns 0 if push was successful, 1 if nothing to push.
5048 Returns 0 if push was successful, 1 if nothing to push.
5046 """
5049 """
5047
5050
5048 if opts.get('bookmark'):
5051 if opts.get('bookmark'):
5049 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5052 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5050 for b in opts['bookmark']:
5053 for b in opts['bookmark']:
5051 # translate -B options to -r so changesets get pushed
5054 # translate -B options to -r so changesets get pushed
5052 if b in repo._bookmarks:
5055 if b in repo._bookmarks:
5053 opts.setdefault('rev', []).append(b)
5056 opts.setdefault('rev', []).append(b)
5054 else:
5057 else:
5055 # if we try to push a deleted bookmark, translate it to null
5058 # if we try to push a deleted bookmark, translate it to null
5056 # this lets simultaneous -r, -b options continue working
5059 # this lets simultaneous -r, -b options continue working
5057 opts.setdefault('rev', []).append("null")
5060 opts.setdefault('rev', []).append("null")
5058
5061
5059 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5062 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5060 dest, branches = hg.parseurl(dest, opts.get('branch'))
5063 dest, branches = hg.parseurl(dest, opts.get('branch'))
5061 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5064 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5062 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5065 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5063 try:
5066 try:
5064 other = hg.peer(repo, opts, dest)
5067 other = hg.peer(repo, opts, dest)
5065 except error.RepoError:
5068 except error.RepoError:
5066 if dest == "default-push":
5069 if dest == "default-push":
5067 raise util.Abort(_("default repository not configured!"),
5070 raise util.Abort(_("default repository not configured!"),
5068 hint=_('see the "path" section in "hg help config"'))
5071 hint=_('see the "path" section in "hg help config"'))
5069 else:
5072 else:
5070 raise
5073 raise
5071
5074
5072 if revs:
5075 if revs:
5073 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5076 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5074
5077
5075 repo._subtoppath = dest
5078 repo._subtoppath = dest
5076 try:
5079 try:
5077 # push subrepos depth-first for coherent ordering
5080 # push subrepos depth-first for coherent ordering
5078 c = repo['']
5081 c = repo['']
5079 subs = c.substate # only repos that are committed
5082 subs = c.substate # only repos that are committed
5080 for s in sorted(subs):
5083 for s in sorted(subs):
5081 result = c.sub(s).push(opts)
5084 result = c.sub(s).push(opts)
5082 if result == 0:
5085 if result == 0:
5083 return not result
5086 return not result
5084 finally:
5087 finally:
5085 del repo._subtoppath
5088 del repo._subtoppath
5086 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5089 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5087 newbranch=opts.get('new_branch'),
5090 newbranch=opts.get('new_branch'),
5088 bookmarks=opts.get('bookmark', ()))
5091 bookmarks=opts.get('bookmark', ()))
5089
5092
5090 result = not pushop.cgresult
5093 result = not pushop.cgresult
5091
5094
5092 if pushop.bkresult is not None:
5095 if pushop.bkresult is not None:
5093 if pushop.bkresult == 2:
5096 if pushop.bkresult == 2:
5094 result = 2
5097 result = 2
5095 elif not result and pushop.bkresult:
5098 elif not result and pushop.bkresult:
5096 result = 2
5099 result = 2
5097
5100
5098 return result
5101 return result
5099
5102
5100 @command('recover', [])
5103 @command('recover', [])
5101 def recover(ui, repo):
5104 def recover(ui, repo):
5102 """roll back an interrupted transaction
5105 """roll back an interrupted transaction
5103
5106
5104 Recover from an interrupted commit or pull.
5107 Recover from an interrupted commit or pull.
5105
5108
5106 This command tries to fix the repository status after an
5109 This command tries to fix the repository status after an
5107 interrupted operation. It should only be necessary when Mercurial
5110 interrupted operation. It should only be necessary when Mercurial
5108 suggests it.
5111 suggests it.
5109
5112
5110 Returns 0 if successful, 1 if nothing to recover or verify fails.
5113 Returns 0 if successful, 1 if nothing to recover or verify fails.
5111 """
5114 """
5112 if repo.recover():
5115 if repo.recover():
5113 return hg.verify(repo)
5116 return hg.verify(repo)
5114 return 1
5117 return 1
5115
5118
5116 @command('^remove|rm',
5119 @command('^remove|rm',
5117 [('A', 'after', None, _('record delete for missing files')),
5120 [('A', 'after', None, _('record delete for missing files')),
5118 ('f', 'force', None,
5121 ('f', 'force', None,
5119 _('remove (and delete) file even if added or modified')),
5122 _('remove (and delete) file even if added or modified')),
5120 ] + subrepoopts + walkopts,
5123 ] + subrepoopts + walkopts,
5121 _('[OPTION]... FILE...'),
5124 _('[OPTION]... FILE...'),
5122 inferrepo=True)
5125 inferrepo=True)
5123 def remove(ui, repo, *pats, **opts):
5126 def remove(ui, repo, *pats, **opts):
5124 """remove the specified files on the next commit
5127 """remove the specified files on the next commit
5125
5128
5126 Schedule the indicated files for removal from the current branch.
5129 Schedule the indicated files for removal from the current branch.
5127
5130
5128 This command schedules the files to be removed at the next commit.
5131 This command schedules the files to be removed at the next commit.
5129 To undo a remove before that, see :hg:`revert`. To undo added
5132 To undo a remove before that, see :hg:`revert`. To undo added
5130 files, see :hg:`forget`.
5133 files, see :hg:`forget`.
5131
5134
5132 .. container:: verbose
5135 .. container:: verbose
5133
5136
5134 -A/--after can be used to remove only files that have already
5137 -A/--after can be used to remove only files that have already
5135 been deleted, -f/--force can be used to force deletion, and -Af
5138 been deleted, -f/--force can be used to force deletion, and -Af
5136 can be used to remove files from the next revision without
5139 can be used to remove files from the next revision without
5137 deleting them from the working directory.
5140 deleting them from the working directory.
5138
5141
5139 The following table details the behavior of remove for different
5142 The following table details the behavior of remove for different
5140 file states (columns) and option combinations (rows). The file
5143 file states (columns) and option combinations (rows). The file
5141 states are Added [A], Clean [C], Modified [M] and Missing [!]
5144 states are Added [A], Clean [C], Modified [M] and Missing [!]
5142 (as reported by :hg:`status`). The actions are Warn, Remove
5145 (as reported by :hg:`status`). The actions are Warn, Remove
5143 (from branch) and Delete (from disk):
5146 (from branch) and Delete (from disk):
5144
5147
5145 ========= == == == ==
5148 ========= == == == ==
5146 opt/state A C M !
5149 opt/state A C M !
5147 ========= == == == ==
5150 ========= == == == ==
5148 none W RD W R
5151 none W RD W R
5149 -f R RD RD R
5152 -f R RD RD R
5150 -A W W W R
5153 -A W W W R
5151 -Af R R R R
5154 -Af R R R R
5152 ========= == == == ==
5155 ========= == == == ==
5153
5156
5154 Note that remove never deletes files in Added [A] state from the
5157 Note that remove never deletes files in Added [A] state from the
5155 working directory, not even if option --force is specified.
5158 working directory, not even if option --force is specified.
5156
5159
5157 Returns 0 on success, 1 if any warnings encountered.
5160 Returns 0 on success, 1 if any warnings encountered.
5158 """
5161 """
5159
5162
5160 after, force = opts.get('after'), opts.get('force')
5163 after, force = opts.get('after'), opts.get('force')
5161 if not pats and not after:
5164 if not pats and not after:
5162 raise util.Abort(_('no files specified'))
5165 raise util.Abort(_('no files specified'))
5163
5166
5164 m = scmutil.match(repo[None], pats, opts)
5167 m = scmutil.match(repo[None], pats, opts)
5165 subrepos = opts.get('subrepos')
5168 subrepos = opts.get('subrepos')
5166 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5169 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5167
5170
5168 @command('rename|move|mv',
5171 @command('rename|move|mv',
5169 [('A', 'after', None, _('record a rename that has already occurred')),
5172 [('A', 'after', None, _('record a rename that has already occurred')),
5170 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5173 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5171 ] + walkopts + dryrunopts,
5174 ] + walkopts + dryrunopts,
5172 _('[OPTION]... SOURCE... DEST'))
5175 _('[OPTION]... SOURCE... DEST'))
5173 def rename(ui, repo, *pats, **opts):
5176 def rename(ui, repo, *pats, **opts):
5174 """rename files; equivalent of copy + remove
5177 """rename files; equivalent of copy + remove
5175
5178
5176 Mark dest as copies of sources; mark sources for deletion. If dest
5179 Mark dest as copies of sources; mark sources for deletion. If dest
5177 is a directory, copies are put in that directory. If dest is a
5180 is a directory, copies are put in that directory. If dest is a
5178 file, there can only be one source.
5181 file, there can only be one source.
5179
5182
5180 By default, this command copies the contents of files as they
5183 By default, this command copies the contents of files as they
5181 exist in the working directory. If invoked with -A/--after, the
5184 exist in the working directory. If invoked with -A/--after, the
5182 operation is recorded, but no copying is performed.
5185 operation is recorded, but no copying is performed.
5183
5186
5184 This command takes effect at the next commit. To undo a rename
5187 This command takes effect at the next commit. To undo a rename
5185 before that, see :hg:`revert`.
5188 before that, see :hg:`revert`.
5186
5189
5187 Returns 0 on success, 1 if errors are encountered.
5190 Returns 0 on success, 1 if errors are encountered.
5188 """
5191 """
5189 wlock = repo.wlock(False)
5192 wlock = repo.wlock(False)
5190 try:
5193 try:
5191 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5194 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5192 finally:
5195 finally:
5193 wlock.release()
5196 wlock.release()
5194
5197
5195 @command('resolve',
5198 @command('resolve',
5196 [('a', 'all', None, _('select all unresolved files')),
5199 [('a', 'all', None, _('select all unresolved files')),
5197 ('l', 'list', None, _('list state of files needing merge')),
5200 ('l', 'list', None, _('list state of files needing merge')),
5198 ('m', 'mark', None, _('mark files as resolved')),
5201 ('m', 'mark', None, _('mark files as resolved')),
5199 ('u', 'unmark', None, _('mark files as unresolved')),
5202 ('u', 'unmark', None, _('mark files as unresolved')),
5200 ('n', 'no-status', None, _('hide status prefix'))]
5203 ('n', 'no-status', None, _('hide status prefix'))]
5201 + mergetoolopts + walkopts,
5204 + mergetoolopts + walkopts,
5202 _('[OPTION]... [FILE]...'),
5205 _('[OPTION]... [FILE]...'),
5203 inferrepo=True)
5206 inferrepo=True)
5204 def resolve(ui, repo, *pats, **opts):
5207 def resolve(ui, repo, *pats, **opts):
5205 """redo merges or set/view the merge status of files
5208 """redo merges or set/view the merge status of files
5206
5209
5207 Merges with unresolved conflicts are often the result of
5210 Merges with unresolved conflicts are often the result of
5208 non-interactive merging using the ``internal:merge`` configuration
5211 non-interactive merging using the ``internal:merge`` configuration
5209 setting, or a command-line merge tool like ``diff3``. The resolve
5212 setting, or a command-line merge tool like ``diff3``. The resolve
5210 command is used to manage the files involved in a merge, after
5213 command is used to manage the files involved in a merge, after
5211 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5214 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5212 working directory must have two parents). See :hg:`help
5215 working directory must have two parents). See :hg:`help
5213 merge-tools` for information on configuring merge tools.
5216 merge-tools` for information on configuring merge tools.
5214
5217
5215 The resolve command can be used in the following ways:
5218 The resolve command can be used in the following ways:
5216
5219
5217 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5220 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5218 files, discarding any previous merge attempts. Re-merging is not
5221 files, discarding any previous merge attempts. Re-merging is not
5219 performed for files already marked as resolved. Use ``--all/-a``
5222 performed for files already marked as resolved. Use ``--all/-a``
5220 to select all unresolved files. ``--tool`` can be used to specify
5223 to select all unresolved files. ``--tool`` can be used to specify
5221 the merge tool used for the given files. It overrides the HGMERGE
5224 the merge tool used for the given files. It overrides the HGMERGE
5222 environment variable and your configuration files. Previous file
5225 environment variable and your configuration files. Previous file
5223 contents are saved with a ``.orig`` suffix.
5226 contents are saved with a ``.orig`` suffix.
5224
5227
5225 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5228 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5226 (e.g. after having manually fixed-up the files). The default is
5229 (e.g. after having manually fixed-up the files). The default is
5227 to mark all unresolved files.
5230 to mark all unresolved files.
5228
5231
5229 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5232 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5230 default is to mark all resolved files.
5233 default is to mark all resolved files.
5231
5234
5232 - :hg:`resolve -l`: list files which had or still have conflicts.
5235 - :hg:`resolve -l`: list files which had or still have conflicts.
5233 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5236 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5234
5237
5235 Note that Mercurial will not let you commit files with unresolved
5238 Note that Mercurial will not let you commit files with unresolved
5236 merge conflicts. You must use :hg:`resolve -m ...` before you can
5239 merge conflicts. You must use :hg:`resolve -m ...` before you can
5237 commit after a conflicting merge.
5240 commit after a conflicting merge.
5238
5241
5239 Returns 0 on success, 1 if any files fail a resolve attempt.
5242 Returns 0 on success, 1 if any files fail a resolve attempt.
5240 """
5243 """
5241
5244
5242 all, mark, unmark, show, nostatus = \
5245 all, mark, unmark, show, nostatus = \
5243 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5246 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5244
5247
5245 if (show and (mark or unmark)) or (mark and unmark):
5248 if (show and (mark or unmark)) or (mark and unmark):
5246 raise util.Abort(_("too many options specified"))
5249 raise util.Abort(_("too many options specified"))
5247 if pats and all:
5250 if pats and all:
5248 raise util.Abort(_("can't specify --all and patterns"))
5251 raise util.Abort(_("can't specify --all and patterns"))
5249 if not (all or pats or show or mark or unmark):
5252 if not (all or pats or show or mark or unmark):
5250 raise util.Abort(_('no files or directories specified'),
5253 raise util.Abort(_('no files or directories specified'),
5251 hint=('use --all to remerge all files'))
5254 hint=('use --all to remerge all files'))
5252
5255
5253 wlock = repo.wlock()
5256 wlock = repo.wlock()
5254 try:
5257 try:
5255 ms = mergemod.mergestate(repo)
5258 ms = mergemod.mergestate(repo)
5256
5259
5257 if not (ms.active() or repo.dirstate.p2() != nullid) and not show:
5260 if not (ms.active() or repo.dirstate.p2() != nullid) and not show:
5258 raise util.Abort(
5261 raise util.Abort(
5259 _('resolve command not applicable when not merging'))
5262 _('resolve command not applicable when not merging'))
5260
5263
5261 m = scmutil.match(repo[None], pats, opts)
5264 m = scmutil.match(repo[None], pats, opts)
5262 ret = 0
5265 ret = 0
5263 didwork = False
5266 didwork = False
5264
5267
5265 for f in ms:
5268 for f in ms:
5266 if not m(f):
5269 if not m(f):
5267 continue
5270 continue
5268
5271
5269 didwork = True
5272 didwork = True
5270
5273
5271 if show:
5274 if show:
5272 if nostatus:
5275 if nostatus:
5273 ui.write("%s\n" % f)
5276 ui.write("%s\n" % f)
5274 else:
5277 else:
5275 ui.write("%s %s\n" % (ms[f].upper(), f),
5278 ui.write("%s %s\n" % (ms[f].upper(), f),
5276 label='resolve.' +
5279 label='resolve.' +
5277 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5280 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5278 elif mark:
5281 elif mark:
5279 ms.mark(f, "r")
5282 ms.mark(f, "r")
5280 elif unmark:
5283 elif unmark:
5281 ms.mark(f, "u")
5284 ms.mark(f, "u")
5282 else:
5285 else:
5283 wctx = repo[None]
5286 wctx = repo[None]
5284
5287
5285 # backup pre-resolve (merge uses .orig for its own purposes)
5288 # backup pre-resolve (merge uses .orig for its own purposes)
5286 a = repo.wjoin(f)
5289 a = repo.wjoin(f)
5287 util.copyfile(a, a + ".resolve")
5290 util.copyfile(a, a + ".resolve")
5288
5291
5289 try:
5292 try:
5290 # resolve file
5293 # resolve file
5291 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5294 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5292 'resolve')
5295 'resolve')
5293 if ms.resolve(f, wctx):
5296 if ms.resolve(f, wctx):
5294 ret = 1
5297 ret = 1
5295 finally:
5298 finally:
5296 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5299 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5297 ms.commit()
5300 ms.commit()
5298
5301
5299 # replace filemerge's .orig file with our resolve file
5302 # replace filemerge's .orig file with our resolve file
5300 util.rename(a + ".resolve", a + ".orig")
5303 util.rename(a + ".resolve", a + ".orig")
5301
5304
5302 ms.commit()
5305 ms.commit()
5303
5306
5304 if not didwork and pats:
5307 if not didwork and pats:
5305 ui.warn(_("arguments do not match paths that need resolving\n"))
5308 ui.warn(_("arguments do not match paths that need resolving\n"))
5306
5309
5307 finally:
5310 finally:
5308 wlock.release()
5311 wlock.release()
5309
5312
5310 # Nudge users into finishing an unfinished operation. We don't print
5313 # Nudge users into finishing an unfinished operation. We don't print
5311 # this with the list/show operation because we want list/show to remain
5314 # this with the list/show operation because we want list/show to remain
5312 # machine readable.
5315 # machine readable.
5313 if not list(ms.unresolved()) and not show:
5316 if not list(ms.unresolved()) and not show:
5314 ui.status(_('(no more unresolved files)\n'))
5317 ui.status(_('(no more unresolved files)\n'))
5315
5318
5316 return ret
5319 return ret
5317
5320
5318 @command('revert',
5321 @command('revert',
5319 [('a', 'all', None, _('revert all changes when no arguments given')),
5322 [('a', 'all', None, _('revert all changes when no arguments given')),
5320 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5323 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5321 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5324 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5322 ('C', 'no-backup', None, _('do not save backup copies of files')),
5325 ('C', 'no-backup', None, _('do not save backup copies of files')),
5323 ] + walkopts + dryrunopts,
5326 ] + walkopts + dryrunopts,
5324 _('[OPTION]... [-r REV] [NAME]...'))
5327 _('[OPTION]... [-r REV] [NAME]...'))
5325 def revert(ui, repo, *pats, **opts):
5328 def revert(ui, repo, *pats, **opts):
5326 """restore files to their checkout state
5329 """restore files to their checkout state
5327
5330
5328 .. note::
5331 .. note::
5329
5332
5330 To check out earlier revisions, you should use :hg:`update REV`.
5333 To check out earlier revisions, you should use :hg:`update REV`.
5331 To cancel an uncommitted merge (and lose your changes),
5334 To cancel an uncommitted merge (and lose your changes),
5332 use :hg:`update --clean .`.
5335 use :hg:`update --clean .`.
5333
5336
5334 With no revision specified, revert the specified files or directories
5337 With no revision specified, revert the specified files or directories
5335 to the contents they had in the parent of the working directory.
5338 to the contents they had in the parent of the working directory.
5336 This restores the contents of files to an unmodified
5339 This restores the contents of files to an unmodified
5337 state and unschedules adds, removes, copies, and renames. If the
5340 state and unschedules adds, removes, copies, and renames. If the
5338 working directory has two parents, you must explicitly specify a
5341 working directory has two parents, you must explicitly specify a
5339 revision.
5342 revision.
5340
5343
5341 Using the -r/--rev or -d/--date options, revert the given files or
5344 Using the -r/--rev or -d/--date options, revert the given files or
5342 directories to their states as of a specific revision. Because
5345 directories to their states as of a specific revision. Because
5343 revert does not change the working directory parents, this will
5346 revert does not change the working directory parents, this will
5344 cause these files to appear modified. This can be helpful to "back
5347 cause these files to appear modified. This can be helpful to "back
5345 out" some or all of an earlier change. See :hg:`backout` for a
5348 out" some or all of an earlier change. See :hg:`backout` for a
5346 related method.
5349 related method.
5347
5350
5348 Modified files are saved with a .orig suffix before reverting.
5351 Modified files are saved with a .orig suffix before reverting.
5349 To disable these backups, use --no-backup.
5352 To disable these backups, use --no-backup.
5350
5353
5351 See :hg:`help dates` for a list of formats valid for -d/--date.
5354 See :hg:`help dates` for a list of formats valid for -d/--date.
5352
5355
5353 Returns 0 on success.
5356 Returns 0 on success.
5354 """
5357 """
5355
5358
5356 if opts.get("date"):
5359 if opts.get("date"):
5357 if opts.get("rev"):
5360 if opts.get("rev"):
5358 raise util.Abort(_("you can't specify a revision and a date"))
5361 raise util.Abort(_("you can't specify a revision and a date"))
5359 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5362 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5360
5363
5361 parent, p2 = repo.dirstate.parents()
5364 parent, p2 = repo.dirstate.parents()
5362 if not opts.get('rev') and p2 != nullid:
5365 if not opts.get('rev') and p2 != nullid:
5363 # revert after merge is a trap for new users (issue2915)
5366 # revert after merge is a trap for new users (issue2915)
5364 raise util.Abort(_('uncommitted merge with no revision specified'),
5367 raise util.Abort(_('uncommitted merge with no revision specified'),
5365 hint=_('use "hg update" or see "hg help revert"'))
5368 hint=_('use "hg update" or see "hg help revert"'))
5366
5369
5367 ctx = scmutil.revsingle(repo, opts.get('rev'))
5370 ctx = scmutil.revsingle(repo, opts.get('rev'))
5368
5371
5369 if not pats and not opts.get('all'):
5372 if not pats and not opts.get('all'):
5370 msg = _("no files or directories specified")
5373 msg = _("no files or directories specified")
5371 if p2 != nullid:
5374 if p2 != nullid:
5372 hint = _("uncommitted merge, use --all to discard all changes,"
5375 hint = _("uncommitted merge, use --all to discard all changes,"
5373 " or 'hg update -C .' to abort the merge")
5376 " or 'hg update -C .' to abort the merge")
5374 raise util.Abort(msg, hint=hint)
5377 raise util.Abort(msg, hint=hint)
5375 dirty = util.any(repo.status())
5378 dirty = util.any(repo.status())
5376 node = ctx.node()
5379 node = ctx.node()
5377 if node != parent:
5380 if node != parent:
5378 if dirty:
5381 if dirty:
5379 hint = _("uncommitted changes, use --all to discard all"
5382 hint = _("uncommitted changes, use --all to discard all"
5380 " changes, or 'hg update %s' to update") % ctx.rev()
5383 " changes, or 'hg update %s' to update") % ctx.rev()
5381 else:
5384 else:
5382 hint = _("use --all to revert all files,"
5385 hint = _("use --all to revert all files,"
5383 " or 'hg update %s' to update") % ctx.rev()
5386 " or 'hg update %s' to update") % ctx.rev()
5384 elif dirty:
5387 elif dirty:
5385 hint = _("uncommitted changes, use --all to discard all changes")
5388 hint = _("uncommitted changes, use --all to discard all changes")
5386 else:
5389 else:
5387 hint = _("use --all to revert all files")
5390 hint = _("use --all to revert all files")
5388 raise util.Abort(msg, hint=hint)
5391 raise util.Abort(msg, hint=hint)
5389
5392
5390 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5393 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5391
5394
5392 @command('rollback', dryrunopts +
5395 @command('rollback', dryrunopts +
5393 [('f', 'force', False, _('ignore safety measures'))])
5396 [('f', 'force', False, _('ignore safety measures'))])
5394 def rollback(ui, repo, **opts):
5397 def rollback(ui, repo, **opts):
5395 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5398 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5396
5399
5397 Please use :hg:`commit --amend` instead of rollback to correct
5400 Please use :hg:`commit --amend` instead of rollback to correct
5398 mistakes in the last commit.
5401 mistakes in the last commit.
5399
5402
5400 This command should be used with care. There is only one level of
5403 This command should be used with care. There is only one level of
5401 rollback, and there is no way to undo a rollback. It will also
5404 rollback, and there is no way to undo a rollback. It will also
5402 restore the dirstate at the time of the last transaction, losing
5405 restore the dirstate at the time of the last transaction, losing
5403 any dirstate changes since that time. This command does not alter
5406 any dirstate changes since that time. This command does not alter
5404 the working directory.
5407 the working directory.
5405
5408
5406 Transactions are used to encapsulate the effects of all commands
5409 Transactions are used to encapsulate the effects of all commands
5407 that create new changesets or propagate existing changesets into a
5410 that create new changesets or propagate existing changesets into a
5408 repository.
5411 repository.
5409
5412
5410 .. container:: verbose
5413 .. container:: verbose
5411
5414
5412 For example, the following commands are transactional, and their
5415 For example, the following commands are transactional, and their
5413 effects can be rolled back:
5416 effects can be rolled back:
5414
5417
5415 - commit
5418 - commit
5416 - import
5419 - import
5417 - pull
5420 - pull
5418 - push (with this repository as the destination)
5421 - push (with this repository as the destination)
5419 - unbundle
5422 - unbundle
5420
5423
5421 To avoid permanent data loss, rollback will refuse to rollback a
5424 To avoid permanent data loss, rollback will refuse to rollback a
5422 commit transaction if it isn't checked out. Use --force to
5425 commit transaction if it isn't checked out. Use --force to
5423 override this protection.
5426 override this protection.
5424
5427
5425 This command is not intended for use on public repositories. Once
5428 This command is not intended for use on public repositories. Once
5426 changes are visible for pull by other users, rolling a transaction
5429 changes are visible for pull by other users, rolling a transaction
5427 back locally is ineffective (someone else may already have pulled
5430 back locally is ineffective (someone else may already have pulled
5428 the changes). Furthermore, a race is possible with readers of the
5431 the changes). Furthermore, a race is possible with readers of the
5429 repository; for example an in-progress pull from the repository
5432 repository; for example an in-progress pull from the repository
5430 may fail if a rollback is performed.
5433 may fail if a rollback is performed.
5431
5434
5432 Returns 0 on success, 1 if no rollback data is available.
5435 Returns 0 on success, 1 if no rollback data is available.
5433 """
5436 """
5434 return repo.rollback(dryrun=opts.get('dry_run'),
5437 return repo.rollback(dryrun=opts.get('dry_run'),
5435 force=opts.get('force'))
5438 force=opts.get('force'))
5436
5439
5437 @command('root', [])
5440 @command('root', [])
5438 def root(ui, repo):
5441 def root(ui, repo):
5439 """print the root (top) of the current working directory
5442 """print the root (top) of the current working directory
5440
5443
5441 Print the root directory of the current repository.
5444 Print the root directory of the current repository.
5442
5445
5443 Returns 0 on success.
5446 Returns 0 on success.
5444 """
5447 """
5445 ui.write(repo.root + "\n")
5448 ui.write(repo.root + "\n")
5446
5449
5447 @command('^serve',
5450 @command('^serve',
5448 [('A', 'accesslog', '', _('name of access log file to write to'),
5451 [('A', 'accesslog', '', _('name of access log file to write to'),
5449 _('FILE')),
5452 _('FILE')),
5450 ('d', 'daemon', None, _('run server in background')),
5453 ('d', 'daemon', None, _('run server in background')),
5451 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5454 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5452 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5455 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5453 # use string type, then we can check if something was passed
5456 # use string type, then we can check if something was passed
5454 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5457 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5455 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5458 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5456 _('ADDR')),
5459 _('ADDR')),
5457 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5460 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5458 _('PREFIX')),
5461 _('PREFIX')),
5459 ('n', 'name', '',
5462 ('n', 'name', '',
5460 _('name to show in web pages (default: working directory)'), _('NAME')),
5463 _('name to show in web pages (default: working directory)'), _('NAME')),
5461 ('', 'web-conf', '',
5464 ('', 'web-conf', '',
5462 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5465 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5463 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5466 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5464 _('FILE')),
5467 _('FILE')),
5465 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5468 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5466 ('', 'stdio', None, _('for remote clients')),
5469 ('', 'stdio', None, _('for remote clients')),
5467 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5470 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5468 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5471 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5469 ('', 'style', '', _('template style to use'), _('STYLE')),
5472 ('', 'style', '', _('template style to use'), _('STYLE')),
5470 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5473 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5471 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5474 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5472 _('[OPTION]...'),
5475 _('[OPTION]...'),
5473 optionalrepo=True)
5476 optionalrepo=True)
5474 def serve(ui, repo, **opts):
5477 def serve(ui, repo, **opts):
5475 """start stand-alone webserver
5478 """start stand-alone webserver
5476
5479
5477 Start a local HTTP repository browser and pull server. You can use
5480 Start a local HTTP repository browser and pull server. You can use
5478 this for ad-hoc sharing and browsing of repositories. It is
5481 this for ad-hoc sharing and browsing of repositories. It is
5479 recommended to use a real web server to serve a repository for
5482 recommended to use a real web server to serve a repository for
5480 longer periods of time.
5483 longer periods of time.
5481
5484
5482 Please note that the server does not implement access control.
5485 Please note that the server does not implement access control.
5483 This means that, by default, anybody can read from the server and
5486 This means that, by default, anybody can read from the server and
5484 nobody can write to it by default. Set the ``web.allow_push``
5487 nobody can write to it by default. Set the ``web.allow_push``
5485 option to ``*`` to allow everybody to push to the server. You
5488 option to ``*`` to allow everybody to push to the server. You
5486 should use a real web server if you need to authenticate users.
5489 should use a real web server if you need to authenticate users.
5487
5490
5488 By default, the server logs accesses to stdout and errors to
5491 By default, the server logs accesses to stdout and errors to
5489 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5492 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5490 files.
5493 files.
5491
5494
5492 To have the server choose a free port number to listen on, specify
5495 To have the server choose a free port number to listen on, specify
5493 a port number of 0; in this case, the server will print the port
5496 a port number of 0; in this case, the server will print the port
5494 number it uses.
5497 number it uses.
5495
5498
5496 Returns 0 on success.
5499 Returns 0 on success.
5497 """
5500 """
5498
5501
5499 if opts["stdio"] and opts["cmdserver"]:
5502 if opts["stdio"] and opts["cmdserver"]:
5500 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5503 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5501
5504
5502 if opts["stdio"]:
5505 if opts["stdio"]:
5503 if repo is None:
5506 if repo is None:
5504 raise error.RepoError(_("there is no Mercurial repository here"
5507 raise error.RepoError(_("there is no Mercurial repository here"
5505 " (.hg not found)"))
5508 " (.hg not found)"))
5506 s = sshserver.sshserver(ui, repo)
5509 s = sshserver.sshserver(ui, repo)
5507 s.serve_forever()
5510 s.serve_forever()
5508
5511
5509 if opts["cmdserver"]:
5512 if opts["cmdserver"]:
5510 service = commandserver.createservice(ui, repo, opts)
5513 service = commandserver.createservice(ui, repo, opts)
5511 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5514 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5512
5515
5513 # this way we can check if something was given in the command-line
5516 # this way we can check if something was given in the command-line
5514 if opts.get('port'):
5517 if opts.get('port'):
5515 opts['port'] = util.getport(opts.get('port'))
5518 opts['port'] = util.getport(opts.get('port'))
5516
5519
5517 baseui = repo and repo.baseui or ui
5520 baseui = repo and repo.baseui or ui
5518 optlist = ("name templates style address port prefix ipv6"
5521 optlist = ("name templates style address port prefix ipv6"
5519 " accesslog errorlog certificate encoding")
5522 " accesslog errorlog certificate encoding")
5520 for o in optlist.split():
5523 for o in optlist.split():
5521 val = opts.get(o, '')
5524 val = opts.get(o, '')
5522 if val in (None, ''): # should check against default options instead
5525 if val in (None, ''): # should check against default options instead
5523 continue
5526 continue
5524 baseui.setconfig("web", o, val, 'serve')
5527 baseui.setconfig("web", o, val, 'serve')
5525 if repo and repo.ui != baseui:
5528 if repo and repo.ui != baseui:
5526 repo.ui.setconfig("web", o, val, 'serve')
5529 repo.ui.setconfig("web", o, val, 'serve')
5527
5530
5528 o = opts.get('web_conf') or opts.get('webdir_conf')
5531 o = opts.get('web_conf') or opts.get('webdir_conf')
5529 if not o:
5532 if not o:
5530 if not repo:
5533 if not repo:
5531 raise error.RepoError(_("there is no Mercurial repository"
5534 raise error.RepoError(_("there is no Mercurial repository"
5532 " here (.hg not found)"))
5535 " here (.hg not found)"))
5533 o = repo
5536 o = repo
5534
5537
5535 app = hgweb.hgweb(o, baseui=baseui)
5538 app = hgweb.hgweb(o, baseui=baseui)
5536 service = httpservice(ui, app, opts)
5539 service = httpservice(ui, app, opts)
5537 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5540 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5538
5541
5539 class httpservice(object):
5542 class httpservice(object):
5540 def __init__(self, ui, app, opts):
5543 def __init__(self, ui, app, opts):
5541 self.ui = ui
5544 self.ui = ui
5542 self.app = app
5545 self.app = app
5543 self.opts = opts
5546 self.opts = opts
5544
5547
5545 def init(self):
5548 def init(self):
5546 util.setsignalhandler()
5549 util.setsignalhandler()
5547 self.httpd = hgweb_server.create_server(self.ui, self.app)
5550 self.httpd = hgweb_server.create_server(self.ui, self.app)
5548
5551
5549 if self.opts['port'] and not self.ui.verbose:
5552 if self.opts['port'] and not self.ui.verbose:
5550 return
5553 return
5551
5554
5552 if self.httpd.prefix:
5555 if self.httpd.prefix:
5553 prefix = self.httpd.prefix.strip('/') + '/'
5556 prefix = self.httpd.prefix.strip('/') + '/'
5554 else:
5557 else:
5555 prefix = ''
5558 prefix = ''
5556
5559
5557 port = ':%d' % self.httpd.port
5560 port = ':%d' % self.httpd.port
5558 if port == ':80':
5561 if port == ':80':
5559 port = ''
5562 port = ''
5560
5563
5561 bindaddr = self.httpd.addr
5564 bindaddr = self.httpd.addr
5562 if bindaddr == '0.0.0.0':
5565 if bindaddr == '0.0.0.0':
5563 bindaddr = '*'
5566 bindaddr = '*'
5564 elif ':' in bindaddr: # IPv6
5567 elif ':' in bindaddr: # IPv6
5565 bindaddr = '[%s]' % bindaddr
5568 bindaddr = '[%s]' % bindaddr
5566
5569
5567 fqaddr = self.httpd.fqaddr
5570 fqaddr = self.httpd.fqaddr
5568 if ':' in fqaddr:
5571 if ':' in fqaddr:
5569 fqaddr = '[%s]' % fqaddr
5572 fqaddr = '[%s]' % fqaddr
5570 if self.opts['port']:
5573 if self.opts['port']:
5571 write = self.ui.status
5574 write = self.ui.status
5572 else:
5575 else:
5573 write = self.ui.write
5576 write = self.ui.write
5574 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5577 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5575 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5578 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5576 self.ui.flush() # avoid buffering of status message
5579 self.ui.flush() # avoid buffering of status message
5577
5580
5578 def run(self):
5581 def run(self):
5579 self.httpd.serve_forever()
5582 self.httpd.serve_forever()
5580
5583
5581
5584
5582 @command('^status|st',
5585 @command('^status|st',
5583 [('A', 'all', None, _('show status of all files')),
5586 [('A', 'all', None, _('show status of all files')),
5584 ('m', 'modified', None, _('show only modified files')),
5587 ('m', 'modified', None, _('show only modified files')),
5585 ('a', 'added', None, _('show only added files')),
5588 ('a', 'added', None, _('show only added files')),
5586 ('r', 'removed', None, _('show only removed files')),
5589 ('r', 'removed', None, _('show only removed files')),
5587 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5590 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5588 ('c', 'clean', None, _('show only files without changes')),
5591 ('c', 'clean', None, _('show only files without changes')),
5589 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5592 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5590 ('i', 'ignored', None, _('show only ignored files')),
5593 ('i', 'ignored', None, _('show only ignored files')),
5591 ('n', 'no-status', None, _('hide status prefix')),
5594 ('n', 'no-status', None, _('hide status prefix')),
5592 ('C', 'copies', None, _('show source of copied files')),
5595 ('C', 'copies', None, _('show source of copied files')),
5593 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5596 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5594 ('', 'rev', [], _('show difference from revision'), _('REV')),
5597 ('', 'rev', [], _('show difference from revision'), _('REV')),
5595 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5598 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5596 ] + walkopts + subrepoopts + formatteropts,
5599 ] + walkopts + subrepoopts + formatteropts,
5597 _('[OPTION]... [FILE]...'),
5600 _('[OPTION]... [FILE]...'),
5598 inferrepo=True)
5601 inferrepo=True)
5599 def status(ui, repo, *pats, **opts):
5602 def status(ui, repo, *pats, **opts):
5600 """show changed files in the working directory
5603 """show changed files in the working directory
5601
5604
5602 Show status of files in the repository. If names are given, only
5605 Show status of files in the repository. If names are given, only
5603 files that match are shown. Files that are clean or ignored or
5606 files that match are shown. Files that are clean or ignored or
5604 the source of a copy/move operation, are not listed unless
5607 the source of a copy/move operation, are not listed unless
5605 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5608 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5606 Unless options described with "show only ..." are given, the
5609 Unless options described with "show only ..." are given, the
5607 options -mardu are used.
5610 options -mardu are used.
5608
5611
5609 Option -q/--quiet hides untracked (unknown and ignored) files
5612 Option -q/--quiet hides untracked (unknown and ignored) files
5610 unless explicitly requested with -u/--unknown or -i/--ignored.
5613 unless explicitly requested with -u/--unknown or -i/--ignored.
5611
5614
5612 .. note::
5615 .. note::
5613
5616
5614 status may appear to disagree with diff if permissions have
5617 status may appear to disagree with diff if permissions have
5615 changed or a merge has occurred. The standard diff format does
5618 changed or a merge has occurred. The standard diff format does
5616 not report permission changes and diff only reports changes
5619 not report permission changes and diff only reports changes
5617 relative to one merge parent.
5620 relative to one merge parent.
5618
5621
5619 If one revision is given, it is used as the base revision.
5622 If one revision is given, it is used as the base revision.
5620 If two revisions are given, the differences between them are
5623 If two revisions are given, the differences between them are
5621 shown. The --change option can also be used as a shortcut to list
5624 shown. The --change option can also be used as a shortcut to list
5622 the changed files of a revision from its first parent.
5625 the changed files of a revision from its first parent.
5623
5626
5624 The codes used to show the status of files are::
5627 The codes used to show the status of files are::
5625
5628
5626 M = modified
5629 M = modified
5627 A = added
5630 A = added
5628 R = removed
5631 R = removed
5629 C = clean
5632 C = clean
5630 ! = missing (deleted by non-hg command, but still tracked)
5633 ! = missing (deleted by non-hg command, but still tracked)
5631 ? = not tracked
5634 ? = not tracked
5632 I = ignored
5635 I = ignored
5633 = origin of the previous file (with --copies)
5636 = origin of the previous file (with --copies)
5634
5637
5635 .. container:: verbose
5638 .. container:: verbose
5636
5639
5637 Examples:
5640 Examples:
5638
5641
5639 - show changes in the working directory relative to a
5642 - show changes in the working directory relative to a
5640 changeset::
5643 changeset::
5641
5644
5642 hg status --rev 9353
5645 hg status --rev 9353
5643
5646
5644 - show all changes including copies in an existing changeset::
5647 - show all changes including copies in an existing changeset::
5645
5648
5646 hg status --copies --change 9353
5649 hg status --copies --change 9353
5647
5650
5648 - get a NUL separated list of added files, suitable for xargs::
5651 - get a NUL separated list of added files, suitable for xargs::
5649
5652
5650 hg status -an0
5653 hg status -an0
5651
5654
5652 Returns 0 on success.
5655 Returns 0 on success.
5653 """
5656 """
5654
5657
5655 revs = opts.get('rev')
5658 revs = opts.get('rev')
5656 change = opts.get('change')
5659 change = opts.get('change')
5657
5660
5658 if revs and change:
5661 if revs and change:
5659 msg = _('cannot specify --rev and --change at the same time')
5662 msg = _('cannot specify --rev and --change at the same time')
5660 raise util.Abort(msg)
5663 raise util.Abort(msg)
5661 elif change:
5664 elif change:
5662 node2 = scmutil.revsingle(repo, change, None).node()
5665 node2 = scmutil.revsingle(repo, change, None).node()
5663 node1 = repo[node2].p1().node()
5666 node1 = repo[node2].p1().node()
5664 else:
5667 else:
5665 node1, node2 = scmutil.revpair(repo, revs)
5668 node1, node2 = scmutil.revpair(repo, revs)
5666
5669
5667 cwd = (pats and repo.getcwd()) or ''
5670 cwd = (pats and repo.getcwd()) or ''
5668 end = opts.get('print0') and '\0' or '\n'
5671 end = opts.get('print0') and '\0' or '\n'
5669 copy = {}
5672 copy = {}
5670 states = 'modified added removed deleted unknown ignored clean'.split()
5673 states = 'modified added removed deleted unknown ignored clean'.split()
5671 show = [k for k in states if opts.get(k)]
5674 show = [k for k in states if opts.get(k)]
5672 if opts.get('all'):
5675 if opts.get('all'):
5673 show += ui.quiet and (states[:4] + ['clean']) or states
5676 show += ui.quiet and (states[:4] + ['clean']) or states
5674 if not show:
5677 if not show:
5675 show = ui.quiet and states[:4] or states[:5]
5678 show = ui.quiet and states[:4] or states[:5]
5676
5679
5677 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5680 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5678 'ignored' in show, 'clean' in show, 'unknown' in show,
5681 'ignored' in show, 'clean' in show, 'unknown' in show,
5679 opts.get('subrepos'))
5682 opts.get('subrepos'))
5680 changestates = zip(states, 'MAR!?IC', stat)
5683 changestates = zip(states, 'MAR!?IC', stat)
5681
5684
5682 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5685 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5683 copy = copies.pathcopies(repo[node1], repo[node2])
5686 copy = copies.pathcopies(repo[node1], repo[node2])
5684
5687
5685 fm = ui.formatter('status', opts)
5688 fm = ui.formatter('status', opts)
5686 fmt = '%s' + end
5689 fmt = '%s' + end
5687 showchar = not opts.get('no_status')
5690 showchar = not opts.get('no_status')
5688
5691
5689 for state, char, files in changestates:
5692 for state, char, files in changestates:
5690 if state in show:
5693 if state in show:
5691 label = 'status.' + state
5694 label = 'status.' + state
5692 for f in files:
5695 for f in files:
5693 fm.startitem()
5696 fm.startitem()
5694 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5697 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5695 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5698 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5696 if f in copy:
5699 if f in copy:
5697 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5700 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5698 label='status.copied')
5701 label='status.copied')
5699 fm.end()
5702 fm.end()
5700
5703
5701 @command('^summary|sum',
5704 @command('^summary|sum',
5702 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5705 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5703 def summary(ui, repo, **opts):
5706 def summary(ui, repo, **opts):
5704 """summarize working directory state
5707 """summarize working directory state
5705
5708
5706 This generates a brief summary of the working directory state,
5709 This generates a brief summary of the working directory state,
5707 including parents, branch, commit status, and available updates.
5710 including parents, branch, commit status, and available updates.
5708
5711
5709 With the --remote option, this will check the default paths for
5712 With the --remote option, this will check the default paths for
5710 incoming and outgoing changes. This can be time-consuming.
5713 incoming and outgoing changes. This can be time-consuming.
5711
5714
5712 Returns 0 on success.
5715 Returns 0 on success.
5713 """
5716 """
5714
5717
5715 ctx = repo[None]
5718 ctx = repo[None]
5716 parents = ctx.parents()
5719 parents = ctx.parents()
5717 pnode = parents[0].node()
5720 pnode = parents[0].node()
5718 marks = []
5721 marks = []
5719
5722
5720 for p in parents:
5723 for p in parents:
5721 # label with log.changeset (instead of log.parent) since this
5724 # label with log.changeset (instead of log.parent) since this
5722 # shows a working directory parent *changeset*:
5725 # shows a working directory parent *changeset*:
5723 # i18n: column positioning for "hg summary"
5726 # i18n: column positioning for "hg summary"
5724 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5727 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5725 label='log.changeset changeset.%s' % p.phasestr())
5728 label='log.changeset changeset.%s' % p.phasestr())
5726 ui.write(' '.join(p.tags()), label='log.tag')
5729 ui.write(' '.join(p.tags()), label='log.tag')
5727 if p.bookmarks():
5730 if p.bookmarks():
5728 marks.extend(p.bookmarks())
5731 marks.extend(p.bookmarks())
5729 if p.rev() == -1:
5732 if p.rev() == -1:
5730 if not len(repo):
5733 if not len(repo):
5731 ui.write(_(' (empty repository)'))
5734 ui.write(_(' (empty repository)'))
5732 else:
5735 else:
5733 ui.write(_(' (no revision checked out)'))
5736 ui.write(_(' (no revision checked out)'))
5734 ui.write('\n')
5737 ui.write('\n')
5735 if p.description():
5738 if p.description():
5736 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5739 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5737 label='log.summary')
5740 label='log.summary')
5738
5741
5739 branch = ctx.branch()
5742 branch = ctx.branch()
5740 bheads = repo.branchheads(branch)
5743 bheads = repo.branchheads(branch)
5741 # i18n: column positioning for "hg summary"
5744 # i18n: column positioning for "hg summary"
5742 m = _('branch: %s\n') % branch
5745 m = _('branch: %s\n') % branch
5743 if branch != 'default':
5746 if branch != 'default':
5744 ui.write(m, label='log.branch')
5747 ui.write(m, label='log.branch')
5745 else:
5748 else:
5746 ui.status(m, label='log.branch')
5749 ui.status(m, label='log.branch')
5747
5750
5748 if marks:
5751 if marks:
5749 current = repo._bookmarkcurrent
5752 current = repo._bookmarkcurrent
5750 # i18n: column positioning for "hg summary"
5753 # i18n: column positioning for "hg summary"
5751 ui.write(_('bookmarks:'), label='log.bookmark')
5754 ui.write(_('bookmarks:'), label='log.bookmark')
5752 if current is not None:
5755 if current is not None:
5753 if current in marks:
5756 if current in marks:
5754 ui.write(' *' + current, label='bookmarks.current')
5757 ui.write(' *' + current, label='bookmarks.current')
5755 marks.remove(current)
5758 marks.remove(current)
5756 else:
5759 else:
5757 ui.write(' [%s]' % current, label='bookmarks.current')
5760 ui.write(' [%s]' % current, label='bookmarks.current')
5758 for m in marks:
5761 for m in marks:
5759 ui.write(' ' + m, label='log.bookmark')
5762 ui.write(' ' + m, label='log.bookmark')
5760 ui.write('\n', label='log.bookmark')
5763 ui.write('\n', label='log.bookmark')
5761
5764
5762 status = repo.status(unknown=True)
5765 status = repo.status(unknown=True)
5763
5766
5764 c = repo.dirstate.copies()
5767 c = repo.dirstate.copies()
5765 copied, renamed = [], []
5768 copied, renamed = [], []
5766 for d, s in c.iteritems():
5769 for d, s in c.iteritems():
5767 if s in status.removed:
5770 if s in status.removed:
5768 status.removed.remove(s)
5771 status.removed.remove(s)
5769 renamed.append(d)
5772 renamed.append(d)
5770 else:
5773 else:
5771 copied.append(d)
5774 copied.append(d)
5772 if d in status.added:
5775 if d in status.added:
5773 status.added.remove(d)
5776 status.added.remove(d)
5774
5777
5775 ms = mergemod.mergestate(repo)
5778 ms = mergemod.mergestate(repo)
5776 unresolved = [f for f in ms if ms[f] == 'u']
5779 unresolved = [f for f in ms if ms[f] == 'u']
5777
5780
5778 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5781 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5779
5782
5780 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5783 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5781 (ui.label(_('%d added'), 'status.added'), status.added),
5784 (ui.label(_('%d added'), 'status.added'), status.added),
5782 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5785 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5783 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5786 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5784 (ui.label(_('%d copied'), 'status.copied'), copied),
5787 (ui.label(_('%d copied'), 'status.copied'), copied),
5785 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5788 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5786 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5789 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5787 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5790 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5788 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5791 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5789 t = []
5792 t = []
5790 for l, s in labels:
5793 for l, s in labels:
5791 if s:
5794 if s:
5792 t.append(l % len(s))
5795 t.append(l % len(s))
5793
5796
5794 t = ', '.join(t)
5797 t = ', '.join(t)
5795 cleanworkdir = False
5798 cleanworkdir = False
5796
5799
5797 if repo.vfs.exists('updatestate'):
5800 if repo.vfs.exists('updatestate'):
5798 t += _(' (interrupted update)')
5801 t += _(' (interrupted update)')
5799 elif len(parents) > 1:
5802 elif len(parents) > 1:
5800 t += _(' (merge)')
5803 t += _(' (merge)')
5801 elif branch != parents[0].branch():
5804 elif branch != parents[0].branch():
5802 t += _(' (new branch)')
5805 t += _(' (new branch)')
5803 elif (parents[0].closesbranch() and
5806 elif (parents[0].closesbranch() and
5804 pnode in repo.branchheads(branch, closed=True)):
5807 pnode in repo.branchheads(branch, closed=True)):
5805 t += _(' (head closed)')
5808 t += _(' (head closed)')
5806 elif not (status.modified or status.added or status.removed or renamed or
5809 elif not (status.modified or status.added or status.removed or renamed or
5807 copied or subs):
5810 copied or subs):
5808 t += _(' (clean)')
5811 t += _(' (clean)')
5809 cleanworkdir = True
5812 cleanworkdir = True
5810 elif pnode not in bheads:
5813 elif pnode not in bheads:
5811 t += _(' (new branch head)')
5814 t += _(' (new branch head)')
5812
5815
5813 if cleanworkdir:
5816 if cleanworkdir:
5814 # i18n: column positioning for "hg summary"
5817 # i18n: column positioning for "hg summary"
5815 ui.status(_('commit: %s\n') % t.strip())
5818 ui.status(_('commit: %s\n') % t.strip())
5816 else:
5819 else:
5817 # i18n: column positioning for "hg summary"
5820 # i18n: column positioning for "hg summary"
5818 ui.write(_('commit: %s\n') % t.strip())
5821 ui.write(_('commit: %s\n') % t.strip())
5819
5822
5820 # all ancestors of branch heads - all ancestors of parent = new csets
5823 # all ancestors of branch heads - all ancestors of parent = new csets
5821 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5824 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5822 bheads))
5825 bheads))
5823
5826
5824 if new == 0:
5827 if new == 0:
5825 # i18n: column positioning for "hg summary"
5828 # i18n: column positioning for "hg summary"
5826 ui.status(_('update: (current)\n'))
5829 ui.status(_('update: (current)\n'))
5827 elif pnode not in bheads:
5830 elif pnode not in bheads:
5828 # i18n: column positioning for "hg summary"
5831 # i18n: column positioning for "hg summary"
5829 ui.write(_('update: %d new changesets (update)\n') % new)
5832 ui.write(_('update: %d new changesets (update)\n') % new)
5830 else:
5833 else:
5831 # i18n: column positioning for "hg summary"
5834 # i18n: column positioning for "hg summary"
5832 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5835 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5833 (new, len(bheads)))
5836 (new, len(bheads)))
5834
5837
5835 cmdutil.summaryhooks(ui, repo)
5838 cmdutil.summaryhooks(ui, repo)
5836
5839
5837 if opts.get('remote'):
5840 if opts.get('remote'):
5838 needsincoming, needsoutgoing = True, True
5841 needsincoming, needsoutgoing = True, True
5839 else:
5842 else:
5840 needsincoming, needsoutgoing = False, False
5843 needsincoming, needsoutgoing = False, False
5841 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5844 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5842 if i:
5845 if i:
5843 needsincoming = True
5846 needsincoming = True
5844 if o:
5847 if o:
5845 needsoutgoing = True
5848 needsoutgoing = True
5846 if not needsincoming and not needsoutgoing:
5849 if not needsincoming and not needsoutgoing:
5847 return
5850 return
5848
5851
5849 def getincoming():
5852 def getincoming():
5850 source, branches = hg.parseurl(ui.expandpath('default'))
5853 source, branches = hg.parseurl(ui.expandpath('default'))
5851 sbranch = branches[0]
5854 sbranch = branches[0]
5852 try:
5855 try:
5853 other = hg.peer(repo, {}, source)
5856 other = hg.peer(repo, {}, source)
5854 except error.RepoError:
5857 except error.RepoError:
5855 if opts.get('remote'):
5858 if opts.get('remote'):
5856 raise
5859 raise
5857 return source, sbranch, None, None, None
5860 return source, sbranch, None, None, None
5858 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5861 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5859 if revs:
5862 if revs:
5860 revs = [other.lookup(rev) for rev in revs]
5863 revs = [other.lookup(rev) for rev in revs]
5861 ui.debug('comparing with %s\n' % util.hidepassword(source))
5864 ui.debug('comparing with %s\n' % util.hidepassword(source))
5862 repo.ui.pushbuffer()
5865 repo.ui.pushbuffer()
5863 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5866 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5864 repo.ui.popbuffer()
5867 repo.ui.popbuffer()
5865 return source, sbranch, other, commoninc, commoninc[1]
5868 return source, sbranch, other, commoninc, commoninc[1]
5866
5869
5867 if needsincoming:
5870 if needsincoming:
5868 source, sbranch, sother, commoninc, incoming = getincoming()
5871 source, sbranch, sother, commoninc, incoming = getincoming()
5869 else:
5872 else:
5870 source = sbranch = sother = commoninc = incoming = None
5873 source = sbranch = sother = commoninc = incoming = None
5871
5874
5872 def getoutgoing():
5875 def getoutgoing():
5873 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5876 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5874 dbranch = branches[0]
5877 dbranch = branches[0]
5875 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5878 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5876 if source != dest:
5879 if source != dest:
5877 try:
5880 try:
5878 dother = hg.peer(repo, {}, dest)
5881 dother = hg.peer(repo, {}, dest)
5879 except error.RepoError:
5882 except error.RepoError:
5880 if opts.get('remote'):
5883 if opts.get('remote'):
5881 raise
5884 raise
5882 return dest, dbranch, None, None
5885 return dest, dbranch, None, None
5883 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5886 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5884 elif sother is None:
5887 elif sother is None:
5885 # there is no explicit destination peer, but source one is invalid
5888 # there is no explicit destination peer, but source one is invalid
5886 return dest, dbranch, None, None
5889 return dest, dbranch, None, None
5887 else:
5890 else:
5888 dother = sother
5891 dother = sother
5889 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5892 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5890 common = None
5893 common = None
5891 else:
5894 else:
5892 common = commoninc
5895 common = commoninc
5893 if revs:
5896 if revs:
5894 revs = [repo.lookup(rev) for rev in revs]
5897 revs = [repo.lookup(rev) for rev in revs]
5895 repo.ui.pushbuffer()
5898 repo.ui.pushbuffer()
5896 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5899 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5897 commoninc=common)
5900 commoninc=common)
5898 repo.ui.popbuffer()
5901 repo.ui.popbuffer()
5899 return dest, dbranch, dother, outgoing
5902 return dest, dbranch, dother, outgoing
5900
5903
5901 if needsoutgoing:
5904 if needsoutgoing:
5902 dest, dbranch, dother, outgoing = getoutgoing()
5905 dest, dbranch, dother, outgoing = getoutgoing()
5903 else:
5906 else:
5904 dest = dbranch = dother = outgoing = None
5907 dest = dbranch = dother = outgoing = None
5905
5908
5906 if opts.get('remote'):
5909 if opts.get('remote'):
5907 t = []
5910 t = []
5908 if incoming:
5911 if incoming:
5909 t.append(_('1 or more incoming'))
5912 t.append(_('1 or more incoming'))
5910 o = outgoing.missing
5913 o = outgoing.missing
5911 if o:
5914 if o:
5912 t.append(_('%d outgoing') % len(o))
5915 t.append(_('%d outgoing') % len(o))
5913 other = dother or sother
5916 other = dother or sother
5914 if 'bookmarks' in other.listkeys('namespaces'):
5917 if 'bookmarks' in other.listkeys('namespaces'):
5915 lmarks = repo.listkeys('bookmarks')
5918 lmarks = repo.listkeys('bookmarks')
5916 rmarks = other.listkeys('bookmarks')
5919 rmarks = other.listkeys('bookmarks')
5917 diff = set(rmarks) - set(lmarks)
5920 diff = set(rmarks) - set(lmarks)
5918 if len(diff) > 0:
5921 if len(diff) > 0:
5919 t.append(_('%d incoming bookmarks') % len(diff))
5922 t.append(_('%d incoming bookmarks') % len(diff))
5920 diff = set(lmarks) - set(rmarks)
5923 diff = set(lmarks) - set(rmarks)
5921 if len(diff) > 0:
5924 if len(diff) > 0:
5922 t.append(_('%d outgoing bookmarks') % len(diff))
5925 t.append(_('%d outgoing bookmarks') % len(diff))
5923
5926
5924 if t:
5927 if t:
5925 # i18n: column positioning for "hg summary"
5928 # i18n: column positioning for "hg summary"
5926 ui.write(_('remote: %s\n') % (', '.join(t)))
5929 ui.write(_('remote: %s\n') % (', '.join(t)))
5927 else:
5930 else:
5928 # i18n: column positioning for "hg summary"
5931 # i18n: column positioning for "hg summary"
5929 ui.status(_('remote: (synced)\n'))
5932 ui.status(_('remote: (synced)\n'))
5930
5933
5931 cmdutil.summaryremotehooks(ui, repo, opts,
5934 cmdutil.summaryremotehooks(ui, repo, opts,
5932 ((source, sbranch, sother, commoninc),
5935 ((source, sbranch, sother, commoninc),
5933 (dest, dbranch, dother, outgoing)))
5936 (dest, dbranch, dother, outgoing)))
5934
5937
5935 @command('tag',
5938 @command('tag',
5936 [('f', 'force', None, _('force tag')),
5939 [('f', 'force', None, _('force tag')),
5937 ('l', 'local', None, _('make the tag local')),
5940 ('l', 'local', None, _('make the tag local')),
5938 ('r', 'rev', '', _('revision to tag'), _('REV')),
5941 ('r', 'rev', '', _('revision to tag'), _('REV')),
5939 ('', 'remove', None, _('remove a tag')),
5942 ('', 'remove', None, _('remove a tag')),
5940 # -l/--local is already there, commitopts cannot be used
5943 # -l/--local is already there, commitopts cannot be used
5941 ('e', 'edit', None, _('invoke editor on commit messages')),
5944 ('e', 'edit', None, _('invoke editor on commit messages')),
5942 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5945 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5943 ] + commitopts2,
5946 ] + commitopts2,
5944 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5947 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5945 def tag(ui, repo, name1, *names, **opts):
5948 def tag(ui, repo, name1, *names, **opts):
5946 """add one or more tags for the current or given revision
5949 """add one or more tags for the current or given revision
5947
5950
5948 Name a particular revision using <name>.
5951 Name a particular revision using <name>.
5949
5952
5950 Tags are used to name particular revisions of the repository and are
5953 Tags are used to name particular revisions of the repository and are
5951 very useful to compare different revisions, to go back to significant
5954 very useful to compare different revisions, to go back to significant
5952 earlier versions or to mark branch points as releases, etc. Changing
5955 earlier versions or to mark branch points as releases, etc. Changing
5953 an existing tag is normally disallowed; use -f/--force to override.
5956 an existing tag is normally disallowed; use -f/--force to override.
5954
5957
5955 If no revision is given, the parent of the working directory is
5958 If no revision is given, the parent of the working directory is
5956 used.
5959 used.
5957
5960
5958 To facilitate version control, distribution, and merging of tags,
5961 To facilitate version control, distribution, and merging of tags,
5959 they are stored as a file named ".hgtags" which is managed similarly
5962 they are stored as a file named ".hgtags" which is managed similarly
5960 to other project files and can be hand-edited if necessary. This
5963 to other project files and can be hand-edited if necessary. This
5961 also means that tagging creates a new commit. The file
5964 also means that tagging creates a new commit. The file
5962 ".hg/localtags" is used for local tags (not shared among
5965 ".hg/localtags" is used for local tags (not shared among
5963 repositories).
5966 repositories).
5964
5967
5965 Tag commits are usually made at the head of a branch. If the parent
5968 Tag commits are usually made at the head of a branch. If the parent
5966 of the working directory is not a branch head, :hg:`tag` aborts; use
5969 of the working directory is not a branch head, :hg:`tag` aborts; use
5967 -f/--force to force the tag commit to be based on a non-head
5970 -f/--force to force the tag commit to be based on a non-head
5968 changeset.
5971 changeset.
5969
5972
5970 See :hg:`help dates` for a list of formats valid for -d/--date.
5973 See :hg:`help dates` for a list of formats valid for -d/--date.
5971
5974
5972 Since tag names have priority over branch names during revision
5975 Since tag names have priority over branch names during revision
5973 lookup, using an existing branch name as a tag name is discouraged.
5976 lookup, using an existing branch name as a tag name is discouraged.
5974
5977
5975 Returns 0 on success.
5978 Returns 0 on success.
5976 """
5979 """
5977 wlock = lock = None
5980 wlock = lock = None
5978 try:
5981 try:
5979 wlock = repo.wlock()
5982 wlock = repo.wlock()
5980 lock = repo.lock()
5983 lock = repo.lock()
5981 rev_ = "."
5984 rev_ = "."
5982 names = [t.strip() for t in (name1,) + names]
5985 names = [t.strip() for t in (name1,) + names]
5983 if len(names) != len(set(names)):
5986 if len(names) != len(set(names)):
5984 raise util.Abort(_('tag names must be unique'))
5987 raise util.Abort(_('tag names must be unique'))
5985 for n in names:
5988 for n in names:
5986 scmutil.checknewlabel(repo, n, 'tag')
5989 scmutil.checknewlabel(repo, n, 'tag')
5987 if not n:
5990 if not n:
5988 raise util.Abort(_('tag names cannot consist entirely of '
5991 raise util.Abort(_('tag names cannot consist entirely of '
5989 'whitespace'))
5992 'whitespace'))
5990 if opts.get('rev') and opts.get('remove'):
5993 if opts.get('rev') and opts.get('remove'):
5991 raise util.Abort(_("--rev and --remove are incompatible"))
5994 raise util.Abort(_("--rev and --remove are incompatible"))
5992 if opts.get('rev'):
5995 if opts.get('rev'):
5993 rev_ = opts['rev']
5996 rev_ = opts['rev']
5994 message = opts.get('message')
5997 message = opts.get('message')
5995 if opts.get('remove'):
5998 if opts.get('remove'):
5996 expectedtype = opts.get('local') and 'local' or 'global'
5999 expectedtype = opts.get('local') and 'local' or 'global'
5997 for n in names:
6000 for n in names:
5998 if not repo.tagtype(n):
6001 if not repo.tagtype(n):
5999 raise util.Abort(_("tag '%s' does not exist") % n)
6002 raise util.Abort(_("tag '%s' does not exist") % n)
6000 if repo.tagtype(n) != expectedtype:
6003 if repo.tagtype(n) != expectedtype:
6001 if expectedtype == 'global':
6004 if expectedtype == 'global':
6002 raise util.Abort(_("tag '%s' is not a global tag") % n)
6005 raise util.Abort(_("tag '%s' is not a global tag") % n)
6003 else:
6006 else:
6004 raise util.Abort(_("tag '%s' is not a local tag") % n)
6007 raise util.Abort(_("tag '%s' is not a local tag") % n)
6005 rev_ = nullid
6008 rev_ = nullid
6006 if not message:
6009 if not message:
6007 # we don't translate commit messages
6010 # we don't translate commit messages
6008 message = 'Removed tag %s' % ', '.join(names)
6011 message = 'Removed tag %s' % ', '.join(names)
6009 elif not opts.get('force'):
6012 elif not opts.get('force'):
6010 for n in names:
6013 for n in names:
6011 if n in repo.tags():
6014 if n in repo.tags():
6012 raise util.Abort(_("tag '%s' already exists "
6015 raise util.Abort(_("tag '%s' already exists "
6013 "(use -f to force)") % n)
6016 "(use -f to force)") % n)
6014 if not opts.get('local'):
6017 if not opts.get('local'):
6015 p1, p2 = repo.dirstate.parents()
6018 p1, p2 = repo.dirstate.parents()
6016 if p2 != nullid:
6019 if p2 != nullid:
6017 raise util.Abort(_('uncommitted merge'))
6020 raise util.Abort(_('uncommitted merge'))
6018 bheads = repo.branchheads()
6021 bheads = repo.branchheads()
6019 if not opts.get('force') and bheads and p1 not in bheads:
6022 if not opts.get('force') and bheads and p1 not in bheads:
6020 raise util.Abort(_('not at a branch head (use -f to force)'))
6023 raise util.Abort(_('not at a branch head (use -f to force)'))
6021 r = scmutil.revsingle(repo, rev_).node()
6024 r = scmutil.revsingle(repo, rev_).node()
6022
6025
6023 if not message:
6026 if not message:
6024 # we don't translate commit messages
6027 # we don't translate commit messages
6025 message = ('Added tag %s for changeset %s' %
6028 message = ('Added tag %s for changeset %s' %
6026 (', '.join(names), short(r)))
6029 (', '.join(names), short(r)))
6027
6030
6028 date = opts.get('date')
6031 date = opts.get('date')
6029 if date:
6032 if date:
6030 date = util.parsedate(date)
6033 date = util.parsedate(date)
6031
6034
6032 if opts.get('remove'):
6035 if opts.get('remove'):
6033 editform = 'tag.remove'
6036 editform = 'tag.remove'
6034 else:
6037 else:
6035 editform = 'tag.add'
6038 editform = 'tag.add'
6036 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6039 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6037
6040
6038 # don't allow tagging the null rev
6041 # don't allow tagging the null rev
6039 if (not opts.get('remove') and
6042 if (not opts.get('remove') and
6040 scmutil.revsingle(repo, rev_).rev() == nullrev):
6043 scmutil.revsingle(repo, rev_).rev() == nullrev):
6041 raise util.Abort(_("cannot tag null revision"))
6044 raise util.Abort(_("cannot tag null revision"))
6042
6045
6043 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6046 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6044 editor=editor)
6047 editor=editor)
6045 finally:
6048 finally:
6046 release(lock, wlock)
6049 release(lock, wlock)
6047
6050
6048 @command('tags', formatteropts, '')
6051 @command('tags', formatteropts, '')
6049 def tags(ui, repo, **opts):
6052 def tags(ui, repo, **opts):
6050 """list repository tags
6053 """list repository tags
6051
6054
6052 This lists both regular and local tags. When the -v/--verbose
6055 This lists both regular and local tags. When the -v/--verbose
6053 switch is used, a third column "local" is printed for local tags.
6056 switch is used, a third column "local" is printed for local tags.
6054
6057
6055 Returns 0 on success.
6058 Returns 0 on success.
6056 """
6059 """
6057
6060
6058 fm = ui.formatter('tags', opts)
6061 fm = ui.formatter('tags', opts)
6059 hexfunc = fm.hexfunc
6062 hexfunc = fm.hexfunc
6060 tagtype = ""
6063 tagtype = ""
6061
6064
6062 for t, n in reversed(repo.tagslist()):
6065 for t, n in reversed(repo.tagslist()):
6063 hn = hexfunc(n)
6066 hn = hexfunc(n)
6064 label = 'tags.normal'
6067 label = 'tags.normal'
6065 tagtype = ''
6068 tagtype = ''
6066 if repo.tagtype(t) == 'local':
6069 if repo.tagtype(t) == 'local':
6067 label = 'tags.local'
6070 label = 'tags.local'
6068 tagtype = 'local'
6071 tagtype = 'local'
6069
6072
6070 fm.startitem()
6073 fm.startitem()
6071 fm.write('tag', '%s', t, label=label)
6074 fm.write('tag', '%s', t, label=label)
6072 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6075 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6073 fm.condwrite(not ui.quiet, 'rev node', fmt,
6076 fm.condwrite(not ui.quiet, 'rev node', fmt,
6074 repo.changelog.rev(n), hn, label=label)
6077 repo.changelog.rev(n), hn, label=label)
6075 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6078 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6076 tagtype, label=label)
6079 tagtype, label=label)
6077 fm.plain('\n')
6080 fm.plain('\n')
6078 fm.end()
6081 fm.end()
6079
6082
6080 @command('tip',
6083 @command('tip',
6081 [('p', 'patch', None, _('show patch')),
6084 [('p', 'patch', None, _('show patch')),
6082 ('g', 'git', None, _('use git extended diff format')),
6085 ('g', 'git', None, _('use git extended diff format')),
6083 ] + templateopts,
6086 ] + templateopts,
6084 _('[-p] [-g]'))
6087 _('[-p] [-g]'))
6085 def tip(ui, repo, **opts):
6088 def tip(ui, repo, **opts):
6086 """show the tip revision (DEPRECATED)
6089 """show the tip revision (DEPRECATED)
6087
6090
6088 The tip revision (usually just called the tip) is the changeset
6091 The tip revision (usually just called the tip) is the changeset
6089 most recently added to the repository (and therefore the most
6092 most recently added to the repository (and therefore the most
6090 recently changed head).
6093 recently changed head).
6091
6094
6092 If you have just made a commit, that commit will be the tip. If
6095 If you have just made a commit, that commit will be the tip. If
6093 you have just pulled changes from another repository, the tip of
6096 you have just pulled changes from another repository, the tip of
6094 that repository becomes the current tip. The "tip" tag is special
6097 that repository becomes the current tip. The "tip" tag is special
6095 and cannot be renamed or assigned to a different changeset.
6098 and cannot be renamed or assigned to a different changeset.
6096
6099
6097 This command is deprecated, please use :hg:`heads` instead.
6100 This command is deprecated, please use :hg:`heads` instead.
6098
6101
6099 Returns 0 on success.
6102 Returns 0 on success.
6100 """
6103 """
6101 displayer = cmdutil.show_changeset(ui, repo, opts)
6104 displayer = cmdutil.show_changeset(ui, repo, opts)
6102 displayer.show(repo['tip'])
6105 displayer.show(repo['tip'])
6103 displayer.close()
6106 displayer.close()
6104
6107
6105 @command('unbundle',
6108 @command('unbundle',
6106 [('u', 'update', None,
6109 [('u', 'update', None,
6107 _('update to new branch head if changesets were unbundled'))],
6110 _('update to new branch head if changesets were unbundled'))],
6108 _('[-u] FILE...'))
6111 _('[-u] FILE...'))
6109 def unbundle(ui, repo, fname1, *fnames, **opts):
6112 def unbundle(ui, repo, fname1, *fnames, **opts):
6110 """apply one or more changegroup files
6113 """apply one or more changegroup files
6111
6114
6112 Apply one or more compressed changegroup files generated by the
6115 Apply one or more compressed changegroup files generated by the
6113 bundle command.
6116 bundle command.
6114
6117
6115 Returns 0 on success, 1 if an update has unresolved files.
6118 Returns 0 on success, 1 if an update has unresolved files.
6116 """
6119 """
6117 fnames = (fname1,) + fnames
6120 fnames = (fname1,) + fnames
6118
6121
6119 lock = repo.lock()
6122 lock = repo.lock()
6120 try:
6123 try:
6121 for fname in fnames:
6124 for fname in fnames:
6122 f = hg.openpath(ui, fname)
6125 f = hg.openpath(ui, fname)
6123 gen = exchange.readbundle(ui, f, fname)
6126 gen = exchange.readbundle(ui, f, fname)
6124 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6127 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6125 'bundle:' + fname)
6128 'bundle:' + fname)
6126 finally:
6129 finally:
6127 lock.release()
6130 lock.release()
6128
6131
6129 return postincoming(ui, repo, modheads, opts.get('update'), None)
6132 return postincoming(ui, repo, modheads, opts.get('update'), None)
6130
6133
6131 @command('^update|up|checkout|co',
6134 @command('^update|up|checkout|co',
6132 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6135 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6133 ('c', 'check', None,
6136 ('c', 'check', None,
6134 _('update across branches if no uncommitted changes')),
6137 _('update across branches if no uncommitted changes')),
6135 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6138 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6136 ('r', 'rev', '', _('revision'), _('REV'))
6139 ('r', 'rev', '', _('revision'), _('REV'))
6137 ] + mergetoolopts,
6140 ] + mergetoolopts,
6138 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6141 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6139 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6142 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6140 tool=None):
6143 tool=None):
6141 """update working directory (or switch revisions)
6144 """update working directory (or switch revisions)
6142
6145
6143 Update the repository's working directory to the specified
6146 Update the repository's working directory to the specified
6144 changeset. If no changeset is specified, update to the tip of the
6147 changeset. If no changeset is specified, update to the tip of the
6145 current named branch and move the current bookmark (see :hg:`help
6148 current named branch and move the current bookmark (see :hg:`help
6146 bookmarks`).
6149 bookmarks`).
6147
6150
6148 Update sets the working directory's parent revision to the specified
6151 Update sets the working directory's parent revision to the specified
6149 changeset (see :hg:`help parents`).
6152 changeset (see :hg:`help parents`).
6150
6153
6151 If the changeset is not a descendant or ancestor of the working
6154 If the changeset is not a descendant or ancestor of the working
6152 directory's parent, the update is aborted. With the -c/--check
6155 directory's parent, the update is aborted. With the -c/--check
6153 option, the working directory is checked for uncommitted changes; if
6156 option, the working directory is checked for uncommitted changes; if
6154 none are found, the working directory is updated to the specified
6157 none are found, the working directory is updated to the specified
6155 changeset.
6158 changeset.
6156
6159
6157 .. container:: verbose
6160 .. container:: verbose
6158
6161
6159 The following rules apply when the working directory contains
6162 The following rules apply when the working directory contains
6160 uncommitted changes:
6163 uncommitted changes:
6161
6164
6162 1. If neither -c/--check nor -C/--clean is specified, and if
6165 1. If neither -c/--check nor -C/--clean is specified, and if
6163 the requested changeset is an ancestor or descendant of
6166 the requested changeset is an ancestor or descendant of
6164 the working directory's parent, the uncommitted changes
6167 the working directory's parent, the uncommitted changes
6165 are merged into the requested changeset and the merged
6168 are merged into the requested changeset and the merged
6166 result is left uncommitted. If the requested changeset is
6169 result is left uncommitted. If the requested changeset is
6167 not an ancestor or descendant (that is, it is on another
6170 not an ancestor or descendant (that is, it is on another
6168 branch), the update is aborted and the uncommitted changes
6171 branch), the update is aborted and the uncommitted changes
6169 are preserved.
6172 are preserved.
6170
6173
6171 2. With the -c/--check option, the update is aborted and the
6174 2. With the -c/--check option, the update is aborted and the
6172 uncommitted changes are preserved.
6175 uncommitted changes are preserved.
6173
6176
6174 3. With the -C/--clean option, uncommitted changes are discarded and
6177 3. With the -C/--clean option, uncommitted changes are discarded and
6175 the working directory is updated to the requested changeset.
6178 the working directory is updated to the requested changeset.
6176
6179
6177 To cancel an uncommitted merge (and lose your changes), use
6180 To cancel an uncommitted merge (and lose your changes), use
6178 :hg:`update --clean .`.
6181 :hg:`update --clean .`.
6179
6182
6180 Use null as the changeset to remove the working directory (like
6183 Use null as the changeset to remove the working directory (like
6181 :hg:`clone -U`).
6184 :hg:`clone -U`).
6182
6185
6183 If you want to revert just one file to an older revision, use
6186 If you want to revert just one file to an older revision, use
6184 :hg:`revert [-r REV] NAME`.
6187 :hg:`revert [-r REV] NAME`.
6185
6188
6186 See :hg:`help dates` for a list of formats valid for -d/--date.
6189 See :hg:`help dates` for a list of formats valid for -d/--date.
6187
6190
6188 Returns 0 on success, 1 if there are unresolved files.
6191 Returns 0 on success, 1 if there are unresolved files.
6189 """
6192 """
6190 if rev and node:
6193 if rev and node:
6191 raise util.Abort(_("please specify just one revision"))
6194 raise util.Abort(_("please specify just one revision"))
6192
6195
6193 if rev is None or rev == '':
6196 if rev is None or rev == '':
6194 rev = node
6197 rev = node
6195
6198
6196 cmdutil.clearunfinished(repo)
6199 cmdutil.clearunfinished(repo)
6197
6200
6198 # with no argument, we also move the current bookmark, if any
6201 # with no argument, we also move the current bookmark, if any
6199 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6202 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6200
6203
6201 # if we defined a bookmark, we have to remember the original bookmark name
6204 # if we defined a bookmark, we have to remember the original bookmark name
6202 brev = rev
6205 brev = rev
6203 rev = scmutil.revsingle(repo, rev, rev).rev()
6206 rev = scmutil.revsingle(repo, rev, rev).rev()
6204
6207
6205 if check and clean:
6208 if check and clean:
6206 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6209 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6207
6210
6208 if date:
6211 if date:
6209 if rev is not None:
6212 if rev is not None:
6210 raise util.Abort(_("you can't specify a revision and a date"))
6213 raise util.Abort(_("you can't specify a revision and a date"))
6211 rev = cmdutil.finddate(ui, repo, date)
6214 rev = cmdutil.finddate(ui, repo, date)
6212
6215
6213 if check:
6216 if check:
6214 c = repo[None]
6217 c = repo[None]
6215 if c.dirty(merge=False, branch=False, missing=True):
6218 if c.dirty(merge=False, branch=False, missing=True):
6216 raise util.Abort(_("uncommitted changes"))
6219 raise util.Abort(_("uncommitted changes"))
6217 if rev is None:
6220 if rev is None:
6218 rev = repo[repo[None].branch()].rev()
6221 rev = repo[repo[None].branch()].rev()
6219
6222
6220 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6223 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6221
6224
6222 if clean:
6225 if clean:
6223 ret = hg.clean(repo, rev)
6226 ret = hg.clean(repo, rev)
6224 else:
6227 else:
6225 ret = hg.update(repo, rev)
6228 ret = hg.update(repo, rev)
6226
6229
6227 if not ret and movemarkfrom:
6230 if not ret and movemarkfrom:
6228 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6231 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6229 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6232 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6230 elif brev in repo._bookmarks:
6233 elif brev in repo._bookmarks:
6231 bookmarks.setcurrent(repo, brev)
6234 bookmarks.setcurrent(repo, brev)
6232 ui.status(_("(activating bookmark %s)\n") % brev)
6235 ui.status(_("(activating bookmark %s)\n") % brev)
6233 elif brev:
6236 elif brev:
6234 if repo._bookmarkcurrent:
6237 if repo._bookmarkcurrent:
6235 ui.status(_("(leaving bookmark %s)\n") %
6238 ui.status(_("(leaving bookmark %s)\n") %
6236 repo._bookmarkcurrent)
6239 repo._bookmarkcurrent)
6237 bookmarks.unsetcurrent(repo)
6240 bookmarks.unsetcurrent(repo)
6238
6241
6239 return ret
6242 return ret
6240
6243
6241 @command('verify', [])
6244 @command('verify', [])
6242 def verify(ui, repo):
6245 def verify(ui, repo):
6243 """verify the integrity of the repository
6246 """verify the integrity of the repository
6244
6247
6245 Verify the integrity of the current repository.
6248 Verify the integrity of the current repository.
6246
6249
6247 This will perform an extensive check of the repository's
6250 This will perform an extensive check of the repository's
6248 integrity, validating the hashes and checksums of each entry in
6251 integrity, validating the hashes and checksums of each entry in
6249 the changelog, manifest, and tracked files, as well as the
6252 the changelog, manifest, and tracked files, as well as the
6250 integrity of their crosslinks and indices.
6253 integrity of their crosslinks and indices.
6251
6254
6252 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6255 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6253 for more information about recovery from corruption of the
6256 for more information about recovery from corruption of the
6254 repository.
6257 repository.
6255
6258
6256 Returns 0 on success, 1 if errors are encountered.
6259 Returns 0 on success, 1 if errors are encountered.
6257 """
6260 """
6258 return hg.verify(repo)
6261 return hg.verify(repo)
6259
6262
6260 @command('version', [], norepo=True)
6263 @command('version', [], norepo=True)
6261 def version_(ui):
6264 def version_(ui):
6262 """output version and copyright information"""
6265 """output version and copyright information"""
6263 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6266 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6264 % util.version())
6267 % util.version())
6265 ui.status(_(
6268 ui.status(_(
6266 "(see http://mercurial.selenic.com for more information)\n"
6269 "(see http://mercurial.selenic.com for more information)\n"
6267 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6270 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6268 "This is free software; see the source for copying conditions. "
6271 "This is free software; see the source for copying conditions. "
6269 "There is NO\nwarranty; "
6272 "There is NO\nwarranty; "
6270 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6273 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6271 ))
6274 ))
6272
6275
6273 ui.note(_("\nEnabled extensions:\n\n"))
6276 ui.note(_("\nEnabled extensions:\n\n"))
6274 if ui.verbose:
6277 if ui.verbose:
6275 # format names and versions into columns
6278 # format names and versions into columns
6276 names = []
6279 names = []
6277 vers = []
6280 vers = []
6278 for name, module in extensions.extensions():
6281 for name, module in extensions.extensions():
6279 names.append(name)
6282 names.append(name)
6280 vers.append(extensions.moduleversion(module))
6283 vers.append(extensions.moduleversion(module))
6281 if names:
6284 if names:
6282 maxnamelen = max(len(n) for n in names)
6285 maxnamelen = max(len(n) for n in names)
6283 for i, name in enumerate(names):
6286 for i, name in enumerate(names):
6284 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6287 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now