##// END OF EJS Templates
debuglock: access the lock file using the proper vfs...
Pierre-Yves David -
r24820:6a6b69d9 stable
parent child Browse files
Show More
@@ -1,6460 +1,6460 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys, socket
12 import sys, socket
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 import extensions
17 import extensions
18 from hgweb import server as hgweb_server
18 from hgweb import server as hgweb_server
19 import merge as mergemod
19 import merge as mergemod
20 import minirst, revset, fileset
20 import minirst, revset, fileset
21 import dagparser, context, simplemerge, graphmod, copies
21 import dagparser, context, simplemerge, graphmod, copies
22 import random
22 import random
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 import phases, obsolete, exchange, bundle2
24 import phases, obsolete, exchange, bundle2
25 import ui as uimod
25 import ui as uimod
26
26
27 table = {}
27 table = {}
28
28
29 command = cmdutil.command(table)
29 command = cmdutil.command(table)
30
30
31 # Space delimited list of commands that don't require local repositories.
31 # Space delimited list of commands that don't require local repositories.
32 # This should be populated by passing norepo=True into the @command decorator.
32 # This should be populated by passing norepo=True into the @command decorator.
33 norepo = ''
33 norepo = ''
34 # Space delimited list of commands that optionally require local repositories.
34 # Space delimited list of commands that optionally require local repositories.
35 # This should be populated by passing optionalrepo=True into the @command
35 # This should be populated by passing optionalrepo=True into the @command
36 # decorator.
36 # decorator.
37 optionalrepo = ''
37 optionalrepo = ''
38 # Space delimited list of commands that will examine arguments looking for
38 # Space delimited list of commands that will examine arguments looking for
39 # a repository. This should be populated by passing inferrepo=True into the
39 # a repository. This should be populated by passing inferrepo=True into the
40 # @command decorator.
40 # @command decorator.
41 inferrepo = ''
41 inferrepo = ''
42
42
43 # common command options
43 # common command options
44
44
45 globalopts = [
45 globalopts = [
46 ('R', 'repository', '',
46 ('R', 'repository', '',
47 _('repository root directory or name of overlay bundle file'),
47 _('repository root directory or name of overlay bundle file'),
48 _('REPO')),
48 _('REPO')),
49 ('', 'cwd', '',
49 ('', 'cwd', '',
50 _('change working directory'), _('DIR')),
50 _('change working directory'), _('DIR')),
51 ('y', 'noninteractive', None,
51 ('y', 'noninteractive', None,
52 _('do not prompt, automatically pick the first choice for all prompts')),
52 _('do not prompt, automatically pick the first choice for all prompts')),
53 ('q', 'quiet', None, _('suppress output')),
53 ('q', 'quiet', None, _('suppress output')),
54 ('v', 'verbose', None, _('enable additional output')),
54 ('v', 'verbose', None, _('enable additional output')),
55 ('', 'config', [],
55 ('', 'config', [],
56 _('set/override config option (use \'section.name=value\')'),
56 _('set/override config option (use \'section.name=value\')'),
57 _('CONFIG')),
57 _('CONFIG')),
58 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debug', None, _('enable debugging output')),
59 ('', 'debugger', None, _('start debugger')),
59 ('', 'debugger', None, _('start debugger')),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
61 _('ENCODE')),
61 _('ENCODE')),
62 ('', 'encodingmode', encoding.encodingmode,
62 ('', 'encodingmode', encoding.encodingmode,
63 _('set the charset encoding mode'), _('MODE')),
63 _('set the charset encoding mode'), _('MODE')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
65 ('', 'time', None, _('time how long the command takes')),
65 ('', 'time', None, _('time how long the command takes')),
66 ('', 'profile', None, _('print command execution profile')),
66 ('', 'profile', None, _('print command execution profile')),
67 ('', 'version', None, _('output version information and exit')),
67 ('', 'version', None, _('output version information and exit')),
68 ('h', 'help', None, _('display help and exit')),
68 ('h', 'help', None, _('display help and exit')),
69 ('', 'hidden', False, _('consider hidden changesets')),
69 ('', 'hidden', False, _('consider hidden changesets')),
70 ]
70 ]
71
71
72 dryrunopts = [('n', 'dry-run', None,
72 dryrunopts = [('n', 'dry-run', None,
73 _('do not perform actions, just print output'))]
73 _('do not perform actions, just print output'))]
74
74
75 remoteopts = [
75 remoteopts = [
76 ('e', 'ssh', '',
76 ('e', 'ssh', '',
77 _('specify ssh command to use'), _('CMD')),
77 _('specify ssh command to use'), _('CMD')),
78 ('', 'remotecmd', '',
78 ('', 'remotecmd', '',
79 _('specify hg command to run on the remote side'), _('CMD')),
79 _('specify hg command to run on the remote side'), _('CMD')),
80 ('', 'insecure', None,
80 ('', 'insecure', None,
81 _('do not verify server certificate (ignoring web.cacerts config)')),
81 _('do not verify server certificate (ignoring web.cacerts config)')),
82 ]
82 ]
83
83
84 walkopts = [
84 walkopts = [
85 ('I', 'include', [],
85 ('I', 'include', [],
86 _('include names matching the given patterns'), _('PATTERN')),
86 _('include names matching the given patterns'), _('PATTERN')),
87 ('X', 'exclude', [],
87 ('X', 'exclude', [],
88 _('exclude names matching the given patterns'), _('PATTERN')),
88 _('exclude names matching the given patterns'), _('PATTERN')),
89 ]
89 ]
90
90
91 commitopts = [
91 commitopts = [
92 ('m', 'message', '',
92 ('m', 'message', '',
93 _('use text as commit message'), _('TEXT')),
93 _('use text as commit message'), _('TEXT')),
94 ('l', 'logfile', '',
94 ('l', 'logfile', '',
95 _('read commit message from file'), _('FILE')),
95 _('read commit message from file'), _('FILE')),
96 ]
96 ]
97
97
98 commitopts2 = [
98 commitopts2 = [
99 ('d', 'date', '',
99 ('d', 'date', '',
100 _('record the specified date as commit date'), _('DATE')),
100 _('record the specified date as commit date'), _('DATE')),
101 ('u', 'user', '',
101 ('u', 'user', '',
102 _('record the specified user as committer'), _('USER')),
102 _('record the specified user as committer'), _('USER')),
103 ]
103 ]
104
104
105 # hidden for now
105 # hidden for now
106 formatteropts = [
106 formatteropts = [
107 ('T', 'template', '',
107 ('T', 'template', '',
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
109 ]
109 ]
110
110
111 templateopts = [
111 templateopts = [
112 ('', 'style', '',
112 ('', 'style', '',
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template'), _('TEMPLATE')),
115 _('display with template'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 logopts = [
118 logopts = [
119 ('p', 'patch', None, _('show patch')),
119 ('p', 'patch', None, _('show patch')),
120 ('g', 'git', None, _('use git extended diff format')),
120 ('g', 'git', None, _('use git extended diff format')),
121 ('l', 'limit', '',
121 ('l', 'limit', '',
122 _('limit number of changes displayed'), _('NUM')),
122 _('limit number of changes displayed'), _('NUM')),
123 ('M', 'no-merges', None, _('do not show merges')),
123 ('M', 'no-merges', None, _('do not show merges')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('G', 'graph', None, _("show the revision DAG")),
125 ('G', 'graph', None, _("show the revision DAG")),
126 ] + templateopts
126 ] + templateopts
127
127
128 diffopts = [
128 diffopts = [
129 ('a', 'text', None, _('treat all files as text')),
129 ('a', 'text', None, _('treat all files as text')),
130 ('g', 'git', None, _('use git extended diff format')),
130 ('g', 'git', None, _('use git extended diff format')),
131 ('', 'nodates', None, _('omit dates from diff headers'))
131 ('', 'nodates', None, _('omit dates from diff headers'))
132 ]
132 ]
133
133
134 diffwsopts = [
134 diffwsopts = [
135 ('w', 'ignore-all-space', None,
135 ('w', 'ignore-all-space', None,
136 _('ignore white space when comparing lines')),
136 _('ignore white space when comparing lines')),
137 ('b', 'ignore-space-change', None,
137 ('b', 'ignore-space-change', None,
138 _('ignore changes in the amount of white space')),
138 _('ignore changes in the amount of white space')),
139 ('B', 'ignore-blank-lines', None,
139 ('B', 'ignore-blank-lines', None,
140 _('ignore changes whose lines are all blank')),
140 _('ignore changes whose lines are all blank')),
141 ]
141 ]
142
142
143 diffopts2 = [
143 diffopts2 = [
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
145 ('p', 'show-function', None, _('show which function each change is in')),
145 ('p', 'show-function', None, _('show which function each change is in')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
147 ] + diffwsopts + [
147 ] + diffwsopts + [
148 ('U', 'unified', '',
148 ('U', 'unified', '',
149 _('number of lines of context to show'), _('NUM')),
149 _('number of lines of context to show'), _('NUM')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
151 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
151 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
152 ]
152 ]
153
153
154 mergetoolopts = [
154 mergetoolopts = [
155 ('t', 'tool', '', _('specify merge tool')),
155 ('t', 'tool', '', _('specify merge tool')),
156 ]
156 ]
157
157
158 similarityopts = [
158 similarityopts = [
159 ('s', 'similarity', '',
159 ('s', 'similarity', '',
160 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
160 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
161 ]
161 ]
162
162
163 subrepoopts = [
163 subrepoopts = [
164 ('S', 'subrepos', None,
164 ('S', 'subrepos', None,
165 _('recurse into subrepositories'))
165 _('recurse into subrepositories'))
166 ]
166 ]
167
167
168 # Commands start here, listed alphabetically
168 # Commands start here, listed alphabetically
169
169
170 @command('^add',
170 @command('^add',
171 walkopts + subrepoopts + dryrunopts,
171 walkopts + subrepoopts + dryrunopts,
172 _('[OPTION]... [FILE]...'),
172 _('[OPTION]... [FILE]...'),
173 inferrepo=True)
173 inferrepo=True)
174 def add(ui, repo, *pats, **opts):
174 def add(ui, repo, *pats, **opts):
175 """add the specified files on the next commit
175 """add the specified files on the next commit
176
176
177 Schedule files to be version controlled and added to the
177 Schedule files to be version controlled and added to the
178 repository.
178 repository.
179
179
180 The files will be added to the repository at the next commit. To
180 The files will be added to the repository at the next commit. To
181 undo an add before that, see :hg:`forget`.
181 undo an add before that, see :hg:`forget`.
182
182
183 If no names are given, add all files to the repository.
183 If no names are given, add all files to the repository.
184
184
185 .. container:: verbose
185 .. container:: verbose
186
186
187 An example showing how new (unknown) files are added
187 An example showing how new (unknown) files are added
188 automatically by :hg:`add`::
188 automatically by :hg:`add`::
189
189
190 $ ls
190 $ ls
191 foo.c
191 foo.c
192 $ hg status
192 $ hg status
193 ? foo.c
193 ? foo.c
194 $ hg add
194 $ hg add
195 adding foo.c
195 adding foo.c
196 $ hg status
196 $ hg status
197 A foo.c
197 A foo.c
198
198
199 Returns 0 if all files are successfully added.
199 Returns 0 if all files are successfully added.
200 """
200 """
201
201
202 m = scmutil.match(repo[None], pats, opts)
202 m = scmutil.match(repo[None], pats, opts)
203 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
203 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
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 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
281
281
282 fm = ui.formatter('annotate', opts)
282 fm = ui.formatter('annotate', opts)
283 if ui.quiet:
283 if ui.quiet:
284 datefunc = util.shortdate
284 datefunc = util.shortdate
285 else:
285 else:
286 datefunc = util.datestr
286 datefunc = util.datestr
287 if ctx.rev() is None:
287 if ctx.rev() is None:
288 def hexfn(node):
288 def hexfn(node):
289 if node is None:
289 if node is None:
290 return None
290 return None
291 else:
291 else:
292 return fm.hexfunc(node)
292 return fm.hexfunc(node)
293 if opts.get('changeset'):
293 if opts.get('changeset'):
294 # omit "+" suffix which is appended to node hex
294 # omit "+" suffix which is appended to node hex
295 def formatrev(rev):
295 def formatrev(rev):
296 if rev is None:
296 if rev is None:
297 return '%d' % ctx.p1().rev()
297 return '%d' % ctx.p1().rev()
298 else:
298 else:
299 return '%d' % rev
299 return '%d' % rev
300 else:
300 else:
301 def formatrev(rev):
301 def formatrev(rev):
302 if rev is None:
302 if rev is None:
303 return '%d+' % ctx.p1().rev()
303 return '%d+' % ctx.p1().rev()
304 else:
304 else:
305 return '%d ' % rev
305 return '%d ' % rev
306 def formathex(hex):
306 def formathex(hex):
307 if hex is None:
307 if hex is None:
308 return '%s+' % fm.hexfunc(ctx.p1().node())
308 return '%s+' % fm.hexfunc(ctx.p1().node())
309 else:
309 else:
310 return '%s ' % hex
310 return '%s ' % hex
311 else:
311 else:
312 hexfn = fm.hexfunc
312 hexfn = fm.hexfunc
313 formatrev = formathex = str
313 formatrev = formathex = str
314
314
315 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
315 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
316 ('number', ' ', lambda x: x[0].rev(), formatrev),
316 ('number', ' ', lambda x: x[0].rev(), formatrev),
317 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
317 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
318 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
318 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
319 ('file', ' ', lambda x: x[0].path(), str),
319 ('file', ' ', lambda x: x[0].path(), str),
320 ('line_number', ':', lambda x: x[1], str),
320 ('line_number', ':', lambda x: x[1], str),
321 ]
321 ]
322 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
322 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
323
323
324 if (not opts.get('user') and not opts.get('changeset')
324 if (not opts.get('user') and not opts.get('changeset')
325 and not opts.get('date') and not opts.get('file')):
325 and not opts.get('date') and not opts.get('file')):
326 opts['number'] = True
326 opts['number'] = True
327
327
328 linenumber = opts.get('line_number') is not None
328 linenumber = opts.get('line_number') is not None
329 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
329 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
330 raise util.Abort(_('at least one of -n/-c is required for -l'))
330 raise util.Abort(_('at least one of -n/-c is required for -l'))
331
331
332 if fm:
332 if fm:
333 def makefunc(get, fmt):
333 def makefunc(get, fmt):
334 return get
334 return get
335 else:
335 else:
336 def makefunc(get, fmt):
336 def makefunc(get, fmt):
337 return lambda x: fmt(get(x))
337 return lambda x: fmt(get(x))
338 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
338 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
339 if opts.get(op)]
339 if opts.get(op)]
340 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
340 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
341 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
341 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
342 if opts.get(op))
342 if opts.get(op))
343
343
344 def bad(x, y):
344 def bad(x, y):
345 raise util.Abort("%s: %s" % (x, y))
345 raise util.Abort("%s: %s" % (x, y))
346
346
347 m = scmutil.match(ctx, pats, opts)
347 m = scmutil.match(ctx, pats, opts)
348 m.bad = bad
348 m.bad = bad
349 follow = not opts.get('no_follow')
349 follow = not opts.get('no_follow')
350 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
350 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
351 whitespace=True)
351 whitespace=True)
352 for abs in ctx.walk(m):
352 for abs in ctx.walk(m):
353 fctx = ctx[abs]
353 fctx = ctx[abs]
354 if not opts.get('text') and util.binary(fctx.data()):
354 if not opts.get('text') and util.binary(fctx.data()):
355 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
355 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
356 continue
356 continue
357
357
358 lines = fctx.annotate(follow=follow, linenumber=linenumber,
358 lines = fctx.annotate(follow=follow, linenumber=linenumber,
359 diffopts=diffopts)
359 diffopts=diffopts)
360 formats = []
360 formats = []
361 pieces = []
361 pieces = []
362
362
363 for f, sep in funcmap:
363 for f, sep in funcmap:
364 l = [f(n) for n, dummy in lines]
364 l = [f(n) for n, dummy in lines]
365 if l:
365 if l:
366 if fm:
366 if fm:
367 formats.append(['%s' for x in l])
367 formats.append(['%s' for x in l])
368 else:
368 else:
369 sizes = [encoding.colwidth(x) for x in l]
369 sizes = [encoding.colwidth(x) for x in l]
370 ml = max(sizes)
370 ml = max(sizes)
371 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
371 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
372 pieces.append(l)
372 pieces.append(l)
373
373
374 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
374 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
375 fm.startitem()
375 fm.startitem()
376 fm.write(fields, "".join(f), *p)
376 fm.write(fields, "".join(f), *p)
377 fm.write('line', ": %s", l[1])
377 fm.write('line', ": %s", l[1])
378
378
379 if lines and not lines[-1][1].endswith('\n'):
379 if lines and not lines[-1][1].endswith('\n'):
380 fm.plain('\n')
380 fm.plain('\n')
381
381
382 fm.end()
382 fm.end()
383
383
384 @command('archive',
384 @command('archive',
385 [('', 'no-decode', None, _('do not pass files through decoders')),
385 [('', 'no-decode', None, _('do not pass files through decoders')),
386 ('p', 'prefix', '', _('directory prefix for files in archive'),
386 ('p', 'prefix', '', _('directory prefix for files in archive'),
387 _('PREFIX')),
387 _('PREFIX')),
388 ('r', 'rev', '', _('revision to distribute'), _('REV')),
388 ('r', 'rev', '', _('revision to distribute'), _('REV')),
389 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
389 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
390 ] + subrepoopts + walkopts,
390 ] + subrepoopts + walkopts,
391 _('[OPTION]... DEST'))
391 _('[OPTION]... DEST'))
392 def archive(ui, repo, dest, **opts):
392 def archive(ui, repo, dest, **opts):
393 '''create an unversioned archive of a repository revision
393 '''create an unversioned archive of a repository revision
394
394
395 By default, the revision used is the parent of the working
395 By default, the revision used is the parent of the working
396 directory; use -r/--rev to specify a different revision.
396 directory; use -r/--rev to specify a different revision.
397
397
398 The archive type is automatically detected based on file
398 The archive type is automatically detected based on file
399 extension (or override using -t/--type).
399 extension (or override using -t/--type).
400
400
401 .. container:: verbose
401 .. container:: verbose
402
402
403 Examples:
403 Examples:
404
404
405 - create a zip file containing the 1.0 release::
405 - create a zip file containing the 1.0 release::
406
406
407 hg archive -r 1.0 project-1.0.zip
407 hg archive -r 1.0 project-1.0.zip
408
408
409 - create a tarball excluding .hg files::
409 - create a tarball excluding .hg files::
410
410
411 hg archive project.tar.gz -X ".hg*"
411 hg archive project.tar.gz -X ".hg*"
412
412
413 Valid types are:
413 Valid types are:
414
414
415 :``files``: a directory full of files (default)
415 :``files``: a directory full of files (default)
416 :``tar``: tar archive, uncompressed
416 :``tar``: tar archive, uncompressed
417 :``tbz2``: tar archive, compressed using bzip2
417 :``tbz2``: tar archive, compressed using bzip2
418 :``tgz``: tar archive, compressed using gzip
418 :``tgz``: tar archive, compressed using gzip
419 :``uzip``: zip archive, uncompressed
419 :``uzip``: zip archive, uncompressed
420 :``zip``: zip archive, compressed using deflate
420 :``zip``: zip archive, compressed using deflate
421
421
422 The exact name of the destination archive or directory is given
422 The exact name of the destination archive or directory is given
423 using a format string; see :hg:`help export` for details.
423 using a format string; see :hg:`help export` for details.
424
424
425 Each member added to an archive file has a directory prefix
425 Each member added to an archive file has a directory prefix
426 prepended. Use -p/--prefix to specify a format string for the
426 prepended. Use -p/--prefix to specify a format string for the
427 prefix. The default is the basename of the archive, with suffixes
427 prefix. The default is the basename of the archive, with suffixes
428 removed.
428 removed.
429
429
430 Returns 0 on success.
430 Returns 0 on success.
431 '''
431 '''
432
432
433 ctx = scmutil.revsingle(repo, opts.get('rev'))
433 ctx = scmutil.revsingle(repo, opts.get('rev'))
434 if not ctx:
434 if not ctx:
435 raise util.Abort(_('no working directory: please specify a revision'))
435 raise util.Abort(_('no working directory: please specify a revision'))
436 node = ctx.node()
436 node = ctx.node()
437 dest = cmdutil.makefilename(repo, dest, node)
437 dest = cmdutil.makefilename(repo, dest, node)
438 if os.path.realpath(dest) == repo.root:
438 if os.path.realpath(dest) == repo.root:
439 raise util.Abort(_('repository root cannot be destination'))
439 raise util.Abort(_('repository root cannot be destination'))
440
440
441 kind = opts.get('type') or archival.guesskind(dest) or 'files'
441 kind = opts.get('type') or archival.guesskind(dest) or 'files'
442 prefix = opts.get('prefix')
442 prefix = opts.get('prefix')
443
443
444 if dest == '-':
444 if dest == '-':
445 if kind == 'files':
445 if kind == 'files':
446 raise util.Abort(_('cannot archive plain files to stdout'))
446 raise util.Abort(_('cannot archive plain files to stdout'))
447 dest = cmdutil.makefileobj(repo, dest)
447 dest = cmdutil.makefileobj(repo, dest)
448 if not prefix:
448 if not prefix:
449 prefix = os.path.basename(repo.root) + '-%h'
449 prefix = os.path.basename(repo.root) + '-%h'
450
450
451 prefix = cmdutil.makefilename(repo, prefix, node)
451 prefix = cmdutil.makefilename(repo, prefix, node)
452 matchfn = scmutil.match(ctx, [], opts)
452 matchfn = scmutil.match(ctx, [], opts)
453 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
453 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
454 matchfn, prefix, subrepos=opts.get('subrepos'))
454 matchfn, prefix, subrepos=opts.get('subrepos'))
455
455
456 @command('backout',
456 @command('backout',
457 [('', 'merge', None, _('merge with old dirstate parent after backout')),
457 [('', 'merge', None, _('merge with old dirstate parent after backout')),
458 ('', 'commit', None, _('commit if no conflicts were encountered')),
458 ('', 'commit', None, _('commit if no conflicts were encountered')),
459 ('', 'parent', '',
459 ('', 'parent', '',
460 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
460 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
461 ('r', 'rev', '', _('revision to backout'), _('REV')),
461 ('r', 'rev', '', _('revision to backout'), _('REV')),
462 ('e', 'edit', False, _('invoke editor on commit messages')),
462 ('e', 'edit', False, _('invoke editor on commit messages')),
463 ] + mergetoolopts + walkopts + commitopts + commitopts2,
463 ] + mergetoolopts + walkopts + commitopts + commitopts2,
464 _('[OPTION]... [-r] REV'))
464 _('[OPTION]... [-r] REV'))
465 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
465 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
466 '''reverse effect of earlier changeset
466 '''reverse effect of earlier changeset
467
467
468 Prepare a new changeset with the effect of REV undone in the
468 Prepare a new changeset with the effect of REV undone in the
469 current working directory.
469 current working directory.
470
470
471 If REV is the parent of the working directory, then this new changeset
471 If REV is the parent of the working directory, then this new changeset
472 is committed automatically. Otherwise, hg needs to merge the
472 is committed automatically. Otherwise, hg needs to merge the
473 changes and the merged result is left uncommitted.
473 changes and the merged result is left uncommitted.
474
474
475 .. note::
475 .. note::
476
476
477 backout cannot be used to fix either an unwanted or
477 backout cannot be used to fix either an unwanted or
478 incorrect merge.
478 incorrect merge.
479
479
480 .. container:: verbose
480 .. container:: verbose
481
481
482 By default, the pending changeset will have one parent,
482 By default, the pending changeset will have one parent,
483 maintaining a linear history. With --merge, the pending
483 maintaining a linear history. With --merge, the pending
484 changeset will instead have two parents: the old parent of the
484 changeset will instead have two parents: the old parent of the
485 working directory and a new child of REV that simply undoes REV.
485 working directory and a new child of REV that simply undoes REV.
486
486
487 Before version 1.7, the behavior without --merge was equivalent
487 Before version 1.7, the behavior without --merge was equivalent
488 to specifying --merge followed by :hg:`update --clean .` to
488 to specifying --merge followed by :hg:`update --clean .` to
489 cancel the merge and leave the child of REV as a head to be
489 cancel the merge and leave the child of REV as a head to be
490 merged separately.
490 merged separately.
491
491
492 See :hg:`help dates` for a list of formats valid for -d/--date.
492 See :hg:`help dates` for a list of formats valid for -d/--date.
493
493
494 Returns 0 on success, 1 if nothing to backout or there are unresolved
494 Returns 0 on success, 1 if nothing to backout or there are unresolved
495 files.
495 files.
496 '''
496 '''
497 if rev and node:
497 if rev and node:
498 raise util.Abort(_("please specify just one revision"))
498 raise util.Abort(_("please specify just one revision"))
499
499
500 if not rev:
500 if not rev:
501 rev = node
501 rev = node
502
502
503 if not rev:
503 if not rev:
504 raise util.Abort(_("please specify a revision to backout"))
504 raise util.Abort(_("please specify a revision to backout"))
505
505
506 date = opts.get('date')
506 date = opts.get('date')
507 if date:
507 if date:
508 opts['date'] = util.parsedate(date)
508 opts['date'] = util.parsedate(date)
509
509
510 cmdutil.checkunfinished(repo)
510 cmdutil.checkunfinished(repo)
511 cmdutil.bailifchanged(repo)
511 cmdutil.bailifchanged(repo)
512 node = scmutil.revsingle(repo, rev).node()
512 node = scmutil.revsingle(repo, rev).node()
513
513
514 op1, op2 = repo.dirstate.parents()
514 op1, op2 = repo.dirstate.parents()
515 if not repo.changelog.isancestor(node, op1):
515 if not repo.changelog.isancestor(node, op1):
516 raise util.Abort(_('cannot backout change that is not an ancestor'))
516 raise util.Abort(_('cannot backout change that is not an ancestor'))
517
517
518 p1, p2 = repo.changelog.parents(node)
518 p1, p2 = repo.changelog.parents(node)
519 if p1 == nullid:
519 if p1 == nullid:
520 raise util.Abort(_('cannot backout a change with no parents'))
520 raise util.Abort(_('cannot backout a change with no parents'))
521 if p2 != nullid:
521 if p2 != nullid:
522 if not opts.get('parent'):
522 if not opts.get('parent'):
523 raise util.Abort(_('cannot backout a merge changeset'))
523 raise util.Abort(_('cannot backout a merge changeset'))
524 p = repo.lookup(opts['parent'])
524 p = repo.lookup(opts['parent'])
525 if p not in (p1, p2):
525 if p not in (p1, p2):
526 raise util.Abort(_('%s is not a parent of %s') %
526 raise util.Abort(_('%s is not a parent of %s') %
527 (short(p), short(node)))
527 (short(p), short(node)))
528 parent = p
528 parent = p
529 else:
529 else:
530 if opts.get('parent'):
530 if opts.get('parent'):
531 raise util.Abort(_('cannot use --parent on non-merge changeset'))
531 raise util.Abort(_('cannot use --parent on non-merge changeset'))
532 parent = p1
532 parent = p1
533
533
534 # the backout should appear on the same branch
534 # the backout should appear on the same branch
535 wlock = repo.wlock()
535 wlock = repo.wlock()
536 try:
536 try:
537 branch = repo.dirstate.branch()
537 branch = repo.dirstate.branch()
538 bheads = repo.branchheads(branch)
538 bheads = repo.branchheads(branch)
539 rctx = scmutil.revsingle(repo, hex(parent))
539 rctx = scmutil.revsingle(repo, hex(parent))
540 if not opts.get('merge') and op1 != node:
540 if not opts.get('merge') and op1 != node:
541 try:
541 try:
542 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
542 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
543 'backout')
543 'backout')
544 repo.dirstate.beginparentchange()
544 repo.dirstate.beginparentchange()
545 stats = mergemod.update(repo, parent, True, True, False,
545 stats = mergemod.update(repo, parent, True, True, False,
546 node, False)
546 node, False)
547 repo.setparents(op1, op2)
547 repo.setparents(op1, op2)
548 repo.dirstate.endparentchange()
548 repo.dirstate.endparentchange()
549 hg._showstats(repo, stats)
549 hg._showstats(repo, stats)
550 if stats[3]:
550 if stats[3]:
551 repo.ui.status(_("use 'hg resolve' to retry unresolved "
551 repo.ui.status(_("use 'hg resolve' to retry unresolved "
552 "file merges\n"))
552 "file merges\n"))
553 return 1
553 return 1
554 elif not commit:
554 elif not commit:
555 msg = _("changeset %s backed out, "
555 msg = _("changeset %s backed out, "
556 "don't forget to commit.\n")
556 "don't forget to commit.\n")
557 ui.status(msg % short(node))
557 ui.status(msg % short(node))
558 return 0
558 return 0
559 finally:
559 finally:
560 ui.setconfig('ui', 'forcemerge', '', '')
560 ui.setconfig('ui', 'forcemerge', '', '')
561 else:
561 else:
562 hg.clean(repo, node, show_stats=False)
562 hg.clean(repo, node, show_stats=False)
563 repo.dirstate.setbranch(branch)
563 repo.dirstate.setbranch(branch)
564 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
564 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
565
565
566
566
567 def commitfunc(ui, repo, message, match, opts):
567 def commitfunc(ui, repo, message, match, opts):
568 editform = 'backout'
568 editform = 'backout'
569 e = cmdutil.getcommiteditor(editform=editform, **opts)
569 e = cmdutil.getcommiteditor(editform=editform, **opts)
570 if not message:
570 if not message:
571 # we don't translate commit messages
571 # we don't translate commit messages
572 message = "Backed out changeset %s" % short(node)
572 message = "Backed out changeset %s" % short(node)
573 e = cmdutil.getcommiteditor(edit=True, editform=editform)
573 e = cmdutil.getcommiteditor(edit=True, editform=editform)
574 return repo.commit(message, opts.get('user'), opts.get('date'),
574 return repo.commit(message, opts.get('user'), opts.get('date'),
575 match, editor=e)
575 match, editor=e)
576 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
576 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
577 if not newnode:
577 if not newnode:
578 ui.status(_("nothing changed\n"))
578 ui.status(_("nothing changed\n"))
579 return 1
579 return 1
580 cmdutil.commitstatus(repo, newnode, branch, bheads)
580 cmdutil.commitstatus(repo, newnode, branch, bheads)
581
581
582 def nice(node):
582 def nice(node):
583 return '%d:%s' % (repo.changelog.rev(node), short(node))
583 return '%d:%s' % (repo.changelog.rev(node), short(node))
584 ui.status(_('changeset %s backs out changeset %s\n') %
584 ui.status(_('changeset %s backs out changeset %s\n') %
585 (nice(repo.changelog.tip()), nice(node)))
585 (nice(repo.changelog.tip()), nice(node)))
586 if opts.get('merge') and op1 != node:
586 if opts.get('merge') and op1 != node:
587 hg.clean(repo, op1, show_stats=False)
587 hg.clean(repo, op1, show_stats=False)
588 ui.status(_('merging with changeset %s\n')
588 ui.status(_('merging with changeset %s\n')
589 % nice(repo.changelog.tip()))
589 % nice(repo.changelog.tip()))
590 try:
590 try:
591 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
591 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
592 'backout')
592 'backout')
593 return hg.merge(repo, hex(repo.changelog.tip()))
593 return hg.merge(repo, hex(repo.changelog.tip()))
594 finally:
594 finally:
595 ui.setconfig('ui', 'forcemerge', '', '')
595 ui.setconfig('ui', 'forcemerge', '', '')
596 finally:
596 finally:
597 wlock.release()
597 wlock.release()
598 return 0
598 return 0
599
599
600 @command('bisect',
600 @command('bisect',
601 [('r', 'reset', False, _('reset bisect state')),
601 [('r', 'reset', False, _('reset bisect state')),
602 ('g', 'good', False, _('mark changeset good')),
602 ('g', 'good', False, _('mark changeset good')),
603 ('b', 'bad', False, _('mark changeset bad')),
603 ('b', 'bad', False, _('mark changeset bad')),
604 ('s', 'skip', False, _('skip testing changeset')),
604 ('s', 'skip', False, _('skip testing changeset')),
605 ('e', 'extend', False, _('extend the bisect range')),
605 ('e', 'extend', False, _('extend the bisect range')),
606 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
606 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
607 ('U', 'noupdate', False, _('do not update to target'))],
607 ('U', 'noupdate', False, _('do not update to target'))],
608 _("[-gbsr] [-U] [-c CMD] [REV]"))
608 _("[-gbsr] [-U] [-c CMD] [REV]"))
609 def bisect(ui, repo, rev=None, extra=None, command=None,
609 def bisect(ui, repo, rev=None, extra=None, command=None,
610 reset=None, good=None, bad=None, skip=None, extend=None,
610 reset=None, good=None, bad=None, skip=None, extend=None,
611 noupdate=None):
611 noupdate=None):
612 """subdivision search of changesets
612 """subdivision search of changesets
613
613
614 This command helps to find changesets which introduce problems. To
614 This command helps to find changesets which introduce problems. To
615 use, mark the earliest changeset you know exhibits the problem as
615 use, mark the earliest changeset you know exhibits the problem as
616 bad, then mark the latest changeset which is free from the problem
616 bad, then mark the latest changeset which is free from the problem
617 as good. Bisect will update your working directory to a revision
617 as good. Bisect will update your working directory to a revision
618 for testing (unless the -U/--noupdate option is specified). Once
618 for testing (unless the -U/--noupdate option is specified). Once
619 you have performed tests, mark the working directory as good or
619 you have performed tests, mark the working directory as good or
620 bad, and bisect will either update to another candidate changeset
620 bad, and bisect will either update to another candidate changeset
621 or announce that it has found the bad revision.
621 or announce that it has found the bad revision.
622
622
623 As a shortcut, you can also use the revision argument to mark a
623 As a shortcut, you can also use the revision argument to mark a
624 revision as good or bad without checking it out first.
624 revision as good or bad without checking it out first.
625
625
626 If you supply a command, it will be used for automatic bisection.
626 If you supply a command, it will be used for automatic bisection.
627 The environment variable HG_NODE will contain the ID of the
627 The environment variable HG_NODE will contain the ID of the
628 changeset being tested. The exit status of the command will be
628 changeset being tested. The exit status of the command will be
629 used to mark revisions as good or bad: status 0 means good, 125
629 used to mark revisions as good or bad: status 0 means good, 125
630 means to skip the revision, 127 (command not found) will abort the
630 means to skip the revision, 127 (command not found) will abort the
631 bisection, and any other non-zero exit status means the revision
631 bisection, and any other non-zero exit status means the revision
632 is bad.
632 is bad.
633
633
634 .. container:: verbose
634 .. container:: verbose
635
635
636 Some examples:
636 Some examples:
637
637
638 - start a bisection with known bad revision 34, and good revision 12::
638 - start a bisection with known bad revision 34, and good revision 12::
639
639
640 hg bisect --bad 34
640 hg bisect --bad 34
641 hg bisect --good 12
641 hg bisect --good 12
642
642
643 - advance the current bisection by marking current revision as good or
643 - advance the current bisection by marking current revision as good or
644 bad::
644 bad::
645
645
646 hg bisect --good
646 hg bisect --good
647 hg bisect --bad
647 hg bisect --bad
648
648
649 - mark the current revision, or a known revision, to be skipped (e.g. if
649 - mark the current revision, or a known revision, to be skipped (e.g. if
650 that revision is not usable because of another issue)::
650 that revision is not usable because of another issue)::
651
651
652 hg bisect --skip
652 hg bisect --skip
653 hg bisect --skip 23
653 hg bisect --skip 23
654
654
655 - skip all revisions that do not touch directories ``foo`` or ``bar``::
655 - skip all revisions that do not touch directories ``foo`` or ``bar``::
656
656
657 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
657 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
658
658
659 - forget the current bisection::
659 - forget the current bisection::
660
660
661 hg bisect --reset
661 hg bisect --reset
662
662
663 - use 'make && make tests' to automatically find the first broken
663 - use 'make && make tests' to automatically find the first broken
664 revision::
664 revision::
665
665
666 hg bisect --reset
666 hg bisect --reset
667 hg bisect --bad 34
667 hg bisect --bad 34
668 hg bisect --good 12
668 hg bisect --good 12
669 hg bisect --command "make && make tests"
669 hg bisect --command "make && make tests"
670
670
671 - see all changesets whose states are already known in the current
671 - see all changesets whose states are already known in the current
672 bisection::
672 bisection::
673
673
674 hg log -r "bisect(pruned)"
674 hg log -r "bisect(pruned)"
675
675
676 - see the changeset currently being bisected (especially useful
676 - see the changeset currently being bisected (especially useful
677 if running with -U/--noupdate)::
677 if running with -U/--noupdate)::
678
678
679 hg log -r "bisect(current)"
679 hg log -r "bisect(current)"
680
680
681 - see all changesets that took part in the current bisection::
681 - see all changesets that took part in the current bisection::
682
682
683 hg log -r "bisect(range)"
683 hg log -r "bisect(range)"
684
684
685 - you can even get a nice graph::
685 - you can even get a nice graph::
686
686
687 hg log --graph -r "bisect(range)"
687 hg log --graph -r "bisect(range)"
688
688
689 See :hg:`help revsets` for more about the `bisect()` keyword.
689 See :hg:`help revsets` for more about the `bisect()` keyword.
690
690
691 Returns 0 on success.
691 Returns 0 on success.
692 """
692 """
693 def extendbisectrange(nodes, good):
693 def extendbisectrange(nodes, good):
694 # bisect is incomplete when it ends on a merge node and
694 # bisect is incomplete when it ends on a merge node and
695 # one of the parent was not checked.
695 # one of the parent was not checked.
696 parents = repo[nodes[0]].parents()
696 parents = repo[nodes[0]].parents()
697 if len(parents) > 1:
697 if len(parents) > 1:
698 if good:
698 if good:
699 side = state['bad']
699 side = state['bad']
700 else:
700 else:
701 side = state['good']
701 side = state['good']
702 num = len(set(i.node() for i in parents) & set(side))
702 num = len(set(i.node() for i in parents) & set(side))
703 if num == 1:
703 if num == 1:
704 return parents[0].ancestor(parents[1])
704 return parents[0].ancestor(parents[1])
705 return None
705 return None
706
706
707 def print_result(nodes, good):
707 def print_result(nodes, good):
708 displayer = cmdutil.show_changeset(ui, repo, {})
708 displayer = cmdutil.show_changeset(ui, repo, {})
709 if len(nodes) == 1:
709 if len(nodes) == 1:
710 # narrowed it down to a single revision
710 # narrowed it down to a single revision
711 if good:
711 if good:
712 ui.write(_("The first good revision is:\n"))
712 ui.write(_("The first good revision is:\n"))
713 else:
713 else:
714 ui.write(_("The first bad revision is:\n"))
714 ui.write(_("The first bad revision is:\n"))
715 displayer.show(repo[nodes[0]])
715 displayer.show(repo[nodes[0]])
716 extendnode = extendbisectrange(nodes, good)
716 extendnode = extendbisectrange(nodes, good)
717 if extendnode is not None:
717 if extendnode is not None:
718 ui.write(_('Not all ancestors of this changeset have been'
718 ui.write(_('Not all ancestors of this changeset have been'
719 ' checked.\nUse bisect --extend to continue the '
719 ' checked.\nUse bisect --extend to continue the '
720 'bisection from\nthe common ancestor, %s.\n')
720 'bisection from\nthe common ancestor, %s.\n')
721 % extendnode)
721 % extendnode)
722 else:
722 else:
723 # multiple possible revisions
723 # multiple possible revisions
724 if good:
724 if good:
725 ui.write(_("Due to skipped revisions, the first "
725 ui.write(_("Due to skipped revisions, the first "
726 "good revision could be any of:\n"))
726 "good revision could be any of:\n"))
727 else:
727 else:
728 ui.write(_("Due to skipped revisions, the first "
728 ui.write(_("Due to skipped revisions, the first "
729 "bad revision could be any of:\n"))
729 "bad revision could be any of:\n"))
730 for n in nodes:
730 for n in nodes:
731 displayer.show(repo[n])
731 displayer.show(repo[n])
732 displayer.close()
732 displayer.close()
733
733
734 def check_state(state, interactive=True):
734 def check_state(state, interactive=True):
735 if not state['good'] or not state['bad']:
735 if not state['good'] or not state['bad']:
736 if (good or bad or skip or reset) and interactive:
736 if (good or bad or skip or reset) and interactive:
737 return
737 return
738 if not state['good']:
738 if not state['good']:
739 raise util.Abort(_('cannot bisect (no known good revisions)'))
739 raise util.Abort(_('cannot bisect (no known good revisions)'))
740 else:
740 else:
741 raise util.Abort(_('cannot bisect (no known bad revisions)'))
741 raise util.Abort(_('cannot bisect (no known bad revisions)'))
742 return True
742 return True
743
743
744 # backward compatibility
744 # backward compatibility
745 if rev in "good bad reset init".split():
745 if rev in "good bad reset init".split():
746 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
746 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
747 cmd, rev, extra = rev, extra, None
747 cmd, rev, extra = rev, extra, None
748 if cmd == "good":
748 if cmd == "good":
749 good = True
749 good = True
750 elif cmd == "bad":
750 elif cmd == "bad":
751 bad = True
751 bad = True
752 else:
752 else:
753 reset = True
753 reset = True
754 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
754 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
755 raise util.Abort(_('incompatible arguments'))
755 raise util.Abort(_('incompatible arguments'))
756
756
757 cmdutil.checkunfinished(repo)
757 cmdutil.checkunfinished(repo)
758
758
759 if reset:
759 if reset:
760 p = repo.join("bisect.state")
760 p = repo.join("bisect.state")
761 if os.path.exists(p):
761 if os.path.exists(p):
762 os.unlink(p)
762 os.unlink(p)
763 return
763 return
764
764
765 state = hbisect.load_state(repo)
765 state = hbisect.load_state(repo)
766
766
767 if command:
767 if command:
768 changesets = 1
768 changesets = 1
769 if noupdate:
769 if noupdate:
770 try:
770 try:
771 node = state['current'][0]
771 node = state['current'][0]
772 except LookupError:
772 except LookupError:
773 raise util.Abort(_('current bisect revision is unknown - '
773 raise util.Abort(_('current bisect revision is unknown - '
774 'start a new bisect to fix'))
774 'start a new bisect to fix'))
775 else:
775 else:
776 node, p2 = repo.dirstate.parents()
776 node, p2 = repo.dirstate.parents()
777 if p2 != nullid:
777 if p2 != nullid:
778 raise util.Abort(_('current bisect revision is a merge'))
778 raise util.Abort(_('current bisect revision is a merge'))
779 try:
779 try:
780 while changesets:
780 while changesets:
781 # update state
781 # update state
782 state['current'] = [node]
782 state['current'] = [node]
783 hbisect.save_state(repo, state)
783 hbisect.save_state(repo, state)
784 status = ui.system(command, environ={'HG_NODE': hex(node)})
784 status = ui.system(command, environ={'HG_NODE': hex(node)})
785 if status == 125:
785 if status == 125:
786 transition = "skip"
786 transition = "skip"
787 elif status == 0:
787 elif status == 0:
788 transition = "good"
788 transition = "good"
789 # status < 0 means process was killed
789 # status < 0 means process was killed
790 elif status == 127:
790 elif status == 127:
791 raise util.Abort(_("failed to execute %s") % command)
791 raise util.Abort(_("failed to execute %s") % command)
792 elif status < 0:
792 elif status < 0:
793 raise util.Abort(_("%s killed") % command)
793 raise util.Abort(_("%s killed") % command)
794 else:
794 else:
795 transition = "bad"
795 transition = "bad"
796 ctx = scmutil.revsingle(repo, rev, node)
796 ctx = scmutil.revsingle(repo, rev, node)
797 rev = None # clear for future iterations
797 rev = None # clear for future iterations
798 state[transition].append(ctx.node())
798 state[transition].append(ctx.node())
799 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
799 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
800 check_state(state, interactive=False)
800 check_state(state, interactive=False)
801 # bisect
801 # bisect
802 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
802 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
803 # update to next check
803 # update to next check
804 node = nodes[0]
804 node = nodes[0]
805 if not noupdate:
805 if not noupdate:
806 cmdutil.bailifchanged(repo)
806 cmdutil.bailifchanged(repo)
807 hg.clean(repo, node, show_stats=False)
807 hg.clean(repo, node, show_stats=False)
808 finally:
808 finally:
809 state['current'] = [node]
809 state['current'] = [node]
810 hbisect.save_state(repo, state)
810 hbisect.save_state(repo, state)
811 print_result(nodes, bgood)
811 print_result(nodes, bgood)
812 return
812 return
813
813
814 # update state
814 # update state
815
815
816 if rev:
816 if rev:
817 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
817 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
818 else:
818 else:
819 nodes = [repo.lookup('.')]
819 nodes = [repo.lookup('.')]
820
820
821 if good or bad or skip:
821 if good or bad or skip:
822 if good:
822 if good:
823 state['good'] += nodes
823 state['good'] += nodes
824 elif bad:
824 elif bad:
825 state['bad'] += nodes
825 state['bad'] += nodes
826 elif skip:
826 elif skip:
827 state['skip'] += nodes
827 state['skip'] += nodes
828 hbisect.save_state(repo, state)
828 hbisect.save_state(repo, state)
829
829
830 if not check_state(state):
830 if not check_state(state):
831 return
831 return
832
832
833 # actually bisect
833 # actually bisect
834 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
834 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
835 if extend:
835 if extend:
836 if not changesets:
836 if not changesets:
837 extendnode = extendbisectrange(nodes, good)
837 extendnode = extendbisectrange(nodes, good)
838 if extendnode is not None:
838 if extendnode is not None:
839 ui.write(_("Extending search to changeset %d:%s\n")
839 ui.write(_("Extending search to changeset %d:%s\n")
840 % (extendnode.rev(), extendnode))
840 % (extendnode.rev(), extendnode))
841 state['current'] = [extendnode.node()]
841 state['current'] = [extendnode.node()]
842 hbisect.save_state(repo, state)
842 hbisect.save_state(repo, state)
843 if noupdate:
843 if noupdate:
844 return
844 return
845 cmdutil.bailifchanged(repo)
845 cmdutil.bailifchanged(repo)
846 return hg.clean(repo, extendnode.node())
846 return hg.clean(repo, extendnode.node())
847 raise util.Abort(_("nothing to extend"))
847 raise util.Abort(_("nothing to extend"))
848
848
849 if changesets == 0:
849 if changesets == 0:
850 print_result(nodes, good)
850 print_result(nodes, good)
851 else:
851 else:
852 assert len(nodes) == 1 # only a single node can be tested next
852 assert len(nodes) == 1 # only a single node can be tested next
853 node = nodes[0]
853 node = nodes[0]
854 # compute the approximate number of remaining tests
854 # compute the approximate number of remaining tests
855 tests, size = 0, 2
855 tests, size = 0, 2
856 while size <= changesets:
856 while size <= changesets:
857 tests, size = tests + 1, size * 2
857 tests, size = tests + 1, size * 2
858 rev = repo.changelog.rev(node)
858 rev = repo.changelog.rev(node)
859 ui.write(_("Testing changeset %d:%s "
859 ui.write(_("Testing changeset %d:%s "
860 "(%d changesets remaining, ~%d tests)\n")
860 "(%d changesets remaining, ~%d tests)\n")
861 % (rev, short(node), changesets, tests))
861 % (rev, short(node), changesets, tests))
862 state['current'] = [node]
862 state['current'] = [node]
863 hbisect.save_state(repo, state)
863 hbisect.save_state(repo, state)
864 if not noupdate:
864 if not noupdate:
865 cmdutil.bailifchanged(repo)
865 cmdutil.bailifchanged(repo)
866 return hg.clean(repo, node)
866 return hg.clean(repo, node)
867
867
868 @command('bookmarks|bookmark',
868 @command('bookmarks|bookmark',
869 [('f', 'force', False, _('force')),
869 [('f', 'force', False, _('force')),
870 ('r', 'rev', '', _('revision'), _('REV')),
870 ('r', 'rev', '', _('revision'), _('REV')),
871 ('d', 'delete', False, _('delete a given bookmark')),
871 ('d', 'delete', False, _('delete a given bookmark')),
872 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
872 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
873 ('i', 'inactive', False, _('mark a bookmark inactive')),
873 ('i', 'inactive', False, _('mark a bookmark inactive')),
874 ] + formatteropts,
874 ] + formatteropts,
875 _('hg bookmarks [OPTIONS]... [NAME]...'))
875 _('hg bookmarks [OPTIONS]... [NAME]...'))
876 def bookmark(ui, repo, *names, **opts):
876 def bookmark(ui, repo, *names, **opts):
877 '''create a new bookmark or list existing bookmarks
877 '''create a new bookmark or list existing bookmarks
878
878
879 Bookmarks are labels on changesets to help track lines of development.
879 Bookmarks are labels on changesets to help track lines of development.
880 Bookmarks are unversioned and can be moved, renamed and deleted.
880 Bookmarks are unversioned and can be moved, renamed and deleted.
881 Deleting or moving a bookmark has no effect on the associated changesets.
881 Deleting or moving a bookmark has no effect on the associated changesets.
882
882
883 Creating or updating to a bookmark causes it to be marked as 'active'.
883 Creating or updating to a bookmark causes it to be marked as 'active'.
884 The active bookmark is indicated with a '*'.
884 The active bookmark is indicated with a '*'.
885 When a commit is made, the active bookmark will advance to the new commit.
885 When a commit is made, the active bookmark will advance to the new commit.
886 A plain :hg:`update` will also advance an active bookmark, if possible.
886 A plain :hg:`update` will also advance an active bookmark, if possible.
887 Updating away from a bookmark will cause it to be deactivated.
887 Updating away from a bookmark will cause it to be deactivated.
888
888
889 Bookmarks can be pushed and pulled between repositories (see
889 Bookmarks can be pushed and pulled between repositories (see
890 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
890 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
891 diverged, a new 'divergent bookmark' of the form 'name@path' will
891 diverged, a new 'divergent bookmark' of the form 'name@path' will
892 be created. Using :hg:`merge` will resolve the divergence.
892 be created. Using :hg:`merge` will resolve the divergence.
893
893
894 A bookmark named '@' has the special property that :hg:`clone` will
894 A bookmark named '@' has the special property that :hg:`clone` will
895 check it out by default if it exists.
895 check it out by default if it exists.
896
896
897 .. container:: verbose
897 .. container:: verbose
898
898
899 Examples:
899 Examples:
900
900
901 - create an active bookmark for a new line of development::
901 - create an active bookmark for a new line of development::
902
902
903 hg book new-feature
903 hg book new-feature
904
904
905 - create an inactive bookmark as a place marker::
905 - create an inactive bookmark as a place marker::
906
906
907 hg book -i reviewed
907 hg book -i reviewed
908
908
909 - create an inactive bookmark on another changeset::
909 - create an inactive bookmark on another changeset::
910
910
911 hg book -r .^ tested
911 hg book -r .^ tested
912
912
913 - move the '@' bookmark from another branch::
913 - move the '@' bookmark from another branch::
914
914
915 hg book -f @
915 hg book -f @
916 '''
916 '''
917 force = opts.get('force')
917 force = opts.get('force')
918 rev = opts.get('rev')
918 rev = opts.get('rev')
919 delete = opts.get('delete')
919 delete = opts.get('delete')
920 rename = opts.get('rename')
920 rename = opts.get('rename')
921 inactive = opts.get('inactive')
921 inactive = opts.get('inactive')
922
922
923 def checkformat(mark):
923 def checkformat(mark):
924 mark = mark.strip()
924 mark = mark.strip()
925 if not mark:
925 if not mark:
926 raise util.Abort(_("bookmark names cannot consist entirely of "
926 raise util.Abort(_("bookmark names cannot consist entirely of "
927 "whitespace"))
927 "whitespace"))
928 scmutil.checknewlabel(repo, mark, 'bookmark')
928 scmutil.checknewlabel(repo, mark, 'bookmark')
929 return mark
929 return mark
930
930
931 def checkconflict(repo, mark, cur, force=False, target=None):
931 def checkconflict(repo, mark, cur, force=False, target=None):
932 if mark in marks and not force:
932 if mark in marks and not force:
933 if target:
933 if target:
934 if marks[mark] == target and target == cur:
934 if marks[mark] == target and target == cur:
935 # re-activating a bookmark
935 # re-activating a bookmark
936 return
936 return
937 anc = repo.changelog.ancestors([repo[target].rev()])
937 anc = repo.changelog.ancestors([repo[target].rev()])
938 bmctx = repo[marks[mark]]
938 bmctx = repo[marks[mark]]
939 divs = [repo[b].node() for b in marks
939 divs = [repo[b].node() for b in marks
940 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
940 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
941
941
942 # allow resolving a single divergent bookmark even if moving
942 # allow resolving a single divergent bookmark even if moving
943 # the bookmark across branches when a revision is specified
943 # the bookmark across branches when a revision is specified
944 # that contains a divergent bookmark
944 # that contains a divergent bookmark
945 if bmctx.rev() not in anc and target in divs:
945 if bmctx.rev() not in anc and target in divs:
946 bookmarks.deletedivergent(repo, [target], mark)
946 bookmarks.deletedivergent(repo, [target], mark)
947 return
947 return
948
948
949 deletefrom = [b for b in divs
949 deletefrom = [b for b in divs
950 if repo[b].rev() in anc or b == target]
950 if repo[b].rev() in anc or b == target]
951 bookmarks.deletedivergent(repo, deletefrom, mark)
951 bookmarks.deletedivergent(repo, deletefrom, mark)
952 if bookmarks.validdest(repo, bmctx, repo[target]):
952 if bookmarks.validdest(repo, bmctx, repo[target]):
953 ui.status(_("moving bookmark '%s' forward from %s\n") %
953 ui.status(_("moving bookmark '%s' forward from %s\n") %
954 (mark, short(bmctx.node())))
954 (mark, short(bmctx.node())))
955 return
955 return
956 raise util.Abort(_("bookmark '%s' already exists "
956 raise util.Abort(_("bookmark '%s' already exists "
957 "(use -f to force)") % mark)
957 "(use -f to force)") % mark)
958 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
958 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
959 and not force):
959 and not force):
960 raise util.Abort(
960 raise util.Abort(
961 _("a bookmark cannot have the name of an existing branch"))
961 _("a bookmark cannot have the name of an existing branch"))
962
962
963 if delete and rename:
963 if delete and rename:
964 raise util.Abort(_("--delete and --rename are incompatible"))
964 raise util.Abort(_("--delete and --rename are incompatible"))
965 if delete and rev:
965 if delete and rev:
966 raise util.Abort(_("--rev is incompatible with --delete"))
966 raise util.Abort(_("--rev is incompatible with --delete"))
967 if rename and rev:
967 if rename and rev:
968 raise util.Abort(_("--rev is incompatible with --rename"))
968 raise util.Abort(_("--rev is incompatible with --rename"))
969 if not names and (delete or rev):
969 if not names and (delete or rev):
970 raise util.Abort(_("bookmark name required"))
970 raise util.Abort(_("bookmark name required"))
971
971
972 if delete or rename or names or inactive:
972 if delete or rename or names or inactive:
973 wlock = repo.wlock()
973 wlock = repo.wlock()
974 try:
974 try:
975 cur = repo.changectx('.').node()
975 cur = repo.changectx('.').node()
976 marks = repo._bookmarks
976 marks = repo._bookmarks
977 if delete:
977 if delete:
978 for mark in names:
978 for mark in names:
979 if mark not in marks:
979 if mark not in marks:
980 raise util.Abort(_("bookmark '%s' does not exist") %
980 raise util.Abort(_("bookmark '%s' does not exist") %
981 mark)
981 mark)
982 if mark == repo._bookmarkcurrent:
982 if mark == repo._bookmarkcurrent:
983 bookmarks.unsetcurrent(repo)
983 bookmarks.unsetcurrent(repo)
984 del marks[mark]
984 del marks[mark]
985 marks.write()
985 marks.write()
986
986
987 elif rename:
987 elif rename:
988 if not names:
988 if not names:
989 raise util.Abort(_("new bookmark name required"))
989 raise util.Abort(_("new bookmark name required"))
990 elif len(names) > 1:
990 elif len(names) > 1:
991 raise util.Abort(_("only one new bookmark name allowed"))
991 raise util.Abort(_("only one new bookmark name allowed"))
992 mark = checkformat(names[0])
992 mark = checkformat(names[0])
993 if rename not in marks:
993 if rename not in marks:
994 raise util.Abort(_("bookmark '%s' does not exist") % rename)
994 raise util.Abort(_("bookmark '%s' does not exist") % rename)
995 checkconflict(repo, mark, cur, force)
995 checkconflict(repo, mark, cur, force)
996 marks[mark] = marks[rename]
996 marks[mark] = marks[rename]
997 if repo._bookmarkcurrent == rename and not inactive:
997 if repo._bookmarkcurrent == rename and not inactive:
998 bookmarks.setcurrent(repo, mark)
998 bookmarks.setcurrent(repo, mark)
999 del marks[rename]
999 del marks[rename]
1000 marks.write()
1000 marks.write()
1001
1001
1002 elif names:
1002 elif names:
1003 newact = None
1003 newact = None
1004 for mark in names:
1004 for mark in names:
1005 mark = checkformat(mark)
1005 mark = checkformat(mark)
1006 if newact is None:
1006 if newact is None:
1007 newact = mark
1007 newact = mark
1008 if inactive and mark == repo._bookmarkcurrent:
1008 if inactive and mark == repo._bookmarkcurrent:
1009 bookmarks.unsetcurrent(repo)
1009 bookmarks.unsetcurrent(repo)
1010 return
1010 return
1011 tgt = cur
1011 tgt = cur
1012 if rev:
1012 if rev:
1013 tgt = scmutil.revsingle(repo, rev).node()
1013 tgt = scmutil.revsingle(repo, rev).node()
1014 checkconflict(repo, mark, cur, force, tgt)
1014 checkconflict(repo, mark, cur, force, tgt)
1015 marks[mark] = tgt
1015 marks[mark] = tgt
1016 if not inactive and cur == marks[newact] and not rev:
1016 if not inactive and cur == marks[newact] and not rev:
1017 bookmarks.setcurrent(repo, newact)
1017 bookmarks.setcurrent(repo, newact)
1018 elif cur != tgt and newact == repo._bookmarkcurrent:
1018 elif cur != tgt and newact == repo._bookmarkcurrent:
1019 bookmarks.unsetcurrent(repo)
1019 bookmarks.unsetcurrent(repo)
1020 marks.write()
1020 marks.write()
1021
1021
1022 elif inactive:
1022 elif inactive:
1023 if len(marks) == 0:
1023 if len(marks) == 0:
1024 ui.status(_("no bookmarks set\n"))
1024 ui.status(_("no bookmarks set\n"))
1025 elif not repo._bookmarkcurrent:
1025 elif not repo._bookmarkcurrent:
1026 ui.status(_("no active bookmark\n"))
1026 ui.status(_("no active bookmark\n"))
1027 else:
1027 else:
1028 bookmarks.unsetcurrent(repo)
1028 bookmarks.unsetcurrent(repo)
1029 finally:
1029 finally:
1030 wlock.release()
1030 wlock.release()
1031 else: # show bookmarks
1031 else: # show bookmarks
1032 fm = ui.formatter('bookmarks', opts)
1032 fm = ui.formatter('bookmarks', opts)
1033 hexfn = fm.hexfunc
1033 hexfn = fm.hexfunc
1034 marks = repo._bookmarks
1034 marks = repo._bookmarks
1035 if len(marks) == 0 and not fm:
1035 if len(marks) == 0 and not fm:
1036 ui.status(_("no bookmarks set\n"))
1036 ui.status(_("no bookmarks set\n"))
1037 for bmark, n in sorted(marks.iteritems()):
1037 for bmark, n in sorted(marks.iteritems()):
1038 current = repo._bookmarkcurrent
1038 current = repo._bookmarkcurrent
1039 if bmark == current:
1039 if bmark == current:
1040 prefix, label = '*', 'bookmarks.current'
1040 prefix, label = '*', 'bookmarks.current'
1041 else:
1041 else:
1042 prefix, label = ' ', ''
1042 prefix, label = ' ', ''
1043
1043
1044 fm.startitem()
1044 fm.startitem()
1045 if not ui.quiet:
1045 if not ui.quiet:
1046 fm.plain(' %s ' % prefix, label=label)
1046 fm.plain(' %s ' % prefix, label=label)
1047 fm.write('bookmark', '%s', bmark, label=label)
1047 fm.write('bookmark', '%s', bmark, label=label)
1048 pad = " " * (25 - encoding.colwidth(bmark))
1048 pad = " " * (25 - encoding.colwidth(bmark))
1049 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1049 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1050 repo.changelog.rev(n), hexfn(n), label=label)
1050 repo.changelog.rev(n), hexfn(n), label=label)
1051 fm.data(active=(bmark == current))
1051 fm.data(active=(bmark == current))
1052 fm.plain('\n')
1052 fm.plain('\n')
1053 fm.end()
1053 fm.end()
1054
1054
1055 @command('branch',
1055 @command('branch',
1056 [('f', 'force', None,
1056 [('f', 'force', None,
1057 _('set branch name even if it shadows an existing branch')),
1057 _('set branch name even if it shadows an existing branch')),
1058 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1058 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1059 _('[-fC] [NAME]'))
1059 _('[-fC] [NAME]'))
1060 def branch(ui, repo, label=None, **opts):
1060 def branch(ui, repo, label=None, **opts):
1061 """set or show the current branch name
1061 """set or show the current branch name
1062
1062
1063 .. note::
1063 .. note::
1064
1064
1065 Branch names are permanent and global. Use :hg:`bookmark` to create a
1065 Branch names are permanent and global. Use :hg:`bookmark` to create a
1066 light-weight bookmark instead. See :hg:`help glossary` for more
1066 light-weight bookmark instead. See :hg:`help glossary` for more
1067 information about named branches and bookmarks.
1067 information about named branches and bookmarks.
1068
1068
1069 With no argument, show the current branch name. With one argument,
1069 With no argument, show the current branch name. With one argument,
1070 set the working directory branch name (the branch will not exist
1070 set the working directory branch name (the branch will not exist
1071 in the repository until the next commit). Standard practice
1071 in the repository until the next commit). Standard practice
1072 recommends that primary development take place on the 'default'
1072 recommends that primary development take place on the 'default'
1073 branch.
1073 branch.
1074
1074
1075 Unless -f/--force is specified, branch will not let you set a
1075 Unless -f/--force is specified, branch will not let you set a
1076 branch name that already exists.
1076 branch name that already exists.
1077
1077
1078 Use -C/--clean to reset the working directory branch to that of
1078 Use -C/--clean to reset the working directory branch to that of
1079 the parent of the working directory, negating a previous branch
1079 the parent of the working directory, negating a previous branch
1080 change.
1080 change.
1081
1081
1082 Use the command :hg:`update` to switch to an existing branch. Use
1082 Use the command :hg:`update` to switch to an existing branch. Use
1083 :hg:`commit --close-branch` to mark this branch as closed.
1083 :hg:`commit --close-branch` to mark this branch as closed.
1084
1084
1085 Returns 0 on success.
1085 Returns 0 on success.
1086 """
1086 """
1087 if label:
1087 if label:
1088 label = label.strip()
1088 label = label.strip()
1089
1089
1090 if not opts.get('clean') and not label:
1090 if not opts.get('clean') and not label:
1091 ui.write("%s\n" % repo.dirstate.branch())
1091 ui.write("%s\n" % repo.dirstate.branch())
1092 return
1092 return
1093
1093
1094 wlock = repo.wlock()
1094 wlock = repo.wlock()
1095 try:
1095 try:
1096 if opts.get('clean'):
1096 if opts.get('clean'):
1097 label = repo[None].p1().branch()
1097 label = repo[None].p1().branch()
1098 repo.dirstate.setbranch(label)
1098 repo.dirstate.setbranch(label)
1099 ui.status(_('reset working directory to branch %s\n') % label)
1099 ui.status(_('reset working directory to branch %s\n') % label)
1100 elif label:
1100 elif label:
1101 if not opts.get('force') and label in repo.branchmap():
1101 if not opts.get('force') and label in repo.branchmap():
1102 if label not in [p.branch() for p in repo.parents()]:
1102 if label not in [p.branch() for p in repo.parents()]:
1103 raise util.Abort(_('a branch of the same name already'
1103 raise util.Abort(_('a branch of the same name already'
1104 ' exists'),
1104 ' exists'),
1105 # i18n: "it" refers to an existing branch
1105 # i18n: "it" refers to an existing branch
1106 hint=_("use 'hg update' to switch to it"))
1106 hint=_("use 'hg update' to switch to it"))
1107 scmutil.checknewlabel(repo, label, 'branch')
1107 scmutil.checknewlabel(repo, label, 'branch')
1108 repo.dirstate.setbranch(label)
1108 repo.dirstate.setbranch(label)
1109 ui.status(_('marked working directory as branch %s\n') % label)
1109 ui.status(_('marked working directory as branch %s\n') % label)
1110 ui.status(_('(branches are permanent and global, '
1110 ui.status(_('(branches are permanent and global, '
1111 'did you want a bookmark?)\n'))
1111 'did you want a bookmark?)\n'))
1112 finally:
1112 finally:
1113 wlock.release()
1113 wlock.release()
1114
1114
1115 @command('branches',
1115 @command('branches',
1116 [('a', 'active', False,
1116 [('a', 'active', False,
1117 _('show only branches that have unmerged heads (DEPRECATED)')),
1117 _('show only branches that have unmerged heads (DEPRECATED)')),
1118 ('c', 'closed', False, _('show normal and closed branches')),
1118 ('c', 'closed', False, _('show normal and closed branches')),
1119 ] + formatteropts,
1119 ] + formatteropts,
1120 _('[-ac]'))
1120 _('[-ac]'))
1121 def branches(ui, repo, active=False, closed=False, **opts):
1121 def branches(ui, repo, active=False, closed=False, **opts):
1122 """list repository named branches
1122 """list repository named branches
1123
1123
1124 List the repository's named branches, indicating which ones are
1124 List the repository's named branches, indicating which ones are
1125 inactive. If -c/--closed is specified, also list branches which have
1125 inactive. If -c/--closed is specified, also list branches which have
1126 been marked closed (see :hg:`commit --close-branch`).
1126 been marked closed (see :hg:`commit --close-branch`).
1127
1127
1128 Use the command :hg:`update` to switch to an existing branch.
1128 Use the command :hg:`update` to switch to an existing branch.
1129
1129
1130 Returns 0.
1130 Returns 0.
1131 """
1131 """
1132
1132
1133 fm = ui.formatter('branches', opts)
1133 fm = ui.formatter('branches', opts)
1134 hexfunc = fm.hexfunc
1134 hexfunc = fm.hexfunc
1135
1135
1136 allheads = set(repo.heads())
1136 allheads = set(repo.heads())
1137 branches = []
1137 branches = []
1138 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1138 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1139 isactive = not isclosed and bool(set(heads) & allheads)
1139 isactive = not isclosed and bool(set(heads) & allheads)
1140 branches.append((tag, repo[tip], isactive, not isclosed))
1140 branches.append((tag, repo[tip], isactive, not isclosed))
1141 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1141 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1142 reverse=True)
1142 reverse=True)
1143
1143
1144 for tag, ctx, isactive, isopen in branches:
1144 for tag, ctx, isactive, isopen in branches:
1145 if active and not isactive:
1145 if active and not isactive:
1146 continue
1146 continue
1147 if isactive:
1147 if isactive:
1148 label = 'branches.active'
1148 label = 'branches.active'
1149 notice = ''
1149 notice = ''
1150 elif not isopen:
1150 elif not isopen:
1151 if not closed:
1151 if not closed:
1152 continue
1152 continue
1153 label = 'branches.closed'
1153 label = 'branches.closed'
1154 notice = _(' (closed)')
1154 notice = _(' (closed)')
1155 else:
1155 else:
1156 label = 'branches.inactive'
1156 label = 'branches.inactive'
1157 notice = _(' (inactive)')
1157 notice = _(' (inactive)')
1158 current = (tag == repo.dirstate.branch())
1158 current = (tag == repo.dirstate.branch())
1159 if current:
1159 if current:
1160 label = 'branches.current'
1160 label = 'branches.current'
1161
1161
1162 fm.startitem()
1162 fm.startitem()
1163 fm.write('branch', '%s', tag, label=label)
1163 fm.write('branch', '%s', tag, label=label)
1164 rev = ctx.rev()
1164 rev = ctx.rev()
1165 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1165 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1166 fmt = ' ' * padsize + ' %d:%s'
1166 fmt = ' ' * padsize + ' %d:%s'
1167 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1167 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1168 label='log.changeset changeset.%s' % ctx.phasestr())
1168 label='log.changeset changeset.%s' % ctx.phasestr())
1169 fm.data(active=isactive, closed=not isopen, current=current)
1169 fm.data(active=isactive, closed=not isopen, current=current)
1170 if not ui.quiet:
1170 if not ui.quiet:
1171 fm.plain(notice)
1171 fm.plain(notice)
1172 fm.plain('\n')
1172 fm.plain('\n')
1173 fm.end()
1173 fm.end()
1174
1174
1175 @command('bundle',
1175 @command('bundle',
1176 [('f', 'force', None, _('run even when the destination is unrelated')),
1176 [('f', 'force', None, _('run even when the destination is unrelated')),
1177 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1177 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1178 _('REV')),
1178 _('REV')),
1179 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1179 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1180 _('BRANCH')),
1180 _('BRANCH')),
1181 ('', 'base', [],
1181 ('', 'base', [],
1182 _('a base changeset assumed to be available at the destination'),
1182 _('a base changeset assumed to be available at the destination'),
1183 _('REV')),
1183 _('REV')),
1184 ('a', 'all', None, _('bundle all changesets in the repository')),
1184 ('a', 'all', None, _('bundle all changesets in the repository')),
1185 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1185 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1186 ] + remoteopts,
1186 ] + remoteopts,
1187 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1187 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1188 def bundle(ui, repo, fname, dest=None, **opts):
1188 def bundle(ui, repo, fname, dest=None, **opts):
1189 """create a changegroup file
1189 """create a changegroup file
1190
1190
1191 Generate a compressed changegroup file collecting changesets not
1191 Generate a compressed changegroup file collecting changesets not
1192 known to be in another repository.
1192 known to be in another repository.
1193
1193
1194 If you omit the destination repository, then hg assumes the
1194 If you omit the destination repository, then hg assumes the
1195 destination will have all the nodes you specify with --base
1195 destination will have all the nodes you specify with --base
1196 parameters. To create a bundle containing all changesets, use
1196 parameters. To create a bundle containing all changesets, use
1197 -a/--all (or --base null).
1197 -a/--all (or --base null).
1198
1198
1199 You can change compression method with the -t/--type option.
1199 You can change compression method with the -t/--type option.
1200 The available compression methods are: none, bzip2, and
1200 The available compression methods are: none, bzip2, and
1201 gzip (by default, bundles are compressed using bzip2).
1201 gzip (by default, bundles are compressed using bzip2).
1202
1202
1203 The bundle file can then be transferred using conventional means
1203 The bundle file can then be transferred using conventional means
1204 and applied to another repository with the unbundle or pull
1204 and applied to another repository with the unbundle or pull
1205 command. This is useful when direct push and pull are not
1205 command. This is useful when direct push and pull are not
1206 available or when exporting an entire repository is undesirable.
1206 available or when exporting an entire repository is undesirable.
1207
1207
1208 Applying bundles preserves all changeset contents including
1208 Applying bundles preserves all changeset contents including
1209 permissions, copy/rename information, and revision history.
1209 permissions, copy/rename information, and revision history.
1210
1210
1211 Returns 0 on success, 1 if no changes found.
1211 Returns 0 on success, 1 if no changes found.
1212 """
1212 """
1213 revs = None
1213 revs = None
1214 if 'rev' in opts:
1214 if 'rev' in opts:
1215 revs = scmutil.revrange(repo, opts['rev'])
1215 revs = scmutil.revrange(repo, opts['rev'])
1216
1216
1217 bundletype = opts.get('type', 'bzip2').lower()
1217 bundletype = opts.get('type', 'bzip2').lower()
1218 btypes = {'none': 'HG10UN',
1218 btypes = {'none': 'HG10UN',
1219 'bzip2': 'HG10BZ',
1219 'bzip2': 'HG10BZ',
1220 'gzip': 'HG10GZ',
1220 'gzip': 'HG10GZ',
1221 'bundle2': 'HG20'}
1221 'bundle2': 'HG20'}
1222 bundletype = btypes.get(bundletype)
1222 bundletype = btypes.get(bundletype)
1223 if bundletype not in changegroup.bundletypes:
1223 if bundletype not in changegroup.bundletypes:
1224 raise util.Abort(_('unknown bundle type specified with --type'))
1224 raise util.Abort(_('unknown bundle type specified with --type'))
1225
1225
1226 if opts.get('all'):
1226 if opts.get('all'):
1227 base = ['null']
1227 base = ['null']
1228 else:
1228 else:
1229 base = scmutil.revrange(repo, opts.get('base'))
1229 base = scmutil.revrange(repo, opts.get('base'))
1230 # TODO: get desired bundlecaps from command line.
1230 # TODO: get desired bundlecaps from command line.
1231 bundlecaps = None
1231 bundlecaps = None
1232 if base:
1232 if base:
1233 if dest:
1233 if dest:
1234 raise util.Abort(_("--base is incompatible with specifying "
1234 raise util.Abort(_("--base is incompatible with specifying "
1235 "a destination"))
1235 "a destination"))
1236 common = [repo.lookup(rev) for rev in base]
1236 common = [repo.lookup(rev) for rev in base]
1237 heads = revs and map(repo.lookup, revs) or revs
1237 heads = revs and map(repo.lookup, revs) or revs
1238 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1238 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1239 common=common, bundlecaps=bundlecaps)
1239 common=common, bundlecaps=bundlecaps)
1240 outgoing = None
1240 outgoing = None
1241 else:
1241 else:
1242 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1242 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1243 dest, branches = hg.parseurl(dest, opts.get('branch'))
1243 dest, branches = hg.parseurl(dest, opts.get('branch'))
1244 other = hg.peer(repo, opts, dest)
1244 other = hg.peer(repo, opts, dest)
1245 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1245 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1246 heads = revs and map(repo.lookup, revs) or revs
1246 heads = revs and map(repo.lookup, revs) or revs
1247 outgoing = discovery.findcommonoutgoing(repo, other,
1247 outgoing = discovery.findcommonoutgoing(repo, other,
1248 onlyheads=heads,
1248 onlyheads=heads,
1249 force=opts.get('force'),
1249 force=opts.get('force'),
1250 portable=True)
1250 portable=True)
1251 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1251 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1252 bundlecaps)
1252 bundlecaps)
1253 if not cg:
1253 if not cg:
1254 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1254 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1255 return 1
1255 return 1
1256
1256
1257 changegroup.writebundle(ui, cg, fname, bundletype)
1257 changegroup.writebundle(ui, cg, fname, bundletype)
1258
1258
1259 @command('cat',
1259 @command('cat',
1260 [('o', 'output', '',
1260 [('o', 'output', '',
1261 _('print output to file with formatted name'), _('FORMAT')),
1261 _('print output to file with formatted name'), _('FORMAT')),
1262 ('r', 'rev', '', _('print the given revision'), _('REV')),
1262 ('r', 'rev', '', _('print the given revision'), _('REV')),
1263 ('', 'decode', None, _('apply any matching decode filter')),
1263 ('', 'decode', None, _('apply any matching decode filter')),
1264 ] + walkopts,
1264 ] + walkopts,
1265 _('[OPTION]... FILE...'),
1265 _('[OPTION]... FILE...'),
1266 inferrepo=True)
1266 inferrepo=True)
1267 def cat(ui, repo, file1, *pats, **opts):
1267 def cat(ui, repo, file1, *pats, **opts):
1268 """output the current or given revision of files
1268 """output the current or given revision of files
1269
1269
1270 Print the specified files as they were at the given revision. If
1270 Print the specified files as they were at the given revision. If
1271 no revision is given, the parent of the working directory is used.
1271 no revision is given, the parent of the working directory is used.
1272
1272
1273 Output may be to a file, in which case the name of the file is
1273 Output may be to a file, in which case the name of the file is
1274 given using a format string. The formatting rules as follows:
1274 given using a format string. The formatting rules as follows:
1275
1275
1276 :``%%``: literal "%" character
1276 :``%%``: literal "%" character
1277 :``%s``: basename of file being printed
1277 :``%s``: basename of file being printed
1278 :``%d``: dirname of file being printed, or '.' if in repository root
1278 :``%d``: dirname of file being printed, or '.' if in repository root
1279 :``%p``: root-relative path name of file being printed
1279 :``%p``: root-relative path name of file being printed
1280 :``%H``: changeset hash (40 hexadecimal digits)
1280 :``%H``: changeset hash (40 hexadecimal digits)
1281 :``%R``: changeset revision number
1281 :``%R``: changeset revision number
1282 :``%h``: short-form changeset hash (12 hexadecimal digits)
1282 :``%h``: short-form changeset hash (12 hexadecimal digits)
1283 :``%r``: zero-padded changeset revision number
1283 :``%r``: zero-padded changeset revision number
1284 :``%b``: basename of the exporting repository
1284 :``%b``: basename of the exporting repository
1285
1285
1286 Returns 0 on success.
1286 Returns 0 on success.
1287 """
1287 """
1288 ctx = scmutil.revsingle(repo, opts.get('rev'))
1288 ctx = scmutil.revsingle(repo, opts.get('rev'))
1289 m = scmutil.match(ctx, (file1,) + pats, opts)
1289 m = scmutil.match(ctx, (file1,) + pats, opts)
1290
1290
1291 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1291 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1292
1292
1293 @command('^clone',
1293 @command('^clone',
1294 [('U', 'noupdate', None, _('the clone will include an empty working '
1294 [('U', 'noupdate', None, _('the clone will include an empty working '
1295 'directory (only a repository)')),
1295 'directory (only a repository)')),
1296 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1296 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1297 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1297 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1298 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1298 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1299 ('', 'pull', None, _('use pull protocol to copy metadata')),
1299 ('', 'pull', None, _('use pull protocol to copy metadata')),
1300 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1300 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1301 ] + remoteopts,
1301 ] + remoteopts,
1302 _('[OPTION]... SOURCE [DEST]'),
1302 _('[OPTION]... SOURCE [DEST]'),
1303 norepo=True)
1303 norepo=True)
1304 def clone(ui, source, dest=None, **opts):
1304 def clone(ui, source, dest=None, **opts):
1305 """make a copy of an existing repository
1305 """make a copy of an existing repository
1306
1306
1307 Create a copy of an existing repository in a new directory.
1307 Create a copy of an existing repository in a new directory.
1308
1308
1309 If no destination directory name is specified, it defaults to the
1309 If no destination directory name is specified, it defaults to the
1310 basename of the source.
1310 basename of the source.
1311
1311
1312 The location of the source is added to the new repository's
1312 The location of the source is added to the new repository's
1313 ``.hg/hgrc`` file, as the default to be used for future pulls.
1313 ``.hg/hgrc`` file, as the default to be used for future pulls.
1314
1314
1315 Only local paths and ``ssh://`` URLs are supported as
1315 Only local paths and ``ssh://`` URLs are supported as
1316 destinations. For ``ssh://`` destinations, no working directory or
1316 destinations. For ``ssh://`` destinations, no working directory or
1317 ``.hg/hgrc`` will be created on the remote side.
1317 ``.hg/hgrc`` will be created on the remote side.
1318
1318
1319 To pull only a subset of changesets, specify one or more revisions
1319 To pull only a subset of changesets, specify one or more revisions
1320 identifiers with -r/--rev or branches with -b/--branch. The
1320 identifiers with -r/--rev or branches with -b/--branch. The
1321 resulting clone will contain only the specified changesets and
1321 resulting clone will contain only the specified changesets and
1322 their ancestors. These options (or 'clone src#rev dest') imply
1322 their ancestors. These options (or 'clone src#rev dest') imply
1323 --pull, even for local source repositories. Note that specifying a
1323 --pull, even for local source repositories. Note that specifying a
1324 tag will include the tagged changeset but not the changeset
1324 tag will include the tagged changeset but not the changeset
1325 containing the tag.
1325 containing the tag.
1326
1326
1327 If the source repository has a bookmark called '@' set, that
1327 If the source repository has a bookmark called '@' set, that
1328 revision will be checked out in the new repository by default.
1328 revision will be checked out in the new repository by default.
1329
1329
1330 To check out a particular version, use -u/--update, or
1330 To check out a particular version, use -u/--update, or
1331 -U/--noupdate to create a clone with no working directory.
1331 -U/--noupdate to create a clone with no working directory.
1332
1332
1333 .. container:: verbose
1333 .. container:: verbose
1334
1334
1335 For efficiency, hardlinks are used for cloning whenever the
1335 For efficiency, hardlinks are used for cloning whenever the
1336 source and destination are on the same filesystem (note this
1336 source and destination are on the same filesystem (note this
1337 applies only to the repository data, not to the working
1337 applies only to the repository data, not to the working
1338 directory). Some filesystems, such as AFS, implement hardlinking
1338 directory). Some filesystems, such as AFS, implement hardlinking
1339 incorrectly, but do not report errors. In these cases, use the
1339 incorrectly, but do not report errors. In these cases, use the
1340 --pull option to avoid hardlinking.
1340 --pull option to avoid hardlinking.
1341
1341
1342 In some cases, you can clone repositories and the working
1342 In some cases, you can clone repositories and the working
1343 directory using full hardlinks with ::
1343 directory using full hardlinks with ::
1344
1344
1345 $ cp -al REPO REPOCLONE
1345 $ cp -al REPO REPOCLONE
1346
1346
1347 This is the fastest way to clone, but it is not always safe. The
1347 This is the fastest way to clone, but it is not always safe. The
1348 operation is not atomic (making sure REPO is not modified during
1348 operation is not atomic (making sure REPO is not modified during
1349 the operation is up to you) and you have to make sure your
1349 the operation is up to you) and you have to make sure your
1350 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1350 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1351 so). Also, this is not compatible with certain extensions that
1351 so). Also, this is not compatible with certain extensions that
1352 place their metadata under the .hg directory, such as mq.
1352 place their metadata under the .hg directory, such as mq.
1353
1353
1354 Mercurial will update the working directory to the first applicable
1354 Mercurial will update the working directory to the first applicable
1355 revision from this list:
1355 revision from this list:
1356
1356
1357 a) null if -U or the source repository has no changesets
1357 a) null if -U or the source repository has no changesets
1358 b) if -u . and the source repository is local, the first parent of
1358 b) if -u . and the source repository is local, the first parent of
1359 the source repository's working directory
1359 the source repository's working directory
1360 c) the changeset specified with -u (if a branch name, this means the
1360 c) the changeset specified with -u (if a branch name, this means the
1361 latest head of that branch)
1361 latest head of that branch)
1362 d) the changeset specified with -r
1362 d) the changeset specified with -r
1363 e) the tipmost head specified with -b
1363 e) the tipmost head specified with -b
1364 f) the tipmost head specified with the url#branch source syntax
1364 f) the tipmost head specified with the url#branch source syntax
1365 g) the revision marked with the '@' bookmark, if present
1365 g) the revision marked with the '@' bookmark, if present
1366 h) the tipmost head of the default branch
1366 h) the tipmost head of the default branch
1367 i) tip
1367 i) tip
1368
1368
1369 Examples:
1369 Examples:
1370
1370
1371 - clone a remote repository to a new directory named hg/::
1371 - clone a remote repository to a new directory named hg/::
1372
1372
1373 hg clone http://selenic.com/hg
1373 hg clone http://selenic.com/hg
1374
1374
1375 - create a lightweight local clone::
1375 - create a lightweight local clone::
1376
1376
1377 hg clone project/ project-feature/
1377 hg clone project/ project-feature/
1378
1378
1379 - clone from an absolute path on an ssh server (note double-slash)::
1379 - clone from an absolute path on an ssh server (note double-slash)::
1380
1380
1381 hg clone ssh://user@server//home/projects/alpha/
1381 hg clone ssh://user@server//home/projects/alpha/
1382
1382
1383 - do a high-speed clone over a LAN while checking out a
1383 - do a high-speed clone over a LAN while checking out a
1384 specified version::
1384 specified version::
1385
1385
1386 hg clone --uncompressed http://server/repo -u 1.5
1386 hg clone --uncompressed http://server/repo -u 1.5
1387
1387
1388 - create a repository without changesets after a particular revision::
1388 - create a repository without changesets after a particular revision::
1389
1389
1390 hg clone -r 04e544 experimental/ good/
1390 hg clone -r 04e544 experimental/ good/
1391
1391
1392 - clone (and track) a particular named branch::
1392 - clone (and track) a particular named branch::
1393
1393
1394 hg clone http://selenic.com/hg#stable
1394 hg clone http://selenic.com/hg#stable
1395
1395
1396 See :hg:`help urls` for details on specifying URLs.
1396 See :hg:`help urls` for details on specifying URLs.
1397
1397
1398 Returns 0 on success.
1398 Returns 0 on success.
1399 """
1399 """
1400 if opts.get('noupdate') and opts.get('updaterev'):
1400 if opts.get('noupdate') and opts.get('updaterev'):
1401 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1401 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1402
1402
1403 r = hg.clone(ui, opts, source, dest,
1403 r = hg.clone(ui, opts, source, dest,
1404 pull=opts.get('pull'),
1404 pull=opts.get('pull'),
1405 stream=opts.get('uncompressed'),
1405 stream=opts.get('uncompressed'),
1406 rev=opts.get('rev'),
1406 rev=opts.get('rev'),
1407 update=opts.get('updaterev') or not opts.get('noupdate'),
1407 update=opts.get('updaterev') or not opts.get('noupdate'),
1408 branch=opts.get('branch'))
1408 branch=opts.get('branch'))
1409
1409
1410 return r is None
1410 return r is None
1411
1411
1412 @command('^commit|ci',
1412 @command('^commit|ci',
1413 [('A', 'addremove', None,
1413 [('A', 'addremove', None,
1414 _('mark new/missing files as added/removed before committing')),
1414 _('mark new/missing files as added/removed before committing')),
1415 ('', 'close-branch', None,
1415 ('', 'close-branch', None,
1416 _('mark a branch as closed, hiding it from the branch list')),
1416 _('mark a branch as closed, hiding it from the branch list')),
1417 ('', 'amend', None, _('amend the parent of the working directory')),
1417 ('', 'amend', None, _('amend the parent of the working directory')),
1418 ('s', 'secret', None, _('use the secret phase for committing')),
1418 ('s', 'secret', None, _('use the secret phase for committing')),
1419 ('e', 'edit', None, _('invoke editor on commit messages')),
1419 ('e', 'edit', None, _('invoke editor on commit messages')),
1420 ('i', 'interactive', None, _('use interactive mode')),
1420 ('i', 'interactive', None, _('use interactive mode')),
1421 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1421 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1422 _('[OPTION]... [FILE]...'),
1422 _('[OPTION]... [FILE]...'),
1423 inferrepo=True)
1423 inferrepo=True)
1424 def commit(ui, repo, *pats, **opts):
1424 def commit(ui, repo, *pats, **opts):
1425 """commit the specified files or all outstanding changes
1425 """commit the specified files or all outstanding changes
1426
1426
1427 Commit changes to the given files into the repository. Unlike a
1427 Commit changes to the given files into the repository. Unlike a
1428 centralized SCM, this operation is a local operation. See
1428 centralized SCM, this operation is a local operation. See
1429 :hg:`push` for a way to actively distribute your changes.
1429 :hg:`push` for a way to actively distribute your changes.
1430
1430
1431 If a list of files is omitted, all changes reported by :hg:`status`
1431 If a list of files is omitted, all changes reported by :hg:`status`
1432 will be committed.
1432 will be committed.
1433
1433
1434 If you are committing the result of a merge, do not provide any
1434 If you are committing the result of a merge, do not provide any
1435 filenames or -I/-X filters.
1435 filenames or -I/-X filters.
1436
1436
1437 If no commit message is specified, Mercurial starts your
1437 If no commit message is specified, Mercurial starts your
1438 configured editor where you can enter a message. In case your
1438 configured editor where you can enter a message. In case your
1439 commit fails, you will find a backup of your message in
1439 commit fails, you will find a backup of your message in
1440 ``.hg/last-message.txt``.
1440 ``.hg/last-message.txt``.
1441
1441
1442 The --amend flag can be used to amend the parent of the
1442 The --amend flag can be used to amend the parent of the
1443 working directory with a new commit that contains the changes
1443 working directory with a new commit that contains the changes
1444 in the parent in addition to those currently reported by :hg:`status`,
1444 in the parent in addition to those currently reported by :hg:`status`,
1445 if there are any. The old commit is stored in a backup bundle in
1445 if there are any. The old commit is stored in a backup bundle in
1446 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1446 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1447 on how to restore it).
1447 on how to restore it).
1448
1448
1449 Message, user and date are taken from the amended commit unless
1449 Message, user and date are taken from the amended commit unless
1450 specified. When a message isn't specified on the command line,
1450 specified. When a message isn't specified on the command line,
1451 the editor will open with the message of the amended commit.
1451 the editor will open with the message of the amended commit.
1452
1452
1453 It is not possible to amend public changesets (see :hg:`help phases`)
1453 It is not possible to amend public changesets (see :hg:`help phases`)
1454 or changesets that have children.
1454 or changesets that have children.
1455
1455
1456 See :hg:`help dates` for a list of formats valid for -d/--date.
1456 See :hg:`help dates` for a list of formats valid for -d/--date.
1457
1457
1458 Returns 0 on success, 1 if nothing changed.
1458 Returns 0 on success, 1 if nothing changed.
1459 """
1459 """
1460 if opts.get('interactive'):
1460 if opts.get('interactive'):
1461 opts.pop('interactive')
1461 opts.pop('interactive')
1462 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1462 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1463 cmdutil.recordfilter, *pats, **opts)
1463 cmdutil.recordfilter, *pats, **opts)
1464 return
1464 return
1465
1465
1466 if opts.get('subrepos'):
1466 if opts.get('subrepos'):
1467 if opts.get('amend'):
1467 if opts.get('amend'):
1468 raise util.Abort(_('cannot amend with --subrepos'))
1468 raise util.Abort(_('cannot amend with --subrepos'))
1469 # Let --subrepos on the command line override config setting.
1469 # Let --subrepos on the command line override config setting.
1470 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1470 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1471
1471
1472 cmdutil.checkunfinished(repo, commit=True)
1472 cmdutil.checkunfinished(repo, commit=True)
1473
1473
1474 branch = repo[None].branch()
1474 branch = repo[None].branch()
1475 bheads = repo.branchheads(branch)
1475 bheads = repo.branchheads(branch)
1476
1476
1477 extra = {}
1477 extra = {}
1478 if opts.get('close_branch'):
1478 if opts.get('close_branch'):
1479 extra['close'] = 1
1479 extra['close'] = 1
1480
1480
1481 if not bheads:
1481 if not bheads:
1482 raise util.Abort(_('can only close branch heads'))
1482 raise util.Abort(_('can only close branch heads'))
1483 elif opts.get('amend'):
1483 elif opts.get('amend'):
1484 if repo.parents()[0].p1().branch() != branch and \
1484 if repo.parents()[0].p1().branch() != branch and \
1485 repo.parents()[0].p2().branch() != branch:
1485 repo.parents()[0].p2().branch() != branch:
1486 raise util.Abort(_('can only close branch heads'))
1486 raise util.Abort(_('can only close branch heads'))
1487
1487
1488 if opts.get('amend'):
1488 if opts.get('amend'):
1489 if ui.configbool('ui', 'commitsubrepos'):
1489 if ui.configbool('ui', 'commitsubrepos'):
1490 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1490 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1491
1491
1492 old = repo['.']
1492 old = repo['.']
1493 if not old.mutable():
1493 if not old.mutable():
1494 raise util.Abort(_('cannot amend public changesets'))
1494 raise util.Abort(_('cannot amend public changesets'))
1495 if len(repo[None].parents()) > 1:
1495 if len(repo[None].parents()) > 1:
1496 raise util.Abort(_('cannot amend while merging'))
1496 raise util.Abort(_('cannot amend while merging'))
1497 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1497 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1498 if not allowunstable and old.children():
1498 if not allowunstable and old.children():
1499 raise util.Abort(_('cannot amend changeset with children'))
1499 raise util.Abort(_('cannot amend changeset with children'))
1500
1500
1501 # commitfunc is used only for temporary amend commit by cmdutil.amend
1501 # commitfunc is used only for temporary amend commit by cmdutil.amend
1502 def commitfunc(ui, repo, message, match, opts):
1502 def commitfunc(ui, repo, message, match, opts):
1503 return repo.commit(message,
1503 return repo.commit(message,
1504 opts.get('user') or old.user(),
1504 opts.get('user') or old.user(),
1505 opts.get('date') or old.date(),
1505 opts.get('date') or old.date(),
1506 match,
1506 match,
1507 extra=extra)
1507 extra=extra)
1508
1508
1509 current = repo._bookmarkcurrent
1509 current = repo._bookmarkcurrent
1510 marks = old.bookmarks()
1510 marks = old.bookmarks()
1511 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1511 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1512 if node == old.node():
1512 if node == old.node():
1513 ui.status(_("nothing changed\n"))
1513 ui.status(_("nothing changed\n"))
1514 return 1
1514 return 1
1515 elif marks:
1515 elif marks:
1516 ui.debug('moving bookmarks %r from %s to %s\n' %
1516 ui.debug('moving bookmarks %r from %s to %s\n' %
1517 (marks, old.hex(), hex(node)))
1517 (marks, old.hex(), hex(node)))
1518 newmarks = repo._bookmarks
1518 newmarks = repo._bookmarks
1519 for bm in marks:
1519 for bm in marks:
1520 newmarks[bm] = node
1520 newmarks[bm] = node
1521 if bm == current:
1521 if bm == current:
1522 bookmarks.setcurrent(repo, bm)
1522 bookmarks.setcurrent(repo, bm)
1523 newmarks.write()
1523 newmarks.write()
1524 else:
1524 else:
1525 def commitfunc(ui, repo, message, match, opts):
1525 def commitfunc(ui, repo, message, match, opts):
1526 backup = ui.backupconfig('phases', 'new-commit')
1526 backup = ui.backupconfig('phases', 'new-commit')
1527 baseui = repo.baseui
1527 baseui = repo.baseui
1528 basebackup = baseui.backupconfig('phases', 'new-commit')
1528 basebackup = baseui.backupconfig('phases', 'new-commit')
1529 try:
1529 try:
1530 if opts.get('secret'):
1530 if opts.get('secret'):
1531 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1531 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1532 # Propagate to subrepos
1532 # Propagate to subrepos
1533 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1533 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1534
1534
1535 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1535 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1536 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1536 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1537 return repo.commit(message, opts.get('user'), opts.get('date'),
1537 return repo.commit(message, opts.get('user'), opts.get('date'),
1538 match,
1538 match,
1539 editor=editor,
1539 editor=editor,
1540 extra=extra)
1540 extra=extra)
1541 finally:
1541 finally:
1542 ui.restoreconfig(backup)
1542 ui.restoreconfig(backup)
1543 repo.baseui.restoreconfig(basebackup)
1543 repo.baseui.restoreconfig(basebackup)
1544
1544
1545
1545
1546 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1546 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1547
1547
1548 if not node:
1548 if not node:
1549 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1549 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1550 if stat[3]:
1550 if stat[3]:
1551 ui.status(_("nothing changed (%d missing files, see "
1551 ui.status(_("nothing changed (%d missing files, see "
1552 "'hg status')\n") % len(stat[3]))
1552 "'hg status')\n") % len(stat[3]))
1553 else:
1553 else:
1554 ui.status(_("nothing changed\n"))
1554 ui.status(_("nothing changed\n"))
1555 return 1
1555 return 1
1556
1556
1557 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1557 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1558
1558
1559 @command('config|showconfig|debugconfig',
1559 @command('config|showconfig|debugconfig',
1560 [('u', 'untrusted', None, _('show untrusted configuration options')),
1560 [('u', 'untrusted', None, _('show untrusted configuration options')),
1561 ('e', 'edit', None, _('edit user config')),
1561 ('e', 'edit', None, _('edit user config')),
1562 ('l', 'local', None, _('edit repository config')),
1562 ('l', 'local', None, _('edit repository config')),
1563 ('g', 'global', None, _('edit global config'))],
1563 ('g', 'global', None, _('edit global config'))],
1564 _('[-u] [NAME]...'),
1564 _('[-u] [NAME]...'),
1565 optionalrepo=True)
1565 optionalrepo=True)
1566 def config(ui, repo, *values, **opts):
1566 def config(ui, repo, *values, **opts):
1567 """show combined config settings from all hgrc files
1567 """show combined config settings from all hgrc files
1568
1568
1569 With no arguments, print names and values of all config items.
1569 With no arguments, print names and values of all config items.
1570
1570
1571 With one argument of the form section.name, print just the value
1571 With one argument of the form section.name, print just the value
1572 of that config item.
1572 of that config item.
1573
1573
1574 With multiple arguments, print names and values of all config
1574 With multiple arguments, print names and values of all config
1575 items with matching section names.
1575 items with matching section names.
1576
1576
1577 With --edit, start an editor on the user-level config file. With
1577 With --edit, start an editor on the user-level config file. With
1578 --global, edit the system-wide config file. With --local, edit the
1578 --global, edit the system-wide config file. With --local, edit the
1579 repository-level config file.
1579 repository-level config file.
1580
1580
1581 With --debug, the source (filename and line number) is printed
1581 With --debug, the source (filename and line number) is printed
1582 for each config item.
1582 for each config item.
1583
1583
1584 See :hg:`help config` for more information about config files.
1584 See :hg:`help config` for more information about config files.
1585
1585
1586 Returns 0 on success, 1 if NAME does not exist.
1586 Returns 0 on success, 1 if NAME does not exist.
1587
1587
1588 """
1588 """
1589
1589
1590 if opts.get('edit') or opts.get('local') or opts.get('global'):
1590 if opts.get('edit') or opts.get('local') or opts.get('global'):
1591 if opts.get('local') and opts.get('global'):
1591 if opts.get('local') and opts.get('global'):
1592 raise util.Abort(_("can't use --local and --global together"))
1592 raise util.Abort(_("can't use --local and --global together"))
1593
1593
1594 if opts.get('local'):
1594 if opts.get('local'):
1595 if not repo:
1595 if not repo:
1596 raise util.Abort(_("can't use --local outside a repository"))
1596 raise util.Abort(_("can't use --local outside a repository"))
1597 paths = [repo.join('hgrc')]
1597 paths = [repo.join('hgrc')]
1598 elif opts.get('global'):
1598 elif opts.get('global'):
1599 paths = scmutil.systemrcpath()
1599 paths = scmutil.systemrcpath()
1600 else:
1600 else:
1601 paths = scmutil.userrcpath()
1601 paths = scmutil.userrcpath()
1602
1602
1603 for f in paths:
1603 for f in paths:
1604 if os.path.exists(f):
1604 if os.path.exists(f):
1605 break
1605 break
1606 else:
1606 else:
1607 if opts.get('global'):
1607 if opts.get('global'):
1608 samplehgrc = uimod.samplehgrcs['global']
1608 samplehgrc = uimod.samplehgrcs['global']
1609 elif opts.get('local'):
1609 elif opts.get('local'):
1610 samplehgrc = uimod.samplehgrcs['local']
1610 samplehgrc = uimod.samplehgrcs['local']
1611 else:
1611 else:
1612 samplehgrc = uimod.samplehgrcs['user']
1612 samplehgrc = uimod.samplehgrcs['user']
1613
1613
1614 f = paths[0]
1614 f = paths[0]
1615 fp = open(f, "w")
1615 fp = open(f, "w")
1616 fp.write(samplehgrc)
1616 fp.write(samplehgrc)
1617 fp.close()
1617 fp.close()
1618
1618
1619 editor = ui.geteditor()
1619 editor = ui.geteditor()
1620 ui.system("%s \"%s\"" % (editor, f),
1620 ui.system("%s \"%s\"" % (editor, f),
1621 onerr=util.Abort, errprefix=_("edit failed"))
1621 onerr=util.Abort, errprefix=_("edit failed"))
1622 return
1622 return
1623
1623
1624 for f in scmutil.rcpath():
1624 for f in scmutil.rcpath():
1625 ui.debug('read config from: %s\n' % f)
1625 ui.debug('read config from: %s\n' % f)
1626 untrusted = bool(opts.get('untrusted'))
1626 untrusted = bool(opts.get('untrusted'))
1627 if values:
1627 if values:
1628 sections = [v for v in values if '.' not in v]
1628 sections = [v for v in values if '.' not in v]
1629 items = [v for v in values if '.' in v]
1629 items = [v for v in values if '.' in v]
1630 if len(items) > 1 or items and sections:
1630 if len(items) > 1 or items and sections:
1631 raise util.Abort(_('only one config item permitted'))
1631 raise util.Abort(_('only one config item permitted'))
1632 matched = False
1632 matched = False
1633 for section, name, value in ui.walkconfig(untrusted=untrusted):
1633 for section, name, value in ui.walkconfig(untrusted=untrusted):
1634 value = str(value).replace('\n', '\\n')
1634 value = str(value).replace('\n', '\\n')
1635 sectname = section + '.' + name
1635 sectname = section + '.' + name
1636 if values:
1636 if values:
1637 for v in values:
1637 for v in values:
1638 if v == section:
1638 if v == section:
1639 ui.debug('%s: ' %
1639 ui.debug('%s: ' %
1640 ui.configsource(section, name, untrusted))
1640 ui.configsource(section, name, untrusted))
1641 ui.write('%s=%s\n' % (sectname, value))
1641 ui.write('%s=%s\n' % (sectname, value))
1642 matched = True
1642 matched = True
1643 elif v == sectname:
1643 elif v == sectname:
1644 ui.debug('%s: ' %
1644 ui.debug('%s: ' %
1645 ui.configsource(section, name, untrusted))
1645 ui.configsource(section, name, untrusted))
1646 ui.write(value, '\n')
1646 ui.write(value, '\n')
1647 matched = True
1647 matched = True
1648 else:
1648 else:
1649 ui.debug('%s: ' %
1649 ui.debug('%s: ' %
1650 ui.configsource(section, name, untrusted))
1650 ui.configsource(section, name, untrusted))
1651 ui.write('%s=%s\n' % (sectname, value))
1651 ui.write('%s=%s\n' % (sectname, value))
1652 matched = True
1652 matched = True
1653 if matched:
1653 if matched:
1654 return 0
1654 return 0
1655 return 1
1655 return 1
1656
1656
1657 @command('copy|cp',
1657 @command('copy|cp',
1658 [('A', 'after', None, _('record a copy that has already occurred')),
1658 [('A', 'after', None, _('record a copy that has already occurred')),
1659 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1659 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1660 ] + walkopts + dryrunopts,
1660 ] + walkopts + dryrunopts,
1661 _('[OPTION]... [SOURCE]... DEST'))
1661 _('[OPTION]... [SOURCE]... DEST'))
1662 def copy(ui, repo, *pats, **opts):
1662 def copy(ui, repo, *pats, **opts):
1663 """mark files as copied for the next commit
1663 """mark files as copied for the next commit
1664
1664
1665 Mark dest as having copies of source files. If dest is a
1665 Mark dest as having copies of source files. If dest is a
1666 directory, copies are put in that directory. If dest is a file,
1666 directory, copies are put in that directory. If dest is a file,
1667 the source must be a single file.
1667 the source must be a single file.
1668
1668
1669 By default, this command copies the contents of files as they
1669 By default, this command copies the contents of files as they
1670 exist in the working directory. If invoked with -A/--after, the
1670 exist in the working directory. If invoked with -A/--after, the
1671 operation is recorded, but no copying is performed.
1671 operation is recorded, but no copying is performed.
1672
1672
1673 This command takes effect with the next commit. To undo a copy
1673 This command takes effect with the next commit. To undo a copy
1674 before that, see :hg:`revert`.
1674 before that, see :hg:`revert`.
1675
1675
1676 Returns 0 on success, 1 if errors are encountered.
1676 Returns 0 on success, 1 if errors are encountered.
1677 """
1677 """
1678 wlock = repo.wlock(False)
1678 wlock = repo.wlock(False)
1679 try:
1679 try:
1680 return cmdutil.copy(ui, repo, pats, opts)
1680 return cmdutil.copy(ui, repo, pats, opts)
1681 finally:
1681 finally:
1682 wlock.release()
1682 wlock.release()
1683
1683
1684 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1684 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1685 def debugancestor(ui, repo, *args):
1685 def debugancestor(ui, repo, *args):
1686 """find the ancestor revision of two revisions in a given index"""
1686 """find the ancestor revision of two revisions in a given index"""
1687 if len(args) == 3:
1687 if len(args) == 3:
1688 index, rev1, rev2 = args
1688 index, rev1, rev2 = args
1689 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1689 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1690 lookup = r.lookup
1690 lookup = r.lookup
1691 elif len(args) == 2:
1691 elif len(args) == 2:
1692 if not repo:
1692 if not repo:
1693 raise util.Abort(_("there is no Mercurial repository here "
1693 raise util.Abort(_("there is no Mercurial repository here "
1694 "(.hg not found)"))
1694 "(.hg not found)"))
1695 rev1, rev2 = args
1695 rev1, rev2 = args
1696 r = repo.changelog
1696 r = repo.changelog
1697 lookup = repo.lookup
1697 lookup = repo.lookup
1698 else:
1698 else:
1699 raise util.Abort(_('either two or three arguments required'))
1699 raise util.Abort(_('either two or three arguments required'))
1700 a = r.ancestor(lookup(rev1), lookup(rev2))
1700 a = r.ancestor(lookup(rev1), lookup(rev2))
1701 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1701 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1702
1702
1703 @command('debugbuilddag',
1703 @command('debugbuilddag',
1704 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1704 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1705 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1705 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1706 ('n', 'new-file', None, _('add new file at each rev'))],
1706 ('n', 'new-file', None, _('add new file at each rev'))],
1707 _('[OPTION]... [TEXT]'))
1707 _('[OPTION]... [TEXT]'))
1708 def debugbuilddag(ui, repo, text=None,
1708 def debugbuilddag(ui, repo, text=None,
1709 mergeable_file=False,
1709 mergeable_file=False,
1710 overwritten_file=False,
1710 overwritten_file=False,
1711 new_file=False):
1711 new_file=False):
1712 """builds a repo with a given DAG from scratch in the current empty repo
1712 """builds a repo with a given DAG from scratch in the current empty repo
1713
1713
1714 The description of the DAG is read from stdin if not given on the
1714 The description of the DAG is read from stdin if not given on the
1715 command line.
1715 command line.
1716
1716
1717 Elements:
1717 Elements:
1718
1718
1719 - "+n" is a linear run of n nodes based on the current default parent
1719 - "+n" is a linear run of n nodes based on the current default parent
1720 - "." is a single node based on the current default parent
1720 - "." is a single node based on the current default parent
1721 - "$" resets the default parent to null (implied at the start);
1721 - "$" resets the default parent to null (implied at the start);
1722 otherwise the default parent is always the last node created
1722 otherwise the default parent is always the last node created
1723 - "<p" sets the default parent to the backref p
1723 - "<p" sets the default parent to the backref p
1724 - "*p" is a fork at parent p, which is a backref
1724 - "*p" is a fork at parent p, which is a backref
1725 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1725 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1726 - "/p2" is a merge of the preceding node and p2
1726 - "/p2" is a merge of the preceding node and p2
1727 - ":tag" defines a local tag for the preceding node
1727 - ":tag" defines a local tag for the preceding node
1728 - "@branch" sets the named branch for subsequent nodes
1728 - "@branch" sets the named branch for subsequent nodes
1729 - "#...\\n" is a comment up to the end of the line
1729 - "#...\\n" is a comment up to the end of the line
1730
1730
1731 Whitespace between the above elements is ignored.
1731 Whitespace between the above elements is ignored.
1732
1732
1733 A backref is either
1733 A backref is either
1734
1734
1735 - a number n, which references the node curr-n, where curr is the current
1735 - a number n, which references the node curr-n, where curr is the current
1736 node, or
1736 node, or
1737 - the name of a local tag you placed earlier using ":tag", or
1737 - the name of a local tag you placed earlier using ":tag", or
1738 - empty to denote the default parent.
1738 - empty to denote the default parent.
1739
1739
1740 All string valued-elements are either strictly alphanumeric, or must
1740 All string valued-elements are either strictly alphanumeric, or must
1741 be enclosed in double quotes ("..."), with "\\" as escape character.
1741 be enclosed in double quotes ("..."), with "\\" as escape character.
1742 """
1742 """
1743
1743
1744 if text is None:
1744 if text is None:
1745 ui.status(_("reading DAG from stdin\n"))
1745 ui.status(_("reading DAG from stdin\n"))
1746 text = ui.fin.read()
1746 text = ui.fin.read()
1747
1747
1748 cl = repo.changelog
1748 cl = repo.changelog
1749 if len(cl) > 0:
1749 if len(cl) > 0:
1750 raise util.Abort(_('repository is not empty'))
1750 raise util.Abort(_('repository is not empty'))
1751
1751
1752 # determine number of revs in DAG
1752 # determine number of revs in DAG
1753 total = 0
1753 total = 0
1754 for type, data in dagparser.parsedag(text):
1754 for type, data in dagparser.parsedag(text):
1755 if type == 'n':
1755 if type == 'n':
1756 total += 1
1756 total += 1
1757
1757
1758 if mergeable_file:
1758 if mergeable_file:
1759 linesperrev = 2
1759 linesperrev = 2
1760 # make a file with k lines per rev
1760 # make a file with k lines per rev
1761 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1761 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1762 initialmergedlines.append("")
1762 initialmergedlines.append("")
1763
1763
1764 tags = []
1764 tags = []
1765
1765
1766 lock = tr = None
1766 lock = tr = None
1767 try:
1767 try:
1768 lock = repo.lock()
1768 lock = repo.lock()
1769 tr = repo.transaction("builddag")
1769 tr = repo.transaction("builddag")
1770
1770
1771 at = -1
1771 at = -1
1772 atbranch = 'default'
1772 atbranch = 'default'
1773 nodeids = []
1773 nodeids = []
1774 id = 0
1774 id = 0
1775 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1775 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1776 for type, data in dagparser.parsedag(text):
1776 for type, data in dagparser.parsedag(text):
1777 if type == 'n':
1777 if type == 'n':
1778 ui.note(('node %s\n' % str(data)))
1778 ui.note(('node %s\n' % str(data)))
1779 id, ps = data
1779 id, ps = data
1780
1780
1781 files = []
1781 files = []
1782 fctxs = {}
1782 fctxs = {}
1783
1783
1784 p2 = None
1784 p2 = None
1785 if mergeable_file:
1785 if mergeable_file:
1786 fn = "mf"
1786 fn = "mf"
1787 p1 = repo[ps[0]]
1787 p1 = repo[ps[0]]
1788 if len(ps) > 1:
1788 if len(ps) > 1:
1789 p2 = repo[ps[1]]
1789 p2 = repo[ps[1]]
1790 pa = p1.ancestor(p2)
1790 pa = p1.ancestor(p2)
1791 base, local, other = [x[fn].data() for x in (pa, p1,
1791 base, local, other = [x[fn].data() for x in (pa, p1,
1792 p2)]
1792 p2)]
1793 m3 = simplemerge.Merge3Text(base, local, other)
1793 m3 = simplemerge.Merge3Text(base, local, other)
1794 ml = [l.strip() for l in m3.merge_lines()]
1794 ml = [l.strip() for l in m3.merge_lines()]
1795 ml.append("")
1795 ml.append("")
1796 elif at > 0:
1796 elif at > 0:
1797 ml = p1[fn].data().split("\n")
1797 ml = p1[fn].data().split("\n")
1798 else:
1798 else:
1799 ml = initialmergedlines
1799 ml = initialmergedlines
1800 ml[id * linesperrev] += " r%i" % id
1800 ml[id * linesperrev] += " r%i" % id
1801 mergedtext = "\n".join(ml)
1801 mergedtext = "\n".join(ml)
1802 files.append(fn)
1802 files.append(fn)
1803 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1803 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1804
1804
1805 if overwritten_file:
1805 if overwritten_file:
1806 fn = "of"
1806 fn = "of"
1807 files.append(fn)
1807 files.append(fn)
1808 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1808 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1809
1809
1810 if new_file:
1810 if new_file:
1811 fn = "nf%i" % id
1811 fn = "nf%i" % id
1812 files.append(fn)
1812 files.append(fn)
1813 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1813 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1814 if len(ps) > 1:
1814 if len(ps) > 1:
1815 if not p2:
1815 if not p2:
1816 p2 = repo[ps[1]]
1816 p2 = repo[ps[1]]
1817 for fn in p2:
1817 for fn in p2:
1818 if fn.startswith("nf"):
1818 if fn.startswith("nf"):
1819 files.append(fn)
1819 files.append(fn)
1820 fctxs[fn] = p2[fn]
1820 fctxs[fn] = p2[fn]
1821
1821
1822 def fctxfn(repo, cx, path):
1822 def fctxfn(repo, cx, path):
1823 return fctxs.get(path)
1823 return fctxs.get(path)
1824
1824
1825 if len(ps) == 0 or ps[0] < 0:
1825 if len(ps) == 0 or ps[0] < 0:
1826 pars = [None, None]
1826 pars = [None, None]
1827 elif len(ps) == 1:
1827 elif len(ps) == 1:
1828 pars = [nodeids[ps[0]], None]
1828 pars = [nodeids[ps[0]], None]
1829 else:
1829 else:
1830 pars = [nodeids[p] for p in ps]
1830 pars = [nodeids[p] for p in ps]
1831 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1831 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1832 date=(id, 0),
1832 date=(id, 0),
1833 user="debugbuilddag",
1833 user="debugbuilddag",
1834 extra={'branch': atbranch})
1834 extra={'branch': atbranch})
1835 nodeid = repo.commitctx(cx)
1835 nodeid = repo.commitctx(cx)
1836 nodeids.append(nodeid)
1836 nodeids.append(nodeid)
1837 at = id
1837 at = id
1838 elif type == 'l':
1838 elif type == 'l':
1839 id, name = data
1839 id, name = data
1840 ui.note(('tag %s\n' % name))
1840 ui.note(('tag %s\n' % name))
1841 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1841 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1842 elif type == 'a':
1842 elif type == 'a':
1843 ui.note(('branch %s\n' % data))
1843 ui.note(('branch %s\n' % data))
1844 atbranch = data
1844 atbranch = data
1845 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1845 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1846 tr.close()
1846 tr.close()
1847
1847
1848 if tags:
1848 if tags:
1849 repo.vfs.write("localtags", "".join(tags))
1849 repo.vfs.write("localtags", "".join(tags))
1850 finally:
1850 finally:
1851 ui.progress(_('building'), None)
1851 ui.progress(_('building'), None)
1852 release(tr, lock)
1852 release(tr, lock)
1853
1853
1854 @command('debugbundle',
1854 @command('debugbundle',
1855 [('a', 'all', None, _('show all details'))],
1855 [('a', 'all', None, _('show all details'))],
1856 _('FILE'),
1856 _('FILE'),
1857 norepo=True)
1857 norepo=True)
1858 def debugbundle(ui, bundlepath, all=None, **opts):
1858 def debugbundle(ui, bundlepath, all=None, **opts):
1859 """lists the contents of a bundle"""
1859 """lists the contents of a bundle"""
1860 f = hg.openpath(ui, bundlepath)
1860 f = hg.openpath(ui, bundlepath)
1861 try:
1861 try:
1862 gen = exchange.readbundle(ui, f, bundlepath)
1862 gen = exchange.readbundle(ui, f, bundlepath)
1863 if isinstance(gen, bundle2.unbundle20):
1863 if isinstance(gen, bundle2.unbundle20):
1864 return _debugbundle2(ui, gen, all=all, **opts)
1864 return _debugbundle2(ui, gen, all=all, **opts)
1865 if all:
1865 if all:
1866 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1866 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1867
1867
1868 def showchunks(named):
1868 def showchunks(named):
1869 ui.write("\n%s\n" % named)
1869 ui.write("\n%s\n" % named)
1870 chain = None
1870 chain = None
1871 while True:
1871 while True:
1872 chunkdata = gen.deltachunk(chain)
1872 chunkdata = gen.deltachunk(chain)
1873 if not chunkdata:
1873 if not chunkdata:
1874 break
1874 break
1875 node = chunkdata['node']
1875 node = chunkdata['node']
1876 p1 = chunkdata['p1']
1876 p1 = chunkdata['p1']
1877 p2 = chunkdata['p2']
1877 p2 = chunkdata['p2']
1878 cs = chunkdata['cs']
1878 cs = chunkdata['cs']
1879 deltabase = chunkdata['deltabase']
1879 deltabase = chunkdata['deltabase']
1880 delta = chunkdata['delta']
1880 delta = chunkdata['delta']
1881 ui.write("%s %s %s %s %s %s\n" %
1881 ui.write("%s %s %s %s %s %s\n" %
1882 (hex(node), hex(p1), hex(p2),
1882 (hex(node), hex(p1), hex(p2),
1883 hex(cs), hex(deltabase), len(delta)))
1883 hex(cs), hex(deltabase), len(delta)))
1884 chain = node
1884 chain = node
1885
1885
1886 chunkdata = gen.changelogheader()
1886 chunkdata = gen.changelogheader()
1887 showchunks("changelog")
1887 showchunks("changelog")
1888 chunkdata = gen.manifestheader()
1888 chunkdata = gen.manifestheader()
1889 showchunks("manifest")
1889 showchunks("manifest")
1890 while True:
1890 while True:
1891 chunkdata = gen.filelogheader()
1891 chunkdata = gen.filelogheader()
1892 if not chunkdata:
1892 if not chunkdata:
1893 break
1893 break
1894 fname = chunkdata['filename']
1894 fname = chunkdata['filename']
1895 showchunks(fname)
1895 showchunks(fname)
1896 else:
1896 else:
1897 if isinstance(gen, bundle2.unbundle20):
1897 if isinstance(gen, bundle2.unbundle20):
1898 raise util.Abort(_('use debugbundle2 for this file'))
1898 raise util.Abort(_('use debugbundle2 for this file'))
1899 chunkdata = gen.changelogheader()
1899 chunkdata = gen.changelogheader()
1900 chain = None
1900 chain = None
1901 while True:
1901 while True:
1902 chunkdata = gen.deltachunk(chain)
1902 chunkdata = gen.deltachunk(chain)
1903 if not chunkdata:
1903 if not chunkdata:
1904 break
1904 break
1905 node = chunkdata['node']
1905 node = chunkdata['node']
1906 ui.write("%s\n" % hex(node))
1906 ui.write("%s\n" % hex(node))
1907 chain = node
1907 chain = node
1908 finally:
1908 finally:
1909 f.close()
1909 f.close()
1910
1910
1911 def _debugbundle2(ui, gen, **opts):
1911 def _debugbundle2(ui, gen, **opts):
1912 """lists the contents of a bundle2"""
1912 """lists the contents of a bundle2"""
1913 if not isinstance(gen, bundle2.unbundle20):
1913 if not isinstance(gen, bundle2.unbundle20):
1914 raise util.Abort(_('not a bundle2 file'))
1914 raise util.Abort(_('not a bundle2 file'))
1915 ui.write(('Stream params: %s\n' % repr(gen.params)))
1915 ui.write(('Stream params: %s\n' % repr(gen.params)))
1916 for part in gen.iterparts():
1916 for part in gen.iterparts():
1917 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1917 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1918 if part.type == 'changegroup':
1918 if part.type == 'changegroup':
1919 version = part.params.get('version', '01')
1919 version = part.params.get('version', '01')
1920 cg = changegroup.packermap[version][1](part, 'UN')
1920 cg = changegroup.packermap[version][1](part, 'UN')
1921 chunkdata = cg.changelogheader()
1921 chunkdata = cg.changelogheader()
1922 chain = None
1922 chain = None
1923 while True:
1923 while True:
1924 chunkdata = cg.deltachunk(chain)
1924 chunkdata = cg.deltachunk(chain)
1925 if not chunkdata:
1925 if not chunkdata:
1926 break
1926 break
1927 node = chunkdata['node']
1927 node = chunkdata['node']
1928 ui.write(" %s\n" % hex(node))
1928 ui.write(" %s\n" % hex(node))
1929 chain = node
1929 chain = node
1930
1930
1931 @command('debugcheckstate', [], '')
1931 @command('debugcheckstate', [], '')
1932 def debugcheckstate(ui, repo):
1932 def debugcheckstate(ui, repo):
1933 """validate the correctness of the current dirstate"""
1933 """validate the correctness of the current dirstate"""
1934 parent1, parent2 = repo.dirstate.parents()
1934 parent1, parent2 = repo.dirstate.parents()
1935 m1 = repo[parent1].manifest()
1935 m1 = repo[parent1].manifest()
1936 m2 = repo[parent2].manifest()
1936 m2 = repo[parent2].manifest()
1937 errors = 0
1937 errors = 0
1938 for f in repo.dirstate:
1938 for f in repo.dirstate:
1939 state = repo.dirstate[f]
1939 state = repo.dirstate[f]
1940 if state in "nr" and f not in m1:
1940 if state in "nr" and f not in m1:
1941 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1941 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1942 errors += 1
1942 errors += 1
1943 if state in "a" and f in m1:
1943 if state in "a" and f in m1:
1944 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1944 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1945 errors += 1
1945 errors += 1
1946 if state in "m" and f not in m1 and f not in m2:
1946 if state in "m" and f not in m1 and f not in m2:
1947 ui.warn(_("%s in state %s, but not in either manifest\n") %
1947 ui.warn(_("%s in state %s, but not in either manifest\n") %
1948 (f, state))
1948 (f, state))
1949 errors += 1
1949 errors += 1
1950 for f in m1:
1950 for f in m1:
1951 state = repo.dirstate[f]
1951 state = repo.dirstate[f]
1952 if state not in "nrm":
1952 if state not in "nrm":
1953 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1953 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1954 errors += 1
1954 errors += 1
1955 if errors:
1955 if errors:
1956 error = _(".hg/dirstate inconsistent with current parent's manifest")
1956 error = _(".hg/dirstate inconsistent with current parent's manifest")
1957 raise util.Abort(error)
1957 raise util.Abort(error)
1958
1958
1959 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1959 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1960 def debugcommands(ui, cmd='', *args):
1960 def debugcommands(ui, cmd='', *args):
1961 """list all available commands and options"""
1961 """list all available commands and options"""
1962 for cmd, vals in sorted(table.iteritems()):
1962 for cmd, vals in sorted(table.iteritems()):
1963 cmd = cmd.split('|')[0].strip('^')
1963 cmd = cmd.split('|')[0].strip('^')
1964 opts = ', '.join([i[1] for i in vals[1]])
1964 opts = ', '.join([i[1] for i in vals[1]])
1965 ui.write('%s: %s\n' % (cmd, opts))
1965 ui.write('%s: %s\n' % (cmd, opts))
1966
1966
1967 @command('debugcomplete',
1967 @command('debugcomplete',
1968 [('o', 'options', None, _('show the command options'))],
1968 [('o', 'options', None, _('show the command options'))],
1969 _('[-o] CMD'),
1969 _('[-o] CMD'),
1970 norepo=True)
1970 norepo=True)
1971 def debugcomplete(ui, cmd='', **opts):
1971 def debugcomplete(ui, cmd='', **opts):
1972 """returns the completion list associated with the given command"""
1972 """returns the completion list associated with the given command"""
1973
1973
1974 if opts.get('options'):
1974 if opts.get('options'):
1975 options = []
1975 options = []
1976 otables = [globalopts]
1976 otables = [globalopts]
1977 if cmd:
1977 if cmd:
1978 aliases, entry = cmdutil.findcmd(cmd, table, False)
1978 aliases, entry = cmdutil.findcmd(cmd, table, False)
1979 otables.append(entry[1])
1979 otables.append(entry[1])
1980 for t in otables:
1980 for t in otables:
1981 for o in t:
1981 for o in t:
1982 if "(DEPRECATED)" in o[3]:
1982 if "(DEPRECATED)" in o[3]:
1983 continue
1983 continue
1984 if o[0]:
1984 if o[0]:
1985 options.append('-%s' % o[0])
1985 options.append('-%s' % o[0])
1986 options.append('--%s' % o[1])
1986 options.append('--%s' % o[1])
1987 ui.write("%s\n" % "\n".join(options))
1987 ui.write("%s\n" % "\n".join(options))
1988 return
1988 return
1989
1989
1990 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1990 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1991 if ui.verbose:
1991 if ui.verbose:
1992 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1992 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1993 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1993 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1994
1994
1995 @command('debugdag',
1995 @command('debugdag',
1996 [('t', 'tags', None, _('use tags as labels')),
1996 [('t', 'tags', None, _('use tags as labels')),
1997 ('b', 'branches', None, _('annotate with branch names')),
1997 ('b', 'branches', None, _('annotate with branch names')),
1998 ('', 'dots', None, _('use dots for runs')),
1998 ('', 'dots', None, _('use dots for runs')),
1999 ('s', 'spaces', None, _('separate elements by spaces'))],
1999 ('s', 'spaces', None, _('separate elements by spaces'))],
2000 _('[OPTION]... [FILE [REV]...]'),
2000 _('[OPTION]... [FILE [REV]...]'),
2001 optionalrepo=True)
2001 optionalrepo=True)
2002 def debugdag(ui, repo, file_=None, *revs, **opts):
2002 def debugdag(ui, repo, file_=None, *revs, **opts):
2003 """format the changelog or an index DAG as a concise textual description
2003 """format the changelog or an index DAG as a concise textual description
2004
2004
2005 If you pass a revlog index, the revlog's DAG is emitted. If you list
2005 If you pass a revlog index, the revlog's DAG is emitted. If you list
2006 revision numbers, they get labeled in the output as rN.
2006 revision numbers, they get labeled in the output as rN.
2007
2007
2008 Otherwise, the changelog DAG of the current repo is emitted.
2008 Otherwise, the changelog DAG of the current repo is emitted.
2009 """
2009 """
2010 spaces = opts.get('spaces')
2010 spaces = opts.get('spaces')
2011 dots = opts.get('dots')
2011 dots = opts.get('dots')
2012 if file_:
2012 if file_:
2013 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2013 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2014 revs = set((int(r) for r in revs))
2014 revs = set((int(r) for r in revs))
2015 def events():
2015 def events():
2016 for r in rlog:
2016 for r in rlog:
2017 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2017 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2018 if p != -1))
2018 if p != -1))
2019 if r in revs:
2019 if r in revs:
2020 yield 'l', (r, "r%i" % r)
2020 yield 'l', (r, "r%i" % r)
2021 elif repo:
2021 elif repo:
2022 cl = repo.changelog
2022 cl = repo.changelog
2023 tags = opts.get('tags')
2023 tags = opts.get('tags')
2024 branches = opts.get('branches')
2024 branches = opts.get('branches')
2025 if tags:
2025 if tags:
2026 labels = {}
2026 labels = {}
2027 for l, n in repo.tags().items():
2027 for l, n in repo.tags().items():
2028 labels.setdefault(cl.rev(n), []).append(l)
2028 labels.setdefault(cl.rev(n), []).append(l)
2029 def events():
2029 def events():
2030 b = "default"
2030 b = "default"
2031 for r in cl:
2031 for r in cl:
2032 if branches:
2032 if branches:
2033 newb = cl.read(cl.node(r))[5]['branch']
2033 newb = cl.read(cl.node(r))[5]['branch']
2034 if newb != b:
2034 if newb != b:
2035 yield 'a', newb
2035 yield 'a', newb
2036 b = newb
2036 b = newb
2037 yield 'n', (r, list(p for p in cl.parentrevs(r)
2037 yield 'n', (r, list(p for p in cl.parentrevs(r)
2038 if p != -1))
2038 if p != -1))
2039 if tags:
2039 if tags:
2040 ls = labels.get(r)
2040 ls = labels.get(r)
2041 if ls:
2041 if ls:
2042 for l in ls:
2042 for l in ls:
2043 yield 'l', (r, l)
2043 yield 'l', (r, l)
2044 else:
2044 else:
2045 raise util.Abort(_('need repo for changelog dag'))
2045 raise util.Abort(_('need repo for changelog dag'))
2046
2046
2047 for line in dagparser.dagtextlines(events(),
2047 for line in dagparser.dagtextlines(events(),
2048 addspaces=spaces,
2048 addspaces=spaces,
2049 wraplabels=True,
2049 wraplabels=True,
2050 wrapannotations=True,
2050 wrapannotations=True,
2051 wrapnonlinear=dots,
2051 wrapnonlinear=dots,
2052 usedots=dots,
2052 usedots=dots,
2053 maxlinewidth=70):
2053 maxlinewidth=70):
2054 ui.write(line)
2054 ui.write(line)
2055 ui.write("\n")
2055 ui.write("\n")
2056
2056
2057 @command('debugdata',
2057 @command('debugdata',
2058 [('c', 'changelog', False, _('open changelog')),
2058 [('c', 'changelog', False, _('open changelog')),
2059 ('m', 'manifest', False, _('open manifest'))],
2059 ('m', 'manifest', False, _('open manifest'))],
2060 _('-c|-m|FILE REV'))
2060 _('-c|-m|FILE REV'))
2061 def debugdata(ui, repo, file_, rev=None, **opts):
2061 def debugdata(ui, repo, file_, rev=None, **opts):
2062 """dump the contents of a data file revision"""
2062 """dump the contents of a data file revision"""
2063 if opts.get('changelog') or opts.get('manifest'):
2063 if opts.get('changelog') or opts.get('manifest'):
2064 file_, rev = None, file_
2064 file_, rev = None, file_
2065 elif rev is None:
2065 elif rev is None:
2066 raise error.CommandError('debugdata', _('invalid arguments'))
2066 raise error.CommandError('debugdata', _('invalid arguments'))
2067 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2067 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2068 try:
2068 try:
2069 ui.write(r.revision(r.lookup(rev)))
2069 ui.write(r.revision(r.lookup(rev)))
2070 except KeyError:
2070 except KeyError:
2071 raise util.Abort(_('invalid revision identifier %s') % rev)
2071 raise util.Abort(_('invalid revision identifier %s') % rev)
2072
2072
2073 @command('debugdate',
2073 @command('debugdate',
2074 [('e', 'extended', None, _('try extended date formats'))],
2074 [('e', 'extended', None, _('try extended date formats'))],
2075 _('[-e] DATE [RANGE]'),
2075 _('[-e] DATE [RANGE]'),
2076 norepo=True, optionalrepo=True)
2076 norepo=True, optionalrepo=True)
2077 def debugdate(ui, date, range=None, **opts):
2077 def debugdate(ui, date, range=None, **opts):
2078 """parse and display a date"""
2078 """parse and display a date"""
2079 if opts["extended"]:
2079 if opts["extended"]:
2080 d = util.parsedate(date, util.extendeddateformats)
2080 d = util.parsedate(date, util.extendeddateformats)
2081 else:
2081 else:
2082 d = util.parsedate(date)
2082 d = util.parsedate(date)
2083 ui.write(("internal: %s %s\n") % d)
2083 ui.write(("internal: %s %s\n") % d)
2084 ui.write(("standard: %s\n") % util.datestr(d))
2084 ui.write(("standard: %s\n") % util.datestr(d))
2085 if range:
2085 if range:
2086 m = util.matchdate(range)
2086 m = util.matchdate(range)
2087 ui.write(("match: %s\n") % m(d[0]))
2087 ui.write(("match: %s\n") % m(d[0]))
2088
2088
2089 @command('debugdiscovery',
2089 @command('debugdiscovery',
2090 [('', 'old', None, _('use old-style discovery')),
2090 [('', 'old', None, _('use old-style discovery')),
2091 ('', 'nonheads', None,
2091 ('', 'nonheads', None,
2092 _('use old-style discovery with non-heads included')),
2092 _('use old-style discovery with non-heads included')),
2093 ] + remoteopts,
2093 ] + remoteopts,
2094 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2094 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2095 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2095 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2096 """runs the changeset discovery protocol in isolation"""
2096 """runs the changeset discovery protocol in isolation"""
2097 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2097 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2098 opts.get('branch'))
2098 opts.get('branch'))
2099 remote = hg.peer(repo, opts, remoteurl)
2099 remote = hg.peer(repo, opts, remoteurl)
2100 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2100 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2101
2101
2102 # make sure tests are repeatable
2102 # make sure tests are repeatable
2103 random.seed(12323)
2103 random.seed(12323)
2104
2104
2105 def doit(localheads, remoteheads, remote=remote):
2105 def doit(localheads, remoteheads, remote=remote):
2106 if opts.get('old'):
2106 if opts.get('old'):
2107 if localheads:
2107 if localheads:
2108 raise util.Abort('cannot use localheads with old style '
2108 raise util.Abort('cannot use localheads with old style '
2109 'discovery')
2109 'discovery')
2110 if not util.safehasattr(remote, 'branches'):
2110 if not util.safehasattr(remote, 'branches'):
2111 # enable in-client legacy support
2111 # enable in-client legacy support
2112 remote = localrepo.locallegacypeer(remote.local())
2112 remote = localrepo.locallegacypeer(remote.local())
2113 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2113 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2114 force=True)
2114 force=True)
2115 common = set(common)
2115 common = set(common)
2116 if not opts.get('nonheads'):
2116 if not opts.get('nonheads'):
2117 ui.write(("unpruned common: %s\n") %
2117 ui.write(("unpruned common: %s\n") %
2118 " ".join(sorted(short(n) for n in common)))
2118 " ".join(sorted(short(n) for n in common)))
2119 dag = dagutil.revlogdag(repo.changelog)
2119 dag = dagutil.revlogdag(repo.changelog)
2120 all = dag.ancestorset(dag.internalizeall(common))
2120 all = dag.ancestorset(dag.internalizeall(common))
2121 common = dag.externalizeall(dag.headsetofconnecteds(all))
2121 common = dag.externalizeall(dag.headsetofconnecteds(all))
2122 else:
2122 else:
2123 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2123 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2124 common = set(common)
2124 common = set(common)
2125 rheads = set(hds)
2125 rheads = set(hds)
2126 lheads = set(repo.heads())
2126 lheads = set(repo.heads())
2127 ui.write(("common heads: %s\n") %
2127 ui.write(("common heads: %s\n") %
2128 " ".join(sorted(short(n) for n in common)))
2128 " ".join(sorted(short(n) for n in common)))
2129 if lheads <= common:
2129 if lheads <= common:
2130 ui.write(("local is subset\n"))
2130 ui.write(("local is subset\n"))
2131 elif rheads <= common:
2131 elif rheads <= common:
2132 ui.write(("remote is subset\n"))
2132 ui.write(("remote is subset\n"))
2133
2133
2134 serverlogs = opts.get('serverlog')
2134 serverlogs = opts.get('serverlog')
2135 if serverlogs:
2135 if serverlogs:
2136 for filename in serverlogs:
2136 for filename in serverlogs:
2137 logfile = open(filename, 'r')
2137 logfile = open(filename, 'r')
2138 try:
2138 try:
2139 line = logfile.readline()
2139 line = logfile.readline()
2140 while line:
2140 while line:
2141 parts = line.strip().split(';')
2141 parts = line.strip().split(';')
2142 op = parts[1]
2142 op = parts[1]
2143 if op == 'cg':
2143 if op == 'cg':
2144 pass
2144 pass
2145 elif op == 'cgss':
2145 elif op == 'cgss':
2146 doit(parts[2].split(' '), parts[3].split(' '))
2146 doit(parts[2].split(' '), parts[3].split(' '))
2147 elif op == 'unb':
2147 elif op == 'unb':
2148 doit(parts[3].split(' '), parts[2].split(' '))
2148 doit(parts[3].split(' '), parts[2].split(' '))
2149 line = logfile.readline()
2149 line = logfile.readline()
2150 finally:
2150 finally:
2151 logfile.close()
2151 logfile.close()
2152
2152
2153 else:
2153 else:
2154 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2154 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2155 opts.get('remote_head'))
2155 opts.get('remote_head'))
2156 localrevs = opts.get('local_head')
2156 localrevs = opts.get('local_head')
2157 doit(localrevs, remoterevs)
2157 doit(localrevs, remoterevs)
2158
2158
2159 @command('debugfileset',
2159 @command('debugfileset',
2160 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2160 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2161 _('[-r REV] FILESPEC'))
2161 _('[-r REV] FILESPEC'))
2162 def debugfileset(ui, repo, expr, **opts):
2162 def debugfileset(ui, repo, expr, **opts):
2163 '''parse and apply a fileset specification'''
2163 '''parse and apply a fileset specification'''
2164 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2164 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2165 if ui.verbose:
2165 if ui.verbose:
2166 tree = fileset.parse(expr)[0]
2166 tree = fileset.parse(expr)[0]
2167 ui.note(tree, "\n")
2167 ui.note(tree, "\n")
2168
2168
2169 for f in ctx.getfileset(expr):
2169 for f in ctx.getfileset(expr):
2170 ui.write("%s\n" % f)
2170 ui.write("%s\n" % f)
2171
2171
2172 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2172 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2173 def debugfsinfo(ui, path="."):
2173 def debugfsinfo(ui, path="."):
2174 """show information detected about current filesystem"""
2174 """show information detected about current filesystem"""
2175 util.writefile('.debugfsinfo', '')
2175 util.writefile('.debugfsinfo', '')
2176 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2176 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2177 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2177 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2178 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2178 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2179 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2179 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2180 and 'yes' or 'no'))
2180 and 'yes' or 'no'))
2181 os.unlink('.debugfsinfo')
2181 os.unlink('.debugfsinfo')
2182
2182
2183 @command('debuggetbundle',
2183 @command('debuggetbundle',
2184 [('H', 'head', [], _('id of head node'), _('ID')),
2184 [('H', 'head', [], _('id of head node'), _('ID')),
2185 ('C', 'common', [], _('id of common node'), _('ID')),
2185 ('C', 'common', [], _('id of common node'), _('ID')),
2186 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2186 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2187 _('REPO FILE [-H|-C ID]...'),
2187 _('REPO FILE [-H|-C ID]...'),
2188 norepo=True)
2188 norepo=True)
2189 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2189 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2190 """retrieves a bundle from a repo
2190 """retrieves a bundle from a repo
2191
2191
2192 Every ID must be a full-length hex node id string. Saves the bundle to the
2192 Every ID must be a full-length hex node id string. Saves the bundle to the
2193 given file.
2193 given file.
2194 """
2194 """
2195 repo = hg.peer(ui, opts, repopath)
2195 repo = hg.peer(ui, opts, repopath)
2196 if not repo.capable('getbundle'):
2196 if not repo.capable('getbundle'):
2197 raise util.Abort("getbundle() not supported by target repository")
2197 raise util.Abort("getbundle() not supported by target repository")
2198 args = {}
2198 args = {}
2199 if common:
2199 if common:
2200 args['common'] = [bin(s) for s in common]
2200 args['common'] = [bin(s) for s in common]
2201 if head:
2201 if head:
2202 args['heads'] = [bin(s) for s in head]
2202 args['heads'] = [bin(s) for s in head]
2203 # TODO: get desired bundlecaps from command line.
2203 # TODO: get desired bundlecaps from command line.
2204 args['bundlecaps'] = None
2204 args['bundlecaps'] = None
2205 bundle = repo.getbundle('debug', **args)
2205 bundle = repo.getbundle('debug', **args)
2206
2206
2207 bundletype = opts.get('type', 'bzip2').lower()
2207 bundletype = opts.get('type', 'bzip2').lower()
2208 btypes = {'none': 'HG10UN',
2208 btypes = {'none': 'HG10UN',
2209 'bzip2': 'HG10BZ',
2209 'bzip2': 'HG10BZ',
2210 'gzip': 'HG10GZ',
2210 'gzip': 'HG10GZ',
2211 'bundle2': 'HG20'}
2211 'bundle2': 'HG20'}
2212 bundletype = btypes.get(bundletype)
2212 bundletype = btypes.get(bundletype)
2213 if bundletype not in changegroup.bundletypes:
2213 if bundletype not in changegroup.bundletypes:
2214 raise util.Abort(_('unknown bundle type specified with --type'))
2214 raise util.Abort(_('unknown bundle type specified with --type'))
2215 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2215 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2216
2216
2217 @command('debugignore', [], '')
2217 @command('debugignore', [], '')
2218 def debugignore(ui, repo, *values, **opts):
2218 def debugignore(ui, repo, *values, **opts):
2219 """display the combined ignore pattern"""
2219 """display the combined ignore pattern"""
2220 ignore = repo.dirstate._ignore
2220 ignore = repo.dirstate._ignore
2221 includepat = getattr(ignore, 'includepat', None)
2221 includepat = getattr(ignore, 'includepat', None)
2222 if includepat is not None:
2222 if includepat is not None:
2223 ui.write("%s\n" % includepat)
2223 ui.write("%s\n" % includepat)
2224 else:
2224 else:
2225 raise util.Abort(_("no ignore patterns found"))
2225 raise util.Abort(_("no ignore patterns found"))
2226
2226
2227 @command('debugindex',
2227 @command('debugindex',
2228 [('c', 'changelog', False, _('open changelog')),
2228 [('c', 'changelog', False, _('open changelog')),
2229 ('m', 'manifest', False, _('open manifest')),
2229 ('m', 'manifest', False, _('open manifest')),
2230 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2230 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2231 _('[-f FORMAT] -c|-m|FILE'),
2231 _('[-f FORMAT] -c|-m|FILE'),
2232 optionalrepo=True)
2232 optionalrepo=True)
2233 def debugindex(ui, repo, file_=None, **opts):
2233 def debugindex(ui, repo, file_=None, **opts):
2234 """dump the contents of an index file"""
2234 """dump the contents of an index file"""
2235 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2235 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2236 format = opts.get('format', 0)
2236 format = opts.get('format', 0)
2237 if format not in (0, 1):
2237 if format not in (0, 1):
2238 raise util.Abort(_("unknown format %d") % format)
2238 raise util.Abort(_("unknown format %d") % format)
2239
2239
2240 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2240 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2241 if generaldelta:
2241 if generaldelta:
2242 basehdr = ' delta'
2242 basehdr = ' delta'
2243 else:
2243 else:
2244 basehdr = ' base'
2244 basehdr = ' base'
2245
2245
2246 if ui.debugflag:
2246 if ui.debugflag:
2247 shortfn = hex
2247 shortfn = hex
2248 else:
2248 else:
2249 shortfn = short
2249 shortfn = short
2250
2250
2251 # There might not be anything in r, so have a sane default
2251 # There might not be anything in r, so have a sane default
2252 idlen = 12
2252 idlen = 12
2253 for i in r:
2253 for i in r:
2254 idlen = len(shortfn(r.node(i)))
2254 idlen = len(shortfn(r.node(i)))
2255 break
2255 break
2256
2256
2257 if format == 0:
2257 if format == 0:
2258 ui.write(" rev offset length " + basehdr + " linkrev"
2258 ui.write(" rev offset length " + basehdr + " linkrev"
2259 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2259 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2260 elif format == 1:
2260 elif format == 1:
2261 ui.write(" rev flag offset length"
2261 ui.write(" rev flag offset length"
2262 " size " + basehdr + " link p1 p2"
2262 " size " + basehdr + " link p1 p2"
2263 " %s\n" % "nodeid".rjust(idlen))
2263 " %s\n" % "nodeid".rjust(idlen))
2264
2264
2265 for i in r:
2265 for i in r:
2266 node = r.node(i)
2266 node = r.node(i)
2267 if generaldelta:
2267 if generaldelta:
2268 base = r.deltaparent(i)
2268 base = r.deltaparent(i)
2269 else:
2269 else:
2270 base = r.chainbase(i)
2270 base = r.chainbase(i)
2271 if format == 0:
2271 if format == 0:
2272 try:
2272 try:
2273 pp = r.parents(node)
2273 pp = r.parents(node)
2274 except Exception:
2274 except Exception:
2275 pp = [nullid, nullid]
2275 pp = [nullid, nullid]
2276 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2276 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2277 i, r.start(i), r.length(i), base, r.linkrev(i),
2277 i, r.start(i), r.length(i), base, r.linkrev(i),
2278 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2278 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2279 elif format == 1:
2279 elif format == 1:
2280 pr = r.parentrevs(i)
2280 pr = r.parentrevs(i)
2281 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2281 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2282 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2282 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2283 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2283 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2284
2284
2285 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2285 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2286 def debugindexdot(ui, repo, file_):
2286 def debugindexdot(ui, repo, file_):
2287 """dump an index DAG as a graphviz dot file"""
2287 """dump an index DAG as a graphviz dot file"""
2288 r = None
2288 r = None
2289 if repo:
2289 if repo:
2290 filelog = repo.file(file_)
2290 filelog = repo.file(file_)
2291 if len(filelog):
2291 if len(filelog):
2292 r = filelog
2292 r = filelog
2293 if not r:
2293 if not r:
2294 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2294 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2295 ui.write(("digraph G {\n"))
2295 ui.write(("digraph G {\n"))
2296 for i in r:
2296 for i in r:
2297 node = r.node(i)
2297 node = r.node(i)
2298 pp = r.parents(node)
2298 pp = r.parents(node)
2299 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2299 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2300 if pp[1] != nullid:
2300 if pp[1] != nullid:
2301 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2301 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2302 ui.write("}\n")
2302 ui.write("}\n")
2303
2303
2304 @command('debuginstall', [], '', norepo=True)
2304 @command('debuginstall', [], '', norepo=True)
2305 def debuginstall(ui):
2305 def debuginstall(ui):
2306 '''test Mercurial installation
2306 '''test Mercurial installation
2307
2307
2308 Returns 0 on success.
2308 Returns 0 on success.
2309 '''
2309 '''
2310
2310
2311 def writetemp(contents):
2311 def writetemp(contents):
2312 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2312 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2313 f = os.fdopen(fd, "wb")
2313 f = os.fdopen(fd, "wb")
2314 f.write(contents)
2314 f.write(contents)
2315 f.close()
2315 f.close()
2316 return name
2316 return name
2317
2317
2318 problems = 0
2318 problems = 0
2319
2319
2320 # encoding
2320 # encoding
2321 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2321 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2322 try:
2322 try:
2323 encoding.fromlocal("test")
2323 encoding.fromlocal("test")
2324 except util.Abort, inst:
2324 except util.Abort, inst:
2325 ui.write(" %s\n" % inst)
2325 ui.write(" %s\n" % inst)
2326 ui.write(_(" (check that your locale is properly set)\n"))
2326 ui.write(_(" (check that your locale is properly set)\n"))
2327 problems += 1
2327 problems += 1
2328
2328
2329 # Python
2329 # Python
2330 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2330 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2331 ui.status(_("checking Python version (%s)\n")
2331 ui.status(_("checking Python version (%s)\n")
2332 % ("%s.%s.%s" % sys.version_info[:3]))
2332 % ("%s.%s.%s" % sys.version_info[:3]))
2333 ui.status(_("checking Python lib (%s)...\n")
2333 ui.status(_("checking Python lib (%s)...\n")
2334 % os.path.dirname(os.__file__))
2334 % os.path.dirname(os.__file__))
2335
2335
2336 # compiled modules
2336 # compiled modules
2337 ui.status(_("checking installed modules (%s)...\n")
2337 ui.status(_("checking installed modules (%s)...\n")
2338 % os.path.dirname(__file__))
2338 % os.path.dirname(__file__))
2339 try:
2339 try:
2340 import bdiff, mpatch, base85, osutil
2340 import bdiff, mpatch, base85, osutil
2341 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2341 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2342 except Exception, inst:
2342 except Exception, inst:
2343 ui.write(" %s\n" % inst)
2343 ui.write(" %s\n" % inst)
2344 ui.write(_(" One or more extensions could not be found"))
2344 ui.write(_(" One or more extensions could not be found"))
2345 ui.write(_(" (check that you compiled the extensions)\n"))
2345 ui.write(_(" (check that you compiled the extensions)\n"))
2346 problems += 1
2346 problems += 1
2347
2347
2348 # templates
2348 # templates
2349 import templater
2349 import templater
2350 p = templater.templatepaths()
2350 p = templater.templatepaths()
2351 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2351 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2352 if p:
2352 if p:
2353 m = templater.templatepath("map-cmdline.default")
2353 m = templater.templatepath("map-cmdline.default")
2354 if m:
2354 if m:
2355 # template found, check if it is working
2355 # template found, check if it is working
2356 try:
2356 try:
2357 templater.templater(m)
2357 templater.templater(m)
2358 except Exception, inst:
2358 except Exception, inst:
2359 ui.write(" %s\n" % inst)
2359 ui.write(" %s\n" % inst)
2360 p = None
2360 p = None
2361 else:
2361 else:
2362 ui.write(_(" template 'default' not found\n"))
2362 ui.write(_(" template 'default' not found\n"))
2363 p = None
2363 p = None
2364 else:
2364 else:
2365 ui.write(_(" no template directories found\n"))
2365 ui.write(_(" no template directories found\n"))
2366 if not p:
2366 if not p:
2367 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2367 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2368 problems += 1
2368 problems += 1
2369
2369
2370 # editor
2370 # editor
2371 ui.status(_("checking commit editor...\n"))
2371 ui.status(_("checking commit editor...\n"))
2372 editor = ui.geteditor()
2372 editor = ui.geteditor()
2373 cmdpath = util.findexe(shlex.split(editor)[0])
2373 cmdpath = util.findexe(shlex.split(editor)[0])
2374 if not cmdpath:
2374 if not cmdpath:
2375 if editor == 'vi':
2375 if editor == 'vi':
2376 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2376 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2377 ui.write(_(" (specify a commit editor in your configuration"
2377 ui.write(_(" (specify a commit editor in your configuration"
2378 " file)\n"))
2378 " file)\n"))
2379 else:
2379 else:
2380 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2380 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2381 ui.write(_(" (specify a commit editor in your configuration"
2381 ui.write(_(" (specify a commit editor in your configuration"
2382 " file)\n"))
2382 " file)\n"))
2383 problems += 1
2383 problems += 1
2384
2384
2385 # check username
2385 # check username
2386 ui.status(_("checking username...\n"))
2386 ui.status(_("checking username...\n"))
2387 try:
2387 try:
2388 ui.username()
2388 ui.username()
2389 except util.Abort, e:
2389 except util.Abort, e:
2390 ui.write(" %s\n" % e)
2390 ui.write(" %s\n" % e)
2391 ui.write(_(" (specify a username in your configuration file)\n"))
2391 ui.write(_(" (specify a username in your configuration file)\n"))
2392 problems += 1
2392 problems += 1
2393
2393
2394 if not problems:
2394 if not problems:
2395 ui.status(_("no problems detected\n"))
2395 ui.status(_("no problems detected\n"))
2396 else:
2396 else:
2397 ui.write(_("%s problems detected,"
2397 ui.write(_("%s problems detected,"
2398 " please check your install!\n") % problems)
2398 " please check your install!\n") % problems)
2399
2399
2400 return problems
2400 return problems
2401
2401
2402 @command('debugknown', [], _('REPO ID...'), norepo=True)
2402 @command('debugknown', [], _('REPO ID...'), norepo=True)
2403 def debugknown(ui, repopath, *ids, **opts):
2403 def debugknown(ui, repopath, *ids, **opts):
2404 """test whether node ids are known to a repo
2404 """test whether node ids are known to a repo
2405
2405
2406 Every ID must be a full-length hex node id string. Returns a list of 0s
2406 Every ID must be a full-length hex node id string. Returns a list of 0s
2407 and 1s indicating unknown/known.
2407 and 1s indicating unknown/known.
2408 """
2408 """
2409 repo = hg.peer(ui, opts, repopath)
2409 repo = hg.peer(ui, opts, repopath)
2410 if not repo.capable('known'):
2410 if not repo.capable('known'):
2411 raise util.Abort("known() not supported by target repository")
2411 raise util.Abort("known() not supported by target repository")
2412 flags = repo.known([bin(s) for s in ids])
2412 flags = repo.known([bin(s) for s in ids])
2413 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2413 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2414
2414
2415 @command('debuglabelcomplete', [], _('LABEL...'))
2415 @command('debuglabelcomplete', [], _('LABEL...'))
2416 def debuglabelcomplete(ui, repo, *args):
2416 def debuglabelcomplete(ui, repo, *args):
2417 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2417 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2418 debugnamecomplete(ui, repo, *args)
2418 debugnamecomplete(ui, repo, *args)
2419
2419
2420 @command('debugnamecomplete', [], _('NAME...'))
2420 @command('debugnamecomplete', [], _('NAME...'))
2421 def debugnamecomplete(ui, repo, *args):
2421 def debugnamecomplete(ui, repo, *args):
2422 '''complete "names" - tags, open branch names, bookmark names'''
2422 '''complete "names" - tags, open branch names, bookmark names'''
2423
2423
2424 names = set()
2424 names = set()
2425 # since we previously only listed open branches, we will handle that
2425 # since we previously only listed open branches, we will handle that
2426 # specially (after this for loop)
2426 # specially (after this for loop)
2427 for name, ns in repo.names.iteritems():
2427 for name, ns in repo.names.iteritems():
2428 if name != 'branches':
2428 if name != 'branches':
2429 names.update(ns.listnames(repo))
2429 names.update(ns.listnames(repo))
2430 names.update(tag for (tag, heads, tip, closed)
2430 names.update(tag for (tag, heads, tip, closed)
2431 in repo.branchmap().iterbranches() if not closed)
2431 in repo.branchmap().iterbranches() if not closed)
2432 completions = set()
2432 completions = set()
2433 if not args:
2433 if not args:
2434 args = ['']
2434 args = ['']
2435 for a in args:
2435 for a in args:
2436 completions.update(n for n in names if n.startswith(a))
2436 completions.update(n for n in names if n.startswith(a))
2437 ui.write('\n'.join(sorted(completions)))
2437 ui.write('\n'.join(sorted(completions)))
2438 ui.write('\n')
2438 ui.write('\n')
2439
2439
2440 @command('debuglocks',
2440 @command('debuglocks',
2441 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2441 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2442 ('W', 'force-wlock', None,
2442 ('W', 'force-wlock', None,
2443 _('free the working state lock (DANGEROUS)'))],
2443 _('free the working state lock (DANGEROUS)'))],
2444 _('[OPTION]...'))
2444 _('[OPTION]...'))
2445 def debuglocks(ui, repo, **opts):
2445 def debuglocks(ui, repo, **opts):
2446 """show or modify state of locks
2446 """show or modify state of locks
2447
2447
2448 By default, this command will show which locks are held. This
2448 By default, this command will show which locks are held. This
2449 includes the user and process holding the lock, the amount of time
2449 includes the user and process holding the lock, the amount of time
2450 the lock has been held, and the machine name where the process is
2450 the lock has been held, and the machine name where the process is
2451 running if it's not local.
2451 running if it's not local.
2452
2452
2453 Locks protect the integrity of Mercurial's data, so should be
2453 Locks protect the integrity of Mercurial's data, so should be
2454 treated with care. System crashes or other interruptions may cause
2454 treated with care. System crashes or other interruptions may cause
2455 locks to not be properly released, though Mercurial will usually
2455 locks to not be properly released, though Mercurial will usually
2456 detect and remove such stale locks automatically.
2456 detect and remove such stale locks automatically.
2457
2457
2458 However, detecting stale locks may not always be possible (for
2458 However, detecting stale locks may not always be possible (for
2459 instance, on a shared filesystem). Removing locks may also be
2459 instance, on a shared filesystem). Removing locks may also be
2460 blocked by filesystem permissions.
2460 blocked by filesystem permissions.
2461
2461
2462 Returns 0 if no locks are held.
2462 Returns 0 if no locks are held.
2463
2463
2464 """
2464 """
2465
2465
2466 if opts.get('force_lock'):
2466 if opts.get('force_lock'):
2467 repo.svfs.unlink('lock')
2467 repo.svfs.unlink('lock')
2468 if opts.get('force_wlock'):
2468 if opts.get('force_wlock'):
2469 repo.vfs.unlink('wlock')
2469 repo.vfs.unlink('wlock')
2470 if opts.get('force_lock') or opts.get('force_lock'):
2470 if opts.get('force_lock') or opts.get('force_lock'):
2471 return 0
2471 return 0
2472
2472
2473 now = time.time()
2473 now = time.time()
2474 held = 0
2474 held = 0
2475
2475
2476 def report(vfs, name, method):
2476 def report(vfs, name, method):
2477 # this causes stale locks to get reaped for more accurate reporting
2477 # this causes stale locks to get reaped for more accurate reporting
2478 try:
2478 try:
2479 l = method(False)
2479 l = method(False)
2480 except error.LockHeld:
2480 except error.LockHeld:
2481 l = None
2481 l = None
2482
2482
2483 if l:
2483 if l:
2484 l.release()
2484 l.release()
2485 else:
2485 else:
2486 try:
2486 try:
2487 stat = repo.svfs.lstat(name)
2487 stat = vfs.lstat(name)
2488 age = now - stat.st_mtime
2488 age = now - stat.st_mtime
2489 user = util.username(stat.st_uid)
2489 user = util.username(stat.st_uid)
2490 locker = vfs.readlock(name)
2490 locker = vfs.readlock(name)
2491 if ":" in locker:
2491 if ":" in locker:
2492 host, pid = locker.split(':')
2492 host, pid = locker.split(':')
2493 if host == socket.gethostname():
2493 if host == socket.gethostname():
2494 locker = 'user %s, process %s' % (user, pid)
2494 locker = 'user %s, process %s' % (user, pid)
2495 else:
2495 else:
2496 locker = 'user %s, process %s, host %s' \
2496 locker = 'user %s, process %s, host %s' \
2497 % (user, pid, host)
2497 % (user, pid, host)
2498 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2498 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2499 return 1
2499 return 1
2500 except OSError, e:
2500 except OSError, e:
2501 if e.errno != errno.ENOENT:
2501 if e.errno != errno.ENOENT:
2502 raise
2502 raise
2503
2503
2504 ui.write("%-6s free\n" % (name + ":"))
2504 ui.write("%-6s free\n" % (name + ":"))
2505 return 0
2505 return 0
2506
2506
2507 held += report(repo.svfs, "lock", repo.lock)
2507 held += report(repo.svfs, "lock", repo.lock)
2508 held += report(repo.vfs, "wlock", repo.wlock)
2508 held += report(repo.vfs, "wlock", repo.wlock)
2509
2509
2510 return held
2510 return held
2511
2511
2512 @command('debugobsolete',
2512 @command('debugobsolete',
2513 [('', 'flags', 0, _('markers flag')),
2513 [('', 'flags', 0, _('markers flag')),
2514 ('', 'record-parents', False,
2514 ('', 'record-parents', False,
2515 _('record parent information for the precursor')),
2515 _('record parent information for the precursor')),
2516 ('r', 'rev', [], _('display markers relevant to REV')),
2516 ('r', 'rev', [], _('display markers relevant to REV')),
2517 ] + commitopts2,
2517 ] + commitopts2,
2518 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2518 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2519 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2519 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2520 """create arbitrary obsolete marker
2520 """create arbitrary obsolete marker
2521
2521
2522 With no arguments, displays the list of obsolescence markers."""
2522 With no arguments, displays the list of obsolescence markers."""
2523
2523
2524 def parsenodeid(s):
2524 def parsenodeid(s):
2525 try:
2525 try:
2526 # We do not use revsingle/revrange functions here to accept
2526 # We do not use revsingle/revrange functions here to accept
2527 # arbitrary node identifiers, possibly not present in the
2527 # arbitrary node identifiers, possibly not present in the
2528 # local repository.
2528 # local repository.
2529 n = bin(s)
2529 n = bin(s)
2530 if len(n) != len(nullid):
2530 if len(n) != len(nullid):
2531 raise TypeError()
2531 raise TypeError()
2532 return n
2532 return n
2533 except TypeError:
2533 except TypeError:
2534 raise util.Abort('changeset references must be full hexadecimal '
2534 raise util.Abort('changeset references must be full hexadecimal '
2535 'node identifiers')
2535 'node identifiers')
2536
2536
2537 if precursor is not None:
2537 if precursor is not None:
2538 if opts['rev']:
2538 if opts['rev']:
2539 raise util.Abort('cannot select revision when creating marker')
2539 raise util.Abort('cannot select revision when creating marker')
2540 metadata = {}
2540 metadata = {}
2541 metadata['user'] = opts['user'] or ui.username()
2541 metadata['user'] = opts['user'] or ui.username()
2542 succs = tuple(parsenodeid(succ) for succ in successors)
2542 succs = tuple(parsenodeid(succ) for succ in successors)
2543 l = repo.lock()
2543 l = repo.lock()
2544 try:
2544 try:
2545 tr = repo.transaction('debugobsolete')
2545 tr = repo.transaction('debugobsolete')
2546 try:
2546 try:
2547 try:
2547 try:
2548 date = opts.get('date')
2548 date = opts.get('date')
2549 if date:
2549 if date:
2550 date = util.parsedate(date)
2550 date = util.parsedate(date)
2551 else:
2551 else:
2552 date = None
2552 date = None
2553 prec = parsenodeid(precursor)
2553 prec = parsenodeid(precursor)
2554 parents = None
2554 parents = None
2555 if opts['record_parents']:
2555 if opts['record_parents']:
2556 if prec not in repo.unfiltered():
2556 if prec not in repo.unfiltered():
2557 raise util.Abort('cannot used --record-parents on '
2557 raise util.Abort('cannot used --record-parents on '
2558 'unknown changesets')
2558 'unknown changesets')
2559 parents = repo.unfiltered()[prec].parents()
2559 parents = repo.unfiltered()[prec].parents()
2560 parents = tuple(p.node() for p in parents)
2560 parents = tuple(p.node() for p in parents)
2561 repo.obsstore.create(tr, prec, succs, opts['flags'],
2561 repo.obsstore.create(tr, prec, succs, opts['flags'],
2562 parents=parents, date=date,
2562 parents=parents, date=date,
2563 metadata=metadata)
2563 metadata=metadata)
2564 tr.close()
2564 tr.close()
2565 except ValueError, exc:
2565 except ValueError, exc:
2566 raise util.Abort(_('bad obsmarker input: %s') % exc)
2566 raise util.Abort(_('bad obsmarker input: %s') % exc)
2567 finally:
2567 finally:
2568 tr.release()
2568 tr.release()
2569 finally:
2569 finally:
2570 l.release()
2570 l.release()
2571 else:
2571 else:
2572 if opts['rev']:
2572 if opts['rev']:
2573 revs = scmutil.revrange(repo, opts['rev'])
2573 revs = scmutil.revrange(repo, opts['rev'])
2574 nodes = [repo[r].node() for r in revs]
2574 nodes = [repo[r].node() for r in revs]
2575 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2575 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2576 markers.sort(key=lambda x: x._data)
2576 markers.sort(key=lambda x: x._data)
2577 else:
2577 else:
2578 markers = obsolete.getmarkers(repo)
2578 markers = obsolete.getmarkers(repo)
2579
2579
2580 for m in markers:
2580 for m in markers:
2581 cmdutil.showmarker(ui, m)
2581 cmdutil.showmarker(ui, m)
2582
2582
2583 @command('debugpathcomplete',
2583 @command('debugpathcomplete',
2584 [('f', 'full', None, _('complete an entire path')),
2584 [('f', 'full', None, _('complete an entire path')),
2585 ('n', 'normal', None, _('show only normal files')),
2585 ('n', 'normal', None, _('show only normal files')),
2586 ('a', 'added', None, _('show only added files')),
2586 ('a', 'added', None, _('show only added files')),
2587 ('r', 'removed', None, _('show only removed files'))],
2587 ('r', 'removed', None, _('show only removed files'))],
2588 _('FILESPEC...'))
2588 _('FILESPEC...'))
2589 def debugpathcomplete(ui, repo, *specs, **opts):
2589 def debugpathcomplete(ui, repo, *specs, **opts):
2590 '''complete part or all of a tracked path
2590 '''complete part or all of a tracked path
2591
2591
2592 This command supports shells that offer path name completion. It
2592 This command supports shells that offer path name completion. It
2593 currently completes only files already known to the dirstate.
2593 currently completes only files already known to the dirstate.
2594
2594
2595 Completion extends only to the next path segment unless
2595 Completion extends only to the next path segment unless
2596 --full is specified, in which case entire paths are used.'''
2596 --full is specified, in which case entire paths are used.'''
2597
2597
2598 def complete(path, acceptable):
2598 def complete(path, acceptable):
2599 dirstate = repo.dirstate
2599 dirstate = repo.dirstate
2600 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2600 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2601 rootdir = repo.root + os.sep
2601 rootdir = repo.root + os.sep
2602 if spec != repo.root and not spec.startswith(rootdir):
2602 if spec != repo.root and not spec.startswith(rootdir):
2603 return [], []
2603 return [], []
2604 if os.path.isdir(spec):
2604 if os.path.isdir(spec):
2605 spec += '/'
2605 spec += '/'
2606 spec = spec[len(rootdir):]
2606 spec = spec[len(rootdir):]
2607 fixpaths = os.sep != '/'
2607 fixpaths = os.sep != '/'
2608 if fixpaths:
2608 if fixpaths:
2609 spec = spec.replace(os.sep, '/')
2609 spec = spec.replace(os.sep, '/')
2610 speclen = len(spec)
2610 speclen = len(spec)
2611 fullpaths = opts['full']
2611 fullpaths = opts['full']
2612 files, dirs = set(), set()
2612 files, dirs = set(), set()
2613 adddir, addfile = dirs.add, files.add
2613 adddir, addfile = dirs.add, files.add
2614 for f, st in dirstate.iteritems():
2614 for f, st in dirstate.iteritems():
2615 if f.startswith(spec) and st[0] in acceptable:
2615 if f.startswith(spec) and st[0] in acceptable:
2616 if fixpaths:
2616 if fixpaths:
2617 f = f.replace('/', os.sep)
2617 f = f.replace('/', os.sep)
2618 if fullpaths:
2618 if fullpaths:
2619 addfile(f)
2619 addfile(f)
2620 continue
2620 continue
2621 s = f.find(os.sep, speclen)
2621 s = f.find(os.sep, speclen)
2622 if s >= 0:
2622 if s >= 0:
2623 adddir(f[:s])
2623 adddir(f[:s])
2624 else:
2624 else:
2625 addfile(f)
2625 addfile(f)
2626 return files, dirs
2626 return files, dirs
2627
2627
2628 acceptable = ''
2628 acceptable = ''
2629 if opts['normal']:
2629 if opts['normal']:
2630 acceptable += 'nm'
2630 acceptable += 'nm'
2631 if opts['added']:
2631 if opts['added']:
2632 acceptable += 'a'
2632 acceptable += 'a'
2633 if opts['removed']:
2633 if opts['removed']:
2634 acceptable += 'r'
2634 acceptable += 'r'
2635 cwd = repo.getcwd()
2635 cwd = repo.getcwd()
2636 if not specs:
2636 if not specs:
2637 specs = ['.']
2637 specs = ['.']
2638
2638
2639 files, dirs = set(), set()
2639 files, dirs = set(), set()
2640 for spec in specs:
2640 for spec in specs:
2641 f, d = complete(spec, acceptable or 'nmar')
2641 f, d = complete(spec, acceptable or 'nmar')
2642 files.update(f)
2642 files.update(f)
2643 dirs.update(d)
2643 dirs.update(d)
2644 files.update(dirs)
2644 files.update(dirs)
2645 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2645 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2646 ui.write('\n')
2646 ui.write('\n')
2647
2647
2648 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2648 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2649 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2649 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2650 '''access the pushkey key/value protocol
2650 '''access the pushkey key/value protocol
2651
2651
2652 With two args, list the keys in the given namespace.
2652 With two args, list the keys in the given namespace.
2653
2653
2654 With five args, set a key to new if it currently is set to old.
2654 With five args, set a key to new if it currently is set to old.
2655 Reports success or failure.
2655 Reports success or failure.
2656 '''
2656 '''
2657
2657
2658 target = hg.peer(ui, {}, repopath)
2658 target = hg.peer(ui, {}, repopath)
2659 if keyinfo:
2659 if keyinfo:
2660 key, old, new = keyinfo
2660 key, old, new = keyinfo
2661 r = target.pushkey(namespace, key, old, new)
2661 r = target.pushkey(namespace, key, old, new)
2662 ui.status(str(r) + '\n')
2662 ui.status(str(r) + '\n')
2663 return not r
2663 return not r
2664 else:
2664 else:
2665 for k, v in sorted(target.listkeys(namespace).iteritems()):
2665 for k, v in sorted(target.listkeys(namespace).iteritems()):
2666 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2666 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2667 v.encode('string-escape')))
2667 v.encode('string-escape')))
2668
2668
2669 @command('debugpvec', [], _('A B'))
2669 @command('debugpvec', [], _('A B'))
2670 def debugpvec(ui, repo, a, b=None):
2670 def debugpvec(ui, repo, a, b=None):
2671 ca = scmutil.revsingle(repo, a)
2671 ca = scmutil.revsingle(repo, a)
2672 cb = scmutil.revsingle(repo, b)
2672 cb = scmutil.revsingle(repo, b)
2673 pa = pvec.ctxpvec(ca)
2673 pa = pvec.ctxpvec(ca)
2674 pb = pvec.ctxpvec(cb)
2674 pb = pvec.ctxpvec(cb)
2675 if pa == pb:
2675 if pa == pb:
2676 rel = "="
2676 rel = "="
2677 elif pa > pb:
2677 elif pa > pb:
2678 rel = ">"
2678 rel = ">"
2679 elif pa < pb:
2679 elif pa < pb:
2680 rel = "<"
2680 rel = "<"
2681 elif pa | pb:
2681 elif pa | pb:
2682 rel = "|"
2682 rel = "|"
2683 ui.write(_("a: %s\n") % pa)
2683 ui.write(_("a: %s\n") % pa)
2684 ui.write(_("b: %s\n") % pb)
2684 ui.write(_("b: %s\n") % pb)
2685 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2685 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2686 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2686 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2687 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2687 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2688 pa.distance(pb), rel))
2688 pa.distance(pb), rel))
2689
2689
2690 @command('debugrebuilddirstate|debugrebuildstate',
2690 @command('debugrebuilddirstate|debugrebuildstate',
2691 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2691 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2692 _('[-r REV]'))
2692 _('[-r REV]'))
2693 def debugrebuilddirstate(ui, repo, rev):
2693 def debugrebuilddirstate(ui, repo, rev):
2694 """rebuild the dirstate as it would look like for the given revision
2694 """rebuild the dirstate as it would look like for the given revision
2695
2695
2696 If no revision is specified the first current parent will be used.
2696 If no revision is specified the first current parent will be used.
2697
2697
2698 The dirstate will be set to the files of the given revision.
2698 The dirstate will be set to the files of the given revision.
2699 The actual working directory content or existing dirstate
2699 The actual working directory content or existing dirstate
2700 information such as adds or removes is not considered.
2700 information such as adds or removes is not considered.
2701
2701
2702 One use of this command is to make the next :hg:`status` invocation
2702 One use of this command is to make the next :hg:`status` invocation
2703 check the actual file content.
2703 check the actual file content.
2704 """
2704 """
2705 ctx = scmutil.revsingle(repo, rev)
2705 ctx = scmutil.revsingle(repo, rev)
2706 wlock = repo.wlock()
2706 wlock = repo.wlock()
2707 try:
2707 try:
2708 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2708 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2709 finally:
2709 finally:
2710 wlock.release()
2710 wlock.release()
2711
2711
2712 @command('debugrename',
2712 @command('debugrename',
2713 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2713 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2714 _('[-r REV] FILE'))
2714 _('[-r REV] FILE'))
2715 def debugrename(ui, repo, file1, *pats, **opts):
2715 def debugrename(ui, repo, file1, *pats, **opts):
2716 """dump rename information"""
2716 """dump rename information"""
2717
2717
2718 ctx = scmutil.revsingle(repo, opts.get('rev'))
2718 ctx = scmutil.revsingle(repo, opts.get('rev'))
2719 m = scmutil.match(ctx, (file1,) + pats, opts)
2719 m = scmutil.match(ctx, (file1,) + pats, opts)
2720 for abs in ctx.walk(m):
2720 for abs in ctx.walk(m):
2721 fctx = ctx[abs]
2721 fctx = ctx[abs]
2722 o = fctx.filelog().renamed(fctx.filenode())
2722 o = fctx.filelog().renamed(fctx.filenode())
2723 rel = m.rel(abs)
2723 rel = m.rel(abs)
2724 if o:
2724 if o:
2725 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2725 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2726 else:
2726 else:
2727 ui.write(_("%s not renamed\n") % rel)
2727 ui.write(_("%s not renamed\n") % rel)
2728
2728
2729 @command('debugrevlog',
2729 @command('debugrevlog',
2730 [('c', 'changelog', False, _('open changelog')),
2730 [('c', 'changelog', False, _('open changelog')),
2731 ('m', 'manifest', False, _('open manifest')),
2731 ('m', 'manifest', False, _('open manifest')),
2732 ('d', 'dump', False, _('dump index data'))],
2732 ('d', 'dump', False, _('dump index data'))],
2733 _('-c|-m|FILE'),
2733 _('-c|-m|FILE'),
2734 optionalrepo=True)
2734 optionalrepo=True)
2735 def debugrevlog(ui, repo, file_=None, **opts):
2735 def debugrevlog(ui, repo, file_=None, **opts):
2736 """show data and statistics about a revlog"""
2736 """show data and statistics about a revlog"""
2737 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2737 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2738
2738
2739 if opts.get("dump"):
2739 if opts.get("dump"):
2740 numrevs = len(r)
2740 numrevs = len(r)
2741 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2741 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2742 " rawsize totalsize compression heads chainlen\n")
2742 " rawsize totalsize compression heads chainlen\n")
2743 ts = 0
2743 ts = 0
2744 heads = set()
2744 heads = set()
2745
2745
2746 for rev in xrange(numrevs):
2746 for rev in xrange(numrevs):
2747 dbase = r.deltaparent(rev)
2747 dbase = r.deltaparent(rev)
2748 if dbase == -1:
2748 if dbase == -1:
2749 dbase = rev
2749 dbase = rev
2750 cbase = r.chainbase(rev)
2750 cbase = r.chainbase(rev)
2751 clen = r.chainlen(rev)
2751 clen = r.chainlen(rev)
2752 p1, p2 = r.parentrevs(rev)
2752 p1, p2 = r.parentrevs(rev)
2753 rs = r.rawsize(rev)
2753 rs = r.rawsize(rev)
2754 ts = ts + rs
2754 ts = ts + rs
2755 heads -= set(r.parentrevs(rev))
2755 heads -= set(r.parentrevs(rev))
2756 heads.add(rev)
2756 heads.add(rev)
2757 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2757 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2758 "%11d %5d %8d\n" %
2758 "%11d %5d %8d\n" %
2759 (rev, p1, p2, r.start(rev), r.end(rev),
2759 (rev, p1, p2, r.start(rev), r.end(rev),
2760 r.start(dbase), r.start(cbase),
2760 r.start(dbase), r.start(cbase),
2761 r.start(p1), r.start(p2),
2761 r.start(p1), r.start(p2),
2762 rs, ts, ts / r.end(rev), len(heads), clen))
2762 rs, ts, ts / r.end(rev), len(heads), clen))
2763 return 0
2763 return 0
2764
2764
2765 v = r.version
2765 v = r.version
2766 format = v & 0xFFFF
2766 format = v & 0xFFFF
2767 flags = []
2767 flags = []
2768 gdelta = False
2768 gdelta = False
2769 if v & revlog.REVLOGNGINLINEDATA:
2769 if v & revlog.REVLOGNGINLINEDATA:
2770 flags.append('inline')
2770 flags.append('inline')
2771 if v & revlog.REVLOGGENERALDELTA:
2771 if v & revlog.REVLOGGENERALDELTA:
2772 gdelta = True
2772 gdelta = True
2773 flags.append('generaldelta')
2773 flags.append('generaldelta')
2774 if not flags:
2774 if not flags:
2775 flags = ['(none)']
2775 flags = ['(none)']
2776
2776
2777 nummerges = 0
2777 nummerges = 0
2778 numfull = 0
2778 numfull = 0
2779 numprev = 0
2779 numprev = 0
2780 nump1 = 0
2780 nump1 = 0
2781 nump2 = 0
2781 nump2 = 0
2782 numother = 0
2782 numother = 0
2783 nump1prev = 0
2783 nump1prev = 0
2784 nump2prev = 0
2784 nump2prev = 0
2785 chainlengths = []
2785 chainlengths = []
2786
2786
2787 datasize = [None, 0, 0L]
2787 datasize = [None, 0, 0L]
2788 fullsize = [None, 0, 0L]
2788 fullsize = [None, 0, 0L]
2789 deltasize = [None, 0, 0L]
2789 deltasize = [None, 0, 0L]
2790
2790
2791 def addsize(size, l):
2791 def addsize(size, l):
2792 if l[0] is None or size < l[0]:
2792 if l[0] is None or size < l[0]:
2793 l[0] = size
2793 l[0] = size
2794 if size > l[1]:
2794 if size > l[1]:
2795 l[1] = size
2795 l[1] = size
2796 l[2] += size
2796 l[2] += size
2797
2797
2798 numrevs = len(r)
2798 numrevs = len(r)
2799 for rev in xrange(numrevs):
2799 for rev in xrange(numrevs):
2800 p1, p2 = r.parentrevs(rev)
2800 p1, p2 = r.parentrevs(rev)
2801 delta = r.deltaparent(rev)
2801 delta = r.deltaparent(rev)
2802 if format > 0:
2802 if format > 0:
2803 addsize(r.rawsize(rev), datasize)
2803 addsize(r.rawsize(rev), datasize)
2804 if p2 != nullrev:
2804 if p2 != nullrev:
2805 nummerges += 1
2805 nummerges += 1
2806 size = r.length(rev)
2806 size = r.length(rev)
2807 if delta == nullrev:
2807 if delta == nullrev:
2808 chainlengths.append(0)
2808 chainlengths.append(0)
2809 numfull += 1
2809 numfull += 1
2810 addsize(size, fullsize)
2810 addsize(size, fullsize)
2811 else:
2811 else:
2812 chainlengths.append(chainlengths[delta] + 1)
2812 chainlengths.append(chainlengths[delta] + 1)
2813 addsize(size, deltasize)
2813 addsize(size, deltasize)
2814 if delta == rev - 1:
2814 if delta == rev - 1:
2815 numprev += 1
2815 numprev += 1
2816 if delta == p1:
2816 if delta == p1:
2817 nump1prev += 1
2817 nump1prev += 1
2818 elif delta == p2:
2818 elif delta == p2:
2819 nump2prev += 1
2819 nump2prev += 1
2820 elif delta == p1:
2820 elif delta == p1:
2821 nump1 += 1
2821 nump1 += 1
2822 elif delta == p2:
2822 elif delta == p2:
2823 nump2 += 1
2823 nump2 += 1
2824 elif delta != nullrev:
2824 elif delta != nullrev:
2825 numother += 1
2825 numother += 1
2826
2826
2827 # Adjust size min value for empty cases
2827 # Adjust size min value for empty cases
2828 for size in (datasize, fullsize, deltasize):
2828 for size in (datasize, fullsize, deltasize):
2829 if size[0] is None:
2829 if size[0] is None:
2830 size[0] = 0
2830 size[0] = 0
2831
2831
2832 numdeltas = numrevs - numfull
2832 numdeltas = numrevs - numfull
2833 numoprev = numprev - nump1prev - nump2prev
2833 numoprev = numprev - nump1prev - nump2prev
2834 totalrawsize = datasize[2]
2834 totalrawsize = datasize[2]
2835 datasize[2] /= numrevs
2835 datasize[2] /= numrevs
2836 fulltotal = fullsize[2]
2836 fulltotal = fullsize[2]
2837 fullsize[2] /= numfull
2837 fullsize[2] /= numfull
2838 deltatotal = deltasize[2]
2838 deltatotal = deltasize[2]
2839 if numrevs - numfull > 0:
2839 if numrevs - numfull > 0:
2840 deltasize[2] /= numrevs - numfull
2840 deltasize[2] /= numrevs - numfull
2841 totalsize = fulltotal + deltatotal
2841 totalsize = fulltotal + deltatotal
2842 avgchainlen = sum(chainlengths) / numrevs
2842 avgchainlen = sum(chainlengths) / numrevs
2843 maxchainlen = max(chainlengths)
2843 maxchainlen = max(chainlengths)
2844 compratio = totalrawsize / totalsize
2844 compratio = totalrawsize / totalsize
2845
2845
2846 basedfmtstr = '%%%dd\n'
2846 basedfmtstr = '%%%dd\n'
2847 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2847 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2848
2848
2849 def dfmtstr(max):
2849 def dfmtstr(max):
2850 return basedfmtstr % len(str(max))
2850 return basedfmtstr % len(str(max))
2851 def pcfmtstr(max, padding=0):
2851 def pcfmtstr(max, padding=0):
2852 return basepcfmtstr % (len(str(max)), ' ' * padding)
2852 return basepcfmtstr % (len(str(max)), ' ' * padding)
2853
2853
2854 def pcfmt(value, total):
2854 def pcfmt(value, total):
2855 return (value, 100 * float(value) / total)
2855 return (value, 100 * float(value) / total)
2856
2856
2857 ui.write(('format : %d\n') % format)
2857 ui.write(('format : %d\n') % format)
2858 ui.write(('flags : %s\n') % ', '.join(flags))
2858 ui.write(('flags : %s\n') % ', '.join(flags))
2859
2859
2860 ui.write('\n')
2860 ui.write('\n')
2861 fmt = pcfmtstr(totalsize)
2861 fmt = pcfmtstr(totalsize)
2862 fmt2 = dfmtstr(totalsize)
2862 fmt2 = dfmtstr(totalsize)
2863 ui.write(('revisions : ') + fmt2 % numrevs)
2863 ui.write(('revisions : ') + fmt2 % numrevs)
2864 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2864 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2865 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2865 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2867 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2867 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2868 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2868 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2869 ui.write(('revision size : ') + fmt2 % totalsize)
2869 ui.write(('revision size : ') + fmt2 % totalsize)
2870 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2870 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2871 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2871 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2872
2872
2873 ui.write('\n')
2873 ui.write('\n')
2874 fmt = dfmtstr(max(avgchainlen, compratio))
2874 fmt = dfmtstr(max(avgchainlen, compratio))
2875 ui.write(('avg chain length : ') + fmt % avgchainlen)
2875 ui.write(('avg chain length : ') + fmt % avgchainlen)
2876 ui.write(('max chain length : ') + fmt % maxchainlen)
2876 ui.write(('max chain length : ') + fmt % maxchainlen)
2877 ui.write(('compression ratio : ') + fmt % compratio)
2877 ui.write(('compression ratio : ') + fmt % compratio)
2878
2878
2879 if format > 0:
2879 if format > 0:
2880 ui.write('\n')
2880 ui.write('\n')
2881 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2881 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2882 % tuple(datasize))
2882 % tuple(datasize))
2883 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2883 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2884 % tuple(fullsize))
2884 % tuple(fullsize))
2885 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2885 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2886 % tuple(deltasize))
2886 % tuple(deltasize))
2887
2887
2888 if numdeltas > 0:
2888 if numdeltas > 0:
2889 ui.write('\n')
2889 ui.write('\n')
2890 fmt = pcfmtstr(numdeltas)
2890 fmt = pcfmtstr(numdeltas)
2891 fmt2 = pcfmtstr(numdeltas, 4)
2891 fmt2 = pcfmtstr(numdeltas, 4)
2892 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2892 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2893 if numprev > 0:
2893 if numprev > 0:
2894 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2894 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2895 numprev))
2895 numprev))
2896 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2896 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2897 numprev))
2897 numprev))
2898 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2898 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2899 numprev))
2899 numprev))
2900 if gdelta:
2900 if gdelta:
2901 ui.write(('deltas against p1 : ')
2901 ui.write(('deltas against p1 : ')
2902 + fmt % pcfmt(nump1, numdeltas))
2902 + fmt % pcfmt(nump1, numdeltas))
2903 ui.write(('deltas against p2 : ')
2903 ui.write(('deltas against p2 : ')
2904 + fmt % pcfmt(nump2, numdeltas))
2904 + fmt % pcfmt(nump2, numdeltas))
2905 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2905 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2906 numdeltas))
2906 numdeltas))
2907
2907
2908 @command('debugrevspec',
2908 @command('debugrevspec',
2909 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2909 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2910 ('REVSPEC'))
2910 ('REVSPEC'))
2911 def debugrevspec(ui, repo, expr, **opts):
2911 def debugrevspec(ui, repo, expr, **opts):
2912 """parse and apply a revision specification
2912 """parse and apply a revision specification
2913
2913
2914 Use --verbose to print the parsed tree before and after aliases
2914 Use --verbose to print the parsed tree before and after aliases
2915 expansion.
2915 expansion.
2916 """
2916 """
2917 if ui.verbose:
2917 if ui.verbose:
2918 tree = revset.parse(expr)[0]
2918 tree = revset.parse(expr)[0]
2919 ui.note(revset.prettyformat(tree), "\n")
2919 ui.note(revset.prettyformat(tree), "\n")
2920 newtree = revset.findaliases(ui, tree)
2920 newtree = revset.findaliases(ui, tree)
2921 if newtree != tree:
2921 if newtree != tree:
2922 ui.note(revset.prettyformat(newtree), "\n")
2922 ui.note(revset.prettyformat(newtree), "\n")
2923 tree = newtree
2923 tree = newtree
2924 newtree = revset.foldconcat(tree)
2924 newtree = revset.foldconcat(tree)
2925 if newtree != tree:
2925 if newtree != tree:
2926 ui.note(revset.prettyformat(newtree), "\n")
2926 ui.note(revset.prettyformat(newtree), "\n")
2927 if opts["optimize"]:
2927 if opts["optimize"]:
2928 weight, optimizedtree = revset.optimize(newtree, True)
2928 weight, optimizedtree = revset.optimize(newtree, True)
2929 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2929 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2930 func = revset.match(ui, expr)
2930 func = revset.match(ui, expr)
2931 revs = func(repo)
2931 revs = func(repo)
2932 if ui.verbose:
2932 if ui.verbose:
2933 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2933 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2934 for c in revs:
2934 for c in revs:
2935 ui.write("%s\n" % c)
2935 ui.write("%s\n" % c)
2936
2936
2937 @command('debugsetparents', [], _('REV1 [REV2]'))
2937 @command('debugsetparents', [], _('REV1 [REV2]'))
2938 def debugsetparents(ui, repo, rev1, rev2=None):
2938 def debugsetparents(ui, repo, rev1, rev2=None):
2939 """manually set the parents of the current working directory
2939 """manually set the parents of the current working directory
2940
2940
2941 This is useful for writing repository conversion tools, but should
2941 This is useful for writing repository conversion tools, but should
2942 be used with care. For example, neither the working directory nor the
2942 be used with care. For example, neither the working directory nor the
2943 dirstate is updated, so file status may be incorrect after running this
2943 dirstate is updated, so file status may be incorrect after running this
2944 command.
2944 command.
2945
2945
2946 Returns 0 on success.
2946 Returns 0 on success.
2947 """
2947 """
2948
2948
2949 r1 = scmutil.revsingle(repo, rev1).node()
2949 r1 = scmutil.revsingle(repo, rev1).node()
2950 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2950 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2951
2951
2952 wlock = repo.wlock()
2952 wlock = repo.wlock()
2953 try:
2953 try:
2954 repo.dirstate.beginparentchange()
2954 repo.dirstate.beginparentchange()
2955 repo.setparents(r1, r2)
2955 repo.setparents(r1, r2)
2956 repo.dirstate.endparentchange()
2956 repo.dirstate.endparentchange()
2957 finally:
2957 finally:
2958 wlock.release()
2958 wlock.release()
2959
2959
2960 @command('debugdirstate|debugstate',
2960 @command('debugdirstate|debugstate',
2961 [('', 'nodates', None, _('do not display the saved mtime')),
2961 [('', 'nodates', None, _('do not display the saved mtime')),
2962 ('', 'datesort', None, _('sort by saved mtime'))],
2962 ('', 'datesort', None, _('sort by saved mtime'))],
2963 _('[OPTION]...'))
2963 _('[OPTION]...'))
2964 def debugstate(ui, repo, nodates=None, datesort=None):
2964 def debugstate(ui, repo, nodates=None, datesort=None):
2965 """show the contents of the current dirstate"""
2965 """show the contents of the current dirstate"""
2966 timestr = ""
2966 timestr = ""
2967 if datesort:
2967 if datesort:
2968 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2968 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2969 else:
2969 else:
2970 keyfunc = None # sort by filename
2970 keyfunc = None # sort by filename
2971 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2971 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2972 if ent[3] == -1:
2972 if ent[3] == -1:
2973 timestr = 'unset '
2973 timestr = 'unset '
2974 elif nodates:
2974 elif nodates:
2975 timestr = 'set '
2975 timestr = 'set '
2976 else:
2976 else:
2977 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2977 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2978 time.localtime(ent[3]))
2978 time.localtime(ent[3]))
2979 if ent[1] & 020000:
2979 if ent[1] & 020000:
2980 mode = 'lnk'
2980 mode = 'lnk'
2981 else:
2981 else:
2982 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2982 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2983 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2983 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2984 for f in repo.dirstate.copies():
2984 for f in repo.dirstate.copies():
2985 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2985 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2986
2986
2987 @command('debugsub',
2987 @command('debugsub',
2988 [('r', 'rev', '',
2988 [('r', 'rev', '',
2989 _('revision to check'), _('REV'))],
2989 _('revision to check'), _('REV'))],
2990 _('[-r REV] [REV]'))
2990 _('[-r REV] [REV]'))
2991 def debugsub(ui, repo, rev=None):
2991 def debugsub(ui, repo, rev=None):
2992 ctx = scmutil.revsingle(repo, rev, None)
2992 ctx = scmutil.revsingle(repo, rev, None)
2993 for k, v in sorted(ctx.substate.items()):
2993 for k, v in sorted(ctx.substate.items()):
2994 ui.write(('path %s\n') % k)
2994 ui.write(('path %s\n') % k)
2995 ui.write((' source %s\n') % v[0])
2995 ui.write((' source %s\n') % v[0])
2996 ui.write((' revision %s\n') % v[1])
2996 ui.write((' revision %s\n') % v[1])
2997
2997
2998 @command('debugsuccessorssets',
2998 @command('debugsuccessorssets',
2999 [],
2999 [],
3000 _('[REV]'))
3000 _('[REV]'))
3001 def debugsuccessorssets(ui, repo, *revs):
3001 def debugsuccessorssets(ui, repo, *revs):
3002 """show set of successors for revision
3002 """show set of successors for revision
3003
3003
3004 A successors set of changeset A is a consistent group of revisions that
3004 A successors set of changeset A is a consistent group of revisions that
3005 succeed A. It contains non-obsolete changesets only.
3005 succeed A. It contains non-obsolete changesets only.
3006
3006
3007 In most cases a changeset A has a single successors set containing a single
3007 In most cases a changeset A has a single successors set containing a single
3008 successor (changeset A replaced by A').
3008 successor (changeset A replaced by A').
3009
3009
3010 A changeset that is made obsolete with no successors are called "pruned".
3010 A changeset that is made obsolete with no successors are called "pruned".
3011 Such changesets have no successors sets at all.
3011 Such changesets have no successors sets at all.
3012
3012
3013 A changeset that has been "split" will have a successors set containing
3013 A changeset that has been "split" will have a successors set containing
3014 more than one successor.
3014 more than one successor.
3015
3015
3016 A changeset that has been rewritten in multiple different ways is called
3016 A changeset that has been rewritten in multiple different ways is called
3017 "divergent". Such changesets have multiple successor sets (each of which
3017 "divergent". Such changesets have multiple successor sets (each of which
3018 may also be split, i.e. have multiple successors).
3018 may also be split, i.e. have multiple successors).
3019
3019
3020 Results are displayed as follows::
3020 Results are displayed as follows::
3021
3021
3022 <rev1>
3022 <rev1>
3023 <successors-1A>
3023 <successors-1A>
3024 <rev2>
3024 <rev2>
3025 <successors-2A>
3025 <successors-2A>
3026 <successors-2B1> <successors-2B2> <successors-2B3>
3026 <successors-2B1> <successors-2B2> <successors-2B3>
3027
3027
3028 Here rev2 has two possible (i.e. divergent) successors sets. The first
3028 Here rev2 has two possible (i.e. divergent) successors sets. The first
3029 holds one element, whereas the second holds three (i.e. the changeset has
3029 holds one element, whereas the second holds three (i.e. the changeset has
3030 been split).
3030 been split).
3031 """
3031 """
3032 # passed to successorssets caching computation from one call to another
3032 # passed to successorssets caching computation from one call to another
3033 cache = {}
3033 cache = {}
3034 ctx2str = str
3034 ctx2str = str
3035 node2str = short
3035 node2str = short
3036 if ui.debug():
3036 if ui.debug():
3037 def ctx2str(ctx):
3037 def ctx2str(ctx):
3038 return ctx.hex()
3038 return ctx.hex()
3039 node2str = hex
3039 node2str = hex
3040 for rev in scmutil.revrange(repo, revs):
3040 for rev in scmutil.revrange(repo, revs):
3041 ctx = repo[rev]
3041 ctx = repo[rev]
3042 ui.write('%s\n'% ctx2str(ctx))
3042 ui.write('%s\n'% ctx2str(ctx))
3043 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3043 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3044 if succsset:
3044 if succsset:
3045 ui.write(' ')
3045 ui.write(' ')
3046 ui.write(node2str(succsset[0]))
3046 ui.write(node2str(succsset[0]))
3047 for node in succsset[1:]:
3047 for node in succsset[1:]:
3048 ui.write(' ')
3048 ui.write(' ')
3049 ui.write(node2str(node))
3049 ui.write(node2str(node))
3050 ui.write('\n')
3050 ui.write('\n')
3051
3051
3052 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3052 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3053 def debugwalk(ui, repo, *pats, **opts):
3053 def debugwalk(ui, repo, *pats, **opts):
3054 """show how files match on given patterns"""
3054 """show how files match on given patterns"""
3055 m = scmutil.match(repo[None], pats, opts)
3055 m = scmutil.match(repo[None], pats, opts)
3056 items = list(repo.walk(m))
3056 items = list(repo.walk(m))
3057 if not items:
3057 if not items:
3058 return
3058 return
3059 f = lambda fn: fn
3059 f = lambda fn: fn
3060 if ui.configbool('ui', 'slash') and os.sep != '/':
3060 if ui.configbool('ui', 'slash') and os.sep != '/':
3061 f = lambda fn: util.normpath(fn)
3061 f = lambda fn: util.normpath(fn)
3062 fmt = 'f %%-%ds %%-%ds %%s' % (
3062 fmt = 'f %%-%ds %%-%ds %%s' % (
3063 max([len(abs) for abs in items]),
3063 max([len(abs) for abs in items]),
3064 max([len(m.rel(abs)) for abs in items]))
3064 max([len(m.rel(abs)) for abs in items]))
3065 for abs in items:
3065 for abs in items:
3066 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3066 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3067 ui.write("%s\n" % line.rstrip())
3067 ui.write("%s\n" % line.rstrip())
3068
3068
3069 @command('debugwireargs',
3069 @command('debugwireargs',
3070 [('', 'three', '', 'three'),
3070 [('', 'three', '', 'three'),
3071 ('', 'four', '', 'four'),
3071 ('', 'four', '', 'four'),
3072 ('', 'five', '', 'five'),
3072 ('', 'five', '', 'five'),
3073 ] + remoteopts,
3073 ] + remoteopts,
3074 _('REPO [OPTIONS]... [ONE [TWO]]'),
3074 _('REPO [OPTIONS]... [ONE [TWO]]'),
3075 norepo=True)
3075 norepo=True)
3076 def debugwireargs(ui, repopath, *vals, **opts):
3076 def debugwireargs(ui, repopath, *vals, **opts):
3077 repo = hg.peer(ui, opts, repopath)
3077 repo = hg.peer(ui, opts, repopath)
3078 for opt in remoteopts:
3078 for opt in remoteopts:
3079 del opts[opt[1]]
3079 del opts[opt[1]]
3080 args = {}
3080 args = {}
3081 for k, v in opts.iteritems():
3081 for k, v in opts.iteritems():
3082 if v:
3082 if v:
3083 args[k] = v
3083 args[k] = v
3084 # run twice to check that we don't mess up the stream for the next command
3084 # run twice to check that we don't mess up the stream for the next command
3085 res1 = repo.debugwireargs(*vals, **args)
3085 res1 = repo.debugwireargs(*vals, **args)
3086 res2 = repo.debugwireargs(*vals, **args)
3086 res2 = repo.debugwireargs(*vals, **args)
3087 ui.write("%s\n" % res1)
3087 ui.write("%s\n" % res1)
3088 if res1 != res2:
3088 if res1 != res2:
3089 ui.warn("%s\n" % res2)
3089 ui.warn("%s\n" % res2)
3090
3090
3091 @command('^diff',
3091 @command('^diff',
3092 [('r', 'rev', [], _('revision'), _('REV')),
3092 [('r', 'rev', [], _('revision'), _('REV')),
3093 ('c', 'change', '', _('change made by revision'), _('REV'))
3093 ('c', 'change', '', _('change made by revision'), _('REV'))
3094 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3094 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3095 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3095 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3096 inferrepo=True)
3096 inferrepo=True)
3097 def diff(ui, repo, *pats, **opts):
3097 def diff(ui, repo, *pats, **opts):
3098 """diff repository (or selected files)
3098 """diff repository (or selected files)
3099
3099
3100 Show differences between revisions for the specified files.
3100 Show differences between revisions for the specified files.
3101
3101
3102 Differences between files are shown using the unified diff format.
3102 Differences between files are shown using the unified diff format.
3103
3103
3104 .. note::
3104 .. note::
3105
3105
3106 diff may generate unexpected results for merges, as it will
3106 diff may generate unexpected results for merges, as it will
3107 default to comparing against the working directory's first
3107 default to comparing against the working directory's first
3108 parent changeset if no revisions are specified.
3108 parent changeset if no revisions are specified.
3109
3109
3110 When two revision arguments are given, then changes are shown
3110 When two revision arguments are given, then changes are shown
3111 between those revisions. If only one revision is specified then
3111 between those revisions. If only one revision is specified then
3112 that revision is compared to the working directory, and, when no
3112 that revision is compared to the working directory, and, when no
3113 revisions are specified, the working directory files are compared
3113 revisions are specified, the working directory files are compared
3114 to its parent.
3114 to its parent.
3115
3115
3116 Alternatively you can specify -c/--change with a revision to see
3116 Alternatively you can specify -c/--change with a revision to see
3117 the changes in that changeset relative to its first parent.
3117 the changes in that changeset relative to its first parent.
3118
3118
3119 Without the -a/--text option, diff will avoid generating diffs of
3119 Without the -a/--text option, diff will avoid generating diffs of
3120 files it detects as binary. With -a, diff will generate a diff
3120 files it detects as binary. With -a, diff will generate a diff
3121 anyway, probably with undesirable results.
3121 anyway, probably with undesirable results.
3122
3122
3123 Use the -g/--git option to generate diffs in the git extended diff
3123 Use the -g/--git option to generate diffs in the git extended diff
3124 format. For more information, read :hg:`help diffs`.
3124 format. For more information, read :hg:`help diffs`.
3125
3125
3126 .. container:: verbose
3126 .. container:: verbose
3127
3127
3128 Examples:
3128 Examples:
3129
3129
3130 - compare a file in the current working directory to its parent::
3130 - compare a file in the current working directory to its parent::
3131
3131
3132 hg diff foo.c
3132 hg diff foo.c
3133
3133
3134 - compare two historical versions of a directory, with rename info::
3134 - compare two historical versions of a directory, with rename info::
3135
3135
3136 hg diff --git -r 1.0:1.2 lib/
3136 hg diff --git -r 1.0:1.2 lib/
3137
3137
3138 - get change stats relative to the last change on some date::
3138 - get change stats relative to the last change on some date::
3139
3139
3140 hg diff --stat -r "date('may 2')"
3140 hg diff --stat -r "date('may 2')"
3141
3141
3142 - diff all newly-added files that contain a keyword::
3142 - diff all newly-added files that contain a keyword::
3143
3143
3144 hg diff "set:added() and grep(GNU)"
3144 hg diff "set:added() and grep(GNU)"
3145
3145
3146 - compare a revision and its parents::
3146 - compare a revision and its parents::
3147
3147
3148 hg diff -c 9353 # compare against first parent
3148 hg diff -c 9353 # compare against first parent
3149 hg diff -r 9353^:9353 # same using revset syntax
3149 hg diff -r 9353^:9353 # same using revset syntax
3150 hg diff -r 9353^2:9353 # compare against the second parent
3150 hg diff -r 9353^2:9353 # compare against the second parent
3151
3151
3152 Returns 0 on success.
3152 Returns 0 on success.
3153 """
3153 """
3154
3154
3155 revs = opts.get('rev')
3155 revs = opts.get('rev')
3156 change = opts.get('change')
3156 change = opts.get('change')
3157 stat = opts.get('stat')
3157 stat = opts.get('stat')
3158 reverse = opts.get('reverse')
3158 reverse = opts.get('reverse')
3159
3159
3160 if revs and change:
3160 if revs and change:
3161 msg = _('cannot specify --rev and --change at the same time')
3161 msg = _('cannot specify --rev and --change at the same time')
3162 raise util.Abort(msg)
3162 raise util.Abort(msg)
3163 elif change:
3163 elif change:
3164 node2 = scmutil.revsingle(repo, change, None).node()
3164 node2 = scmutil.revsingle(repo, change, None).node()
3165 node1 = repo[node2].p1().node()
3165 node1 = repo[node2].p1().node()
3166 else:
3166 else:
3167 node1, node2 = scmutil.revpair(repo, revs)
3167 node1, node2 = scmutil.revpair(repo, revs)
3168
3168
3169 if reverse:
3169 if reverse:
3170 node1, node2 = node2, node1
3170 node1, node2 = node2, node1
3171
3171
3172 diffopts = patch.diffallopts(ui, opts)
3172 diffopts = patch.diffallopts(ui, opts)
3173 m = scmutil.match(repo[node2], pats, opts)
3173 m = scmutil.match(repo[node2], pats, opts)
3174 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3174 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3175 listsubrepos=opts.get('subrepos'),
3175 listsubrepos=opts.get('subrepos'),
3176 root=opts.get('root'))
3176 root=opts.get('root'))
3177
3177
3178 @command('^export',
3178 @command('^export',
3179 [('o', 'output', '',
3179 [('o', 'output', '',
3180 _('print output to file with formatted name'), _('FORMAT')),
3180 _('print output to file with formatted name'), _('FORMAT')),
3181 ('', 'switch-parent', None, _('diff against the second parent')),
3181 ('', 'switch-parent', None, _('diff against the second parent')),
3182 ('r', 'rev', [], _('revisions to export'), _('REV')),
3182 ('r', 'rev', [], _('revisions to export'), _('REV')),
3183 ] + diffopts,
3183 ] + diffopts,
3184 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3184 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3185 def export(ui, repo, *changesets, **opts):
3185 def export(ui, repo, *changesets, **opts):
3186 """dump the header and diffs for one or more changesets
3186 """dump the header and diffs for one or more changesets
3187
3187
3188 Print the changeset header and diffs for one or more revisions.
3188 Print the changeset header and diffs for one or more revisions.
3189 If no revision is given, the parent of the working directory is used.
3189 If no revision is given, the parent of the working directory is used.
3190
3190
3191 The information shown in the changeset header is: author, date,
3191 The information shown in the changeset header is: author, date,
3192 branch name (if non-default), changeset hash, parent(s) and commit
3192 branch name (if non-default), changeset hash, parent(s) and commit
3193 comment.
3193 comment.
3194
3194
3195 .. note::
3195 .. note::
3196
3196
3197 export may generate unexpected diff output for merge
3197 export may generate unexpected diff output for merge
3198 changesets, as it will compare the merge changeset against its
3198 changesets, as it will compare the merge changeset against its
3199 first parent only.
3199 first parent only.
3200
3200
3201 Output may be to a file, in which case the name of the file is
3201 Output may be to a file, in which case the name of the file is
3202 given using a format string. The formatting rules are as follows:
3202 given using a format string. The formatting rules are as follows:
3203
3203
3204 :``%%``: literal "%" character
3204 :``%%``: literal "%" character
3205 :``%H``: changeset hash (40 hexadecimal digits)
3205 :``%H``: changeset hash (40 hexadecimal digits)
3206 :``%N``: number of patches being generated
3206 :``%N``: number of patches being generated
3207 :``%R``: changeset revision number
3207 :``%R``: changeset revision number
3208 :``%b``: basename of the exporting repository
3208 :``%b``: basename of the exporting repository
3209 :``%h``: short-form changeset hash (12 hexadecimal digits)
3209 :``%h``: short-form changeset hash (12 hexadecimal digits)
3210 :``%m``: first line of the commit message (only alphanumeric characters)
3210 :``%m``: first line of the commit message (only alphanumeric characters)
3211 :``%n``: zero-padded sequence number, starting at 1
3211 :``%n``: zero-padded sequence number, starting at 1
3212 :``%r``: zero-padded changeset revision number
3212 :``%r``: zero-padded changeset revision number
3213
3213
3214 Without the -a/--text option, export will avoid generating diffs
3214 Without the -a/--text option, export will avoid generating diffs
3215 of files it detects as binary. With -a, export will generate a
3215 of files it detects as binary. With -a, export will generate a
3216 diff anyway, probably with undesirable results.
3216 diff anyway, probably with undesirable results.
3217
3217
3218 Use the -g/--git option to generate diffs in the git extended diff
3218 Use the -g/--git option to generate diffs in the git extended diff
3219 format. See :hg:`help diffs` for more information.
3219 format. See :hg:`help diffs` for more information.
3220
3220
3221 With the --switch-parent option, the diff will be against the
3221 With the --switch-parent option, the diff will be against the
3222 second parent. It can be useful to review a merge.
3222 second parent. It can be useful to review a merge.
3223
3223
3224 .. container:: verbose
3224 .. container:: verbose
3225
3225
3226 Examples:
3226 Examples:
3227
3227
3228 - use export and import to transplant a bugfix to the current
3228 - use export and import to transplant a bugfix to the current
3229 branch::
3229 branch::
3230
3230
3231 hg export -r 9353 | hg import -
3231 hg export -r 9353 | hg import -
3232
3232
3233 - export all the changesets between two revisions to a file with
3233 - export all the changesets between two revisions to a file with
3234 rename information::
3234 rename information::
3235
3235
3236 hg export --git -r 123:150 > changes.txt
3236 hg export --git -r 123:150 > changes.txt
3237
3237
3238 - split outgoing changes into a series of patches with
3238 - split outgoing changes into a series of patches with
3239 descriptive names::
3239 descriptive names::
3240
3240
3241 hg export -r "outgoing()" -o "%n-%m.patch"
3241 hg export -r "outgoing()" -o "%n-%m.patch"
3242
3242
3243 Returns 0 on success.
3243 Returns 0 on success.
3244 """
3244 """
3245 changesets += tuple(opts.get('rev', []))
3245 changesets += tuple(opts.get('rev', []))
3246 if not changesets:
3246 if not changesets:
3247 changesets = ['.']
3247 changesets = ['.']
3248 revs = scmutil.revrange(repo, changesets)
3248 revs = scmutil.revrange(repo, changesets)
3249 if not revs:
3249 if not revs:
3250 raise util.Abort(_("export requires at least one changeset"))
3250 raise util.Abort(_("export requires at least one changeset"))
3251 if len(revs) > 1:
3251 if len(revs) > 1:
3252 ui.note(_('exporting patches:\n'))
3252 ui.note(_('exporting patches:\n'))
3253 else:
3253 else:
3254 ui.note(_('exporting patch:\n'))
3254 ui.note(_('exporting patch:\n'))
3255 cmdutil.export(repo, revs, template=opts.get('output'),
3255 cmdutil.export(repo, revs, template=opts.get('output'),
3256 switch_parent=opts.get('switch_parent'),
3256 switch_parent=opts.get('switch_parent'),
3257 opts=patch.diffallopts(ui, opts))
3257 opts=patch.diffallopts(ui, opts))
3258
3258
3259 @command('files',
3259 @command('files',
3260 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3260 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3261 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3261 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3262 ] + walkopts + formatteropts + subrepoopts,
3262 ] + walkopts + formatteropts + subrepoopts,
3263 _('[OPTION]... [PATTERN]...'))
3263 _('[OPTION]... [PATTERN]...'))
3264 def files(ui, repo, *pats, **opts):
3264 def files(ui, repo, *pats, **opts):
3265 """list tracked files
3265 """list tracked files
3266
3266
3267 Print files under Mercurial control in the working directory or
3267 Print files under Mercurial control in the working directory or
3268 specified revision whose names match the given patterns (excluding
3268 specified revision whose names match the given patterns (excluding
3269 removed files).
3269 removed files).
3270
3270
3271 If no patterns are given to match, this command prints the names
3271 If no patterns are given to match, this command prints the names
3272 of all files under Mercurial control in the working directory.
3272 of all files under Mercurial control in the working directory.
3273
3273
3274 .. container:: verbose
3274 .. container:: verbose
3275
3275
3276 Examples:
3276 Examples:
3277
3277
3278 - list all files under the current directory::
3278 - list all files under the current directory::
3279
3279
3280 hg files .
3280 hg files .
3281
3281
3282 - shows sizes and flags for current revision::
3282 - shows sizes and flags for current revision::
3283
3283
3284 hg files -vr .
3284 hg files -vr .
3285
3285
3286 - list all files named README::
3286 - list all files named README::
3287
3287
3288 hg files -I "**/README"
3288 hg files -I "**/README"
3289
3289
3290 - list all binary files::
3290 - list all binary files::
3291
3291
3292 hg files "set:binary()"
3292 hg files "set:binary()"
3293
3293
3294 - find files containing a regular expression::
3294 - find files containing a regular expression::
3295
3295
3296 hg files "set:grep('bob')"
3296 hg files "set:grep('bob')"
3297
3297
3298 - search tracked file contents with xargs and grep::
3298 - search tracked file contents with xargs and grep::
3299
3299
3300 hg files -0 | xargs -0 grep foo
3300 hg files -0 | xargs -0 grep foo
3301
3301
3302 See :hg:`help patterns` and :hg:`help filesets` for more information
3302 See :hg:`help patterns` and :hg:`help filesets` for more information
3303 on specifying file patterns.
3303 on specifying file patterns.
3304
3304
3305 Returns 0 if a match is found, 1 otherwise.
3305 Returns 0 if a match is found, 1 otherwise.
3306
3306
3307 """
3307 """
3308 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3308 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3309
3309
3310 end = '\n'
3310 end = '\n'
3311 if opts.get('print0'):
3311 if opts.get('print0'):
3312 end = '\0'
3312 end = '\0'
3313 fm = ui.formatter('files', opts)
3313 fm = ui.formatter('files', opts)
3314 fmt = '%s' + end
3314 fmt = '%s' + end
3315
3315
3316 m = scmutil.match(ctx, pats, opts)
3316 m = scmutil.match(ctx, pats, opts)
3317 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3317 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3318
3318
3319 fm.end()
3319 fm.end()
3320
3320
3321 return ret
3321 return ret
3322
3322
3323 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3323 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3324 def forget(ui, repo, *pats, **opts):
3324 def forget(ui, repo, *pats, **opts):
3325 """forget the specified files on the next commit
3325 """forget the specified files on the next commit
3326
3326
3327 Mark the specified files so they will no longer be tracked
3327 Mark the specified files so they will no longer be tracked
3328 after the next commit.
3328 after the next commit.
3329
3329
3330 This only removes files from the current branch, not from the
3330 This only removes files from the current branch, not from the
3331 entire project history, and it does not delete them from the
3331 entire project history, and it does not delete them from the
3332 working directory.
3332 working directory.
3333
3333
3334 To undo a forget before the next commit, see :hg:`add`.
3334 To undo a forget before the next commit, see :hg:`add`.
3335
3335
3336 .. container:: verbose
3336 .. container:: verbose
3337
3337
3338 Examples:
3338 Examples:
3339
3339
3340 - forget newly-added binary files::
3340 - forget newly-added binary files::
3341
3341
3342 hg forget "set:added() and binary()"
3342 hg forget "set:added() and binary()"
3343
3343
3344 - forget files that would be excluded by .hgignore::
3344 - forget files that would be excluded by .hgignore::
3345
3345
3346 hg forget "set:hgignore()"
3346 hg forget "set:hgignore()"
3347
3347
3348 Returns 0 on success.
3348 Returns 0 on success.
3349 """
3349 """
3350
3350
3351 if not pats:
3351 if not pats:
3352 raise util.Abort(_('no files specified'))
3352 raise util.Abort(_('no files specified'))
3353
3353
3354 m = scmutil.match(repo[None], pats, opts)
3354 m = scmutil.match(repo[None], pats, opts)
3355 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3355 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3356 return rejected and 1 or 0
3356 return rejected and 1 or 0
3357
3357
3358 @command(
3358 @command(
3359 'graft',
3359 'graft',
3360 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3360 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3361 ('c', 'continue', False, _('resume interrupted graft')),
3361 ('c', 'continue', False, _('resume interrupted graft')),
3362 ('e', 'edit', False, _('invoke editor on commit messages')),
3362 ('e', 'edit', False, _('invoke editor on commit messages')),
3363 ('', 'log', None, _('append graft info to log message')),
3363 ('', 'log', None, _('append graft info to log message')),
3364 ('f', 'force', False, _('force graft')),
3364 ('f', 'force', False, _('force graft')),
3365 ('D', 'currentdate', False,
3365 ('D', 'currentdate', False,
3366 _('record the current date as commit date')),
3366 _('record the current date as commit date')),
3367 ('U', 'currentuser', False,
3367 ('U', 'currentuser', False,
3368 _('record the current user as committer'), _('DATE'))]
3368 _('record the current user as committer'), _('DATE'))]
3369 + commitopts2 + mergetoolopts + dryrunopts,
3369 + commitopts2 + mergetoolopts + dryrunopts,
3370 _('[OPTION]... [-r] REV...'))
3370 _('[OPTION]... [-r] REV...'))
3371 def graft(ui, repo, *revs, **opts):
3371 def graft(ui, repo, *revs, **opts):
3372 '''copy changes from other branches onto the current branch
3372 '''copy changes from other branches onto the current branch
3373
3373
3374 This command uses Mercurial's merge logic to copy individual
3374 This command uses Mercurial's merge logic to copy individual
3375 changes from other branches without merging branches in the
3375 changes from other branches without merging branches in the
3376 history graph. This is sometimes known as 'backporting' or
3376 history graph. This is sometimes known as 'backporting' or
3377 'cherry-picking'. By default, graft will copy user, date, and
3377 'cherry-picking'. By default, graft will copy user, date, and
3378 description from the source changesets.
3378 description from the source changesets.
3379
3379
3380 Changesets that are ancestors of the current revision, that have
3380 Changesets that are ancestors of the current revision, that have
3381 already been grafted, or that are merges will be skipped.
3381 already been grafted, or that are merges will be skipped.
3382
3382
3383 If --log is specified, log messages will have a comment appended
3383 If --log is specified, log messages will have a comment appended
3384 of the form::
3384 of the form::
3385
3385
3386 (grafted from CHANGESETHASH)
3386 (grafted from CHANGESETHASH)
3387
3387
3388 If --force is specified, revisions will be grafted even if they
3388 If --force is specified, revisions will be grafted even if they
3389 are already ancestors of or have been grafted to the destination.
3389 are already ancestors of or have been grafted to the destination.
3390 This is useful when the revisions have since been backed out.
3390 This is useful when the revisions have since been backed out.
3391
3391
3392 If a graft merge results in conflicts, the graft process is
3392 If a graft merge results in conflicts, the graft process is
3393 interrupted so that the current merge can be manually resolved.
3393 interrupted so that the current merge can be manually resolved.
3394 Once all conflicts are addressed, the graft process can be
3394 Once all conflicts are addressed, the graft process can be
3395 continued with the -c/--continue option.
3395 continued with the -c/--continue option.
3396
3396
3397 .. note::
3397 .. note::
3398
3398
3399 The -c/--continue option does not reapply earlier options, except
3399 The -c/--continue option does not reapply earlier options, except
3400 for --force.
3400 for --force.
3401
3401
3402 .. container:: verbose
3402 .. container:: verbose
3403
3403
3404 Examples:
3404 Examples:
3405
3405
3406 - copy a single change to the stable branch and edit its description::
3406 - copy a single change to the stable branch and edit its description::
3407
3407
3408 hg update stable
3408 hg update stable
3409 hg graft --edit 9393
3409 hg graft --edit 9393
3410
3410
3411 - graft a range of changesets with one exception, updating dates::
3411 - graft a range of changesets with one exception, updating dates::
3412
3412
3413 hg graft -D "2085::2093 and not 2091"
3413 hg graft -D "2085::2093 and not 2091"
3414
3414
3415 - continue a graft after resolving conflicts::
3415 - continue a graft after resolving conflicts::
3416
3416
3417 hg graft -c
3417 hg graft -c
3418
3418
3419 - show the source of a grafted changeset::
3419 - show the source of a grafted changeset::
3420
3420
3421 hg log --debug -r .
3421 hg log --debug -r .
3422
3422
3423 See :hg:`help revisions` and :hg:`help revsets` for more about
3423 See :hg:`help revisions` and :hg:`help revsets` for more about
3424 specifying revisions.
3424 specifying revisions.
3425
3425
3426 Returns 0 on successful completion.
3426 Returns 0 on successful completion.
3427 '''
3427 '''
3428
3428
3429 revs = list(revs)
3429 revs = list(revs)
3430 revs.extend(opts['rev'])
3430 revs.extend(opts['rev'])
3431
3431
3432 if not opts.get('user') and opts.get('currentuser'):
3432 if not opts.get('user') and opts.get('currentuser'):
3433 opts['user'] = ui.username()
3433 opts['user'] = ui.username()
3434 if not opts.get('date') and opts.get('currentdate'):
3434 if not opts.get('date') and opts.get('currentdate'):
3435 opts['date'] = "%d %d" % util.makedate()
3435 opts['date'] = "%d %d" % util.makedate()
3436
3436
3437 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3437 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3438
3438
3439 cont = False
3439 cont = False
3440 if opts['continue']:
3440 if opts['continue']:
3441 cont = True
3441 cont = True
3442 if revs:
3442 if revs:
3443 raise util.Abort(_("can't specify --continue and revisions"))
3443 raise util.Abort(_("can't specify --continue and revisions"))
3444 # read in unfinished revisions
3444 # read in unfinished revisions
3445 try:
3445 try:
3446 nodes = repo.vfs.read('graftstate').splitlines()
3446 nodes = repo.vfs.read('graftstate').splitlines()
3447 revs = [repo[node].rev() for node in nodes]
3447 revs = [repo[node].rev() for node in nodes]
3448 except IOError, inst:
3448 except IOError, inst:
3449 if inst.errno != errno.ENOENT:
3449 if inst.errno != errno.ENOENT:
3450 raise
3450 raise
3451 raise util.Abort(_("no graft state found, can't continue"))
3451 raise util.Abort(_("no graft state found, can't continue"))
3452 else:
3452 else:
3453 cmdutil.checkunfinished(repo)
3453 cmdutil.checkunfinished(repo)
3454 cmdutil.bailifchanged(repo)
3454 cmdutil.bailifchanged(repo)
3455 if not revs:
3455 if not revs:
3456 raise util.Abort(_('no revisions specified'))
3456 raise util.Abort(_('no revisions specified'))
3457 revs = scmutil.revrange(repo, revs)
3457 revs = scmutil.revrange(repo, revs)
3458
3458
3459 skipped = set()
3459 skipped = set()
3460 # check for merges
3460 # check for merges
3461 for rev in repo.revs('%ld and merge()', revs):
3461 for rev in repo.revs('%ld and merge()', revs):
3462 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3462 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3463 skipped.add(rev)
3463 skipped.add(rev)
3464 revs = [r for r in revs if r not in skipped]
3464 revs = [r for r in revs if r not in skipped]
3465 if not revs:
3465 if not revs:
3466 return -1
3466 return -1
3467
3467
3468 # Don't check in the --continue case, in effect retaining --force across
3468 # Don't check in the --continue case, in effect retaining --force across
3469 # --continues. That's because without --force, any revisions we decided to
3469 # --continues. That's because without --force, any revisions we decided to
3470 # skip would have been filtered out here, so they wouldn't have made their
3470 # skip would have been filtered out here, so they wouldn't have made their
3471 # way to the graftstate. With --force, any revisions we would have otherwise
3471 # way to the graftstate. With --force, any revisions we would have otherwise
3472 # skipped would not have been filtered out, and if they hadn't been applied
3472 # skipped would not have been filtered out, and if they hadn't been applied
3473 # already, they'd have been in the graftstate.
3473 # already, they'd have been in the graftstate.
3474 if not (cont or opts.get('force')):
3474 if not (cont or opts.get('force')):
3475 # check for ancestors of dest branch
3475 # check for ancestors of dest branch
3476 crev = repo['.'].rev()
3476 crev = repo['.'].rev()
3477 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3477 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3478 # Cannot use x.remove(y) on smart set, this has to be a list.
3478 # Cannot use x.remove(y) on smart set, this has to be a list.
3479 # XXX make this lazy in the future
3479 # XXX make this lazy in the future
3480 revs = list(revs)
3480 revs = list(revs)
3481 # don't mutate while iterating, create a copy
3481 # don't mutate while iterating, create a copy
3482 for rev in list(revs):
3482 for rev in list(revs):
3483 if rev in ancestors:
3483 if rev in ancestors:
3484 ui.warn(_('skipping ancestor revision %d:%s\n') %
3484 ui.warn(_('skipping ancestor revision %d:%s\n') %
3485 (rev, repo[rev]))
3485 (rev, repo[rev]))
3486 # XXX remove on list is slow
3486 # XXX remove on list is slow
3487 revs.remove(rev)
3487 revs.remove(rev)
3488 if not revs:
3488 if not revs:
3489 return -1
3489 return -1
3490
3490
3491 # analyze revs for earlier grafts
3491 # analyze revs for earlier grafts
3492 ids = {}
3492 ids = {}
3493 for ctx in repo.set("%ld", revs):
3493 for ctx in repo.set("%ld", revs):
3494 ids[ctx.hex()] = ctx.rev()
3494 ids[ctx.hex()] = ctx.rev()
3495 n = ctx.extra().get('source')
3495 n = ctx.extra().get('source')
3496 if n:
3496 if n:
3497 ids[n] = ctx.rev()
3497 ids[n] = ctx.rev()
3498
3498
3499 # check ancestors for earlier grafts
3499 # check ancestors for earlier grafts
3500 ui.debug('scanning for duplicate grafts\n')
3500 ui.debug('scanning for duplicate grafts\n')
3501
3501
3502 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3502 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3503 ctx = repo[rev]
3503 ctx = repo[rev]
3504 n = ctx.extra().get('source')
3504 n = ctx.extra().get('source')
3505 if n in ids:
3505 if n in ids:
3506 try:
3506 try:
3507 r = repo[n].rev()
3507 r = repo[n].rev()
3508 except error.RepoLookupError:
3508 except error.RepoLookupError:
3509 r = None
3509 r = None
3510 if r in revs:
3510 if r in revs:
3511 ui.warn(_('skipping revision %d:%s '
3511 ui.warn(_('skipping revision %d:%s '
3512 '(already grafted to %d:%s)\n')
3512 '(already grafted to %d:%s)\n')
3513 % (r, repo[r], rev, ctx))
3513 % (r, repo[r], rev, ctx))
3514 revs.remove(r)
3514 revs.remove(r)
3515 elif ids[n] in revs:
3515 elif ids[n] in revs:
3516 if r is None:
3516 if r is None:
3517 ui.warn(_('skipping already grafted revision %d:%s '
3517 ui.warn(_('skipping already grafted revision %d:%s '
3518 '(%d:%s also has unknown origin %s)\n')
3518 '(%d:%s also has unknown origin %s)\n')
3519 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3519 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3520 else:
3520 else:
3521 ui.warn(_('skipping already grafted revision %d:%s '
3521 ui.warn(_('skipping already grafted revision %d:%s '
3522 '(%d:%s also has origin %d:%s)\n')
3522 '(%d:%s also has origin %d:%s)\n')
3523 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3523 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3524 revs.remove(ids[n])
3524 revs.remove(ids[n])
3525 elif ctx.hex() in ids:
3525 elif ctx.hex() in ids:
3526 r = ids[ctx.hex()]
3526 r = ids[ctx.hex()]
3527 ui.warn(_('skipping already grafted revision %d:%s '
3527 ui.warn(_('skipping already grafted revision %d:%s '
3528 '(was grafted from %d:%s)\n') %
3528 '(was grafted from %d:%s)\n') %
3529 (r, repo[r], rev, ctx))
3529 (r, repo[r], rev, ctx))
3530 revs.remove(r)
3530 revs.remove(r)
3531 if not revs:
3531 if not revs:
3532 return -1
3532 return -1
3533
3533
3534 wlock = repo.wlock()
3534 wlock = repo.wlock()
3535 try:
3535 try:
3536 for pos, ctx in enumerate(repo.set("%ld", revs)):
3536 for pos, ctx in enumerate(repo.set("%ld", revs)):
3537 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3537 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3538 ctx.description().split('\n', 1)[0])
3538 ctx.description().split('\n', 1)[0])
3539 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3539 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3540 if names:
3540 if names:
3541 desc += ' (%s)' % ' '.join(names)
3541 desc += ' (%s)' % ' '.join(names)
3542 ui.status(_('grafting %s\n') % desc)
3542 ui.status(_('grafting %s\n') % desc)
3543 if opts.get('dry_run'):
3543 if opts.get('dry_run'):
3544 continue
3544 continue
3545
3545
3546 source = ctx.extra().get('source')
3546 source = ctx.extra().get('source')
3547 extra = {}
3547 extra = {}
3548 if source:
3548 if source:
3549 extra['source'] = source
3549 extra['source'] = source
3550 extra['intermediate-source'] = ctx.hex()
3550 extra['intermediate-source'] = ctx.hex()
3551 else:
3551 else:
3552 extra['source'] = ctx.hex()
3552 extra['source'] = ctx.hex()
3553 user = ctx.user()
3553 user = ctx.user()
3554 if opts.get('user'):
3554 if opts.get('user'):
3555 user = opts['user']
3555 user = opts['user']
3556 date = ctx.date()
3556 date = ctx.date()
3557 if opts.get('date'):
3557 if opts.get('date'):
3558 date = opts['date']
3558 date = opts['date']
3559 message = ctx.description()
3559 message = ctx.description()
3560 if opts.get('log'):
3560 if opts.get('log'):
3561 message += '\n(grafted from %s)' % ctx.hex()
3561 message += '\n(grafted from %s)' % ctx.hex()
3562
3562
3563 # we don't merge the first commit when continuing
3563 # we don't merge the first commit when continuing
3564 if not cont:
3564 if not cont:
3565 # perform the graft merge with p1(rev) as 'ancestor'
3565 # perform the graft merge with p1(rev) as 'ancestor'
3566 try:
3566 try:
3567 # ui.forcemerge is an internal variable, do not document
3567 # ui.forcemerge is an internal variable, do not document
3568 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3568 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3569 'graft')
3569 'graft')
3570 stats = mergemod.graft(repo, ctx, ctx.p1(),
3570 stats = mergemod.graft(repo, ctx, ctx.p1(),
3571 ['local', 'graft'])
3571 ['local', 'graft'])
3572 finally:
3572 finally:
3573 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3573 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3574 # report any conflicts
3574 # report any conflicts
3575 if stats and stats[3] > 0:
3575 if stats and stats[3] > 0:
3576 # write out state for --continue
3576 # write out state for --continue
3577 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3577 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3578 repo.vfs.write('graftstate', ''.join(nodelines))
3578 repo.vfs.write('graftstate', ''.join(nodelines))
3579 raise util.Abort(
3579 raise util.Abort(
3580 _("unresolved conflicts, can't continue"),
3580 _("unresolved conflicts, can't continue"),
3581 hint=_('use hg resolve and hg graft --continue'))
3581 hint=_('use hg resolve and hg graft --continue'))
3582 else:
3582 else:
3583 cont = False
3583 cont = False
3584
3584
3585 # commit
3585 # commit
3586 node = repo.commit(text=message, user=user,
3586 node = repo.commit(text=message, user=user,
3587 date=date, extra=extra, editor=editor)
3587 date=date, extra=extra, editor=editor)
3588 if node is None:
3588 if node is None:
3589 ui.warn(
3589 ui.warn(
3590 _('note: graft of %d:%s created no changes to commit\n') %
3590 _('note: graft of %d:%s created no changes to commit\n') %
3591 (ctx.rev(), ctx))
3591 (ctx.rev(), ctx))
3592 finally:
3592 finally:
3593 wlock.release()
3593 wlock.release()
3594
3594
3595 # remove state when we complete successfully
3595 # remove state when we complete successfully
3596 if not opts.get('dry_run'):
3596 if not opts.get('dry_run'):
3597 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3597 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3598
3598
3599 return 0
3599 return 0
3600
3600
3601 @command('grep',
3601 @command('grep',
3602 [('0', 'print0', None, _('end fields with NUL')),
3602 [('0', 'print0', None, _('end fields with NUL')),
3603 ('', 'all', None, _('print all revisions that match')),
3603 ('', 'all', None, _('print all revisions that match')),
3604 ('a', 'text', None, _('treat all files as text')),
3604 ('a', 'text', None, _('treat all files as text')),
3605 ('f', 'follow', None,
3605 ('f', 'follow', None,
3606 _('follow changeset history,'
3606 _('follow changeset history,'
3607 ' or file history across copies and renames')),
3607 ' or file history across copies and renames')),
3608 ('i', 'ignore-case', None, _('ignore case when matching')),
3608 ('i', 'ignore-case', None, _('ignore case when matching')),
3609 ('l', 'files-with-matches', None,
3609 ('l', 'files-with-matches', None,
3610 _('print only filenames and revisions that match')),
3610 _('print only filenames and revisions that match')),
3611 ('n', 'line-number', None, _('print matching line numbers')),
3611 ('n', 'line-number', None, _('print matching line numbers')),
3612 ('r', 'rev', [],
3612 ('r', 'rev', [],
3613 _('only search files changed within revision range'), _('REV')),
3613 _('only search files changed within revision range'), _('REV')),
3614 ('u', 'user', None, _('list the author (long with -v)')),
3614 ('u', 'user', None, _('list the author (long with -v)')),
3615 ('d', 'date', None, _('list the date (short with -q)')),
3615 ('d', 'date', None, _('list the date (short with -q)')),
3616 ] + walkopts,
3616 ] + walkopts,
3617 _('[OPTION]... PATTERN [FILE]...'),
3617 _('[OPTION]... PATTERN [FILE]...'),
3618 inferrepo=True)
3618 inferrepo=True)
3619 def grep(ui, repo, pattern, *pats, **opts):
3619 def grep(ui, repo, pattern, *pats, **opts):
3620 """search for a pattern in specified files and revisions
3620 """search for a pattern in specified files and revisions
3621
3621
3622 Search revisions of files for a regular expression.
3622 Search revisions of files for a regular expression.
3623
3623
3624 This command behaves differently than Unix grep. It only accepts
3624 This command behaves differently than Unix grep. It only accepts
3625 Python/Perl regexps. It searches repository history, not the
3625 Python/Perl regexps. It searches repository history, not the
3626 working directory. It always prints the revision number in which a
3626 working directory. It always prints the revision number in which a
3627 match appears.
3627 match appears.
3628
3628
3629 By default, grep only prints output for the first revision of a
3629 By default, grep only prints output for the first revision of a
3630 file in which it finds a match. To get it to print every revision
3630 file in which it finds a match. To get it to print every revision
3631 that contains a change in match status ("-" for a match that
3631 that contains a change in match status ("-" for a match that
3632 becomes a non-match, or "+" for a non-match that becomes a match),
3632 becomes a non-match, or "+" for a non-match that becomes a match),
3633 use the --all flag.
3633 use the --all flag.
3634
3634
3635 Returns 0 if a match is found, 1 otherwise.
3635 Returns 0 if a match is found, 1 otherwise.
3636 """
3636 """
3637 reflags = re.M
3637 reflags = re.M
3638 if opts.get('ignore_case'):
3638 if opts.get('ignore_case'):
3639 reflags |= re.I
3639 reflags |= re.I
3640 try:
3640 try:
3641 regexp = util.re.compile(pattern, reflags)
3641 regexp = util.re.compile(pattern, reflags)
3642 except re.error, inst:
3642 except re.error, inst:
3643 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3643 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3644 return 1
3644 return 1
3645 sep, eol = ':', '\n'
3645 sep, eol = ':', '\n'
3646 if opts.get('print0'):
3646 if opts.get('print0'):
3647 sep = eol = '\0'
3647 sep = eol = '\0'
3648
3648
3649 getfile = util.lrucachefunc(repo.file)
3649 getfile = util.lrucachefunc(repo.file)
3650
3650
3651 def matchlines(body):
3651 def matchlines(body):
3652 begin = 0
3652 begin = 0
3653 linenum = 0
3653 linenum = 0
3654 while begin < len(body):
3654 while begin < len(body):
3655 match = regexp.search(body, begin)
3655 match = regexp.search(body, begin)
3656 if not match:
3656 if not match:
3657 break
3657 break
3658 mstart, mend = match.span()
3658 mstart, mend = match.span()
3659 linenum += body.count('\n', begin, mstart) + 1
3659 linenum += body.count('\n', begin, mstart) + 1
3660 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3660 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3661 begin = body.find('\n', mend) + 1 or len(body) + 1
3661 begin = body.find('\n', mend) + 1 or len(body) + 1
3662 lend = begin - 1
3662 lend = begin - 1
3663 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3663 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3664
3664
3665 class linestate(object):
3665 class linestate(object):
3666 def __init__(self, line, linenum, colstart, colend):
3666 def __init__(self, line, linenum, colstart, colend):
3667 self.line = line
3667 self.line = line
3668 self.linenum = linenum
3668 self.linenum = linenum
3669 self.colstart = colstart
3669 self.colstart = colstart
3670 self.colend = colend
3670 self.colend = colend
3671
3671
3672 def __hash__(self):
3672 def __hash__(self):
3673 return hash((self.linenum, self.line))
3673 return hash((self.linenum, self.line))
3674
3674
3675 def __eq__(self, other):
3675 def __eq__(self, other):
3676 return self.line == other.line
3676 return self.line == other.line
3677
3677
3678 def __iter__(self):
3678 def __iter__(self):
3679 yield (self.line[:self.colstart], '')
3679 yield (self.line[:self.colstart], '')
3680 yield (self.line[self.colstart:self.colend], 'grep.match')
3680 yield (self.line[self.colstart:self.colend], 'grep.match')
3681 rest = self.line[self.colend:]
3681 rest = self.line[self.colend:]
3682 while rest != '':
3682 while rest != '':
3683 match = regexp.search(rest)
3683 match = regexp.search(rest)
3684 if not match:
3684 if not match:
3685 yield (rest, '')
3685 yield (rest, '')
3686 break
3686 break
3687 mstart, mend = match.span()
3687 mstart, mend = match.span()
3688 yield (rest[:mstart], '')
3688 yield (rest[:mstart], '')
3689 yield (rest[mstart:mend], 'grep.match')
3689 yield (rest[mstart:mend], 'grep.match')
3690 rest = rest[mend:]
3690 rest = rest[mend:]
3691
3691
3692 matches = {}
3692 matches = {}
3693 copies = {}
3693 copies = {}
3694 def grepbody(fn, rev, body):
3694 def grepbody(fn, rev, body):
3695 matches[rev].setdefault(fn, [])
3695 matches[rev].setdefault(fn, [])
3696 m = matches[rev][fn]
3696 m = matches[rev][fn]
3697 for lnum, cstart, cend, line in matchlines(body):
3697 for lnum, cstart, cend, line in matchlines(body):
3698 s = linestate(line, lnum, cstart, cend)
3698 s = linestate(line, lnum, cstart, cend)
3699 m.append(s)
3699 m.append(s)
3700
3700
3701 def difflinestates(a, b):
3701 def difflinestates(a, b):
3702 sm = difflib.SequenceMatcher(None, a, b)
3702 sm = difflib.SequenceMatcher(None, a, b)
3703 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3703 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3704 if tag == 'insert':
3704 if tag == 'insert':
3705 for i in xrange(blo, bhi):
3705 for i in xrange(blo, bhi):
3706 yield ('+', b[i])
3706 yield ('+', b[i])
3707 elif tag == 'delete':
3707 elif tag == 'delete':
3708 for i in xrange(alo, ahi):
3708 for i in xrange(alo, ahi):
3709 yield ('-', a[i])
3709 yield ('-', a[i])
3710 elif tag == 'replace':
3710 elif tag == 'replace':
3711 for i in xrange(alo, ahi):
3711 for i in xrange(alo, ahi):
3712 yield ('-', a[i])
3712 yield ('-', a[i])
3713 for i in xrange(blo, bhi):
3713 for i in xrange(blo, bhi):
3714 yield ('+', b[i])
3714 yield ('+', b[i])
3715
3715
3716 def display(fn, ctx, pstates, states):
3716 def display(fn, ctx, pstates, states):
3717 rev = ctx.rev()
3717 rev = ctx.rev()
3718 if ui.quiet:
3718 if ui.quiet:
3719 datefunc = util.shortdate
3719 datefunc = util.shortdate
3720 else:
3720 else:
3721 datefunc = util.datestr
3721 datefunc = util.datestr
3722 found = False
3722 found = False
3723 @util.cachefunc
3723 @util.cachefunc
3724 def binary():
3724 def binary():
3725 flog = getfile(fn)
3725 flog = getfile(fn)
3726 return util.binary(flog.read(ctx.filenode(fn)))
3726 return util.binary(flog.read(ctx.filenode(fn)))
3727
3727
3728 if opts.get('all'):
3728 if opts.get('all'):
3729 iter = difflinestates(pstates, states)
3729 iter = difflinestates(pstates, states)
3730 else:
3730 else:
3731 iter = [('', l) for l in states]
3731 iter = [('', l) for l in states]
3732 for change, l in iter:
3732 for change, l in iter:
3733 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3733 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3734
3734
3735 if opts.get('line_number'):
3735 if opts.get('line_number'):
3736 cols.append((str(l.linenum), 'grep.linenumber'))
3736 cols.append((str(l.linenum), 'grep.linenumber'))
3737 if opts.get('all'):
3737 if opts.get('all'):
3738 cols.append((change, 'grep.change'))
3738 cols.append((change, 'grep.change'))
3739 if opts.get('user'):
3739 if opts.get('user'):
3740 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3740 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3741 if opts.get('date'):
3741 if opts.get('date'):
3742 cols.append((datefunc(ctx.date()), 'grep.date'))
3742 cols.append((datefunc(ctx.date()), 'grep.date'))
3743 for col, label in cols[:-1]:
3743 for col, label in cols[:-1]:
3744 ui.write(col, label=label)
3744 ui.write(col, label=label)
3745 ui.write(sep, label='grep.sep')
3745 ui.write(sep, label='grep.sep')
3746 ui.write(cols[-1][0], label=cols[-1][1])
3746 ui.write(cols[-1][0], label=cols[-1][1])
3747 if not opts.get('files_with_matches'):
3747 if not opts.get('files_with_matches'):
3748 ui.write(sep, label='grep.sep')
3748 ui.write(sep, label='grep.sep')
3749 if not opts.get('text') and binary():
3749 if not opts.get('text') and binary():
3750 ui.write(" Binary file matches")
3750 ui.write(" Binary file matches")
3751 else:
3751 else:
3752 for s, label in l:
3752 for s, label in l:
3753 ui.write(s, label=label)
3753 ui.write(s, label=label)
3754 ui.write(eol)
3754 ui.write(eol)
3755 found = True
3755 found = True
3756 if opts.get('files_with_matches'):
3756 if opts.get('files_with_matches'):
3757 break
3757 break
3758 return found
3758 return found
3759
3759
3760 skip = {}
3760 skip = {}
3761 revfiles = {}
3761 revfiles = {}
3762 matchfn = scmutil.match(repo[None], pats, opts)
3762 matchfn = scmutil.match(repo[None], pats, opts)
3763 found = False
3763 found = False
3764 follow = opts.get('follow')
3764 follow = opts.get('follow')
3765
3765
3766 def prep(ctx, fns):
3766 def prep(ctx, fns):
3767 rev = ctx.rev()
3767 rev = ctx.rev()
3768 pctx = ctx.p1()
3768 pctx = ctx.p1()
3769 parent = pctx.rev()
3769 parent = pctx.rev()
3770 matches.setdefault(rev, {})
3770 matches.setdefault(rev, {})
3771 matches.setdefault(parent, {})
3771 matches.setdefault(parent, {})
3772 files = revfiles.setdefault(rev, [])
3772 files = revfiles.setdefault(rev, [])
3773 for fn in fns:
3773 for fn in fns:
3774 flog = getfile(fn)
3774 flog = getfile(fn)
3775 try:
3775 try:
3776 fnode = ctx.filenode(fn)
3776 fnode = ctx.filenode(fn)
3777 except error.LookupError:
3777 except error.LookupError:
3778 continue
3778 continue
3779
3779
3780 copied = flog.renamed(fnode)
3780 copied = flog.renamed(fnode)
3781 copy = follow and copied and copied[0]
3781 copy = follow and copied and copied[0]
3782 if copy:
3782 if copy:
3783 copies.setdefault(rev, {})[fn] = copy
3783 copies.setdefault(rev, {})[fn] = copy
3784 if fn in skip:
3784 if fn in skip:
3785 if copy:
3785 if copy:
3786 skip[copy] = True
3786 skip[copy] = True
3787 continue
3787 continue
3788 files.append(fn)
3788 files.append(fn)
3789
3789
3790 if fn not in matches[rev]:
3790 if fn not in matches[rev]:
3791 grepbody(fn, rev, flog.read(fnode))
3791 grepbody(fn, rev, flog.read(fnode))
3792
3792
3793 pfn = copy or fn
3793 pfn = copy or fn
3794 if pfn not in matches[parent]:
3794 if pfn not in matches[parent]:
3795 try:
3795 try:
3796 fnode = pctx.filenode(pfn)
3796 fnode = pctx.filenode(pfn)
3797 grepbody(pfn, parent, flog.read(fnode))
3797 grepbody(pfn, parent, flog.read(fnode))
3798 except error.LookupError:
3798 except error.LookupError:
3799 pass
3799 pass
3800
3800
3801 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3801 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3802 rev = ctx.rev()
3802 rev = ctx.rev()
3803 parent = ctx.p1().rev()
3803 parent = ctx.p1().rev()
3804 for fn in sorted(revfiles.get(rev, [])):
3804 for fn in sorted(revfiles.get(rev, [])):
3805 states = matches[rev][fn]
3805 states = matches[rev][fn]
3806 copy = copies.get(rev, {}).get(fn)
3806 copy = copies.get(rev, {}).get(fn)
3807 if fn in skip:
3807 if fn in skip:
3808 if copy:
3808 if copy:
3809 skip[copy] = True
3809 skip[copy] = True
3810 continue
3810 continue
3811 pstates = matches.get(parent, {}).get(copy or fn, [])
3811 pstates = matches.get(parent, {}).get(copy or fn, [])
3812 if pstates or states:
3812 if pstates or states:
3813 r = display(fn, ctx, pstates, states)
3813 r = display(fn, ctx, pstates, states)
3814 found = found or r
3814 found = found or r
3815 if r and not opts.get('all'):
3815 if r and not opts.get('all'):
3816 skip[fn] = True
3816 skip[fn] = True
3817 if copy:
3817 if copy:
3818 skip[copy] = True
3818 skip[copy] = True
3819 del matches[rev]
3819 del matches[rev]
3820 del revfiles[rev]
3820 del revfiles[rev]
3821
3821
3822 return not found
3822 return not found
3823
3823
3824 @command('heads',
3824 @command('heads',
3825 [('r', 'rev', '',
3825 [('r', 'rev', '',
3826 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3826 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3827 ('t', 'topo', False, _('show topological heads only')),
3827 ('t', 'topo', False, _('show topological heads only')),
3828 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3828 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3829 ('c', 'closed', False, _('show normal and closed branch heads')),
3829 ('c', 'closed', False, _('show normal and closed branch heads')),
3830 ] + templateopts,
3830 ] + templateopts,
3831 _('[-ct] [-r STARTREV] [REV]...'))
3831 _('[-ct] [-r STARTREV] [REV]...'))
3832 def heads(ui, repo, *branchrevs, **opts):
3832 def heads(ui, repo, *branchrevs, **opts):
3833 """show branch heads
3833 """show branch heads
3834
3834
3835 With no arguments, show all open branch heads in the repository.
3835 With no arguments, show all open branch heads in the repository.
3836 Branch heads are changesets that have no descendants on the
3836 Branch heads are changesets that have no descendants on the
3837 same branch. They are where development generally takes place and
3837 same branch. They are where development generally takes place and
3838 are the usual targets for update and merge operations.
3838 are the usual targets for update and merge operations.
3839
3839
3840 If one or more REVs are given, only open branch heads on the
3840 If one or more REVs are given, only open branch heads on the
3841 branches associated with the specified changesets are shown. This
3841 branches associated with the specified changesets are shown. This
3842 means that you can use :hg:`heads .` to see the heads on the
3842 means that you can use :hg:`heads .` to see the heads on the
3843 currently checked-out branch.
3843 currently checked-out branch.
3844
3844
3845 If -c/--closed is specified, also show branch heads marked closed
3845 If -c/--closed is specified, also show branch heads marked closed
3846 (see :hg:`commit --close-branch`).
3846 (see :hg:`commit --close-branch`).
3847
3847
3848 If STARTREV is specified, only those heads that are descendants of
3848 If STARTREV is specified, only those heads that are descendants of
3849 STARTREV will be displayed.
3849 STARTREV will be displayed.
3850
3850
3851 If -t/--topo is specified, named branch mechanics will be ignored and only
3851 If -t/--topo is specified, named branch mechanics will be ignored and only
3852 topological heads (changesets with no children) will be shown.
3852 topological heads (changesets with no children) will be shown.
3853
3853
3854 Returns 0 if matching heads are found, 1 if not.
3854 Returns 0 if matching heads are found, 1 if not.
3855 """
3855 """
3856
3856
3857 start = None
3857 start = None
3858 if 'rev' in opts:
3858 if 'rev' in opts:
3859 start = scmutil.revsingle(repo, opts['rev'], None).node()
3859 start = scmutil.revsingle(repo, opts['rev'], None).node()
3860
3860
3861 if opts.get('topo'):
3861 if opts.get('topo'):
3862 heads = [repo[h] for h in repo.heads(start)]
3862 heads = [repo[h] for h in repo.heads(start)]
3863 else:
3863 else:
3864 heads = []
3864 heads = []
3865 for branch in repo.branchmap():
3865 for branch in repo.branchmap():
3866 heads += repo.branchheads(branch, start, opts.get('closed'))
3866 heads += repo.branchheads(branch, start, opts.get('closed'))
3867 heads = [repo[h] for h in heads]
3867 heads = [repo[h] for h in heads]
3868
3868
3869 if branchrevs:
3869 if branchrevs:
3870 branches = set(repo[br].branch() for br in branchrevs)
3870 branches = set(repo[br].branch() for br in branchrevs)
3871 heads = [h for h in heads if h.branch() in branches]
3871 heads = [h for h in heads if h.branch() in branches]
3872
3872
3873 if opts.get('active') and branchrevs:
3873 if opts.get('active') and branchrevs:
3874 dagheads = repo.heads(start)
3874 dagheads = repo.heads(start)
3875 heads = [h for h in heads if h.node() in dagheads]
3875 heads = [h for h in heads if h.node() in dagheads]
3876
3876
3877 if branchrevs:
3877 if branchrevs:
3878 haveheads = set(h.branch() for h in heads)
3878 haveheads = set(h.branch() for h in heads)
3879 if branches - haveheads:
3879 if branches - haveheads:
3880 headless = ', '.join(b for b in branches - haveheads)
3880 headless = ', '.join(b for b in branches - haveheads)
3881 msg = _('no open branch heads found on branches %s')
3881 msg = _('no open branch heads found on branches %s')
3882 if opts.get('rev'):
3882 if opts.get('rev'):
3883 msg += _(' (started at %s)') % opts['rev']
3883 msg += _(' (started at %s)') % opts['rev']
3884 ui.warn((msg + '\n') % headless)
3884 ui.warn((msg + '\n') % headless)
3885
3885
3886 if not heads:
3886 if not heads:
3887 return 1
3887 return 1
3888
3888
3889 heads = sorted(heads, key=lambda x: -x.rev())
3889 heads = sorted(heads, key=lambda x: -x.rev())
3890 displayer = cmdutil.show_changeset(ui, repo, opts)
3890 displayer = cmdutil.show_changeset(ui, repo, opts)
3891 for ctx in heads:
3891 for ctx in heads:
3892 displayer.show(ctx)
3892 displayer.show(ctx)
3893 displayer.close()
3893 displayer.close()
3894
3894
3895 @command('help',
3895 @command('help',
3896 [('e', 'extension', None, _('show only help for extensions')),
3896 [('e', 'extension', None, _('show only help for extensions')),
3897 ('c', 'command', None, _('show only help for commands')),
3897 ('c', 'command', None, _('show only help for commands')),
3898 ('k', 'keyword', '', _('show topics matching keyword')),
3898 ('k', 'keyword', '', _('show topics matching keyword')),
3899 ],
3899 ],
3900 _('[-ec] [TOPIC]'),
3900 _('[-ec] [TOPIC]'),
3901 norepo=True)
3901 norepo=True)
3902 def help_(ui, name=None, **opts):
3902 def help_(ui, name=None, **opts):
3903 """show help for a given topic or a help overview
3903 """show help for a given topic or a help overview
3904
3904
3905 With no arguments, print a list of commands with short help messages.
3905 With no arguments, print a list of commands with short help messages.
3906
3906
3907 Given a topic, extension, or command name, print help for that
3907 Given a topic, extension, or command name, print help for that
3908 topic.
3908 topic.
3909
3909
3910 Returns 0 if successful.
3910 Returns 0 if successful.
3911 """
3911 """
3912
3912
3913 textwidth = min(ui.termwidth(), 80) - 2
3913 textwidth = min(ui.termwidth(), 80) - 2
3914
3914
3915 keep = []
3915 keep = []
3916 if ui.verbose:
3916 if ui.verbose:
3917 keep.append('verbose')
3917 keep.append('verbose')
3918 if sys.platform.startswith('win'):
3918 if sys.platform.startswith('win'):
3919 keep.append('windows')
3919 keep.append('windows')
3920 elif sys.platform == 'OpenVMS':
3920 elif sys.platform == 'OpenVMS':
3921 keep.append('vms')
3921 keep.append('vms')
3922 elif sys.platform == 'plan9':
3922 elif sys.platform == 'plan9':
3923 keep.append('plan9')
3923 keep.append('plan9')
3924 else:
3924 else:
3925 keep.append('unix')
3925 keep.append('unix')
3926 keep.append(sys.platform.lower())
3926 keep.append(sys.platform.lower())
3927
3927
3928 section = None
3928 section = None
3929 if name and '.' in name:
3929 if name and '.' in name:
3930 name, section = name.split('.', 1)
3930 name, section = name.split('.', 1)
3931
3931
3932 text = help.help_(ui, name, **opts)
3932 text = help.help_(ui, name, **opts)
3933
3933
3934 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3934 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3935 section=section)
3935 section=section)
3936 if section and not formatted:
3936 if section and not formatted:
3937 raise util.Abort(_("help section not found"))
3937 raise util.Abort(_("help section not found"))
3938
3938
3939 if 'verbose' in pruned:
3939 if 'verbose' in pruned:
3940 keep.append('omitted')
3940 keep.append('omitted')
3941 else:
3941 else:
3942 keep.append('notomitted')
3942 keep.append('notomitted')
3943 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3943 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3944 section=section)
3944 section=section)
3945 ui.write(formatted)
3945 ui.write(formatted)
3946
3946
3947
3947
3948 @command('identify|id',
3948 @command('identify|id',
3949 [('r', 'rev', '',
3949 [('r', 'rev', '',
3950 _('identify the specified revision'), _('REV')),
3950 _('identify the specified revision'), _('REV')),
3951 ('n', 'num', None, _('show local revision number')),
3951 ('n', 'num', None, _('show local revision number')),
3952 ('i', 'id', None, _('show global revision id')),
3952 ('i', 'id', None, _('show global revision id')),
3953 ('b', 'branch', None, _('show branch')),
3953 ('b', 'branch', None, _('show branch')),
3954 ('t', 'tags', None, _('show tags')),
3954 ('t', 'tags', None, _('show tags')),
3955 ('B', 'bookmarks', None, _('show bookmarks')),
3955 ('B', 'bookmarks', None, _('show bookmarks')),
3956 ] + remoteopts,
3956 ] + remoteopts,
3957 _('[-nibtB] [-r REV] [SOURCE]'),
3957 _('[-nibtB] [-r REV] [SOURCE]'),
3958 optionalrepo=True)
3958 optionalrepo=True)
3959 def identify(ui, repo, source=None, rev=None,
3959 def identify(ui, repo, source=None, rev=None,
3960 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3960 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3961 """identify the working directory or specified revision
3961 """identify the working directory or specified revision
3962
3962
3963 Print a summary identifying the repository state at REV using one or
3963 Print a summary identifying the repository state at REV using one or
3964 two parent hash identifiers, followed by a "+" if the working
3964 two parent hash identifiers, followed by a "+" if the working
3965 directory has uncommitted changes, the branch name (if not default),
3965 directory has uncommitted changes, the branch name (if not default),
3966 a list of tags, and a list of bookmarks.
3966 a list of tags, and a list of bookmarks.
3967
3967
3968 When REV is not given, print a summary of the current state of the
3968 When REV is not given, print a summary of the current state of the
3969 repository.
3969 repository.
3970
3970
3971 Specifying a path to a repository root or Mercurial bundle will
3971 Specifying a path to a repository root or Mercurial bundle will
3972 cause lookup to operate on that repository/bundle.
3972 cause lookup to operate on that repository/bundle.
3973
3973
3974 .. container:: verbose
3974 .. container:: verbose
3975
3975
3976 Examples:
3976 Examples:
3977
3977
3978 - generate a build identifier for the working directory::
3978 - generate a build identifier for the working directory::
3979
3979
3980 hg id --id > build-id.dat
3980 hg id --id > build-id.dat
3981
3981
3982 - find the revision corresponding to a tag::
3982 - find the revision corresponding to a tag::
3983
3983
3984 hg id -n -r 1.3
3984 hg id -n -r 1.3
3985
3985
3986 - check the most recent revision of a remote repository::
3986 - check the most recent revision of a remote repository::
3987
3987
3988 hg id -r tip http://selenic.com/hg/
3988 hg id -r tip http://selenic.com/hg/
3989
3989
3990 Returns 0 if successful.
3990 Returns 0 if successful.
3991 """
3991 """
3992
3992
3993 if not repo and not source:
3993 if not repo and not source:
3994 raise util.Abort(_("there is no Mercurial repository here "
3994 raise util.Abort(_("there is no Mercurial repository here "
3995 "(.hg not found)"))
3995 "(.hg not found)"))
3996
3996
3997 if ui.debugflag:
3997 if ui.debugflag:
3998 hexfunc = hex
3998 hexfunc = hex
3999 else:
3999 else:
4000 hexfunc = short
4000 hexfunc = short
4001 default = not (num or id or branch or tags or bookmarks)
4001 default = not (num or id or branch or tags or bookmarks)
4002 output = []
4002 output = []
4003 revs = []
4003 revs = []
4004
4004
4005 if source:
4005 if source:
4006 source, branches = hg.parseurl(ui.expandpath(source))
4006 source, branches = hg.parseurl(ui.expandpath(source))
4007 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4007 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4008 repo = peer.local()
4008 repo = peer.local()
4009 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4009 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4010
4010
4011 if not repo:
4011 if not repo:
4012 if num or branch or tags:
4012 if num or branch or tags:
4013 raise util.Abort(
4013 raise util.Abort(
4014 _("can't query remote revision number, branch, or tags"))
4014 _("can't query remote revision number, branch, or tags"))
4015 if not rev and revs:
4015 if not rev and revs:
4016 rev = revs[0]
4016 rev = revs[0]
4017 if not rev:
4017 if not rev:
4018 rev = "tip"
4018 rev = "tip"
4019
4019
4020 remoterev = peer.lookup(rev)
4020 remoterev = peer.lookup(rev)
4021 if default or id:
4021 if default or id:
4022 output = [hexfunc(remoterev)]
4022 output = [hexfunc(remoterev)]
4023
4023
4024 def getbms():
4024 def getbms():
4025 bms = []
4025 bms = []
4026
4026
4027 if 'bookmarks' in peer.listkeys('namespaces'):
4027 if 'bookmarks' in peer.listkeys('namespaces'):
4028 hexremoterev = hex(remoterev)
4028 hexremoterev = hex(remoterev)
4029 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4029 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4030 if bmr == hexremoterev]
4030 if bmr == hexremoterev]
4031
4031
4032 return sorted(bms)
4032 return sorted(bms)
4033
4033
4034 if bookmarks:
4034 if bookmarks:
4035 output.extend(getbms())
4035 output.extend(getbms())
4036 elif default and not ui.quiet:
4036 elif default and not ui.quiet:
4037 # multiple bookmarks for a single parent separated by '/'
4037 # multiple bookmarks for a single parent separated by '/'
4038 bm = '/'.join(getbms())
4038 bm = '/'.join(getbms())
4039 if bm:
4039 if bm:
4040 output.append(bm)
4040 output.append(bm)
4041 else:
4041 else:
4042 if not rev:
4042 if not rev:
4043 ctx = repo[None]
4043 ctx = repo[None]
4044 parents = ctx.parents()
4044 parents = ctx.parents()
4045 changed = ""
4045 changed = ""
4046 if default or id or num:
4046 if default or id or num:
4047 if (util.any(repo.status())
4047 if (util.any(repo.status())
4048 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4048 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4049 changed = '+'
4049 changed = '+'
4050 if default or id:
4050 if default or id:
4051 output = ["%s%s" %
4051 output = ["%s%s" %
4052 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4052 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4053 if num:
4053 if num:
4054 output.append("%s%s" %
4054 output.append("%s%s" %
4055 ('+'.join([str(p.rev()) for p in parents]), changed))
4055 ('+'.join([str(p.rev()) for p in parents]), changed))
4056 else:
4056 else:
4057 ctx = scmutil.revsingle(repo, rev)
4057 ctx = scmutil.revsingle(repo, rev)
4058 if default or id:
4058 if default or id:
4059 output = [hexfunc(ctx.node())]
4059 output = [hexfunc(ctx.node())]
4060 if num:
4060 if num:
4061 output.append(str(ctx.rev()))
4061 output.append(str(ctx.rev()))
4062
4062
4063 if default and not ui.quiet:
4063 if default and not ui.quiet:
4064 b = ctx.branch()
4064 b = ctx.branch()
4065 if b != 'default':
4065 if b != 'default':
4066 output.append("(%s)" % b)
4066 output.append("(%s)" % b)
4067
4067
4068 # multiple tags for a single parent separated by '/'
4068 # multiple tags for a single parent separated by '/'
4069 t = '/'.join(ctx.tags())
4069 t = '/'.join(ctx.tags())
4070 if t:
4070 if t:
4071 output.append(t)
4071 output.append(t)
4072
4072
4073 # multiple bookmarks for a single parent separated by '/'
4073 # multiple bookmarks for a single parent separated by '/'
4074 bm = '/'.join(ctx.bookmarks())
4074 bm = '/'.join(ctx.bookmarks())
4075 if bm:
4075 if bm:
4076 output.append(bm)
4076 output.append(bm)
4077 else:
4077 else:
4078 if branch:
4078 if branch:
4079 output.append(ctx.branch())
4079 output.append(ctx.branch())
4080
4080
4081 if tags:
4081 if tags:
4082 output.extend(ctx.tags())
4082 output.extend(ctx.tags())
4083
4083
4084 if bookmarks:
4084 if bookmarks:
4085 output.extend(ctx.bookmarks())
4085 output.extend(ctx.bookmarks())
4086
4086
4087 ui.write("%s\n" % ' '.join(output))
4087 ui.write("%s\n" % ' '.join(output))
4088
4088
4089 @command('import|patch',
4089 @command('import|patch',
4090 [('p', 'strip', 1,
4090 [('p', 'strip', 1,
4091 _('directory strip option for patch. This has the same '
4091 _('directory strip option for patch. This has the same '
4092 'meaning as the corresponding patch option'), _('NUM')),
4092 'meaning as the corresponding patch option'), _('NUM')),
4093 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4093 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4094 ('e', 'edit', False, _('invoke editor on commit messages')),
4094 ('e', 'edit', False, _('invoke editor on commit messages')),
4095 ('f', 'force', None,
4095 ('f', 'force', None,
4096 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4096 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4097 ('', 'no-commit', None,
4097 ('', 'no-commit', None,
4098 _("don't commit, just update the working directory")),
4098 _("don't commit, just update the working directory")),
4099 ('', 'bypass', None,
4099 ('', 'bypass', None,
4100 _("apply patch without touching the working directory")),
4100 _("apply patch without touching the working directory")),
4101 ('', 'partial', None,
4101 ('', 'partial', None,
4102 _('commit even if some hunks fail')),
4102 _('commit even if some hunks fail')),
4103 ('', 'exact', None,
4103 ('', 'exact', None,
4104 _('apply patch to the nodes from which it was generated')),
4104 _('apply patch to the nodes from which it was generated')),
4105 ('', 'prefix', '',
4105 ('', 'prefix', '',
4106 _('apply patch to subdirectory'), _('DIR')),
4106 _('apply patch to subdirectory'), _('DIR')),
4107 ('', 'import-branch', None,
4107 ('', 'import-branch', None,
4108 _('use any branch information in patch (implied by --exact)'))] +
4108 _('use any branch information in patch (implied by --exact)'))] +
4109 commitopts + commitopts2 + similarityopts,
4109 commitopts + commitopts2 + similarityopts,
4110 _('[OPTION]... PATCH...'))
4110 _('[OPTION]... PATCH...'))
4111 def import_(ui, repo, patch1=None, *patches, **opts):
4111 def import_(ui, repo, patch1=None, *patches, **opts):
4112 """import an ordered set of patches
4112 """import an ordered set of patches
4113
4113
4114 Import a list of patches and commit them individually (unless
4114 Import a list of patches and commit them individually (unless
4115 --no-commit is specified).
4115 --no-commit is specified).
4116
4116
4117 Because import first applies changes to the working directory,
4117 Because import first applies changes to the working directory,
4118 import will abort if there are outstanding changes.
4118 import will abort if there are outstanding changes.
4119
4119
4120 You can import a patch straight from a mail message. Even patches
4120 You can import a patch straight from a mail message. Even patches
4121 as attachments work (to use the body part, it must have type
4121 as attachments work (to use the body part, it must have type
4122 text/plain or text/x-patch). From and Subject headers of email
4122 text/plain or text/x-patch). From and Subject headers of email
4123 message are used as default committer and commit message. All
4123 message are used as default committer and commit message. All
4124 text/plain body parts before first diff are added to commit
4124 text/plain body parts before first diff are added to commit
4125 message.
4125 message.
4126
4126
4127 If the imported patch was generated by :hg:`export`, user and
4127 If the imported patch was generated by :hg:`export`, user and
4128 description from patch override values from message headers and
4128 description from patch override values from message headers and
4129 body. Values given on command line with -m/--message and -u/--user
4129 body. Values given on command line with -m/--message and -u/--user
4130 override these.
4130 override these.
4131
4131
4132 If --exact is specified, import will set the working directory to
4132 If --exact is specified, import will set the working directory to
4133 the parent of each patch before applying it, and will abort if the
4133 the parent of each patch before applying it, and will abort if the
4134 resulting changeset has a different ID than the one recorded in
4134 resulting changeset has a different ID than the one recorded in
4135 the patch. This may happen due to character set problems or other
4135 the patch. This may happen due to character set problems or other
4136 deficiencies in the text patch format.
4136 deficiencies in the text patch format.
4137
4137
4138 Use --bypass to apply and commit patches directly to the
4138 Use --bypass to apply and commit patches directly to the
4139 repository, not touching the working directory. Without --exact,
4139 repository, not touching the working directory. Without --exact,
4140 patches will be applied on top of the working directory parent
4140 patches will be applied on top of the working directory parent
4141 revision.
4141 revision.
4142
4142
4143 With -s/--similarity, hg will attempt to discover renames and
4143 With -s/--similarity, hg will attempt to discover renames and
4144 copies in the patch in the same way as :hg:`addremove`.
4144 copies in the patch in the same way as :hg:`addremove`.
4145
4145
4146 Use --partial to ensure a changeset will be created from the patch
4146 Use --partial to ensure a changeset will be created from the patch
4147 even if some hunks fail to apply. Hunks that fail to apply will be
4147 even if some hunks fail to apply. Hunks that fail to apply will be
4148 written to a <target-file>.rej file. Conflicts can then be resolved
4148 written to a <target-file>.rej file. Conflicts can then be resolved
4149 by hand before :hg:`commit --amend` is run to update the created
4149 by hand before :hg:`commit --amend` is run to update the created
4150 changeset. This flag exists to let people import patches that
4150 changeset. This flag exists to let people import patches that
4151 partially apply without losing the associated metadata (author,
4151 partially apply without losing the associated metadata (author,
4152 date, description, ...). Note that when none of the hunk applies
4152 date, description, ...). Note that when none of the hunk applies
4153 cleanly, :hg:`import --partial` will create an empty changeset,
4153 cleanly, :hg:`import --partial` will create an empty changeset,
4154 importing only the patch metadata.
4154 importing only the patch metadata.
4155
4155
4156 To read a patch from standard input, use "-" as the patch name. If
4156 To read a patch from standard input, use "-" as the patch name. If
4157 a URL is specified, the patch will be downloaded from it.
4157 a URL is specified, the patch will be downloaded from it.
4158 See :hg:`help dates` for a list of formats valid for -d/--date.
4158 See :hg:`help dates` for a list of formats valid for -d/--date.
4159
4159
4160 .. container:: verbose
4160 .. container:: verbose
4161
4161
4162 Examples:
4162 Examples:
4163
4163
4164 - import a traditional patch from a website and detect renames::
4164 - import a traditional patch from a website and detect renames::
4165
4165
4166 hg import -s 80 http://example.com/bugfix.patch
4166 hg import -s 80 http://example.com/bugfix.patch
4167
4167
4168 - import a changeset from an hgweb server::
4168 - import a changeset from an hgweb server::
4169
4169
4170 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4170 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4171
4171
4172 - import all the patches in an Unix-style mbox::
4172 - import all the patches in an Unix-style mbox::
4173
4173
4174 hg import incoming-patches.mbox
4174 hg import incoming-patches.mbox
4175
4175
4176 - attempt to exactly restore an exported changeset (not always
4176 - attempt to exactly restore an exported changeset (not always
4177 possible)::
4177 possible)::
4178
4178
4179 hg import --exact proposed-fix.patch
4179 hg import --exact proposed-fix.patch
4180
4180
4181 Returns 0 on success, 1 on partial success (see --partial).
4181 Returns 0 on success, 1 on partial success (see --partial).
4182 """
4182 """
4183
4183
4184 if not patch1:
4184 if not patch1:
4185 raise util.Abort(_('need at least one patch to import'))
4185 raise util.Abort(_('need at least one patch to import'))
4186
4186
4187 patches = (patch1,) + patches
4187 patches = (patch1,) + patches
4188
4188
4189 date = opts.get('date')
4189 date = opts.get('date')
4190 if date:
4190 if date:
4191 opts['date'] = util.parsedate(date)
4191 opts['date'] = util.parsedate(date)
4192
4192
4193 update = not opts.get('bypass')
4193 update = not opts.get('bypass')
4194 if not update and opts.get('no_commit'):
4194 if not update and opts.get('no_commit'):
4195 raise util.Abort(_('cannot use --no-commit with --bypass'))
4195 raise util.Abort(_('cannot use --no-commit with --bypass'))
4196 try:
4196 try:
4197 sim = float(opts.get('similarity') or 0)
4197 sim = float(opts.get('similarity') or 0)
4198 except ValueError:
4198 except ValueError:
4199 raise util.Abort(_('similarity must be a number'))
4199 raise util.Abort(_('similarity must be a number'))
4200 if sim < 0 or sim > 100:
4200 if sim < 0 or sim > 100:
4201 raise util.Abort(_('similarity must be between 0 and 100'))
4201 raise util.Abort(_('similarity must be between 0 and 100'))
4202 if sim and not update:
4202 if sim and not update:
4203 raise util.Abort(_('cannot use --similarity with --bypass'))
4203 raise util.Abort(_('cannot use --similarity with --bypass'))
4204 if opts.get('exact') and opts.get('edit'):
4204 if opts.get('exact') and opts.get('edit'):
4205 raise util.Abort(_('cannot use --exact with --edit'))
4205 raise util.Abort(_('cannot use --exact with --edit'))
4206 if opts.get('exact') and opts.get('prefix'):
4206 if opts.get('exact') and opts.get('prefix'):
4207 raise util.Abort(_('cannot use --exact with --prefix'))
4207 raise util.Abort(_('cannot use --exact with --prefix'))
4208
4208
4209 if update:
4209 if update:
4210 cmdutil.checkunfinished(repo)
4210 cmdutil.checkunfinished(repo)
4211 if (opts.get('exact') or not opts.get('force')) and update:
4211 if (opts.get('exact') or not opts.get('force')) and update:
4212 cmdutil.bailifchanged(repo)
4212 cmdutil.bailifchanged(repo)
4213
4213
4214 base = opts["base"]
4214 base = opts["base"]
4215 wlock = lock = tr = None
4215 wlock = lock = tr = None
4216 msgs = []
4216 msgs = []
4217 ret = 0
4217 ret = 0
4218
4218
4219
4219
4220 try:
4220 try:
4221 try:
4221 try:
4222 wlock = repo.wlock()
4222 wlock = repo.wlock()
4223 repo.dirstate.beginparentchange()
4223 repo.dirstate.beginparentchange()
4224 if not opts.get('no_commit'):
4224 if not opts.get('no_commit'):
4225 lock = repo.lock()
4225 lock = repo.lock()
4226 tr = repo.transaction('import')
4226 tr = repo.transaction('import')
4227 parents = repo.parents()
4227 parents = repo.parents()
4228 for patchurl in patches:
4228 for patchurl in patches:
4229 if patchurl == '-':
4229 if patchurl == '-':
4230 ui.status(_('applying patch from stdin\n'))
4230 ui.status(_('applying patch from stdin\n'))
4231 patchfile = ui.fin
4231 patchfile = ui.fin
4232 patchurl = 'stdin' # for error message
4232 patchurl = 'stdin' # for error message
4233 else:
4233 else:
4234 patchurl = os.path.join(base, patchurl)
4234 patchurl = os.path.join(base, patchurl)
4235 ui.status(_('applying %s\n') % patchurl)
4235 ui.status(_('applying %s\n') % patchurl)
4236 patchfile = hg.openpath(ui, patchurl)
4236 patchfile = hg.openpath(ui, patchurl)
4237
4237
4238 haspatch = False
4238 haspatch = False
4239 for hunk in patch.split(patchfile):
4239 for hunk in patch.split(patchfile):
4240 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4240 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4241 parents, opts,
4241 parents, opts,
4242 msgs, hg.clean)
4242 msgs, hg.clean)
4243 if msg:
4243 if msg:
4244 haspatch = True
4244 haspatch = True
4245 ui.note(msg + '\n')
4245 ui.note(msg + '\n')
4246 if update or opts.get('exact'):
4246 if update or opts.get('exact'):
4247 parents = repo.parents()
4247 parents = repo.parents()
4248 else:
4248 else:
4249 parents = [repo[node]]
4249 parents = [repo[node]]
4250 if rej:
4250 if rej:
4251 ui.write_err(_("patch applied partially\n"))
4251 ui.write_err(_("patch applied partially\n"))
4252 ui.write_err(_("(fix the .rej files and run "
4252 ui.write_err(_("(fix the .rej files and run "
4253 "`hg commit --amend`)\n"))
4253 "`hg commit --amend`)\n"))
4254 ret = 1
4254 ret = 1
4255 break
4255 break
4256
4256
4257 if not haspatch:
4257 if not haspatch:
4258 raise util.Abort(_('%s: no diffs found') % patchurl)
4258 raise util.Abort(_('%s: no diffs found') % patchurl)
4259
4259
4260 if tr:
4260 if tr:
4261 tr.close()
4261 tr.close()
4262 if msgs:
4262 if msgs:
4263 repo.savecommitmessage('\n* * *\n'.join(msgs))
4263 repo.savecommitmessage('\n* * *\n'.join(msgs))
4264 repo.dirstate.endparentchange()
4264 repo.dirstate.endparentchange()
4265 return ret
4265 return ret
4266 except: # re-raises
4266 except: # re-raises
4267 # wlock.release() indirectly calls dirstate.write(): since
4267 # wlock.release() indirectly calls dirstate.write(): since
4268 # we're crashing, we do not want to change the working dir
4268 # we're crashing, we do not want to change the working dir
4269 # parent after all, so make sure it writes nothing
4269 # parent after all, so make sure it writes nothing
4270 repo.dirstate.invalidate()
4270 repo.dirstate.invalidate()
4271 raise
4271 raise
4272 finally:
4272 finally:
4273 if tr:
4273 if tr:
4274 tr.release()
4274 tr.release()
4275 release(lock, wlock)
4275 release(lock, wlock)
4276
4276
4277 @command('incoming|in',
4277 @command('incoming|in',
4278 [('f', 'force', None,
4278 [('f', 'force', None,
4279 _('run even if remote repository is unrelated')),
4279 _('run even if remote repository is unrelated')),
4280 ('n', 'newest-first', None, _('show newest record first')),
4280 ('n', 'newest-first', None, _('show newest record first')),
4281 ('', 'bundle', '',
4281 ('', 'bundle', '',
4282 _('file to store the bundles into'), _('FILE')),
4282 _('file to store the bundles into'), _('FILE')),
4283 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4283 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4284 ('B', 'bookmarks', False, _("compare bookmarks")),
4284 ('B', 'bookmarks', False, _("compare bookmarks")),
4285 ('b', 'branch', [],
4285 ('b', 'branch', [],
4286 _('a specific branch you would like to pull'), _('BRANCH')),
4286 _('a specific branch you would like to pull'), _('BRANCH')),
4287 ] + logopts + remoteopts + subrepoopts,
4287 ] + logopts + remoteopts + subrepoopts,
4288 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4288 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4289 def incoming(ui, repo, source="default", **opts):
4289 def incoming(ui, repo, source="default", **opts):
4290 """show new changesets found in source
4290 """show new changesets found in source
4291
4291
4292 Show new changesets found in the specified path/URL or the default
4292 Show new changesets found in the specified path/URL or the default
4293 pull location. These are the changesets that would have been pulled
4293 pull location. These are the changesets that would have been pulled
4294 if a pull at the time you issued this command.
4294 if a pull at the time you issued this command.
4295
4295
4296 See pull for valid source format details.
4296 See pull for valid source format details.
4297
4297
4298 .. container:: verbose
4298 .. container:: verbose
4299
4299
4300 With -B/--bookmarks, the result of bookmark comparison between
4300 With -B/--bookmarks, the result of bookmark comparison between
4301 local and remote repositories is displayed. With -v/--verbose,
4301 local and remote repositories is displayed. With -v/--verbose,
4302 status is also displayed for each bookmark like below::
4302 status is also displayed for each bookmark like below::
4303
4303
4304 BM1 01234567890a added
4304 BM1 01234567890a added
4305 BM2 1234567890ab advanced
4305 BM2 1234567890ab advanced
4306 BM3 234567890abc diverged
4306 BM3 234567890abc diverged
4307 BM4 34567890abcd changed
4307 BM4 34567890abcd changed
4308
4308
4309 The action taken locally when pulling depends on the
4309 The action taken locally when pulling depends on the
4310 status of each bookmark:
4310 status of each bookmark:
4311
4311
4312 :``added``: pull will create it
4312 :``added``: pull will create it
4313 :``advanced``: pull will update it
4313 :``advanced``: pull will update it
4314 :``diverged``: pull will create a divergent bookmark
4314 :``diverged``: pull will create a divergent bookmark
4315 :``changed``: result depends on remote changesets
4315 :``changed``: result depends on remote changesets
4316
4316
4317 From the point of view of pulling behavior, bookmark
4317 From the point of view of pulling behavior, bookmark
4318 existing only in the remote repository are treated as ``added``,
4318 existing only in the remote repository are treated as ``added``,
4319 even if it is in fact locally deleted.
4319 even if it is in fact locally deleted.
4320
4320
4321 .. container:: verbose
4321 .. container:: verbose
4322
4322
4323 For remote repository, using --bundle avoids downloading the
4323 For remote repository, using --bundle avoids downloading the
4324 changesets twice if the incoming is followed by a pull.
4324 changesets twice if the incoming is followed by a pull.
4325
4325
4326 Examples:
4326 Examples:
4327
4327
4328 - show incoming changes with patches and full description::
4328 - show incoming changes with patches and full description::
4329
4329
4330 hg incoming -vp
4330 hg incoming -vp
4331
4331
4332 - show incoming changes excluding merges, store a bundle::
4332 - show incoming changes excluding merges, store a bundle::
4333
4333
4334 hg in -vpM --bundle incoming.hg
4334 hg in -vpM --bundle incoming.hg
4335 hg pull incoming.hg
4335 hg pull incoming.hg
4336
4336
4337 - briefly list changes inside a bundle::
4337 - briefly list changes inside a bundle::
4338
4338
4339 hg in changes.hg -T "{desc|firstline}\\n"
4339 hg in changes.hg -T "{desc|firstline}\\n"
4340
4340
4341 Returns 0 if there are incoming changes, 1 otherwise.
4341 Returns 0 if there are incoming changes, 1 otherwise.
4342 """
4342 """
4343 if opts.get('graph'):
4343 if opts.get('graph'):
4344 cmdutil.checkunsupportedgraphflags([], opts)
4344 cmdutil.checkunsupportedgraphflags([], opts)
4345 def display(other, chlist, displayer):
4345 def display(other, chlist, displayer):
4346 revdag = cmdutil.graphrevs(other, chlist, opts)
4346 revdag = cmdutil.graphrevs(other, chlist, opts)
4347 showparents = [ctx.node() for ctx in repo[None].parents()]
4347 showparents = [ctx.node() for ctx in repo[None].parents()]
4348 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4348 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4349 graphmod.asciiedges)
4349 graphmod.asciiedges)
4350
4350
4351 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4351 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4352 return 0
4352 return 0
4353
4353
4354 if opts.get('bundle') and opts.get('subrepos'):
4354 if opts.get('bundle') and opts.get('subrepos'):
4355 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4355 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4356
4356
4357 if opts.get('bookmarks'):
4357 if opts.get('bookmarks'):
4358 source, branches = hg.parseurl(ui.expandpath(source),
4358 source, branches = hg.parseurl(ui.expandpath(source),
4359 opts.get('branch'))
4359 opts.get('branch'))
4360 other = hg.peer(repo, opts, source)
4360 other = hg.peer(repo, opts, source)
4361 if 'bookmarks' not in other.listkeys('namespaces'):
4361 if 'bookmarks' not in other.listkeys('namespaces'):
4362 ui.warn(_("remote doesn't support bookmarks\n"))
4362 ui.warn(_("remote doesn't support bookmarks\n"))
4363 return 0
4363 return 0
4364 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4364 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4365 return bookmarks.incoming(ui, repo, other)
4365 return bookmarks.incoming(ui, repo, other)
4366
4366
4367 repo._subtoppath = ui.expandpath(source)
4367 repo._subtoppath = ui.expandpath(source)
4368 try:
4368 try:
4369 return hg.incoming(ui, repo, source, opts)
4369 return hg.incoming(ui, repo, source, opts)
4370 finally:
4370 finally:
4371 del repo._subtoppath
4371 del repo._subtoppath
4372
4372
4373
4373
4374 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4374 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4375 norepo=True)
4375 norepo=True)
4376 def init(ui, dest=".", **opts):
4376 def init(ui, dest=".", **opts):
4377 """create a new repository in the given directory
4377 """create a new repository in the given directory
4378
4378
4379 Initialize a new repository in the given directory. If the given
4379 Initialize a new repository in the given directory. If the given
4380 directory does not exist, it will be created.
4380 directory does not exist, it will be created.
4381
4381
4382 If no directory is given, the current directory is used.
4382 If no directory is given, the current directory is used.
4383
4383
4384 It is possible to specify an ``ssh://`` URL as the destination.
4384 It is possible to specify an ``ssh://`` URL as the destination.
4385 See :hg:`help urls` for more information.
4385 See :hg:`help urls` for more information.
4386
4386
4387 Returns 0 on success.
4387 Returns 0 on success.
4388 """
4388 """
4389 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4389 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4390
4390
4391 @command('locate',
4391 @command('locate',
4392 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4392 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4393 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4393 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4394 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4394 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4395 ] + walkopts,
4395 ] + walkopts,
4396 _('[OPTION]... [PATTERN]...'))
4396 _('[OPTION]... [PATTERN]...'))
4397 def locate(ui, repo, *pats, **opts):
4397 def locate(ui, repo, *pats, **opts):
4398 """locate files matching specific patterns (DEPRECATED)
4398 """locate files matching specific patterns (DEPRECATED)
4399
4399
4400 Print files under Mercurial control in the working directory whose
4400 Print files under Mercurial control in the working directory whose
4401 names match the given patterns.
4401 names match the given patterns.
4402
4402
4403 By default, this command searches all directories in the working
4403 By default, this command searches all directories in the working
4404 directory. To search just the current directory and its
4404 directory. To search just the current directory and its
4405 subdirectories, use "--include .".
4405 subdirectories, use "--include .".
4406
4406
4407 If no patterns are given to match, this command prints the names
4407 If no patterns are given to match, this command prints the names
4408 of all files under Mercurial control in the working directory.
4408 of all files under Mercurial control in the working directory.
4409
4409
4410 If you want to feed the output of this command into the "xargs"
4410 If you want to feed the output of this command into the "xargs"
4411 command, use the -0 option to both this command and "xargs". This
4411 command, use the -0 option to both this command and "xargs". This
4412 will avoid the problem of "xargs" treating single filenames that
4412 will avoid the problem of "xargs" treating single filenames that
4413 contain whitespace as multiple filenames.
4413 contain whitespace as multiple filenames.
4414
4414
4415 See :hg:`help files` for a more versatile command.
4415 See :hg:`help files` for a more versatile command.
4416
4416
4417 Returns 0 if a match is found, 1 otherwise.
4417 Returns 0 if a match is found, 1 otherwise.
4418 """
4418 """
4419 if opts.get('print0'):
4419 if opts.get('print0'):
4420 end = '\0'
4420 end = '\0'
4421 else:
4421 else:
4422 end = '\n'
4422 end = '\n'
4423 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4423 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4424
4424
4425 ret = 1
4425 ret = 1
4426 ctx = repo[rev]
4426 ctx = repo[rev]
4427 m = scmutil.match(ctx, pats, opts, default='relglob')
4427 m = scmutil.match(ctx, pats, opts, default='relglob')
4428 m.bad = lambda x, y: False
4428 m.bad = lambda x, y: False
4429
4429
4430 for abs in ctx.matches(m):
4430 for abs in ctx.matches(m):
4431 if opts.get('fullpath'):
4431 if opts.get('fullpath'):
4432 ui.write(repo.wjoin(abs), end)
4432 ui.write(repo.wjoin(abs), end)
4433 else:
4433 else:
4434 ui.write(((pats and m.rel(abs)) or abs), end)
4434 ui.write(((pats and m.rel(abs)) or abs), end)
4435 ret = 0
4435 ret = 0
4436
4436
4437 return ret
4437 return ret
4438
4438
4439 @command('^log|history',
4439 @command('^log|history',
4440 [('f', 'follow', None,
4440 [('f', 'follow', None,
4441 _('follow changeset history, or file history across copies and renames')),
4441 _('follow changeset history, or file history across copies and renames')),
4442 ('', 'follow-first', None,
4442 ('', 'follow-first', None,
4443 _('only follow the first parent of merge changesets (DEPRECATED)')),
4443 _('only follow the first parent of merge changesets (DEPRECATED)')),
4444 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4444 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4445 ('C', 'copies', None, _('show copied files')),
4445 ('C', 'copies', None, _('show copied files')),
4446 ('k', 'keyword', [],
4446 ('k', 'keyword', [],
4447 _('do case-insensitive search for a given text'), _('TEXT')),
4447 _('do case-insensitive search for a given text'), _('TEXT')),
4448 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4448 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4449 ('', 'removed', None, _('include revisions where files were removed')),
4449 ('', 'removed', None, _('include revisions where files were removed')),
4450 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4450 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4451 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4451 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4452 ('', 'only-branch', [],
4452 ('', 'only-branch', [],
4453 _('show only changesets within the given named branch (DEPRECATED)'),
4453 _('show only changesets within the given named branch (DEPRECATED)'),
4454 _('BRANCH')),
4454 _('BRANCH')),
4455 ('b', 'branch', [],
4455 ('b', 'branch', [],
4456 _('show changesets within the given named branch'), _('BRANCH')),
4456 _('show changesets within the given named branch'), _('BRANCH')),
4457 ('P', 'prune', [],
4457 ('P', 'prune', [],
4458 _('do not display revision or any of its ancestors'), _('REV')),
4458 _('do not display revision or any of its ancestors'), _('REV')),
4459 ] + logopts + walkopts,
4459 ] + logopts + walkopts,
4460 _('[OPTION]... [FILE]'),
4460 _('[OPTION]... [FILE]'),
4461 inferrepo=True)
4461 inferrepo=True)
4462 def log(ui, repo, *pats, **opts):
4462 def log(ui, repo, *pats, **opts):
4463 """show revision history of entire repository or files
4463 """show revision history of entire repository or files
4464
4464
4465 Print the revision history of the specified files or the entire
4465 Print the revision history of the specified files or the entire
4466 project.
4466 project.
4467
4467
4468 If no revision range is specified, the default is ``tip:0`` unless
4468 If no revision range is specified, the default is ``tip:0`` unless
4469 --follow is set, in which case the working directory parent is
4469 --follow is set, in which case the working directory parent is
4470 used as the starting revision.
4470 used as the starting revision.
4471
4471
4472 File history is shown without following rename or copy history of
4472 File history is shown without following rename or copy history of
4473 files. Use -f/--follow with a filename to follow history across
4473 files. Use -f/--follow with a filename to follow history across
4474 renames and copies. --follow without a filename will only show
4474 renames and copies. --follow without a filename will only show
4475 ancestors or descendants of the starting revision.
4475 ancestors or descendants of the starting revision.
4476
4476
4477 By default this command prints revision number and changeset id,
4477 By default this command prints revision number and changeset id,
4478 tags, non-trivial parents, user, date and time, and a summary for
4478 tags, non-trivial parents, user, date and time, and a summary for
4479 each commit. When the -v/--verbose switch is used, the list of
4479 each commit. When the -v/--verbose switch is used, the list of
4480 changed files and full commit message are shown.
4480 changed files and full commit message are shown.
4481
4481
4482 With --graph the revisions are shown as an ASCII art DAG with the most
4482 With --graph the revisions are shown as an ASCII art DAG with the most
4483 recent changeset at the top.
4483 recent changeset at the top.
4484 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4484 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4485 and '+' represents a fork where the changeset from the lines below is a
4485 and '+' represents a fork where the changeset from the lines below is a
4486 parent of the 'o' merge on the same line.
4486 parent of the 'o' merge on the same line.
4487
4487
4488 .. note::
4488 .. note::
4489
4489
4490 log -p/--patch may generate unexpected diff output for merge
4490 log -p/--patch may generate unexpected diff output for merge
4491 changesets, as it will only compare the merge changeset against
4491 changesets, as it will only compare the merge changeset against
4492 its first parent. Also, only files different from BOTH parents
4492 its first parent. Also, only files different from BOTH parents
4493 will appear in files:.
4493 will appear in files:.
4494
4494
4495 .. note::
4495 .. note::
4496
4496
4497 for performance reasons, log FILE may omit duplicate changes
4497 for performance reasons, log FILE may omit duplicate changes
4498 made on branches and will not show removals or mode changes. To
4498 made on branches and will not show removals or mode changes. To
4499 see all such changes, use the --removed switch.
4499 see all such changes, use the --removed switch.
4500
4500
4501 .. container:: verbose
4501 .. container:: verbose
4502
4502
4503 Some examples:
4503 Some examples:
4504
4504
4505 - changesets with full descriptions and file lists::
4505 - changesets with full descriptions and file lists::
4506
4506
4507 hg log -v
4507 hg log -v
4508
4508
4509 - changesets ancestral to the working directory::
4509 - changesets ancestral to the working directory::
4510
4510
4511 hg log -f
4511 hg log -f
4512
4512
4513 - last 10 commits on the current branch::
4513 - last 10 commits on the current branch::
4514
4514
4515 hg log -l 10 -b .
4515 hg log -l 10 -b .
4516
4516
4517 - changesets showing all modifications of a file, including removals::
4517 - changesets showing all modifications of a file, including removals::
4518
4518
4519 hg log --removed file.c
4519 hg log --removed file.c
4520
4520
4521 - all changesets that touch a directory, with diffs, excluding merges::
4521 - all changesets that touch a directory, with diffs, excluding merges::
4522
4522
4523 hg log -Mp lib/
4523 hg log -Mp lib/
4524
4524
4525 - all revision numbers that match a keyword::
4525 - all revision numbers that match a keyword::
4526
4526
4527 hg log -k bug --template "{rev}\\n"
4527 hg log -k bug --template "{rev}\\n"
4528
4528
4529 - list available log templates::
4529 - list available log templates::
4530
4530
4531 hg log -T list
4531 hg log -T list
4532
4532
4533 - check if a given changeset is included in a tagged release::
4533 - check if a given changeset is included in a tagged release::
4534
4534
4535 hg log -r "a21ccf and ancestor(1.9)"
4535 hg log -r "a21ccf and ancestor(1.9)"
4536
4536
4537 - find all changesets by some user in a date range::
4537 - find all changesets by some user in a date range::
4538
4538
4539 hg log -k alice -d "may 2008 to jul 2008"
4539 hg log -k alice -d "may 2008 to jul 2008"
4540
4540
4541 - summary of all changesets after the last tag::
4541 - summary of all changesets after the last tag::
4542
4542
4543 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4543 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4544
4544
4545 See :hg:`help dates` for a list of formats valid for -d/--date.
4545 See :hg:`help dates` for a list of formats valid for -d/--date.
4546
4546
4547 See :hg:`help revisions` and :hg:`help revsets` for more about
4547 See :hg:`help revisions` and :hg:`help revsets` for more about
4548 specifying revisions.
4548 specifying revisions.
4549
4549
4550 See :hg:`help templates` for more about pre-packaged styles and
4550 See :hg:`help templates` for more about pre-packaged styles and
4551 specifying custom templates.
4551 specifying custom templates.
4552
4552
4553 Returns 0 on success.
4553 Returns 0 on success.
4554
4554
4555 """
4555 """
4556 if opts.get('follow') and opts.get('rev'):
4556 if opts.get('follow') and opts.get('rev'):
4557 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4557 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4558 del opts['follow']
4558 del opts['follow']
4559
4559
4560 if opts.get('graph'):
4560 if opts.get('graph'):
4561 return cmdutil.graphlog(ui, repo, *pats, **opts)
4561 return cmdutil.graphlog(ui, repo, *pats, **opts)
4562
4562
4563 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4563 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4564 limit = cmdutil.loglimit(opts)
4564 limit = cmdutil.loglimit(opts)
4565 count = 0
4565 count = 0
4566
4566
4567 getrenamed = None
4567 getrenamed = None
4568 if opts.get('copies'):
4568 if opts.get('copies'):
4569 endrev = None
4569 endrev = None
4570 if opts.get('rev'):
4570 if opts.get('rev'):
4571 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4571 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4572 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4572 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4573
4573
4574 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4574 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4575 for rev in revs:
4575 for rev in revs:
4576 if count == limit:
4576 if count == limit:
4577 break
4577 break
4578 ctx = repo[rev]
4578 ctx = repo[rev]
4579 copies = None
4579 copies = None
4580 if getrenamed is not None and rev:
4580 if getrenamed is not None and rev:
4581 copies = []
4581 copies = []
4582 for fn in ctx.files():
4582 for fn in ctx.files():
4583 rename = getrenamed(fn, rev)
4583 rename = getrenamed(fn, rev)
4584 if rename:
4584 if rename:
4585 copies.append((fn, rename[0]))
4585 copies.append((fn, rename[0]))
4586 if filematcher:
4586 if filematcher:
4587 revmatchfn = filematcher(ctx.rev())
4587 revmatchfn = filematcher(ctx.rev())
4588 else:
4588 else:
4589 revmatchfn = None
4589 revmatchfn = None
4590 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4590 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4591 if displayer.flush(rev):
4591 if displayer.flush(rev):
4592 count += 1
4592 count += 1
4593
4593
4594 displayer.close()
4594 displayer.close()
4595
4595
4596 @command('manifest',
4596 @command('manifest',
4597 [('r', 'rev', '', _('revision to display'), _('REV')),
4597 [('r', 'rev', '', _('revision to display'), _('REV')),
4598 ('', 'all', False, _("list files from all revisions"))]
4598 ('', 'all', False, _("list files from all revisions"))]
4599 + formatteropts,
4599 + formatteropts,
4600 _('[-r REV]'))
4600 _('[-r REV]'))
4601 def manifest(ui, repo, node=None, rev=None, **opts):
4601 def manifest(ui, repo, node=None, rev=None, **opts):
4602 """output the current or given revision of the project manifest
4602 """output the current or given revision of the project manifest
4603
4603
4604 Print a list of version controlled files for the given revision.
4604 Print a list of version controlled files for the given revision.
4605 If no revision is given, the first parent of the working directory
4605 If no revision is given, the first parent of the working directory
4606 is used, or the null revision if no revision is checked out.
4606 is used, or the null revision if no revision is checked out.
4607
4607
4608 With -v, print file permissions, symlink and executable bits.
4608 With -v, print file permissions, symlink and executable bits.
4609 With --debug, print file revision hashes.
4609 With --debug, print file revision hashes.
4610
4610
4611 If option --all is specified, the list of all files from all revisions
4611 If option --all is specified, the list of all files from all revisions
4612 is printed. This includes deleted and renamed files.
4612 is printed. This includes deleted and renamed files.
4613
4613
4614 Returns 0 on success.
4614 Returns 0 on success.
4615 """
4615 """
4616
4616
4617 fm = ui.formatter('manifest', opts)
4617 fm = ui.formatter('manifest', opts)
4618
4618
4619 if opts.get('all'):
4619 if opts.get('all'):
4620 if rev or node:
4620 if rev or node:
4621 raise util.Abort(_("can't specify a revision with --all"))
4621 raise util.Abort(_("can't specify a revision with --all"))
4622
4622
4623 res = []
4623 res = []
4624 prefix = "data/"
4624 prefix = "data/"
4625 suffix = ".i"
4625 suffix = ".i"
4626 plen = len(prefix)
4626 plen = len(prefix)
4627 slen = len(suffix)
4627 slen = len(suffix)
4628 lock = repo.lock()
4628 lock = repo.lock()
4629 try:
4629 try:
4630 for fn, b, size in repo.store.datafiles():
4630 for fn, b, size in repo.store.datafiles():
4631 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4631 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4632 res.append(fn[plen:-slen])
4632 res.append(fn[plen:-slen])
4633 finally:
4633 finally:
4634 lock.release()
4634 lock.release()
4635 for f in res:
4635 for f in res:
4636 fm.startitem()
4636 fm.startitem()
4637 fm.write("path", '%s\n', f)
4637 fm.write("path", '%s\n', f)
4638 fm.end()
4638 fm.end()
4639 return
4639 return
4640
4640
4641 if rev and node:
4641 if rev and node:
4642 raise util.Abort(_("please specify just one revision"))
4642 raise util.Abort(_("please specify just one revision"))
4643
4643
4644 if not node:
4644 if not node:
4645 node = rev
4645 node = rev
4646
4646
4647 char = {'l': '@', 'x': '*', '': ''}
4647 char = {'l': '@', 'x': '*', '': ''}
4648 mode = {'l': '644', 'x': '755', '': '644'}
4648 mode = {'l': '644', 'x': '755', '': '644'}
4649 ctx = scmutil.revsingle(repo, node)
4649 ctx = scmutil.revsingle(repo, node)
4650 mf = ctx.manifest()
4650 mf = ctx.manifest()
4651 for f in ctx:
4651 for f in ctx:
4652 fm.startitem()
4652 fm.startitem()
4653 fl = ctx[f].flags()
4653 fl = ctx[f].flags()
4654 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4654 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4655 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4655 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4656 fm.write('path', '%s\n', f)
4656 fm.write('path', '%s\n', f)
4657 fm.end()
4657 fm.end()
4658
4658
4659 @command('^merge',
4659 @command('^merge',
4660 [('f', 'force', None,
4660 [('f', 'force', None,
4661 _('force a merge including outstanding changes (DEPRECATED)')),
4661 _('force a merge including outstanding changes (DEPRECATED)')),
4662 ('r', 'rev', '', _('revision to merge'), _('REV')),
4662 ('r', 'rev', '', _('revision to merge'), _('REV')),
4663 ('P', 'preview', None,
4663 ('P', 'preview', None,
4664 _('review revisions to merge (no merge is performed)'))
4664 _('review revisions to merge (no merge is performed)'))
4665 ] + mergetoolopts,
4665 ] + mergetoolopts,
4666 _('[-P] [-f] [[-r] REV]'))
4666 _('[-P] [-f] [[-r] REV]'))
4667 def merge(ui, repo, node=None, **opts):
4667 def merge(ui, repo, node=None, **opts):
4668 """merge another revision into working directory
4668 """merge another revision into working directory
4669
4669
4670 The current working directory is updated with all changes made in
4670 The current working directory is updated with all changes made in
4671 the requested revision since the last common predecessor revision.
4671 the requested revision since the last common predecessor revision.
4672
4672
4673 Files that changed between either parent are marked as changed for
4673 Files that changed between either parent are marked as changed for
4674 the next commit and a commit must be performed before any further
4674 the next commit and a commit must be performed before any further
4675 updates to the repository are allowed. The next commit will have
4675 updates to the repository are allowed. The next commit will have
4676 two parents.
4676 two parents.
4677
4677
4678 ``--tool`` can be used to specify the merge tool used for file
4678 ``--tool`` can be used to specify the merge tool used for file
4679 merges. It overrides the HGMERGE environment variable and your
4679 merges. It overrides the HGMERGE environment variable and your
4680 configuration files. See :hg:`help merge-tools` for options.
4680 configuration files. See :hg:`help merge-tools` for options.
4681
4681
4682 If no revision is specified, the working directory's parent is a
4682 If no revision is specified, the working directory's parent is a
4683 head revision, and the current branch contains exactly one other
4683 head revision, and the current branch contains exactly one other
4684 head, the other head is merged with by default. Otherwise, an
4684 head, the other head is merged with by default. Otherwise, an
4685 explicit revision with which to merge with must be provided.
4685 explicit revision with which to merge with must be provided.
4686
4686
4687 :hg:`resolve` must be used to resolve unresolved files.
4687 :hg:`resolve` must be used to resolve unresolved files.
4688
4688
4689 To undo an uncommitted merge, use :hg:`update --clean .` which
4689 To undo an uncommitted merge, use :hg:`update --clean .` which
4690 will check out a clean copy of the original merge parent, losing
4690 will check out a clean copy of the original merge parent, losing
4691 all changes.
4691 all changes.
4692
4692
4693 Returns 0 on success, 1 if there are unresolved files.
4693 Returns 0 on success, 1 if there are unresolved files.
4694 """
4694 """
4695
4695
4696 if opts.get('rev') and node:
4696 if opts.get('rev') and node:
4697 raise util.Abort(_("please specify just one revision"))
4697 raise util.Abort(_("please specify just one revision"))
4698 if not node:
4698 if not node:
4699 node = opts.get('rev')
4699 node = opts.get('rev')
4700
4700
4701 if node:
4701 if node:
4702 node = scmutil.revsingle(repo, node).node()
4702 node = scmutil.revsingle(repo, node).node()
4703
4703
4704 if not node and repo._bookmarkcurrent:
4704 if not node and repo._bookmarkcurrent:
4705 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4705 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4706 curhead = repo[repo._bookmarkcurrent].node()
4706 curhead = repo[repo._bookmarkcurrent].node()
4707 if len(bmheads) == 2:
4707 if len(bmheads) == 2:
4708 if curhead == bmheads[0]:
4708 if curhead == bmheads[0]:
4709 node = bmheads[1]
4709 node = bmheads[1]
4710 else:
4710 else:
4711 node = bmheads[0]
4711 node = bmheads[0]
4712 elif len(bmheads) > 2:
4712 elif len(bmheads) > 2:
4713 raise util.Abort(_("multiple matching bookmarks to merge - "
4713 raise util.Abort(_("multiple matching bookmarks to merge - "
4714 "please merge with an explicit rev or bookmark"),
4714 "please merge with an explicit rev or bookmark"),
4715 hint=_("run 'hg heads' to see all heads"))
4715 hint=_("run 'hg heads' to see all heads"))
4716 elif len(bmheads) <= 1:
4716 elif len(bmheads) <= 1:
4717 raise util.Abort(_("no matching bookmark to merge - "
4717 raise util.Abort(_("no matching bookmark to merge - "
4718 "please merge with an explicit rev or bookmark"),
4718 "please merge with an explicit rev or bookmark"),
4719 hint=_("run 'hg heads' to see all heads"))
4719 hint=_("run 'hg heads' to see all heads"))
4720
4720
4721 if not node and not repo._bookmarkcurrent:
4721 if not node and not repo._bookmarkcurrent:
4722 branch = repo[None].branch()
4722 branch = repo[None].branch()
4723 bheads = repo.branchheads(branch)
4723 bheads = repo.branchheads(branch)
4724 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4724 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4725
4725
4726 if len(nbhs) > 2:
4726 if len(nbhs) > 2:
4727 raise util.Abort(_("branch '%s' has %d heads - "
4727 raise util.Abort(_("branch '%s' has %d heads - "
4728 "please merge with an explicit rev")
4728 "please merge with an explicit rev")
4729 % (branch, len(bheads)),
4729 % (branch, len(bheads)),
4730 hint=_("run 'hg heads .' to see heads"))
4730 hint=_("run 'hg heads .' to see heads"))
4731
4731
4732 parent = repo.dirstate.p1()
4732 parent = repo.dirstate.p1()
4733 if len(nbhs) <= 1:
4733 if len(nbhs) <= 1:
4734 if len(bheads) > 1:
4734 if len(bheads) > 1:
4735 raise util.Abort(_("heads are bookmarked - "
4735 raise util.Abort(_("heads are bookmarked - "
4736 "please merge with an explicit rev"),
4736 "please merge with an explicit rev"),
4737 hint=_("run 'hg heads' to see all heads"))
4737 hint=_("run 'hg heads' to see all heads"))
4738 if len(repo.heads()) > 1:
4738 if len(repo.heads()) > 1:
4739 raise util.Abort(_("branch '%s' has one head - "
4739 raise util.Abort(_("branch '%s' has one head - "
4740 "please merge with an explicit rev")
4740 "please merge with an explicit rev")
4741 % branch,
4741 % branch,
4742 hint=_("run 'hg heads' to see all heads"))
4742 hint=_("run 'hg heads' to see all heads"))
4743 msg, hint = _('nothing to merge'), None
4743 msg, hint = _('nothing to merge'), None
4744 if parent != repo.lookup(branch):
4744 if parent != repo.lookup(branch):
4745 hint = _("use 'hg update' instead")
4745 hint = _("use 'hg update' instead")
4746 raise util.Abort(msg, hint=hint)
4746 raise util.Abort(msg, hint=hint)
4747
4747
4748 if parent not in bheads:
4748 if parent not in bheads:
4749 raise util.Abort(_('working directory not at a head revision'),
4749 raise util.Abort(_('working directory not at a head revision'),
4750 hint=_("use 'hg update' or merge with an "
4750 hint=_("use 'hg update' or merge with an "
4751 "explicit revision"))
4751 "explicit revision"))
4752 if parent == nbhs[0]:
4752 if parent == nbhs[0]:
4753 node = nbhs[-1]
4753 node = nbhs[-1]
4754 else:
4754 else:
4755 node = nbhs[0]
4755 node = nbhs[0]
4756
4756
4757 if opts.get('preview'):
4757 if opts.get('preview'):
4758 # find nodes that are ancestors of p2 but not of p1
4758 # find nodes that are ancestors of p2 but not of p1
4759 p1 = repo.lookup('.')
4759 p1 = repo.lookup('.')
4760 p2 = repo.lookup(node)
4760 p2 = repo.lookup(node)
4761 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4761 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4762
4762
4763 displayer = cmdutil.show_changeset(ui, repo, opts)
4763 displayer = cmdutil.show_changeset(ui, repo, opts)
4764 for node in nodes:
4764 for node in nodes:
4765 displayer.show(repo[node])
4765 displayer.show(repo[node])
4766 displayer.close()
4766 displayer.close()
4767 return 0
4767 return 0
4768
4768
4769 try:
4769 try:
4770 # ui.forcemerge is an internal variable, do not document
4770 # ui.forcemerge is an internal variable, do not document
4771 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4771 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4772 return hg.merge(repo, node, force=opts.get('force'))
4772 return hg.merge(repo, node, force=opts.get('force'))
4773 finally:
4773 finally:
4774 ui.setconfig('ui', 'forcemerge', '', 'merge')
4774 ui.setconfig('ui', 'forcemerge', '', 'merge')
4775
4775
4776 @command('outgoing|out',
4776 @command('outgoing|out',
4777 [('f', 'force', None, _('run even when the destination is unrelated')),
4777 [('f', 'force', None, _('run even when the destination is unrelated')),
4778 ('r', 'rev', [],
4778 ('r', 'rev', [],
4779 _('a changeset intended to be included in the destination'), _('REV')),
4779 _('a changeset intended to be included in the destination'), _('REV')),
4780 ('n', 'newest-first', None, _('show newest record first')),
4780 ('n', 'newest-first', None, _('show newest record first')),
4781 ('B', 'bookmarks', False, _('compare bookmarks')),
4781 ('B', 'bookmarks', False, _('compare bookmarks')),
4782 ('b', 'branch', [], _('a specific branch you would like to push'),
4782 ('b', 'branch', [], _('a specific branch you would like to push'),
4783 _('BRANCH')),
4783 _('BRANCH')),
4784 ] + logopts + remoteopts + subrepoopts,
4784 ] + logopts + remoteopts + subrepoopts,
4785 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4785 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4786 def outgoing(ui, repo, dest=None, **opts):
4786 def outgoing(ui, repo, dest=None, **opts):
4787 """show changesets not found in the destination
4787 """show changesets not found in the destination
4788
4788
4789 Show changesets not found in the specified destination repository
4789 Show changesets not found in the specified destination repository
4790 or the default push location. These are the changesets that would
4790 or the default push location. These are the changesets that would
4791 be pushed if a push was requested.
4791 be pushed if a push was requested.
4792
4792
4793 See pull for details of valid destination formats.
4793 See pull for details of valid destination formats.
4794
4794
4795 .. container:: verbose
4795 .. container:: verbose
4796
4796
4797 With -B/--bookmarks, the result of bookmark comparison between
4797 With -B/--bookmarks, the result of bookmark comparison between
4798 local and remote repositories is displayed. With -v/--verbose,
4798 local and remote repositories is displayed. With -v/--verbose,
4799 status is also displayed for each bookmark like below::
4799 status is also displayed for each bookmark like below::
4800
4800
4801 BM1 01234567890a added
4801 BM1 01234567890a added
4802 BM2 deleted
4802 BM2 deleted
4803 BM3 234567890abc advanced
4803 BM3 234567890abc advanced
4804 BM4 34567890abcd diverged
4804 BM4 34567890abcd diverged
4805 BM5 4567890abcde changed
4805 BM5 4567890abcde changed
4806
4806
4807 The action taken when pushing depends on the
4807 The action taken when pushing depends on the
4808 status of each bookmark:
4808 status of each bookmark:
4809
4809
4810 :``added``: push with ``-B`` will create it
4810 :``added``: push with ``-B`` will create it
4811 :``deleted``: push with ``-B`` will delete it
4811 :``deleted``: push with ``-B`` will delete it
4812 :``advanced``: push will update it
4812 :``advanced``: push will update it
4813 :``diverged``: push with ``-B`` will update it
4813 :``diverged``: push with ``-B`` will update it
4814 :``changed``: push with ``-B`` will update it
4814 :``changed``: push with ``-B`` will update it
4815
4815
4816 From the point of view of pushing behavior, bookmarks
4816 From the point of view of pushing behavior, bookmarks
4817 existing only in the remote repository are treated as
4817 existing only in the remote repository are treated as
4818 ``deleted``, even if it is in fact added remotely.
4818 ``deleted``, even if it is in fact added remotely.
4819
4819
4820 Returns 0 if there are outgoing changes, 1 otherwise.
4820 Returns 0 if there are outgoing changes, 1 otherwise.
4821 """
4821 """
4822 if opts.get('graph'):
4822 if opts.get('graph'):
4823 cmdutil.checkunsupportedgraphflags([], opts)
4823 cmdutil.checkunsupportedgraphflags([], opts)
4824 o, other = hg._outgoing(ui, repo, dest, opts)
4824 o, other = hg._outgoing(ui, repo, dest, opts)
4825 if not o:
4825 if not o:
4826 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4826 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4827 return
4827 return
4828
4828
4829 revdag = cmdutil.graphrevs(repo, o, opts)
4829 revdag = cmdutil.graphrevs(repo, o, opts)
4830 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4830 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4831 showparents = [ctx.node() for ctx in repo[None].parents()]
4831 showparents = [ctx.node() for ctx in repo[None].parents()]
4832 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4832 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4833 graphmod.asciiedges)
4833 graphmod.asciiedges)
4834 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4834 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4835 return 0
4835 return 0
4836
4836
4837 if opts.get('bookmarks'):
4837 if opts.get('bookmarks'):
4838 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4838 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4839 dest, branches = hg.parseurl(dest, opts.get('branch'))
4839 dest, branches = hg.parseurl(dest, opts.get('branch'))
4840 other = hg.peer(repo, opts, dest)
4840 other = hg.peer(repo, opts, dest)
4841 if 'bookmarks' not in other.listkeys('namespaces'):
4841 if 'bookmarks' not in other.listkeys('namespaces'):
4842 ui.warn(_("remote doesn't support bookmarks\n"))
4842 ui.warn(_("remote doesn't support bookmarks\n"))
4843 return 0
4843 return 0
4844 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4844 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4845 return bookmarks.outgoing(ui, repo, other)
4845 return bookmarks.outgoing(ui, repo, other)
4846
4846
4847 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4847 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4848 try:
4848 try:
4849 return hg.outgoing(ui, repo, dest, opts)
4849 return hg.outgoing(ui, repo, dest, opts)
4850 finally:
4850 finally:
4851 del repo._subtoppath
4851 del repo._subtoppath
4852
4852
4853 @command('parents',
4853 @command('parents',
4854 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4854 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4855 ] + templateopts,
4855 ] + templateopts,
4856 _('[-r REV] [FILE]'),
4856 _('[-r REV] [FILE]'),
4857 inferrepo=True)
4857 inferrepo=True)
4858 def parents(ui, repo, file_=None, **opts):
4858 def parents(ui, repo, file_=None, **opts):
4859 """show the parents of the working directory or revision (DEPRECATED)
4859 """show the parents of the working directory or revision (DEPRECATED)
4860
4860
4861 Print the working directory's parent revisions. If a revision is
4861 Print the working directory's parent revisions. If a revision is
4862 given via -r/--rev, the parent of that revision will be printed.
4862 given via -r/--rev, the parent of that revision will be printed.
4863 If a file argument is given, the revision in which the file was
4863 If a file argument is given, the revision in which the file was
4864 last changed (before the working directory revision or the
4864 last changed (before the working directory revision or the
4865 argument to --rev if given) is printed.
4865 argument to --rev if given) is printed.
4866
4866
4867 See :hg:`summary` and :hg:`help revsets` for related information.
4867 See :hg:`summary` and :hg:`help revsets` for related information.
4868
4868
4869 Returns 0 on success.
4869 Returns 0 on success.
4870 """
4870 """
4871
4871
4872 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4872 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4873
4873
4874 if file_:
4874 if file_:
4875 m = scmutil.match(ctx, (file_,), opts)
4875 m = scmutil.match(ctx, (file_,), opts)
4876 if m.anypats() or len(m.files()) != 1:
4876 if m.anypats() or len(m.files()) != 1:
4877 raise util.Abort(_('can only specify an explicit filename'))
4877 raise util.Abort(_('can only specify an explicit filename'))
4878 file_ = m.files()[0]
4878 file_ = m.files()[0]
4879 filenodes = []
4879 filenodes = []
4880 for cp in ctx.parents():
4880 for cp in ctx.parents():
4881 if not cp:
4881 if not cp:
4882 continue
4882 continue
4883 try:
4883 try:
4884 filenodes.append(cp.filenode(file_))
4884 filenodes.append(cp.filenode(file_))
4885 except error.LookupError:
4885 except error.LookupError:
4886 pass
4886 pass
4887 if not filenodes:
4887 if not filenodes:
4888 raise util.Abort(_("'%s' not found in manifest!") % file_)
4888 raise util.Abort(_("'%s' not found in manifest!") % file_)
4889 p = []
4889 p = []
4890 for fn in filenodes:
4890 for fn in filenodes:
4891 fctx = repo.filectx(file_, fileid=fn)
4891 fctx = repo.filectx(file_, fileid=fn)
4892 p.append(fctx.node())
4892 p.append(fctx.node())
4893 else:
4893 else:
4894 p = [cp.node() for cp in ctx.parents()]
4894 p = [cp.node() for cp in ctx.parents()]
4895
4895
4896 displayer = cmdutil.show_changeset(ui, repo, opts)
4896 displayer = cmdutil.show_changeset(ui, repo, opts)
4897 for n in p:
4897 for n in p:
4898 if n != nullid:
4898 if n != nullid:
4899 displayer.show(repo[n])
4899 displayer.show(repo[n])
4900 displayer.close()
4900 displayer.close()
4901
4901
4902 @command('paths', [], _('[NAME]'), optionalrepo=True)
4902 @command('paths', [], _('[NAME]'), optionalrepo=True)
4903 def paths(ui, repo, search=None):
4903 def paths(ui, repo, search=None):
4904 """show aliases for remote repositories
4904 """show aliases for remote repositories
4905
4905
4906 Show definition of symbolic path name NAME. If no name is given,
4906 Show definition of symbolic path name NAME. If no name is given,
4907 show definition of all available names.
4907 show definition of all available names.
4908
4908
4909 Option -q/--quiet suppresses all output when searching for NAME
4909 Option -q/--quiet suppresses all output when searching for NAME
4910 and shows only the path names when listing all definitions.
4910 and shows only the path names when listing all definitions.
4911
4911
4912 Path names are defined in the [paths] section of your
4912 Path names are defined in the [paths] section of your
4913 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4913 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4914 repository, ``.hg/hgrc`` is used, too.
4914 repository, ``.hg/hgrc`` is used, too.
4915
4915
4916 The path names ``default`` and ``default-push`` have a special
4916 The path names ``default`` and ``default-push`` have a special
4917 meaning. When performing a push or pull operation, they are used
4917 meaning. When performing a push or pull operation, they are used
4918 as fallbacks if no location is specified on the command-line.
4918 as fallbacks if no location is specified on the command-line.
4919 When ``default-push`` is set, it will be used for push and
4919 When ``default-push`` is set, it will be used for push and
4920 ``default`` will be used for pull; otherwise ``default`` is used
4920 ``default`` will be used for pull; otherwise ``default`` is used
4921 as the fallback for both. When cloning a repository, the clone
4921 as the fallback for both. When cloning a repository, the clone
4922 source is written as ``default`` in ``.hg/hgrc``. Note that
4922 source is written as ``default`` in ``.hg/hgrc``. Note that
4923 ``default`` and ``default-push`` apply to all inbound (e.g.
4923 ``default`` and ``default-push`` apply to all inbound (e.g.
4924 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4924 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4925 :hg:`bundle`) operations.
4925 :hg:`bundle`) operations.
4926
4926
4927 See :hg:`help urls` for more information.
4927 See :hg:`help urls` for more information.
4928
4928
4929 Returns 0 on success.
4929 Returns 0 on success.
4930 """
4930 """
4931 if search:
4931 if search:
4932 for name, path in sorted(ui.paths.iteritems()):
4932 for name, path in sorted(ui.paths.iteritems()):
4933 if name == search:
4933 if name == search:
4934 ui.status("%s\n" % util.hidepassword(path.loc))
4934 ui.status("%s\n" % util.hidepassword(path.loc))
4935 return
4935 return
4936 if not ui.quiet:
4936 if not ui.quiet:
4937 ui.warn(_("not found!\n"))
4937 ui.warn(_("not found!\n"))
4938 return 1
4938 return 1
4939 else:
4939 else:
4940 for name, path in sorted(ui.paths.iteritems()):
4940 for name, path in sorted(ui.paths.iteritems()):
4941 if ui.quiet:
4941 if ui.quiet:
4942 ui.write("%s\n" % name)
4942 ui.write("%s\n" % name)
4943 else:
4943 else:
4944 ui.write("%s = %s\n" % (name,
4944 ui.write("%s = %s\n" % (name,
4945 util.hidepassword(path.loc)))
4945 util.hidepassword(path.loc)))
4946
4946
4947 @command('phase',
4947 @command('phase',
4948 [('p', 'public', False, _('set changeset phase to public')),
4948 [('p', 'public', False, _('set changeset phase to public')),
4949 ('d', 'draft', False, _('set changeset phase to draft')),
4949 ('d', 'draft', False, _('set changeset phase to draft')),
4950 ('s', 'secret', False, _('set changeset phase to secret')),
4950 ('s', 'secret', False, _('set changeset phase to secret')),
4951 ('f', 'force', False, _('allow to move boundary backward')),
4951 ('f', 'force', False, _('allow to move boundary backward')),
4952 ('r', 'rev', [], _('target revision'), _('REV')),
4952 ('r', 'rev', [], _('target revision'), _('REV')),
4953 ],
4953 ],
4954 _('[-p|-d|-s] [-f] [-r] REV...'))
4954 _('[-p|-d|-s] [-f] [-r] REV...'))
4955 def phase(ui, repo, *revs, **opts):
4955 def phase(ui, repo, *revs, **opts):
4956 """set or show the current phase name
4956 """set or show the current phase name
4957
4957
4958 With no argument, show the phase name of specified revisions.
4958 With no argument, show the phase name of specified revisions.
4959
4959
4960 With one of -p/--public, -d/--draft or -s/--secret, change the
4960 With one of -p/--public, -d/--draft or -s/--secret, change the
4961 phase value of the specified revisions.
4961 phase value of the specified revisions.
4962
4962
4963 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4963 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4964 lower phase to an higher phase. Phases are ordered as follows::
4964 lower phase to an higher phase. Phases are ordered as follows::
4965
4965
4966 public < draft < secret
4966 public < draft < secret
4967
4967
4968 Returns 0 on success, 1 if no phases were changed or some could not
4968 Returns 0 on success, 1 if no phases were changed or some could not
4969 be changed.
4969 be changed.
4970 """
4970 """
4971 # search for a unique phase argument
4971 # search for a unique phase argument
4972 targetphase = None
4972 targetphase = None
4973 for idx, name in enumerate(phases.phasenames):
4973 for idx, name in enumerate(phases.phasenames):
4974 if opts[name]:
4974 if opts[name]:
4975 if targetphase is not None:
4975 if targetphase is not None:
4976 raise util.Abort(_('only one phase can be specified'))
4976 raise util.Abort(_('only one phase can be specified'))
4977 targetphase = idx
4977 targetphase = idx
4978
4978
4979 # look for specified revision
4979 # look for specified revision
4980 revs = list(revs)
4980 revs = list(revs)
4981 revs.extend(opts['rev'])
4981 revs.extend(opts['rev'])
4982 if not revs:
4982 if not revs:
4983 raise util.Abort(_('no revisions specified'))
4983 raise util.Abort(_('no revisions specified'))
4984
4984
4985 revs = scmutil.revrange(repo, revs)
4985 revs = scmutil.revrange(repo, revs)
4986
4986
4987 lock = None
4987 lock = None
4988 ret = 0
4988 ret = 0
4989 if targetphase is None:
4989 if targetphase is None:
4990 # display
4990 # display
4991 for r in revs:
4991 for r in revs:
4992 ctx = repo[r]
4992 ctx = repo[r]
4993 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4993 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4994 else:
4994 else:
4995 tr = None
4995 tr = None
4996 lock = repo.lock()
4996 lock = repo.lock()
4997 try:
4997 try:
4998 tr = repo.transaction("phase")
4998 tr = repo.transaction("phase")
4999 # set phase
4999 # set phase
5000 if not revs:
5000 if not revs:
5001 raise util.Abort(_('empty revision set'))
5001 raise util.Abort(_('empty revision set'))
5002 nodes = [repo[r].node() for r in revs]
5002 nodes = [repo[r].node() for r in revs]
5003 # moving revision from public to draft may hide them
5003 # moving revision from public to draft may hide them
5004 # We have to check result on an unfiltered repository
5004 # We have to check result on an unfiltered repository
5005 unfi = repo.unfiltered()
5005 unfi = repo.unfiltered()
5006 getphase = unfi._phasecache.phase
5006 getphase = unfi._phasecache.phase
5007 olddata = [getphase(unfi, r) for r in unfi]
5007 olddata = [getphase(unfi, r) for r in unfi]
5008 phases.advanceboundary(repo, tr, targetphase, nodes)
5008 phases.advanceboundary(repo, tr, targetphase, nodes)
5009 if opts['force']:
5009 if opts['force']:
5010 phases.retractboundary(repo, tr, targetphase, nodes)
5010 phases.retractboundary(repo, tr, targetphase, nodes)
5011 tr.close()
5011 tr.close()
5012 finally:
5012 finally:
5013 if tr is not None:
5013 if tr is not None:
5014 tr.release()
5014 tr.release()
5015 lock.release()
5015 lock.release()
5016 getphase = unfi._phasecache.phase
5016 getphase = unfi._phasecache.phase
5017 newdata = [getphase(unfi, r) for r in unfi]
5017 newdata = [getphase(unfi, r) for r in unfi]
5018 changes = sum(newdata[r] != olddata[r] for r in unfi)
5018 changes = sum(newdata[r] != olddata[r] for r in unfi)
5019 cl = unfi.changelog
5019 cl = unfi.changelog
5020 rejected = [n for n in nodes
5020 rejected = [n for n in nodes
5021 if newdata[cl.rev(n)] < targetphase]
5021 if newdata[cl.rev(n)] < targetphase]
5022 if rejected:
5022 if rejected:
5023 ui.warn(_('cannot move %i changesets to a higher '
5023 ui.warn(_('cannot move %i changesets to a higher '
5024 'phase, use --force\n') % len(rejected))
5024 'phase, use --force\n') % len(rejected))
5025 ret = 1
5025 ret = 1
5026 if changes:
5026 if changes:
5027 msg = _('phase changed for %i changesets\n') % changes
5027 msg = _('phase changed for %i changesets\n') % changes
5028 if ret:
5028 if ret:
5029 ui.status(msg)
5029 ui.status(msg)
5030 else:
5030 else:
5031 ui.note(msg)
5031 ui.note(msg)
5032 else:
5032 else:
5033 ui.warn(_('no phases changed\n'))
5033 ui.warn(_('no phases changed\n'))
5034 ret = 1
5034 ret = 1
5035 return ret
5035 return ret
5036
5036
5037 def postincoming(ui, repo, modheads, optupdate, checkout):
5037 def postincoming(ui, repo, modheads, optupdate, checkout):
5038 if modheads == 0:
5038 if modheads == 0:
5039 return
5039 return
5040 if optupdate:
5040 if optupdate:
5041 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5041 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5042 try:
5042 try:
5043 ret = hg.update(repo, checkout)
5043 ret = hg.update(repo, checkout)
5044 except util.Abort, inst:
5044 except util.Abort, inst:
5045 ui.warn(_("not updating: %s\n") % str(inst))
5045 ui.warn(_("not updating: %s\n") % str(inst))
5046 if inst.hint:
5046 if inst.hint:
5047 ui.warn(_("(%s)\n") % inst.hint)
5047 ui.warn(_("(%s)\n") % inst.hint)
5048 return 0
5048 return 0
5049 if not ret and not checkout:
5049 if not ret and not checkout:
5050 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5050 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5051 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5051 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5052 return ret
5052 return ret
5053 if modheads > 1:
5053 if modheads > 1:
5054 currentbranchheads = len(repo.branchheads())
5054 currentbranchheads = len(repo.branchheads())
5055 if currentbranchheads == modheads:
5055 if currentbranchheads == modheads:
5056 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5056 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5057 elif currentbranchheads > 1:
5057 elif currentbranchheads > 1:
5058 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5058 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5059 "merge)\n"))
5059 "merge)\n"))
5060 else:
5060 else:
5061 ui.status(_("(run 'hg heads' to see heads)\n"))
5061 ui.status(_("(run 'hg heads' to see heads)\n"))
5062 else:
5062 else:
5063 ui.status(_("(run 'hg update' to get a working copy)\n"))
5063 ui.status(_("(run 'hg update' to get a working copy)\n"))
5064
5064
5065 @command('^pull',
5065 @command('^pull',
5066 [('u', 'update', None,
5066 [('u', 'update', None,
5067 _('update to new branch head if changesets were pulled')),
5067 _('update to new branch head if changesets were pulled')),
5068 ('f', 'force', None, _('run even when remote repository is unrelated')),
5068 ('f', 'force', None, _('run even when remote repository is unrelated')),
5069 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5069 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5070 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5070 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5071 ('b', 'branch', [], _('a specific branch you would like to pull'),
5071 ('b', 'branch', [], _('a specific branch you would like to pull'),
5072 _('BRANCH')),
5072 _('BRANCH')),
5073 ] + remoteopts,
5073 ] + remoteopts,
5074 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5074 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5075 def pull(ui, repo, source="default", **opts):
5075 def pull(ui, repo, source="default", **opts):
5076 """pull changes from the specified source
5076 """pull changes from the specified source
5077
5077
5078 Pull changes from a remote repository to a local one.
5078 Pull changes from a remote repository to a local one.
5079
5079
5080 This finds all changes from the repository at the specified path
5080 This finds all changes from the repository at the specified path
5081 or URL and adds them to a local repository (the current one unless
5081 or URL and adds them to a local repository (the current one unless
5082 -R is specified). By default, this does not update the copy of the
5082 -R is specified). By default, this does not update the copy of the
5083 project in the working directory.
5083 project in the working directory.
5084
5084
5085 Use :hg:`incoming` if you want to see what would have been added
5085 Use :hg:`incoming` if you want to see what would have been added
5086 by a pull at the time you issued this command. If you then decide
5086 by a pull at the time you issued this command. If you then decide
5087 to add those changes to the repository, you should use :hg:`pull
5087 to add those changes to the repository, you should use :hg:`pull
5088 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5088 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5089
5089
5090 If SOURCE is omitted, the 'default' path will be used.
5090 If SOURCE is omitted, the 'default' path will be used.
5091 See :hg:`help urls` for more information.
5091 See :hg:`help urls` for more information.
5092
5092
5093 Returns 0 on success, 1 if an update had unresolved files.
5093 Returns 0 on success, 1 if an update had unresolved files.
5094 """
5094 """
5095 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5095 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5096 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5096 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5097 other = hg.peer(repo, opts, source)
5097 other = hg.peer(repo, opts, source)
5098 try:
5098 try:
5099 revs, checkout = hg.addbranchrevs(repo, other, branches,
5099 revs, checkout = hg.addbranchrevs(repo, other, branches,
5100 opts.get('rev'))
5100 opts.get('rev'))
5101
5101
5102 remotebookmarks = other.listkeys('bookmarks')
5102 remotebookmarks = other.listkeys('bookmarks')
5103
5103
5104 if opts.get('bookmark'):
5104 if opts.get('bookmark'):
5105 if not revs:
5105 if not revs:
5106 revs = []
5106 revs = []
5107 for b in opts['bookmark']:
5107 for b in opts['bookmark']:
5108 if b not in remotebookmarks:
5108 if b not in remotebookmarks:
5109 raise util.Abort(_('remote bookmark %s not found!') % b)
5109 raise util.Abort(_('remote bookmark %s not found!') % b)
5110 revs.append(remotebookmarks[b])
5110 revs.append(remotebookmarks[b])
5111
5111
5112 if revs:
5112 if revs:
5113 try:
5113 try:
5114 revs = [other.lookup(rev) for rev in revs]
5114 revs = [other.lookup(rev) for rev in revs]
5115 except error.CapabilityError:
5115 except error.CapabilityError:
5116 err = _("other repository doesn't support revision lookup, "
5116 err = _("other repository doesn't support revision lookup, "
5117 "so a rev cannot be specified.")
5117 "so a rev cannot be specified.")
5118 raise util.Abort(err)
5118 raise util.Abort(err)
5119
5119
5120 modheads = exchange.pull(repo, other, heads=revs,
5120 modheads = exchange.pull(repo, other, heads=revs,
5121 force=opts.get('force'),
5121 force=opts.get('force'),
5122 bookmarks=opts.get('bookmark', ())).cgresult
5122 bookmarks=opts.get('bookmark', ())).cgresult
5123 if checkout:
5123 if checkout:
5124 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5124 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5125 repo._subtoppath = source
5125 repo._subtoppath = source
5126 try:
5126 try:
5127 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5127 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5128
5128
5129 finally:
5129 finally:
5130 del repo._subtoppath
5130 del repo._subtoppath
5131
5131
5132 finally:
5132 finally:
5133 other.close()
5133 other.close()
5134 return ret
5134 return ret
5135
5135
5136 @command('^push',
5136 @command('^push',
5137 [('f', 'force', None, _('force push')),
5137 [('f', 'force', None, _('force push')),
5138 ('r', 'rev', [],
5138 ('r', 'rev', [],
5139 _('a changeset intended to be included in the destination'),
5139 _('a changeset intended to be included in the destination'),
5140 _('REV')),
5140 _('REV')),
5141 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5141 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5142 ('b', 'branch', [],
5142 ('b', 'branch', [],
5143 _('a specific branch you would like to push'), _('BRANCH')),
5143 _('a specific branch you would like to push'), _('BRANCH')),
5144 ('', 'new-branch', False, _('allow pushing a new branch')),
5144 ('', 'new-branch', False, _('allow pushing a new branch')),
5145 ] + remoteopts,
5145 ] + remoteopts,
5146 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5146 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5147 def push(ui, repo, dest=None, **opts):
5147 def push(ui, repo, dest=None, **opts):
5148 """push changes to the specified destination
5148 """push changes to the specified destination
5149
5149
5150 Push changesets from the local repository to the specified
5150 Push changesets from the local repository to the specified
5151 destination.
5151 destination.
5152
5152
5153 This operation is symmetrical to pull: it is identical to a pull
5153 This operation is symmetrical to pull: it is identical to a pull
5154 in the destination repository from the current one.
5154 in the destination repository from the current one.
5155
5155
5156 By default, push will not allow creation of new heads at the
5156 By default, push will not allow creation of new heads at the
5157 destination, since multiple heads would make it unclear which head
5157 destination, since multiple heads would make it unclear which head
5158 to use. In this situation, it is recommended to pull and merge
5158 to use. In this situation, it is recommended to pull and merge
5159 before pushing.
5159 before pushing.
5160
5160
5161 Use --new-branch if you want to allow push to create a new named
5161 Use --new-branch if you want to allow push to create a new named
5162 branch that is not present at the destination. This allows you to
5162 branch that is not present at the destination. This allows you to
5163 only create a new branch without forcing other changes.
5163 only create a new branch without forcing other changes.
5164
5164
5165 .. note::
5165 .. note::
5166
5166
5167 Extra care should be taken with the -f/--force option,
5167 Extra care should be taken with the -f/--force option,
5168 which will push all new heads on all branches, an action which will
5168 which will push all new heads on all branches, an action which will
5169 almost always cause confusion for collaborators.
5169 almost always cause confusion for collaborators.
5170
5170
5171 If -r/--rev is used, the specified revision and all its ancestors
5171 If -r/--rev is used, the specified revision and all its ancestors
5172 will be pushed to the remote repository.
5172 will be pushed to the remote repository.
5173
5173
5174 If -B/--bookmark is used, the specified bookmarked revision, its
5174 If -B/--bookmark is used, the specified bookmarked revision, its
5175 ancestors, and the bookmark will be pushed to the remote
5175 ancestors, and the bookmark will be pushed to the remote
5176 repository.
5176 repository.
5177
5177
5178 Please see :hg:`help urls` for important details about ``ssh://``
5178 Please see :hg:`help urls` for important details about ``ssh://``
5179 URLs. If DESTINATION is omitted, a default path will be used.
5179 URLs. If DESTINATION is omitted, a default path will be used.
5180
5180
5181 Returns 0 if push was successful, 1 if nothing to push.
5181 Returns 0 if push was successful, 1 if nothing to push.
5182 """
5182 """
5183
5183
5184 if opts.get('bookmark'):
5184 if opts.get('bookmark'):
5185 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5185 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5186 for b in opts['bookmark']:
5186 for b in opts['bookmark']:
5187 # translate -B options to -r so changesets get pushed
5187 # translate -B options to -r so changesets get pushed
5188 if b in repo._bookmarks:
5188 if b in repo._bookmarks:
5189 opts.setdefault('rev', []).append(b)
5189 opts.setdefault('rev', []).append(b)
5190 else:
5190 else:
5191 # if we try to push a deleted bookmark, translate it to null
5191 # if we try to push a deleted bookmark, translate it to null
5192 # this lets simultaneous -r, -b options continue working
5192 # this lets simultaneous -r, -b options continue working
5193 opts.setdefault('rev', []).append("null")
5193 opts.setdefault('rev', []).append("null")
5194
5194
5195 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5195 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5196 dest, branches = hg.parseurl(dest, opts.get('branch'))
5196 dest, branches = hg.parseurl(dest, opts.get('branch'))
5197 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5197 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5198 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5198 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5199 try:
5199 try:
5200 other = hg.peer(repo, opts, dest)
5200 other = hg.peer(repo, opts, dest)
5201 except error.RepoError:
5201 except error.RepoError:
5202 if dest == "default-push":
5202 if dest == "default-push":
5203 raise util.Abort(_("default repository not configured!"),
5203 raise util.Abort(_("default repository not configured!"),
5204 hint=_('see the "path" section in "hg help config"'))
5204 hint=_('see the "path" section in "hg help config"'))
5205 else:
5205 else:
5206 raise
5206 raise
5207
5207
5208 if revs:
5208 if revs:
5209 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5209 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5210 if not revs:
5210 if not revs:
5211 raise util.Abort(_("specified revisions evaluate to an empty set"),
5211 raise util.Abort(_("specified revisions evaluate to an empty set"),
5212 hint=_("use different revision arguments"))
5212 hint=_("use different revision arguments"))
5213
5213
5214 repo._subtoppath = dest
5214 repo._subtoppath = dest
5215 try:
5215 try:
5216 # push subrepos depth-first for coherent ordering
5216 # push subrepos depth-first for coherent ordering
5217 c = repo['']
5217 c = repo['']
5218 subs = c.substate # only repos that are committed
5218 subs = c.substate # only repos that are committed
5219 for s in sorted(subs):
5219 for s in sorted(subs):
5220 result = c.sub(s).push(opts)
5220 result = c.sub(s).push(opts)
5221 if result == 0:
5221 if result == 0:
5222 return not result
5222 return not result
5223 finally:
5223 finally:
5224 del repo._subtoppath
5224 del repo._subtoppath
5225 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5225 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5226 newbranch=opts.get('new_branch'),
5226 newbranch=opts.get('new_branch'),
5227 bookmarks=opts.get('bookmark', ()))
5227 bookmarks=opts.get('bookmark', ()))
5228
5228
5229 result = not pushop.cgresult
5229 result = not pushop.cgresult
5230
5230
5231 if pushop.bkresult is not None:
5231 if pushop.bkresult is not None:
5232 if pushop.bkresult == 2:
5232 if pushop.bkresult == 2:
5233 result = 2
5233 result = 2
5234 elif not result and pushop.bkresult:
5234 elif not result and pushop.bkresult:
5235 result = 2
5235 result = 2
5236
5236
5237 return result
5237 return result
5238
5238
5239 @command('recover', [])
5239 @command('recover', [])
5240 def recover(ui, repo):
5240 def recover(ui, repo):
5241 """roll back an interrupted transaction
5241 """roll back an interrupted transaction
5242
5242
5243 Recover from an interrupted commit or pull.
5243 Recover from an interrupted commit or pull.
5244
5244
5245 This command tries to fix the repository status after an
5245 This command tries to fix the repository status after an
5246 interrupted operation. It should only be necessary when Mercurial
5246 interrupted operation. It should only be necessary when Mercurial
5247 suggests it.
5247 suggests it.
5248
5248
5249 Returns 0 if successful, 1 if nothing to recover or verify fails.
5249 Returns 0 if successful, 1 if nothing to recover or verify fails.
5250 """
5250 """
5251 if repo.recover():
5251 if repo.recover():
5252 return hg.verify(repo)
5252 return hg.verify(repo)
5253 return 1
5253 return 1
5254
5254
5255 @command('^remove|rm',
5255 @command('^remove|rm',
5256 [('A', 'after', None, _('record delete for missing files')),
5256 [('A', 'after', None, _('record delete for missing files')),
5257 ('f', 'force', None,
5257 ('f', 'force', None,
5258 _('remove (and delete) file even if added or modified')),
5258 _('remove (and delete) file even if added or modified')),
5259 ] + subrepoopts + walkopts,
5259 ] + subrepoopts + walkopts,
5260 _('[OPTION]... FILE...'),
5260 _('[OPTION]... FILE...'),
5261 inferrepo=True)
5261 inferrepo=True)
5262 def remove(ui, repo, *pats, **opts):
5262 def remove(ui, repo, *pats, **opts):
5263 """remove the specified files on the next commit
5263 """remove the specified files on the next commit
5264
5264
5265 Schedule the indicated files for removal from the current branch.
5265 Schedule the indicated files for removal from the current branch.
5266
5266
5267 This command schedules the files to be removed at the next commit.
5267 This command schedules the files to be removed at the next commit.
5268 To undo a remove before that, see :hg:`revert`. To undo added
5268 To undo a remove before that, see :hg:`revert`. To undo added
5269 files, see :hg:`forget`.
5269 files, see :hg:`forget`.
5270
5270
5271 .. container:: verbose
5271 .. container:: verbose
5272
5272
5273 -A/--after can be used to remove only files that have already
5273 -A/--after can be used to remove only files that have already
5274 been deleted, -f/--force can be used to force deletion, and -Af
5274 been deleted, -f/--force can be used to force deletion, and -Af
5275 can be used to remove files from the next revision without
5275 can be used to remove files from the next revision without
5276 deleting them from the working directory.
5276 deleting them from the working directory.
5277
5277
5278 The following table details the behavior of remove for different
5278 The following table details the behavior of remove for different
5279 file states (columns) and option combinations (rows). The file
5279 file states (columns) and option combinations (rows). The file
5280 states are Added [A], Clean [C], Modified [M] and Missing [!]
5280 states are Added [A], Clean [C], Modified [M] and Missing [!]
5281 (as reported by :hg:`status`). The actions are Warn, Remove
5281 (as reported by :hg:`status`). The actions are Warn, Remove
5282 (from branch) and Delete (from disk):
5282 (from branch) and Delete (from disk):
5283
5283
5284 ========= == == == ==
5284 ========= == == == ==
5285 opt/state A C M !
5285 opt/state A C M !
5286 ========= == == == ==
5286 ========= == == == ==
5287 none W RD W R
5287 none W RD W R
5288 -f R RD RD R
5288 -f R RD RD R
5289 -A W W W R
5289 -A W W W R
5290 -Af R R R R
5290 -Af R R R R
5291 ========= == == == ==
5291 ========= == == == ==
5292
5292
5293 Note that remove never deletes files in Added [A] state from the
5293 Note that remove never deletes files in Added [A] state from the
5294 working directory, not even if option --force is specified.
5294 working directory, not even if option --force is specified.
5295
5295
5296 Returns 0 on success, 1 if any warnings encountered.
5296 Returns 0 on success, 1 if any warnings encountered.
5297 """
5297 """
5298
5298
5299 after, force = opts.get('after'), opts.get('force')
5299 after, force = opts.get('after'), opts.get('force')
5300 if not pats and not after:
5300 if not pats and not after:
5301 raise util.Abort(_('no files specified'))
5301 raise util.Abort(_('no files specified'))
5302
5302
5303 m = scmutil.match(repo[None], pats, opts)
5303 m = scmutil.match(repo[None], pats, opts)
5304 subrepos = opts.get('subrepos')
5304 subrepos = opts.get('subrepos')
5305 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5305 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5306
5306
5307 @command('rename|move|mv',
5307 @command('rename|move|mv',
5308 [('A', 'after', None, _('record a rename that has already occurred')),
5308 [('A', 'after', None, _('record a rename that has already occurred')),
5309 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5309 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5310 ] + walkopts + dryrunopts,
5310 ] + walkopts + dryrunopts,
5311 _('[OPTION]... SOURCE... DEST'))
5311 _('[OPTION]... SOURCE... DEST'))
5312 def rename(ui, repo, *pats, **opts):
5312 def rename(ui, repo, *pats, **opts):
5313 """rename files; equivalent of copy + remove
5313 """rename files; equivalent of copy + remove
5314
5314
5315 Mark dest as copies of sources; mark sources for deletion. If dest
5315 Mark dest as copies of sources; mark sources for deletion. If dest
5316 is a directory, copies are put in that directory. If dest is a
5316 is a directory, copies are put in that directory. If dest is a
5317 file, there can only be one source.
5317 file, there can only be one source.
5318
5318
5319 By default, this command copies the contents of files as they
5319 By default, this command copies the contents of files as they
5320 exist in the working directory. If invoked with -A/--after, the
5320 exist in the working directory. If invoked with -A/--after, the
5321 operation is recorded, but no copying is performed.
5321 operation is recorded, but no copying is performed.
5322
5322
5323 This command takes effect at the next commit. To undo a rename
5323 This command takes effect at the next commit. To undo a rename
5324 before that, see :hg:`revert`.
5324 before that, see :hg:`revert`.
5325
5325
5326 Returns 0 on success, 1 if errors are encountered.
5326 Returns 0 on success, 1 if errors are encountered.
5327 """
5327 """
5328 wlock = repo.wlock(False)
5328 wlock = repo.wlock(False)
5329 try:
5329 try:
5330 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5330 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5331 finally:
5331 finally:
5332 wlock.release()
5332 wlock.release()
5333
5333
5334 @command('resolve',
5334 @command('resolve',
5335 [('a', 'all', None, _('select all unresolved files')),
5335 [('a', 'all', None, _('select all unresolved files')),
5336 ('l', 'list', None, _('list state of files needing merge')),
5336 ('l', 'list', None, _('list state of files needing merge')),
5337 ('m', 'mark', None, _('mark files as resolved')),
5337 ('m', 'mark', None, _('mark files as resolved')),
5338 ('u', 'unmark', None, _('mark files as unresolved')),
5338 ('u', 'unmark', None, _('mark files as unresolved')),
5339 ('n', 'no-status', None, _('hide status prefix'))]
5339 ('n', 'no-status', None, _('hide status prefix'))]
5340 + mergetoolopts + walkopts + formatteropts,
5340 + mergetoolopts + walkopts + formatteropts,
5341 _('[OPTION]... [FILE]...'),
5341 _('[OPTION]... [FILE]...'),
5342 inferrepo=True)
5342 inferrepo=True)
5343 def resolve(ui, repo, *pats, **opts):
5343 def resolve(ui, repo, *pats, **opts):
5344 """redo merges or set/view the merge status of files
5344 """redo merges or set/view the merge status of files
5345
5345
5346 Merges with unresolved conflicts are often the result of
5346 Merges with unresolved conflicts are often the result of
5347 non-interactive merging using the ``internal:merge`` configuration
5347 non-interactive merging using the ``internal:merge`` configuration
5348 setting, or a command-line merge tool like ``diff3``. The resolve
5348 setting, or a command-line merge tool like ``diff3``. The resolve
5349 command is used to manage the files involved in a merge, after
5349 command is used to manage the files involved in a merge, after
5350 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5350 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5351 working directory must have two parents). See :hg:`help
5351 working directory must have two parents). See :hg:`help
5352 merge-tools` for information on configuring merge tools.
5352 merge-tools` for information on configuring merge tools.
5353
5353
5354 The resolve command can be used in the following ways:
5354 The resolve command can be used in the following ways:
5355
5355
5356 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5356 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5357 files, discarding any previous merge attempts. Re-merging is not
5357 files, discarding any previous merge attempts. Re-merging is not
5358 performed for files already marked as resolved. Use ``--all/-a``
5358 performed for files already marked as resolved. Use ``--all/-a``
5359 to select all unresolved files. ``--tool`` can be used to specify
5359 to select all unresolved files. ``--tool`` can be used to specify
5360 the merge tool used for the given files. It overrides the HGMERGE
5360 the merge tool used for the given files. It overrides the HGMERGE
5361 environment variable and your configuration files. Previous file
5361 environment variable and your configuration files. Previous file
5362 contents are saved with a ``.orig`` suffix.
5362 contents are saved with a ``.orig`` suffix.
5363
5363
5364 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5364 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5365 (e.g. after having manually fixed-up the files). The default is
5365 (e.g. after having manually fixed-up the files). The default is
5366 to mark all unresolved files.
5366 to mark all unresolved files.
5367
5367
5368 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5368 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5369 default is to mark all resolved files.
5369 default is to mark all resolved files.
5370
5370
5371 - :hg:`resolve -l`: list files which had or still have conflicts.
5371 - :hg:`resolve -l`: list files which had or still have conflicts.
5372 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5372 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5373
5373
5374 Note that Mercurial will not let you commit files with unresolved
5374 Note that Mercurial will not let you commit files with unresolved
5375 merge conflicts. You must use :hg:`resolve -m ...` before you can
5375 merge conflicts. You must use :hg:`resolve -m ...` before you can
5376 commit after a conflicting merge.
5376 commit after a conflicting merge.
5377
5377
5378 Returns 0 on success, 1 if any files fail a resolve attempt.
5378 Returns 0 on success, 1 if any files fail a resolve attempt.
5379 """
5379 """
5380
5380
5381 all, mark, unmark, show, nostatus = \
5381 all, mark, unmark, show, nostatus = \
5382 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5382 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5383
5383
5384 if (show and (mark or unmark)) or (mark and unmark):
5384 if (show and (mark or unmark)) or (mark and unmark):
5385 raise util.Abort(_("too many options specified"))
5385 raise util.Abort(_("too many options specified"))
5386 if pats and all:
5386 if pats and all:
5387 raise util.Abort(_("can't specify --all and patterns"))
5387 raise util.Abort(_("can't specify --all and patterns"))
5388 if not (all or pats or show or mark or unmark):
5388 if not (all or pats or show or mark or unmark):
5389 raise util.Abort(_('no files or directories specified'),
5389 raise util.Abort(_('no files or directories specified'),
5390 hint=('use --all to remerge all files'))
5390 hint=('use --all to remerge all files'))
5391
5391
5392 if show:
5392 if show:
5393 fm = ui.formatter('resolve', opts)
5393 fm = ui.formatter('resolve', opts)
5394 ms = mergemod.mergestate(repo)
5394 ms = mergemod.mergestate(repo)
5395 m = scmutil.match(repo[None], pats, opts)
5395 m = scmutil.match(repo[None], pats, opts)
5396 for f in ms:
5396 for f in ms:
5397 if not m(f):
5397 if not m(f):
5398 continue
5398 continue
5399 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5399 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5400 fm.startitem()
5400 fm.startitem()
5401 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5401 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5402 fm.write('path', '%s\n', f, label=l)
5402 fm.write('path', '%s\n', f, label=l)
5403 fm.end()
5403 fm.end()
5404 return 0
5404 return 0
5405
5405
5406 wlock = repo.wlock()
5406 wlock = repo.wlock()
5407 try:
5407 try:
5408 ms = mergemod.mergestate(repo)
5408 ms = mergemod.mergestate(repo)
5409
5409
5410 if not (ms.active() or repo.dirstate.p2() != nullid):
5410 if not (ms.active() or repo.dirstate.p2() != nullid):
5411 raise util.Abort(
5411 raise util.Abort(
5412 _('resolve command not applicable when not merging'))
5412 _('resolve command not applicable when not merging'))
5413
5413
5414 m = scmutil.match(repo[None], pats, opts)
5414 m = scmutil.match(repo[None], pats, opts)
5415 ret = 0
5415 ret = 0
5416 didwork = False
5416 didwork = False
5417
5417
5418 for f in ms:
5418 for f in ms:
5419 if not m(f):
5419 if not m(f):
5420 continue
5420 continue
5421
5421
5422 didwork = True
5422 didwork = True
5423
5423
5424 if mark:
5424 if mark:
5425 ms.mark(f, "r")
5425 ms.mark(f, "r")
5426 elif unmark:
5426 elif unmark:
5427 ms.mark(f, "u")
5427 ms.mark(f, "u")
5428 else:
5428 else:
5429 wctx = repo[None]
5429 wctx = repo[None]
5430
5430
5431 # backup pre-resolve (merge uses .orig for its own purposes)
5431 # backup pre-resolve (merge uses .orig for its own purposes)
5432 a = repo.wjoin(f)
5432 a = repo.wjoin(f)
5433 util.copyfile(a, a + ".resolve")
5433 util.copyfile(a, a + ".resolve")
5434
5434
5435 try:
5435 try:
5436 # resolve file
5436 # resolve file
5437 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5437 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5438 'resolve')
5438 'resolve')
5439 if ms.resolve(f, wctx):
5439 if ms.resolve(f, wctx):
5440 ret = 1
5440 ret = 1
5441 finally:
5441 finally:
5442 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5442 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5443 ms.commit()
5443 ms.commit()
5444
5444
5445 # replace filemerge's .orig file with our resolve file
5445 # replace filemerge's .orig file with our resolve file
5446 util.rename(a + ".resolve", a + ".orig")
5446 util.rename(a + ".resolve", a + ".orig")
5447
5447
5448 ms.commit()
5448 ms.commit()
5449
5449
5450 if not didwork and pats:
5450 if not didwork and pats:
5451 ui.warn(_("arguments do not match paths that need resolving\n"))
5451 ui.warn(_("arguments do not match paths that need resolving\n"))
5452
5452
5453 finally:
5453 finally:
5454 wlock.release()
5454 wlock.release()
5455
5455
5456 # Nudge users into finishing an unfinished operation
5456 # Nudge users into finishing an unfinished operation
5457 if not list(ms.unresolved()):
5457 if not list(ms.unresolved()):
5458 ui.status(_('(no more unresolved files)\n'))
5458 ui.status(_('(no more unresolved files)\n'))
5459
5459
5460 return ret
5460 return ret
5461
5461
5462 @command('revert',
5462 @command('revert',
5463 [('a', 'all', None, _('revert all changes when no arguments given')),
5463 [('a', 'all', None, _('revert all changes when no arguments given')),
5464 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5464 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5465 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5465 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5466 ('C', 'no-backup', None, _('do not save backup copies of files')),
5466 ('C', 'no-backup', None, _('do not save backup copies of files')),
5467 ('i', 'interactive', None, _('interactively select the changes')),
5467 ('i', 'interactive', None, _('interactively select the changes')),
5468 ] + walkopts + dryrunopts,
5468 ] + walkopts + dryrunopts,
5469 _('[OPTION]... [-r REV] [NAME]...'))
5469 _('[OPTION]... [-r REV] [NAME]...'))
5470 def revert(ui, repo, *pats, **opts):
5470 def revert(ui, repo, *pats, **opts):
5471 """restore files to their checkout state
5471 """restore files to their checkout state
5472
5472
5473 .. note::
5473 .. note::
5474
5474
5475 To check out earlier revisions, you should use :hg:`update REV`.
5475 To check out earlier revisions, you should use :hg:`update REV`.
5476 To cancel an uncommitted merge (and lose your changes),
5476 To cancel an uncommitted merge (and lose your changes),
5477 use :hg:`update --clean .`.
5477 use :hg:`update --clean .`.
5478
5478
5479 With no revision specified, revert the specified files or directories
5479 With no revision specified, revert the specified files or directories
5480 to the contents they had in the parent of the working directory.
5480 to the contents they had in the parent of the working directory.
5481 This restores the contents of files to an unmodified
5481 This restores the contents of files to an unmodified
5482 state and unschedules adds, removes, copies, and renames. If the
5482 state and unschedules adds, removes, copies, and renames. If the
5483 working directory has two parents, you must explicitly specify a
5483 working directory has two parents, you must explicitly specify a
5484 revision.
5484 revision.
5485
5485
5486 Using the -r/--rev or -d/--date options, revert the given files or
5486 Using the -r/--rev or -d/--date options, revert the given files or
5487 directories to their states as of a specific revision. Because
5487 directories to their states as of a specific revision. Because
5488 revert does not change the working directory parents, this will
5488 revert does not change the working directory parents, this will
5489 cause these files to appear modified. This can be helpful to "back
5489 cause these files to appear modified. This can be helpful to "back
5490 out" some or all of an earlier change. See :hg:`backout` for a
5490 out" some or all of an earlier change. See :hg:`backout` for a
5491 related method.
5491 related method.
5492
5492
5493 Modified files are saved with a .orig suffix before reverting.
5493 Modified files are saved with a .orig suffix before reverting.
5494 To disable these backups, use --no-backup.
5494 To disable these backups, use --no-backup.
5495
5495
5496 See :hg:`help dates` for a list of formats valid for -d/--date.
5496 See :hg:`help dates` for a list of formats valid for -d/--date.
5497
5497
5498 Returns 0 on success.
5498 Returns 0 on success.
5499 """
5499 """
5500
5500
5501 if opts.get("date"):
5501 if opts.get("date"):
5502 if opts.get("rev"):
5502 if opts.get("rev"):
5503 raise util.Abort(_("you can't specify a revision and a date"))
5503 raise util.Abort(_("you can't specify a revision and a date"))
5504 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5504 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5505
5505
5506 parent, p2 = repo.dirstate.parents()
5506 parent, p2 = repo.dirstate.parents()
5507 if not opts.get('rev') and p2 != nullid:
5507 if not opts.get('rev') and p2 != nullid:
5508 # revert after merge is a trap for new users (issue2915)
5508 # revert after merge is a trap for new users (issue2915)
5509 raise util.Abort(_('uncommitted merge with no revision specified'),
5509 raise util.Abort(_('uncommitted merge with no revision specified'),
5510 hint=_('use "hg update" or see "hg help revert"'))
5510 hint=_('use "hg update" or see "hg help revert"'))
5511
5511
5512 ctx = scmutil.revsingle(repo, opts.get('rev'))
5512 ctx = scmutil.revsingle(repo, opts.get('rev'))
5513
5513
5514 if not pats and not (opts.get('all') or opts.get('interactive')):
5514 if not pats and not (opts.get('all') or opts.get('interactive')):
5515 msg = _("no files or directories specified")
5515 msg = _("no files or directories specified")
5516 if p2 != nullid:
5516 if p2 != nullid:
5517 hint = _("uncommitted merge, use --all to discard all changes,"
5517 hint = _("uncommitted merge, use --all to discard all changes,"
5518 " or 'hg update -C .' to abort the merge")
5518 " or 'hg update -C .' to abort the merge")
5519 raise util.Abort(msg, hint=hint)
5519 raise util.Abort(msg, hint=hint)
5520 dirty = util.any(repo.status())
5520 dirty = util.any(repo.status())
5521 node = ctx.node()
5521 node = ctx.node()
5522 if node != parent:
5522 if node != parent:
5523 if dirty:
5523 if dirty:
5524 hint = _("uncommitted changes, use --all to discard all"
5524 hint = _("uncommitted changes, use --all to discard all"
5525 " changes, or 'hg update %s' to update") % ctx.rev()
5525 " changes, or 'hg update %s' to update") % ctx.rev()
5526 else:
5526 else:
5527 hint = _("use --all to revert all files,"
5527 hint = _("use --all to revert all files,"
5528 " or 'hg update %s' to update") % ctx.rev()
5528 " or 'hg update %s' to update") % ctx.rev()
5529 elif dirty:
5529 elif dirty:
5530 hint = _("uncommitted changes, use --all to discard all changes")
5530 hint = _("uncommitted changes, use --all to discard all changes")
5531 else:
5531 else:
5532 hint = _("use --all to revert all files")
5532 hint = _("use --all to revert all files")
5533 raise util.Abort(msg, hint=hint)
5533 raise util.Abort(msg, hint=hint)
5534
5534
5535 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5535 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5536
5536
5537 @command('rollback', dryrunopts +
5537 @command('rollback', dryrunopts +
5538 [('f', 'force', False, _('ignore safety measures'))])
5538 [('f', 'force', False, _('ignore safety measures'))])
5539 def rollback(ui, repo, **opts):
5539 def rollback(ui, repo, **opts):
5540 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5540 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5541
5541
5542 Please use :hg:`commit --amend` instead of rollback to correct
5542 Please use :hg:`commit --amend` instead of rollback to correct
5543 mistakes in the last commit.
5543 mistakes in the last commit.
5544
5544
5545 This command should be used with care. There is only one level of
5545 This command should be used with care. There is only one level of
5546 rollback, and there is no way to undo a rollback. It will also
5546 rollback, and there is no way to undo a rollback. It will also
5547 restore the dirstate at the time of the last transaction, losing
5547 restore the dirstate at the time of the last transaction, losing
5548 any dirstate changes since that time. This command does not alter
5548 any dirstate changes since that time. This command does not alter
5549 the working directory.
5549 the working directory.
5550
5550
5551 Transactions are used to encapsulate the effects of all commands
5551 Transactions are used to encapsulate the effects of all commands
5552 that create new changesets or propagate existing changesets into a
5552 that create new changesets or propagate existing changesets into a
5553 repository.
5553 repository.
5554
5554
5555 .. container:: verbose
5555 .. container:: verbose
5556
5556
5557 For example, the following commands are transactional, and their
5557 For example, the following commands are transactional, and their
5558 effects can be rolled back:
5558 effects can be rolled back:
5559
5559
5560 - commit
5560 - commit
5561 - import
5561 - import
5562 - pull
5562 - pull
5563 - push (with this repository as the destination)
5563 - push (with this repository as the destination)
5564 - unbundle
5564 - unbundle
5565
5565
5566 To avoid permanent data loss, rollback will refuse to rollback a
5566 To avoid permanent data loss, rollback will refuse to rollback a
5567 commit transaction if it isn't checked out. Use --force to
5567 commit transaction if it isn't checked out. Use --force to
5568 override this protection.
5568 override this protection.
5569
5569
5570 This command is not intended for use on public repositories. Once
5570 This command is not intended for use on public repositories. Once
5571 changes are visible for pull by other users, rolling a transaction
5571 changes are visible for pull by other users, rolling a transaction
5572 back locally is ineffective (someone else may already have pulled
5572 back locally is ineffective (someone else may already have pulled
5573 the changes). Furthermore, a race is possible with readers of the
5573 the changes). Furthermore, a race is possible with readers of the
5574 repository; for example an in-progress pull from the repository
5574 repository; for example an in-progress pull from the repository
5575 may fail if a rollback is performed.
5575 may fail if a rollback is performed.
5576
5576
5577 Returns 0 on success, 1 if no rollback data is available.
5577 Returns 0 on success, 1 if no rollback data is available.
5578 """
5578 """
5579 return repo.rollback(dryrun=opts.get('dry_run'),
5579 return repo.rollback(dryrun=opts.get('dry_run'),
5580 force=opts.get('force'))
5580 force=opts.get('force'))
5581
5581
5582 @command('root', [])
5582 @command('root', [])
5583 def root(ui, repo):
5583 def root(ui, repo):
5584 """print the root (top) of the current working directory
5584 """print the root (top) of the current working directory
5585
5585
5586 Print the root directory of the current repository.
5586 Print the root directory of the current repository.
5587
5587
5588 Returns 0 on success.
5588 Returns 0 on success.
5589 """
5589 """
5590 ui.write(repo.root + "\n")
5590 ui.write(repo.root + "\n")
5591
5591
5592 @command('^serve',
5592 @command('^serve',
5593 [('A', 'accesslog', '', _('name of access log file to write to'),
5593 [('A', 'accesslog', '', _('name of access log file to write to'),
5594 _('FILE')),
5594 _('FILE')),
5595 ('d', 'daemon', None, _('run server in background')),
5595 ('d', 'daemon', None, _('run server in background')),
5596 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5596 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5597 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5597 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5598 # use string type, then we can check if something was passed
5598 # use string type, then we can check if something was passed
5599 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5599 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5600 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5600 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5601 _('ADDR')),
5601 _('ADDR')),
5602 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5602 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5603 _('PREFIX')),
5603 _('PREFIX')),
5604 ('n', 'name', '',
5604 ('n', 'name', '',
5605 _('name to show in web pages (default: working directory)'), _('NAME')),
5605 _('name to show in web pages (default: working directory)'), _('NAME')),
5606 ('', 'web-conf', '',
5606 ('', 'web-conf', '',
5607 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5607 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5608 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5608 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5609 _('FILE')),
5609 _('FILE')),
5610 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5610 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5611 ('', 'stdio', None, _('for remote clients')),
5611 ('', 'stdio', None, _('for remote clients')),
5612 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5612 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5613 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5613 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5614 ('', 'style', '', _('template style to use'), _('STYLE')),
5614 ('', 'style', '', _('template style to use'), _('STYLE')),
5615 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5615 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5616 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5616 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5617 _('[OPTION]...'),
5617 _('[OPTION]...'),
5618 optionalrepo=True)
5618 optionalrepo=True)
5619 def serve(ui, repo, **opts):
5619 def serve(ui, repo, **opts):
5620 """start stand-alone webserver
5620 """start stand-alone webserver
5621
5621
5622 Start a local HTTP repository browser and pull server. You can use
5622 Start a local HTTP repository browser and pull server. You can use
5623 this for ad-hoc sharing and browsing of repositories. It is
5623 this for ad-hoc sharing and browsing of repositories. It is
5624 recommended to use a real web server to serve a repository for
5624 recommended to use a real web server to serve a repository for
5625 longer periods of time.
5625 longer periods of time.
5626
5626
5627 Please note that the server does not implement access control.
5627 Please note that the server does not implement access control.
5628 This means that, by default, anybody can read from the server and
5628 This means that, by default, anybody can read from the server and
5629 nobody can write to it by default. Set the ``web.allow_push``
5629 nobody can write to it by default. Set the ``web.allow_push``
5630 option to ``*`` to allow everybody to push to the server. You
5630 option to ``*`` to allow everybody to push to the server. You
5631 should use a real web server if you need to authenticate users.
5631 should use a real web server if you need to authenticate users.
5632
5632
5633 By default, the server logs accesses to stdout and errors to
5633 By default, the server logs accesses to stdout and errors to
5634 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5634 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5635 files.
5635 files.
5636
5636
5637 To have the server choose a free port number to listen on, specify
5637 To have the server choose a free port number to listen on, specify
5638 a port number of 0; in this case, the server will print the port
5638 a port number of 0; in this case, the server will print the port
5639 number it uses.
5639 number it uses.
5640
5640
5641 Returns 0 on success.
5641 Returns 0 on success.
5642 """
5642 """
5643
5643
5644 if opts["stdio"] and opts["cmdserver"]:
5644 if opts["stdio"] and opts["cmdserver"]:
5645 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5645 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5646
5646
5647 if opts["stdio"]:
5647 if opts["stdio"]:
5648 if repo is None:
5648 if repo is None:
5649 raise error.RepoError(_("there is no Mercurial repository here"
5649 raise error.RepoError(_("there is no Mercurial repository here"
5650 " (.hg not found)"))
5650 " (.hg not found)"))
5651 s = sshserver.sshserver(ui, repo)
5651 s = sshserver.sshserver(ui, repo)
5652 s.serve_forever()
5652 s.serve_forever()
5653
5653
5654 if opts["cmdserver"]:
5654 if opts["cmdserver"]:
5655 service = commandserver.createservice(ui, repo, opts)
5655 service = commandserver.createservice(ui, repo, opts)
5656 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5656 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5657
5657
5658 # this way we can check if something was given in the command-line
5658 # this way we can check if something was given in the command-line
5659 if opts.get('port'):
5659 if opts.get('port'):
5660 opts['port'] = util.getport(opts.get('port'))
5660 opts['port'] = util.getport(opts.get('port'))
5661
5661
5662 if repo:
5662 if repo:
5663 baseui = repo.baseui
5663 baseui = repo.baseui
5664 else:
5664 else:
5665 baseui = ui
5665 baseui = ui
5666 optlist = ("name templates style address port prefix ipv6"
5666 optlist = ("name templates style address port prefix ipv6"
5667 " accesslog errorlog certificate encoding")
5667 " accesslog errorlog certificate encoding")
5668 for o in optlist.split():
5668 for o in optlist.split():
5669 val = opts.get(o, '')
5669 val = opts.get(o, '')
5670 if val in (None, ''): # should check against default options instead
5670 if val in (None, ''): # should check against default options instead
5671 continue
5671 continue
5672 baseui.setconfig("web", o, val, 'serve')
5672 baseui.setconfig("web", o, val, 'serve')
5673 if repo and repo.ui != baseui:
5673 if repo and repo.ui != baseui:
5674 repo.ui.setconfig("web", o, val, 'serve')
5674 repo.ui.setconfig("web", o, val, 'serve')
5675
5675
5676 o = opts.get('web_conf') or opts.get('webdir_conf')
5676 o = opts.get('web_conf') or opts.get('webdir_conf')
5677 if not o:
5677 if not o:
5678 if not repo:
5678 if not repo:
5679 raise error.RepoError(_("there is no Mercurial repository"
5679 raise error.RepoError(_("there is no Mercurial repository"
5680 " here (.hg not found)"))
5680 " here (.hg not found)"))
5681 o = repo
5681 o = repo
5682
5682
5683 app = hgweb.hgweb(o, baseui=baseui)
5683 app = hgweb.hgweb(o, baseui=baseui)
5684 service = httpservice(ui, app, opts)
5684 service = httpservice(ui, app, opts)
5685 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5685 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5686
5686
5687 class httpservice(object):
5687 class httpservice(object):
5688 def __init__(self, ui, app, opts):
5688 def __init__(self, ui, app, opts):
5689 self.ui = ui
5689 self.ui = ui
5690 self.app = app
5690 self.app = app
5691 self.opts = opts
5691 self.opts = opts
5692
5692
5693 def init(self):
5693 def init(self):
5694 util.setsignalhandler()
5694 util.setsignalhandler()
5695 self.httpd = hgweb_server.create_server(self.ui, self.app)
5695 self.httpd = hgweb_server.create_server(self.ui, self.app)
5696
5696
5697 if self.opts['port'] and not self.ui.verbose:
5697 if self.opts['port'] and not self.ui.verbose:
5698 return
5698 return
5699
5699
5700 if self.httpd.prefix:
5700 if self.httpd.prefix:
5701 prefix = self.httpd.prefix.strip('/') + '/'
5701 prefix = self.httpd.prefix.strip('/') + '/'
5702 else:
5702 else:
5703 prefix = ''
5703 prefix = ''
5704
5704
5705 port = ':%d' % self.httpd.port
5705 port = ':%d' % self.httpd.port
5706 if port == ':80':
5706 if port == ':80':
5707 port = ''
5707 port = ''
5708
5708
5709 bindaddr = self.httpd.addr
5709 bindaddr = self.httpd.addr
5710 if bindaddr == '0.0.0.0':
5710 if bindaddr == '0.0.0.0':
5711 bindaddr = '*'
5711 bindaddr = '*'
5712 elif ':' in bindaddr: # IPv6
5712 elif ':' in bindaddr: # IPv6
5713 bindaddr = '[%s]' % bindaddr
5713 bindaddr = '[%s]' % bindaddr
5714
5714
5715 fqaddr = self.httpd.fqaddr
5715 fqaddr = self.httpd.fqaddr
5716 if ':' in fqaddr:
5716 if ':' in fqaddr:
5717 fqaddr = '[%s]' % fqaddr
5717 fqaddr = '[%s]' % fqaddr
5718 if self.opts['port']:
5718 if self.opts['port']:
5719 write = self.ui.status
5719 write = self.ui.status
5720 else:
5720 else:
5721 write = self.ui.write
5721 write = self.ui.write
5722 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5722 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5723 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5723 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5724 self.ui.flush() # avoid buffering of status message
5724 self.ui.flush() # avoid buffering of status message
5725
5725
5726 def run(self):
5726 def run(self):
5727 self.httpd.serve_forever()
5727 self.httpd.serve_forever()
5728
5728
5729
5729
5730 @command('^status|st',
5730 @command('^status|st',
5731 [('A', 'all', None, _('show status of all files')),
5731 [('A', 'all', None, _('show status of all files')),
5732 ('m', 'modified', None, _('show only modified files')),
5732 ('m', 'modified', None, _('show only modified files')),
5733 ('a', 'added', None, _('show only added files')),
5733 ('a', 'added', None, _('show only added files')),
5734 ('r', 'removed', None, _('show only removed files')),
5734 ('r', 'removed', None, _('show only removed files')),
5735 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5735 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5736 ('c', 'clean', None, _('show only files without changes')),
5736 ('c', 'clean', None, _('show only files without changes')),
5737 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5737 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5738 ('i', 'ignored', None, _('show only ignored files')),
5738 ('i', 'ignored', None, _('show only ignored files')),
5739 ('n', 'no-status', None, _('hide status prefix')),
5739 ('n', 'no-status', None, _('hide status prefix')),
5740 ('C', 'copies', None, _('show source of copied files')),
5740 ('C', 'copies', None, _('show source of copied files')),
5741 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5741 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5742 ('', 'rev', [], _('show difference from revision'), _('REV')),
5742 ('', 'rev', [], _('show difference from revision'), _('REV')),
5743 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5743 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5744 ] + walkopts + subrepoopts + formatteropts,
5744 ] + walkopts + subrepoopts + formatteropts,
5745 _('[OPTION]... [FILE]...'),
5745 _('[OPTION]... [FILE]...'),
5746 inferrepo=True)
5746 inferrepo=True)
5747 def status(ui, repo, *pats, **opts):
5747 def status(ui, repo, *pats, **opts):
5748 """show changed files in the working directory
5748 """show changed files in the working directory
5749
5749
5750 Show status of files in the repository. If names are given, only
5750 Show status of files in the repository. If names are given, only
5751 files that match are shown. Files that are clean or ignored or
5751 files that match are shown. Files that are clean or ignored or
5752 the source of a copy/move operation, are not listed unless
5752 the source of a copy/move operation, are not listed unless
5753 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5753 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5754 Unless options described with "show only ..." are given, the
5754 Unless options described with "show only ..." are given, the
5755 options -mardu are used.
5755 options -mardu are used.
5756
5756
5757 Option -q/--quiet hides untracked (unknown and ignored) files
5757 Option -q/--quiet hides untracked (unknown and ignored) files
5758 unless explicitly requested with -u/--unknown or -i/--ignored.
5758 unless explicitly requested with -u/--unknown or -i/--ignored.
5759
5759
5760 .. note::
5760 .. note::
5761
5761
5762 status may appear to disagree with diff if permissions have
5762 status may appear to disagree with diff if permissions have
5763 changed or a merge has occurred. The standard diff format does
5763 changed or a merge has occurred. The standard diff format does
5764 not report permission changes and diff only reports changes
5764 not report permission changes and diff only reports changes
5765 relative to one merge parent.
5765 relative to one merge parent.
5766
5766
5767 If one revision is given, it is used as the base revision.
5767 If one revision is given, it is used as the base revision.
5768 If two revisions are given, the differences between them are
5768 If two revisions are given, the differences between them are
5769 shown. The --change option can also be used as a shortcut to list
5769 shown. The --change option can also be used as a shortcut to list
5770 the changed files of a revision from its first parent.
5770 the changed files of a revision from its first parent.
5771
5771
5772 The codes used to show the status of files are::
5772 The codes used to show the status of files are::
5773
5773
5774 M = modified
5774 M = modified
5775 A = added
5775 A = added
5776 R = removed
5776 R = removed
5777 C = clean
5777 C = clean
5778 ! = missing (deleted by non-hg command, but still tracked)
5778 ! = missing (deleted by non-hg command, but still tracked)
5779 ? = not tracked
5779 ? = not tracked
5780 I = ignored
5780 I = ignored
5781 = origin of the previous file (with --copies)
5781 = origin of the previous file (with --copies)
5782
5782
5783 .. container:: verbose
5783 .. container:: verbose
5784
5784
5785 Examples:
5785 Examples:
5786
5786
5787 - show changes in the working directory relative to a
5787 - show changes in the working directory relative to a
5788 changeset::
5788 changeset::
5789
5789
5790 hg status --rev 9353
5790 hg status --rev 9353
5791
5791
5792 - show changes in the working directory relative to the
5792 - show changes in the working directory relative to the
5793 current directory (see :hg:`help patterns` for more information)::
5793 current directory (see :hg:`help patterns` for more information)::
5794
5794
5795 hg status re:
5795 hg status re:
5796
5796
5797 - show all changes including copies in an existing changeset::
5797 - show all changes including copies in an existing changeset::
5798
5798
5799 hg status --copies --change 9353
5799 hg status --copies --change 9353
5800
5800
5801 - get a NUL separated list of added files, suitable for xargs::
5801 - get a NUL separated list of added files, suitable for xargs::
5802
5802
5803 hg status -an0
5803 hg status -an0
5804
5804
5805 Returns 0 on success.
5805 Returns 0 on success.
5806 """
5806 """
5807
5807
5808 revs = opts.get('rev')
5808 revs = opts.get('rev')
5809 change = opts.get('change')
5809 change = opts.get('change')
5810
5810
5811 if revs and change:
5811 if revs and change:
5812 msg = _('cannot specify --rev and --change at the same time')
5812 msg = _('cannot specify --rev and --change at the same time')
5813 raise util.Abort(msg)
5813 raise util.Abort(msg)
5814 elif change:
5814 elif change:
5815 node2 = scmutil.revsingle(repo, change, None).node()
5815 node2 = scmutil.revsingle(repo, change, None).node()
5816 node1 = repo[node2].p1().node()
5816 node1 = repo[node2].p1().node()
5817 else:
5817 else:
5818 node1, node2 = scmutil.revpair(repo, revs)
5818 node1, node2 = scmutil.revpair(repo, revs)
5819
5819
5820 if pats:
5820 if pats:
5821 cwd = repo.getcwd()
5821 cwd = repo.getcwd()
5822 else:
5822 else:
5823 cwd = ''
5823 cwd = ''
5824
5824
5825 if opts.get('print0'):
5825 if opts.get('print0'):
5826 end = '\0'
5826 end = '\0'
5827 else:
5827 else:
5828 end = '\n'
5828 end = '\n'
5829 copy = {}
5829 copy = {}
5830 states = 'modified added removed deleted unknown ignored clean'.split()
5830 states = 'modified added removed deleted unknown ignored clean'.split()
5831 show = [k for k in states if opts.get(k)]
5831 show = [k for k in states if opts.get(k)]
5832 if opts.get('all'):
5832 if opts.get('all'):
5833 show += ui.quiet and (states[:4] + ['clean']) or states
5833 show += ui.quiet and (states[:4] + ['clean']) or states
5834 if not show:
5834 if not show:
5835 if ui.quiet:
5835 if ui.quiet:
5836 show = states[:4]
5836 show = states[:4]
5837 else:
5837 else:
5838 show = states[:5]
5838 show = states[:5]
5839
5839
5840 m = scmutil.match(repo[node2], pats, opts)
5840 m = scmutil.match(repo[node2], pats, opts)
5841 stat = repo.status(node1, node2, m,
5841 stat = repo.status(node1, node2, m,
5842 'ignored' in show, 'clean' in show, 'unknown' in show,
5842 'ignored' in show, 'clean' in show, 'unknown' in show,
5843 opts.get('subrepos'))
5843 opts.get('subrepos'))
5844 changestates = zip(states, 'MAR!?IC', stat)
5844 changestates = zip(states, 'MAR!?IC', stat)
5845
5845
5846 if (opts.get('all') or opts.get('copies')
5846 if (opts.get('all') or opts.get('copies')
5847 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5847 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5848 copy = copies.pathcopies(repo[node1], repo[node2], m)
5848 copy = copies.pathcopies(repo[node1], repo[node2], m)
5849
5849
5850 fm = ui.formatter('status', opts)
5850 fm = ui.formatter('status', opts)
5851 fmt = '%s' + end
5851 fmt = '%s' + end
5852 showchar = not opts.get('no_status')
5852 showchar = not opts.get('no_status')
5853
5853
5854 for state, char, files in changestates:
5854 for state, char, files in changestates:
5855 if state in show:
5855 if state in show:
5856 label = 'status.' + state
5856 label = 'status.' + state
5857 for f in files:
5857 for f in files:
5858 fm.startitem()
5858 fm.startitem()
5859 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5859 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5860 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5860 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5861 if f in copy:
5861 if f in copy:
5862 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5862 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5863 label='status.copied')
5863 label='status.copied')
5864 fm.end()
5864 fm.end()
5865
5865
5866 @command('^summary|sum',
5866 @command('^summary|sum',
5867 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5867 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5868 def summary(ui, repo, **opts):
5868 def summary(ui, repo, **opts):
5869 """summarize working directory state
5869 """summarize working directory state
5870
5870
5871 This generates a brief summary of the working directory state,
5871 This generates a brief summary of the working directory state,
5872 including parents, branch, commit status, and available updates.
5872 including parents, branch, commit status, and available updates.
5873
5873
5874 With the --remote option, this will check the default paths for
5874 With the --remote option, this will check the default paths for
5875 incoming and outgoing changes. This can be time-consuming.
5875 incoming and outgoing changes. This can be time-consuming.
5876
5876
5877 Returns 0 on success.
5877 Returns 0 on success.
5878 """
5878 """
5879
5879
5880 ctx = repo[None]
5880 ctx = repo[None]
5881 parents = ctx.parents()
5881 parents = ctx.parents()
5882 pnode = parents[0].node()
5882 pnode = parents[0].node()
5883 marks = []
5883 marks = []
5884
5884
5885 for p in parents:
5885 for p in parents:
5886 # label with log.changeset (instead of log.parent) since this
5886 # label with log.changeset (instead of log.parent) since this
5887 # shows a working directory parent *changeset*:
5887 # shows a working directory parent *changeset*:
5888 # i18n: column positioning for "hg summary"
5888 # i18n: column positioning for "hg summary"
5889 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5889 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5890 label='log.changeset changeset.%s' % p.phasestr())
5890 label='log.changeset changeset.%s' % p.phasestr())
5891 ui.write(' '.join(p.tags()), label='log.tag')
5891 ui.write(' '.join(p.tags()), label='log.tag')
5892 if p.bookmarks():
5892 if p.bookmarks():
5893 marks.extend(p.bookmarks())
5893 marks.extend(p.bookmarks())
5894 if p.rev() == -1:
5894 if p.rev() == -1:
5895 if not len(repo):
5895 if not len(repo):
5896 ui.write(_(' (empty repository)'))
5896 ui.write(_(' (empty repository)'))
5897 else:
5897 else:
5898 ui.write(_(' (no revision checked out)'))
5898 ui.write(_(' (no revision checked out)'))
5899 ui.write('\n')
5899 ui.write('\n')
5900 if p.description():
5900 if p.description():
5901 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5901 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5902 label='log.summary')
5902 label='log.summary')
5903
5903
5904 branch = ctx.branch()
5904 branch = ctx.branch()
5905 bheads = repo.branchheads(branch)
5905 bheads = repo.branchheads(branch)
5906 # i18n: column positioning for "hg summary"
5906 # i18n: column positioning for "hg summary"
5907 m = _('branch: %s\n') % branch
5907 m = _('branch: %s\n') % branch
5908 if branch != 'default':
5908 if branch != 'default':
5909 ui.write(m, label='log.branch')
5909 ui.write(m, label='log.branch')
5910 else:
5910 else:
5911 ui.status(m, label='log.branch')
5911 ui.status(m, label='log.branch')
5912
5912
5913 if marks:
5913 if marks:
5914 current = repo._bookmarkcurrent
5914 current = repo._bookmarkcurrent
5915 # i18n: column positioning for "hg summary"
5915 # i18n: column positioning for "hg summary"
5916 ui.write(_('bookmarks:'), label='log.bookmark')
5916 ui.write(_('bookmarks:'), label='log.bookmark')
5917 if current is not None:
5917 if current is not None:
5918 if current in marks:
5918 if current in marks:
5919 ui.write(' *' + current, label='bookmarks.current')
5919 ui.write(' *' + current, label='bookmarks.current')
5920 marks.remove(current)
5920 marks.remove(current)
5921 else:
5921 else:
5922 ui.write(' [%s]' % current, label='bookmarks.current')
5922 ui.write(' [%s]' % current, label='bookmarks.current')
5923 for m in marks:
5923 for m in marks:
5924 ui.write(' ' + m, label='log.bookmark')
5924 ui.write(' ' + m, label='log.bookmark')
5925 ui.write('\n', label='log.bookmark')
5925 ui.write('\n', label='log.bookmark')
5926
5926
5927 status = repo.status(unknown=True)
5927 status = repo.status(unknown=True)
5928
5928
5929 c = repo.dirstate.copies()
5929 c = repo.dirstate.copies()
5930 copied, renamed = [], []
5930 copied, renamed = [], []
5931 for d, s in c.iteritems():
5931 for d, s in c.iteritems():
5932 if s in status.removed:
5932 if s in status.removed:
5933 status.removed.remove(s)
5933 status.removed.remove(s)
5934 renamed.append(d)
5934 renamed.append(d)
5935 else:
5935 else:
5936 copied.append(d)
5936 copied.append(d)
5937 if d in status.added:
5937 if d in status.added:
5938 status.added.remove(d)
5938 status.added.remove(d)
5939
5939
5940 ms = mergemod.mergestate(repo)
5940 ms = mergemod.mergestate(repo)
5941 unresolved = [f for f in ms if ms[f] == 'u']
5941 unresolved = [f for f in ms if ms[f] == 'u']
5942
5942
5943 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5943 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5944
5944
5945 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5945 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5946 (ui.label(_('%d added'), 'status.added'), status.added),
5946 (ui.label(_('%d added'), 'status.added'), status.added),
5947 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5947 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5948 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5948 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5949 (ui.label(_('%d copied'), 'status.copied'), copied),
5949 (ui.label(_('%d copied'), 'status.copied'), copied),
5950 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5950 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5951 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5951 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5952 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5952 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5953 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5953 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5954 t = []
5954 t = []
5955 for l, s in labels:
5955 for l, s in labels:
5956 if s:
5956 if s:
5957 t.append(l % len(s))
5957 t.append(l % len(s))
5958
5958
5959 t = ', '.join(t)
5959 t = ', '.join(t)
5960 cleanworkdir = False
5960 cleanworkdir = False
5961
5961
5962 if repo.vfs.exists('updatestate'):
5962 if repo.vfs.exists('updatestate'):
5963 t += _(' (interrupted update)')
5963 t += _(' (interrupted update)')
5964 elif len(parents) > 1:
5964 elif len(parents) > 1:
5965 t += _(' (merge)')
5965 t += _(' (merge)')
5966 elif branch != parents[0].branch():
5966 elif branch != parents[0].branch():
5967 t += _(' (new branch)')
5967 t += _(' (new branch)')
5968 elif (parents[0].closesbranch() and
5968 elif (parents[0].closesbranch() and
5969 pnode in repo.branchheads(branch, closed=True)):
5969 pnode in repo.branchheads(branch, closed=True)):
5970 t += _(' (head closed)')
5970 t += _(' (head closed)')
5971 elif not (status.modified or status.added or status.removed or renamed or
5971 elif not (status.modified or status.added or status.removed or renamed or
5972 copied or subs):
5972 copied or subs):
5973 t += _(' (clean)')
5973 t += _(' (clean)')
5974 cleanworkdir = True
5974 cleanworkdir = True
5975 elif pnode not in bheads:
5975 elif pnode not in bheads:
5976 t += _(' (new branch head)')
5976 t += _(' (new branch head)')
5977
5977
5978 if cleanworkdir:
5978 if cleanworkdir:
5979 # i18n: column positioning for "hg summary"
5979 # i18n: column positioning for "hg summary"
5980 ui.status(_('commit: %s\n') % t.strip())
5980 ui.status(_('commit: %s\n') % t.strip())
5981 else:
5981 else:
5982 # i18n: column positioning for "hg summary"
5982 # i18n: column positioning for "hg summary"
5983 ui.write(_('commit: %s\n') % t.strip())
5983 ui.write(_('commit: %s\n') % t.strip())
5984
5984
5985 # all ancestors of branch heads - all ancestors of parent = new csets
5985 # all ancestors of branch heads - all ancestors of parent = new csets
5986 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5986 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5987 bheads))
5987 bheads))
5988
5988
5989 if new == 0:
5989 if new == 0:
5990 # i18n: column positioning for "hg summary"
5990 # i18n: column positioning for "hg summary"
5991 ui.status(_('update: (current)\n'))
5991 ui.status(_('update: (current)\n'))
5992 elif pnode not in bheads:
5992 elif pnode not in bheads:
5993 # i18n: column positioning for "hg summary"
5993 # i18n: column positioning for "hg summary"
5994 ui.write(_('update: %d new changesets (update)\n') % new)
5994 ui.write(_('update: %d new changesets (update)\n') % new)
5995 else:
5995 else:
5996 # i18n: column positioning for "hg summary"
5996 # i18n: column positioning for "hg summary"
5997 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5997 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5998 (new, len(bheads)))
5998 (new, len(bheads)))
5999
5999
6000 cmdutil.summaryhooks(ui, repo)
6000 cmdutil.summaryhooks(ui, repo)
6001
6001
6002 if opts.get('remote'):
6002 if opts.get('remote'):
6003 needsincoming, needsoutgoing = True, True
6003 needsincoming, needsoutgoing = True, True
6004 else:
6004 else:
6005 needsincoming, needsoutgoing = False, False
6005 needsincoming, needsoutgoing = False, False
6006 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6006 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6007 if i:
6007 if i:
6008 needsincoming = True
6008 needsincoming = True
6009 if o:
6009 if o:
6010 needsoutgoing = True
6010 needsoutgoing = True
6011 if not needsincoming and not needsoutgoing:
6011 if not needsincoming and not needsoutgoing:
6012 return
6012 return
6013
6013
6014 def getincoming():
6014 def getincoming():
6015 source, branches = hg.parseurl(ui.expandpath('default'))
6015 source, branches = hg.parseurl(ui.expandpath('default'))
6016 sbranch = branches[0]
6016 sbranch = branches[0]
6017 try:
6017 try:
6018 other = hg.peer(repo, {}, source)
6018 other = hg.peer(repo, {}, source)
6019 except error.RepoError:
6019 except error.RepoError:
6020 if opts.get('remote'):
6020 if opts.get('remote'):
6021 raise
6021 raise
6022 return source, sbranch, None, None, None
6022 return source, sbranch, None, None, None
6023 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6023 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6024 if revs:
6024 if revs:
6025 revs = [other.lookup(rev) for rev in revs]
6025 revs = [other.lookup(rev) for rev in revs]
6026 ui.debug('comparing with %s\n' % util.hidepassword(source))
6026 ui.debug('comparing with %s\n' % util.hidepassword(source))
6027 repo.ui.pushbuffer()
6027 repo.ui.pushbuffer()
6028 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6028 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6029 repo.ui.popbuffer()
6029 repo.ui.popbuffer()
6030 return source, sbranch, other, commoninc, commoninc[1]
6030 return source, sbranch, other, commoninc, commoninc[1]
6031
6031
6032 if needsincoming:
6032 if needsincoming:
6033 source, sbranch, sother, commoninc, incoming = getincoming()
6033 source, sbranch, sother, commoninc, incoming = getincoming()
6034 else:
6034 else:
6035 source = sbranch = sother = commoninc = incoming = None
6035 source = sbranch = sother = commoninc = incoming = None
6036
6036
6037 def getoutgoing():
6037 def getoutgoing():
6038 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6038 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6039 dbranch = branches[0]
6039 dbranch = branches[0]
6040 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6040 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6041 if source != dest:
6041 if source != dest:
6042 try:
6042 try:
6043 dother = hg.peer(repo, {}, dest)
6043 dother = hg.peer(repo, {}, dest)
6044 except error.RepoError:
6044 except error.RepoError:
6045 if opts.get('remote'):
6045 if opts.get('remote'):
6046 raise
6046 raise
6047 return dest, dbranch, None, None
6047 return dest, dbranch, None, None
6048 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6048 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6049 elif sother is None:
6049 elif sother is None:
6050 # there is no explicit destination peer, but source one is invalid
6050 # there is no explicit destination peer, but source one is invalid
6051 return dest, dbranch, None, None
6051 return dest, dbranch, None, None
6052 else:
6052 else:
6053 dother = sother
6053 dother = sother
6054 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6054 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6055 common = None
6055 common = None
6056 else:
6056 else:
6057 common = commoninc
6057 common = commoninc
6058 if revs:
6058 if revs:
6059 revs = [repo.lookup(rev) for rev in revs]
6059 revs = [repo.lookup(rev) for rev in revs]
6060 repo.ui.pushbuffer()
6060 repo.ui.pushbuffer()
6061 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6061 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6062 commoninc=common)
6062 commoninc=common)
6063 repo.ui.popbuffer()
6063 repo.ui.popbuffer()
6064 return dest, dbranch, dother, outgoing
6064 return dest, dbranch, dother, outgoing
6065
6065
6066 if needsoutgoing:
6066 if needsoutgoing:
6067 dest, dbranch, dother, outgoing = getoutgoing()
6067 dest, dbranch, dother, outgoing = getoutgoing()
6068 else:
6068 else:
6069 dest = dbranch = dother = outgoing = None
6069 dest = dbranch = dother = outgoing = None
6070
6070
6071 if opts.get('remote'):
6071 if opts.get('remote'):
6072 t = []
6072 t = []
6073 if incoming:
6073 if incoming:
6074 t.append(_('1 or more incoming'))
6074 t.append(_('1 or more incoming'))
6075 o = outgoing.missing
6075 o = outgoing.missing
6076 if o:
6076 if o:
6077 t.append(_('%d outgoing') % len(o))
6077 t.append(_('%d outgoing') % len(o))
6078 other = dother or sother
6078 other = dother or sother
6079 if 'bookmarks' in other.listkeys('namespaces'):
6079 if 'bookmarks' in other.listkeys('namespaces'):
6080 counts = bookmarks.summary(repo, other)
6080 counts = bookmarks.summary(repo, other)
6081 if counts[0] > 0:
6081 if counts[0] > 0:
6082 t.append(_('%d incoming bookmarks') % counts[0])
6082 t.append(_('%d incoming bookmarks') % counts[0])
6083 if counts[1] > 0:
6083 if counts[1] > 0:
6084 t.append(_('%d outgoing bookmarks') % counts[1])
6084 t.append(_('%d outgoing bookmarks') % counts[1])
6085
6085
6086 if t:
6086 if t:
6087 # i18n: column positioning for "hg summary"
6087 # i18n: column positioning for "hg summary"
6088 ui.write(_('remote: %s\n') % (', '.join(t)))
6088 ui.write(_('remote: %s\n') % (', '.join(t)))
6089 else:
6089 else:
6090 # i18n: column positioning for "hg summary"
6090 # i18n: column positioning for "hg summary"
6091 ui.status(_('remote: (synced)\n'))
6091 ui.status(_('remote: (synced)\n'))
6092
6092
6093 cmdutil.summaryremotehooks(ui, repo, opts,
6093 cmdutil.summaryremotehooks(ui, repo, opts,
6094 ((source, sbranch, sother, commoninc),
6094 ((source, sbranch, sother, commoninc),
6095 (dest, dbranch, dother, outgoing)))
6095 (dest, dbranch, dother, outgoing)))
6096
6096
6097 @command('tag',
6097 @command('tag',
6098 [('f', 'force', None, _('force tag')),
6098 [('f', 'force', None, _('force tag')),
6099 ('l', 'local', None, _('make the tag local')),
6099 ('l', 'local', None, _('make the tag local')),
6100 ('r', 'rev', '', _('revision to tag'), _('REV')),
6100 ('r', 'rev', '', _('revision to tag'), _('REV')),
6101 ('', 'remove', None, _('remove a tag')),
6101 ('', 'remove', None, _('remove a tag')),
6102 # -l/--local is already there, commitopts cannot be used
6102 # -l/--local is already there, commitopts cannot be used
6103 ('e', 'edit', None, _('invoke editor on commit messages')),
6103 ('e', 'edit', None, _('invoke editor on commit messages')),
6104 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6104 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6105 ] + commitopts2,
6105 ] + commitopts2,
6106 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6106 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6107 def tag(ui, repo, name1, *names, **opts):
6107 def tag(ui, repo, name1, *names, **opts):
6108 """add one or more tags for the current or given revision
6108 """add one or more tags for the current or given revision
6109
6109
6110 Name a particular revision using <name>.
6110 Name a particular revision using <name>.
6111
6111
6112 Tags are used to name particular revisions of the repository and are
6112 Tags are used to name particular revisions of the repository and are
6113 very useful to compare different revisions, to go back to significant
6113 very useful to compare different revisions, to go back to significant
6114 earlier versions or to mark branch points as releases, etc. Changing
6114 earlier versions or to mark branch points as releases, etc. Changing
6115 an existing tag is normally disallowed; use -f/--force to override.
6115 an existing tag is normally disallowed; use -f/--force to override.
6116
6116
6117 If no revision is given, the parent of the working directory is
6117 If no revision is given, the parent of the working directory is
6118 used.
6118 used.
6119
6119
6120 To facilitate version control, distribution, and merging of tags,
6120 To facilitate version control, distribution, and merging of tags,
6121 they are stored as a file named ".hgtags" which is managed similarly
6121 they are stored as a file named ".hgtags" which is managed similarly
6122 to other project files and can be hand-edited if necessary. This
6122 to other project files and can be hand-edited if necessary. This
6123 also means that tagging creates a new commit. The file
6123 also means that tagging creates a new commit. The file
6124 ".hg/localtags" is used for local tags (not shared among
6124 ".hg/localtags" is used for local tags (not shared among
6125 repositories).
6125 repositories).
6126
6126
6127 Tag commits are usually made at the head of a branch. If the parent
6127 Tag commits are usually made at the head of a branch. If the parent
6128 of the working directory is not a branch head, :hg:`tag` aborts; use
6128 of the working directory is not a branch head, :hg:`tag` aborts; use
6129 -f/--force to force the tag commit to be based on a non-head
6129 -f/--force to force the tag commit to be based on a non-head
6130 changeset.
6130 changeset.
6131
6131
6132 See :hg:`help dates` for a list of formats valid for -d/--date.
6132 See :hg:`help dates` for a list of formats valid for -d/--date.
6133
6133
6134 Since tag names have priority over branch names during revision
6134 Since tag names have priority over branch names during revision
6135 lookup, using an existing branch name as a tag name is discouraged.
6135 lookup, using an existing branch name as a tag name is discouraged.
6136
6136
6137 Returns 0 on success.
6137 Returns 0 on success.
6138 """
6138 """
6139 wlock = lock = None
6139 wlock = lock = None
6140 try:
6140 try:
6141 wlock = repo.wlock()
6141 wlock = repo.wlock()
6142 lock = repo.lock()
6142 lock = repo.lock()
6143 rev_ = "."
6143 rev_ = "."
6144 names = [t.strip() for t in (name1,) + names]
6144 names = [t.strip() for t in (name1,) + names]
6145 if len(names) != len(set(names)):
6145 if len(names) != len(set(names)):
6146 raise util.Abort(_('tag names must be unique'))
6146 raise util.Abort(_('tag names must be unique'))
6147 for n in names:
6147 for n in names:
6148 scmutil.checknewlabel(repo, n, 'tag')
6148 scmutil.checknewlabel(repo, n, 'tag')
6149 if not n:
6149 if not n:
6150 raise util.Abort(_('tag names cannot consist entirely of '
6150 raise util.Abort(_('tag names cannot consist entirely of '
6151 'whitespace'))
6151 'whitespace'))
6152 if opts.get('rev') and opts.get('remove'):
6152 if opts.get('rev') and opts.get('remove'):
6153 raise util.Abort(_("--rev and --remove are incompatible"))
6153 raise util.Abort(_("--rev and --remove are incompatible"))
6154 if opts.get('rev'):
6154 if opts.get('rev'):
6155 rev_ = opts['rev']
6155 rev_ = opts['rev']
6156 message = opts.get('message')
6156 message = opts.get('message')
6157 if opts.get('remove'):
6157 if opts.get('remove'):
6158 if opts.get('local'):
6158 if opts.get('local'):
6159 expectedtype = 'local'
6159 expectedtype = 'local'
6160 else:
6160 else:
6161 expectedtype = 'global'
6161 expectedtype = 'global'
6162
6162
6163 for n in names:
6163 for n in names:
6164 if not repo.tagtype(n):
6164 if not repo.tagtype(n):
6165 raise util.Abort(_("tag '%s' does not exist") % n)
6165 raise util.Abort(_("tag '%s' does not exist") % n)
6166 if repo.tagtype(n) != expectedtype:
6166 if repo.tagtype(n) != expectedtype:
6167 if expectedtype == 'global':
6167 if expectedtype == 'global':
6168 raise util.Abort(_("tag '%s' is not a global tag") % n)
6168 raise util.Abort(_("tag '%s' is not a global tag") % n)
6169 else:
6169 else:
6170 raise util.Abort(_("tag '%s' is not a local tag") % n)
6170 raise util.Abort(_("tag '%s' is not a local tag") % n)
6171 rev_ = nullid
6171 rev_ = nullid
6172 if not message:
6172 if not message:
6173 # we don't translate commit messages
6173 # we don't translate commit messages
6174 message = 'Removed tag %s' % ', '.join(names)
6174 message = 'Removed tag %s' % ', '.join(names)
6175 elif not opts.get('force'):
6175 elif not opts.get('force'):
6176 for n in names:
6176 for n in names:
6177 if n in repo.tags():
6177 if n in repo.tags():
6178 raise util.Abort(_("tag '%s' already exists "
6178 raise util.Abort(_("tag '%s' already exists "
6179 "(use -f to force)") % n)
6179 "(use -f to force)") % n)
6180 if not opts.get('local'):
6180 if not opts.get('local'):
6181 p1, p2 = repo.dirstate.parents()
6181 p1, p2 = repo.dirstate.parents()
6182 if p2 != nullid:
6182 if p2 != nullid:
6183 raise util.Abort(_('uncommitted merge'))
6183 raise util.Abort(_('uncommitted merge'))
6184 bheads = repo.branchheads()
6184 bheads = repo.branchheads()
6185 if not opts.get('force') and bheads and p1 not in bheads:
6185 if not opts.get('force') and bheads and p1 not in bheads:
6186 raise util.Abort(_('not at a branch head (use -f to force)'))
6186 raise util.Abort(_('not at a branch head (use -f to force)'))
6187 r = scmutil.revsingle(repo, rev_).node()
6187 r = scmutil.revsingle(repo, rev_).node()
6188
6188
6189 if not message:
6189 if not message:
6190 # we don't translate commit messages
6190 # we don't translate commit messages
6191 message = ('Added tag %s for changeset %s' %
6191 message = ('Added tag %s for changeset %s' %
6192 (', '.join(names), short(r)))
6192 (', '.join(names), short(r)))
6193
6193
6194 date = opts.get('date')
6194 date = opts.get('date')
6195 if date:
6195 if date:
6196 date = util.parsedate(date)
6196 date = util.parsedate(date)
6197
6197
6198 if opts.get('remove'):
6198 if opts.get('remove'):
6199 editform = 'tag.remove'
6199 editform = 'tag.remove'
6200 else:
6200 else:
6201 editform = 'tag.add'
6201 editform = 'tag.add'
6202 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6202 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6203
6203
6204 # don't allow tagging the null rev
6204 # don't allow tagging the null rev
6205 if (not opts.get('remove') and
6205 if (not opts.get('remove') and
6206 scmutil.revsingle(repo, rev_).rev() == nullrev):
6206 scmutil.revsingle(repo, rev_).rev() == nullrev):
6207 raise util.Abort(_("cannot tag null revision"))
6207 raise util.Abort(_("cannot tag null revision"))
6208
6208
6209 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6209 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6210 editor=editor)
6210 editor=editor)
6211 finally:
6211 finally:
6212 release(lock, wlock)
6212 release(lock, wlock)
6213
6213
6214 @command('tags', formatteropts, '')
6214 @command('tags', formatteropts, '')
6215 def tags(ui, repo, **opts):
6215 def tags(ui, repo, **opts):
6216 """list repository tags
6216 """list repository tags
6217
6217
6218 This lists both regular and local tags. When the -v/--verbose
6218 This lists both regular and local tags. When the -v/--verbose
6219 switch is used, a third column "local" is printed for local tags.
6219 switch is used, a third column "local" is printed for local tags.
6220
6220
6221 Returns 0 on success.
6221 Returns 0 on success.
6222 """
6222 """
6223
6223
6224 fm = ui.formatter('tags', opts)
6224 fm = ui.formatter('tags', opts)
6225 hexfunc = fm.hexfunc
6225 hexfunc = fm.hexfunc
6226 tagtype = ""
6226 tagtype = ""
6227
6227
6228 for t, n in reversed(repo.tagslist()):
6228 for t, n in reversed(repo.tagslist()):
6229 hn = hexfunc(n)
6229 hn = hexfunc(n)
6230 label = 'tags.normal'
6230 label = 'tags.normal'
6231 tagtype = ''
6231 tagtype = ''
6232 if repo.tagtype(t) == 'local':
6232 if repo.tagtype(t) == 'local':
6233 label = 'tags.local'
6233 label = 'tags.local'
6234 tagtype = 'local'
6234 tagtype = 'local'
6235
6235
6236 fm.startitem()
6236 fm.startitem()
6237 fm.write('tag', '%s', t, label=label)
6237 fm.write('tag', '%s', t, label=label)
6238 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6238 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6239 fm.condwrite(not ui.quiet, 'rev node', fmt,
6239 fm.condwrite(not ui.quiet, 'rev node', fmt,
6240 repo.changelog.rev(n), hn, label=label)
6240 repo.changelog.rev(n), hn, label=label)
6241 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6241 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6242 tagtype, label=label)
6242 tagtype, label=label)
6243 fm.plain('\n')
6243 fm.plain('\n')
6244 fm.end()
6244 fm.end()
6245
6245
6246 @command('tip',
6246 @command('tip',
6247 [('p', 'patch', None, _('show patch')),
6247 [('p', 'patch', None, _('show patch')),
6248 ('g', 'git', None, _('use git extended diff format')),
6248 ('g', 'git', None, _('use git extended diff format')),
6249 ] + templateopts,
6249 ] + templateopts,
6250 _('[-p] [-g]'))
6250 _('[-p] [-g]'))
6251 def tip(ui, repo, **opts):
6251 def tip(ui, repo, **opts):
6252 """show the tip revision (DEPRECATED)
6252 """show the tip revision (DEPRECATED)
6253
6253
6254 The tip revision (usually just called the tip) is the changeset
6254 The tip revision (usually just called the tip) is the changeset
6255 most recently added to the repository (and therefore the most
6255 most recently added to the repository (and therefore the most
6256 recently changed head).
6256 recently changed head).
6257
6257
6258 If you have just made a commit, that commit will be the tip. If
6258 If you have just made a commit, that commit will be the tip. If
6259 you have just pulled changes from another repository, the tip of
6259 you have just pulled changes from another repository, the tip of
6260 that repository becomes the current tip. The "tip" tag is special
6260 that repository becomes the current tip. The "tip" tag is special
6261 and cannot be renamed or assigned to a different changeset.
6261 and cannot be renamed or assigned to a different changeset.
6262
6262
6263 This command is deprecated, please use :hg:`heads` instead.
6263 This command is deprecated, please use :hg:`heads` instead.
6264
6264
6265 Returns 0 on success.
6265 Returns 0 on success.
6266 """
6266 """
6267 displayer = cmdutil.show_changeset(ui, repo, opts)
6267 displayer = cmdutil.show_changeset(ui, repo, opts)
6268 displayer.show(repo['tip'])
6268 displayer.show(repo['tip'])
6269 displayer.close()
6269 displayer.close()
6270
6270
6271 @command('unbundle',
6271 @command('unbundle',
6272 [('u', 'update', None,
6272 [('u', 'update', None,
6273 _('update to new branch head if changesets were unbundled'))],
6273 _('update to new branch head if changesets were unbundled'))],
6274 _('[-u] FILE...'))
6274 _('[-u] FILE...'))
6275 def unbundle(ui, repo, fname1, *fnames, **opts):
6275 def unbundle(ui, repo, fname1, *fnames, **opts):
6276 """apply one or more changegroup files
6276 """apply one or more changegroup files
6277
6277
6278 Apply one or more compressed changegroup files generated by the
6278 Apply one or more compressed changegroup files generated by the
6279 bundle command.
6279 bundle command.
6280
6280
6281 Returns 0 on success, 1 if an update has unresolved files.
6281 Returns 0 on success, 1 if an update has unresolved files.
6282 """
6282 """
6283 fnames = (fname1,) + fnames
6283 fnames = (fname1,) + fnames
6284
6284
6285 lock = repo.lock()
6285 lock = repo.lock()
6286 try:
6286 try:
6287 for fname in fnames:
6287 for fname in fnames:
6288 f = hg.openpath(ui, fname)
6288 f = hg.openpath(ui, fname)
6289 gen = exchange.readbundle(ui, f, fname)
6289 gen = exchange.readbundle(ui, f, fname)
6290 if isinstance(gen, bundle2.unbundle20):
6290 if isinstance(gen, bundle2.unbundle20):
6291 tr = repo.transaction('unbundle')
6291 tr = repo.transaction('unbundle')
6292 try:
6292 try:
6293 op = bundle2.processbundle(repo, gen, lambda: tr)
6293 op = bundle2.processbundle(repo, gen, lambda: tr)
6294 tr.close()
6294 tr.close()
6295 finally:
6295 finally:
6296 if tr:
6296 if tr:
6297 tr.release()
6297 tr.release()
6298 changes = [r.get('result', 0)
6298 changes = [r.get('result', 0)
6299 for r in op.records['changegroup']]
6299 for r in op.records['changegroup']]
6300 modheads = changegroup.combineresults(changes)
6300 modheads = changegroup.combineresults(changes)
6301 else:
6301 else:
6302 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6302 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6303 'bundle:' + fname)
6303 'bundle:' + fname)
6304 finally:
6304 finally:
6305 lock.release()
6305 lock.release()
6306
6306
6307 return postincoming(ui, repo, modheads, opts.get('update'), None)
6307 return postincoming(ui, repo, modheads, opts.get('update'), None)
6308
6308
6309 @command('^update|up|checkout|co',
6309 @command('^update|up|checkout|co',
6310 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6310 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6311 ('c', 'check', None,
6311 ('c', 'check', None,
6312 _('update across branches if no uncommitted changes')),
6312 _('update across branches if no uncommitted changes')),
6313 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6313 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6314 ('r', 'rev', '', _('revision'), _('REV'))
6314 ('r', 'rev', '', _('revision'), _('REV'))
6315 ] + mergetoolopts,
6315 ] + mergetoolopts,
6316 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6316 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6317 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6317 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6318 tool=None):
6318 tool=None):
6319 """update working directory (or switch revisions)
6319 """update working directory (or switch revisions)
6320
6320
6321 Update the repository's working directory to the specified
6321 Update the repository's working directory to the specified
6322 changeset. If no changeset is specified, update to the tip of the
6322 changeset. If no changeset is specified, update to the tip of the
6323 current named branch and move the current bookmark (see :hg:`help
6323 current named branch and move the current bookmark (see :hg:`help
6324 bookmarks`).
6324 bookmarks`).
6325
6325
6326 Update sets the working directory's parent revision to the specified
6326 Update sets the working directory's parent revision to the specified
6327 changeset (see :hg:`help parents`).
6327 changeset (see :hg:`help parents`).
6328
6328
6329 If the changeset is not a descendant or ancestor of the working
6329 If the changeset is not a descendant or ancestor of the working
6330 directory's parent, the update is aborted. With the -c/--check
6330 directory's parent, the update is aborted. With the -c/--check
6331 option, the working directory is checked for uncommitted changes; if
6331 option, the working directory is checked for uncommitted changes; if
6332 none are found, the working directory is updated to the specified
6332 none are found, the working directory is updated to the specified
6333 changeset.
6333 changeset.
6334
6334
6335 .. container:: verbose
6335 .. container:: verbose
6336
6336
6337 The following rules apply when the working directory contains
6337 The following rules apply when the working directory contains
6338 uncommitted changes:
6338 uncommitted changes:
6339
6339
6340 1. If neither -c/--check nor -C/--clean is specified, and if
6340 1. If neither -c/--check nor -C/--clean is specified, and if
6341 the requested changeset is an ancestor or descendant of
6341 the requested changeset is an ancestor or descendant of
6342 the working directory's parent, the uncommitted changes
6342 the working directory's parent, the uncommitted changes
6343 are merged into the requested changeset and the merged
6343 are merged into the requested changeset and the merged
6344 result is left uncommitted. If the requested changeset is
6344 result is left uncommitted. If the requested changeset is
6345 not an ancestor or descendant (that is, it is on another
6345 not an ancestor or descendant (that is, it is on another
6346 branch), the update is aborted and the uncommitted changes
6346 branch), the update is aborted and the uncommitted changes
6347 are preserved.
6347 are preserved.
6348
6348
6349 2. With the -c/--check option, the update is aborted and the
6349 2. With the -c/--check option, the update is aborted and the
6350 uncommitted changes are preserved.
6350 uncommitted changes are preserved.
6351
6351
6352 3. With the -C/--clean option, uncommitted changes are discarded and
6352 3. With the -C/--clean option, uncommitted changes are discarded and
6353 the working directory is updated to the requested changeset.
6353 the working directory is updated to the requested changeset.
6354
6354
6355 To cancel an uncommitted merge (and lose your changes), use
6355 To cancel an uncommitted merge (and lose your changes), use
6356 :hg:`update --clean .`.
6356 :hg:`update --clean .`.
6357
6357
6358 Use null as the changeset to remove the working directory (like
6358 Use null as the changeset to remove the working directory (like
6359 :hg:`clone -U`).
6359 :hg:`clone -U`).
6360
6360
6361 If you want to revert just one file to an older revision, use
6361 If you want to revert just one file to an older revision, use
6362 :hg:`revert [-r REV] NAME`.
6362 :hg:`revert [-r REV] NAME`.
6363
6363
6364 See :hg:`help dates` for a list of formats valid for -d/--date.
6364 See :hg:`help dates` for a list of formats valid for -d/--date.
6365
6365
6366 Returns 0 on success, 1 if there are unresolved files.
6366 Returns 0 on success, 1 if there are unresolved files.
6367 """
6367 """
6368 if rev and node:
6368 if rev and node:
6369 raise util.Abort(_("please specify just one revision"))
6369 raise util.Abort(_("please specify just one revision"))
6370
6370
6371 if rev is None or rev == '':
6371 if rev is None or rev == '':
6372 rev = node
6372 rev = node
6373
6373
6374 cmdutil.clearunfinished(repo)
6374 cmdutil.clearunfinished(repo)
6375
6375
6376 # with no argument, we also move the current bookmark, if any
6376 # with no argument, we also move the current bookmark, if any
6377 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6377 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6378
6378
6379 # if we defined a bookmark, we have to remember the original bookmark name
6379 # if we defined a bookmark, we have to remember the original bookmark name
6380 brev = rev
6380 brev = rev
6381 rev = scmutil.revsingle(repo, rev, rev).rev()
6381 rev = scmutil.revsingle(repo, rev, rev).rev()
6382
6382
6383 if check and clean:
6383 if check and clean:
6384 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6384 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6385
6385
6386 if date:
6386 if date:
6387 if rev is not None:
6387 if rev is not None:
6388 raise util.Abort(_("you can't specify a revision and a date"))
6388 raise util.Abort(_("you can't specify a revision and a date"))
6389 rev = cmdutil.finddate(ui, repo, date)
6389 rev = cmdutil.finddate(ui, repo, date)
6390
6390
6391 if check:
6391 if check:
6392 cmdutil.bailifchanged(repo, merge=False)
6392 cmdutil.bailifchanged(repo, merge=False)
6393 if rev is None:
6393 if rev is None:
6394 rev = repo[repo[None].branch()].rev()
6394 rev = repo[repo[None].branch()].rev()
6395
6395
6396 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6396 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6397
6397
6398 if clean:
6398 if clean:
6399 ret = hg.clean(repo, rev)
6399 ret = hg.clean(repo, rev)
6400 else:
6400 else:
6401 ret = hg.update(repo, rev)
6401 ret = hg.update(repo, rev)
6402
6402
6403 if not ret and movemarkfrom:
6403 if not ret and movemarkfrom:
6404 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6404 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6405 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6405 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6406 elif brev in repo._bookmarks:
6406 elif brev in repo._bookmarks:
6407 bookmarks.setcurrent(repo, brev)
6407 bookmarks.setcurrent(repo, brev)
6408 ui.status(_("(activating bookmark %s)\n") % brev)
6408 ui.status(_("(activating bookmark %s)\n") % brev)
6409 elif brev:
6409 elif brev:
6410 if repo._bookmarkcurrent:
6410 if repo._bookmarkcurrent:
6411 ui.status(_("(leaving bookmark %s)\n") %
6411 ui.status(_("(leaving bookmark %s)\n") %
6412 repo._bookmarkcurrent)
6412 repo._bookmarkcurrent)
6413 bookmarks.unsetcurrent(repo)
6413 bookmarks.unsetcurrent(repo)
6414
6414
6415 return ret
6415 return ret
6416
6416
6417 @command('verify', [])
6417 @command('verify', [])
6418 def verify(ui, repo):
6418 def verify(ui, repo):
6419 """verify the integrity of the repository
6419 """verify the integrity of the repository
6420
6420
6421 Verify the integrity of the current repository.
6421 Verify the integrity of the current repository.
6422
6422
6423 This will perform an extensive check of the repository's
6423 This will perform an extensive check of the repository's
6424 integrity, validating the hashes and checksums of each entry in
6424 integrity, validating the hashes and checksums of each entry in
6425 the changelog, manifest, and tracked files, as well as the
6425 the changelog, manifest, and tracked files, as well as the
6426 integrity of their crosslinks and indices.
6426 integrity of their crosslinks and indices.
6427
6427
6428 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6428 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6429 for more information about recovery from corruption of the
6429 for more information about recovery from corruption of the
6430 repository.
6430 repository.
6431
6431
6432 Returns 0 on success, 1 if errors are encountered.
6432 Returns 0 on success, 1 if errors are encountered.
6433 """
6433 """
6434 return hg.verify(repo)
6434 return hg.verify(repo)
6435
6435
6436 @command('version', [], norepo=True)
6436 @command('version', [], norepo=True)
6437 def version_(ui):
6437 def version_(ui):
6438 """output version and copyright information"""
6438 """output version and copyright information"""
6439 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6439 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6440 % util.version())
6440 % util.version())
6441 ui.status(_(
6441 ui.status(_(
6442 "(see http://mercurial.selenic.com for more information)\n"
6442 "(see http://mercurial.selenic.com for more information)\n"
6443 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6443 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6444 "This is free software; see the source for copying conditions. "
6444 "This is free software; see the source for copying conditions. "
6445 "There is NO\nwarranty; "
6445 "There is NO\nwarranty; "
6446 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6446 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6447 ))
6447 ))
6448
6448
6449 ui.note(_("\nEnabled extensions:\n\n"))
6449 ui.note(_("\nEnabled extensions:\n\n"))
6450 if ui.verbose:
6450 if ui.verbose:
6451 # format names and versions into columns
6451 # format names and versions into columns
6452 names = []
6452 names = []
6453 vers = []
6453 vers = []
6454 for name, module in extensions.extensions():
6454 for name, module in extensions.extensions():
6455 names.append(name)
6455 names.append(name)
6456 vers.append(extensions.moduleversion(module))
6456 vers.append(extensions.moduleversion(module))
6457 if names:
6457 if names:
6458 maxnamelen = max(len(n) for n in names)
6458 maxnamelen = max(len(n) for n in names)
6459 for i, name in enumerate(names):
6459 for i, name in enumerate(names):
6460 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6460 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now