##// END OF EJS Templates
revert: do not requires '--all' if '--interative' is present...
Pierre-Yves David -
r24698:a85c4ed1 default
parent child Browse files
Show More
@@ -1,6462 +1,6462 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 By default, annotate files in the parent of the working directory.
270 By default, annotate files in the parent of the working directory.
271 Use -r "wdir()" to annotate the working directory files.
271 Use -r "wdir()" to annotate the working directory files.
272
272
273 Returns 0 on success.
273 Returns 0 on success.
274 """
274 """
275 if not pats:
275 if not pats:
276 raise util.Abort(_('at least one filename or pattern is required'))
276 raise util.Abort(_('at least one filename or pattern is required'))
277
277
278 if opts.get('follow'):
278 if opts.get('follow'):
279 # --follow is deprecated and now just an alias for -f/--file
279 # --follow is deprecated and now just an alias for -f/--file
280 # to mimic the behavior of Mercurial before version 1.5
280 # to mimic the behavior of Mercurial before version 1.5
281 opts['file'] = True
281 opts['file'] = True
282
282
283 ctx = scmutil.revsingle(repo, opts.get('rev'))
283 ctx = scmutil.revsingle(repo, opts.get('rev'))
284
284
285 fm = ui.formatter('annotate', opts)
285 fm = ui.formatter('annotate', opts)
286 if ui.quiet:
286 if ui.quiet:
287 datefunc = util.shortdate
287 datefunc = util.shortdate
288 else:
288 else:
289 datefunc = util.datestr
289 datefunc = util.datestr
290 if ctx.rev() is None:
290 if ctx.rev() is None:
291 def hexfn(node):
291 def hexfn(node):
292 if node is None:
292 if node is None:
293 return None
293 return None
294 else:
294 else:
295 return fm.hexfunc(node)
295 return fm.hexfunc(node)
296 if opts.get('changeset'):
296 if opts.get('changeset'):
297 # omit "+" suffix which is appended to node hex
297 # omit "+" suffix which is appended to node hex
298 def formatrev(rev):
298 def formatrev(rev):
299 if rev is None:
299 if rev is None:
300 return '%d' % ctx.p1().rev()
300 return '%d' % ctx.p1().rev()
301 else:
301 else:
302 return '%d' % rev
302 return '%d' % rev
303 else:
303 else:
304 def formatrev(rev):
304 def formatrev(rev):
305 if rev is None:
305 if rev is None:
306 return '%d+' % ctx.p1().rev()
306 return '%d+' % ctx.p1().rev()
307 else:
307 else:
308 return '%d ' % rev
308 return '%d ' % rev
309 def formathex(hex):
309 def formathex(hex):
310 if hex is None:
310 if hex is None:
311 return '%s+' % fm.hexfunc(ctx.p1().node())
311 return '%s+' % fm.hexfunc(ctx.p1().node())
312 else:
312 else:
313 return '%s ' % hex
313 return '%s ' % hex
314 else:
314 else:
315 hexfn = fm.hexfunc
315 hexfn = fm.hexfunc
316 formatrev = formathex = str
316 formatrev = formathex = str
317
317
318 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
318 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
319 ('number', ' ', lambda x: x[0].rev(), formatrev),
319 ('number', ' ', lambda x: x[0].rev(), formatrev),
320 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
320 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
321 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
321 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
322 ('file', ' ', lambda x: x[0].path(), str),
322 ('file', ' ', lambda x: x[0].path(), str),
323 ('line_number', ':', lambda x: x[1], str),
323 ('line_number', ':', lambda x: x[1], str),
324 ]
324 ]
325 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
325 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
326
326
327 if (not opts.get('user') and not opts.get('changeset')
327 if (not opts.get('user') and not opts.get('changeset')
328 and not opts.get('date') and not opts.get('file')):
328 and not opts.get('date') and not opts.get('file')):
329 opts['number'] = True
329 opts['number'] = True
330
330
331 linenumber = opts.get('line_number') is not None
331 linenumber = opts.get('line_number') is not None
332 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
332 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
333 raise util.Abort(_('at least one of -n/-c is required for -l'))
333 raise util.Abort(_('at least one of -n/-c is required for -l'))
334
334
335 if fm:
335 if fm:
336 def makefunc(get, fmt):
336 def makefunc(get, fmt):
337 return get
337 return get
338 else:
338 else:
339 def makefunc(get, fmt):
339 def makefunc(get, fmt):
340 return lambda x: fmt(get(x))
340 return lambda x: fmt(get(x))
341 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
341 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
342 if opts.get(op)]
342 if opts.get(op)]
343 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
343 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
344 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
344 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
345 if opts.get(op))
345 if opts.get(op))
346
346
347 def bad(x, y):
347 def bad(x, y):
348 raise util.Abort("%s: %s" % (x, y))
348 raise util.Abort("%s: %s" % (x, y))
349
349
350 m = scmutil.match(ctx, pats, opts)
350 m = scmutil.match(ctx, pats, opts)
351 m.bad = bad
351 m.bad = bad
352 follow = not opts.get('no_follow')
352 follow = not opts.get('no_follow')
353 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
353 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
354 whitespace=True)
354 whitespace=True)
355 for abs in ctx.walk(m):
355 for abs in ctx.walk(m):
356 fctx = ctx[abs]
356 fctx = ctx[abs]
357 if not opts.get('text') and util.binary(fctx.data()):
357 if not opts.get('text') and util.binary(fctx.data()):
358 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
358 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
359 continue
359 continue
360
360
361 lines = fctx.annotate(follow=follow, linenumber=linenumber,
361 lines = fctx.annotate(follow=follow, linenumber=linenumber,
362 diffopts=diffopts)
362 diffopts=diffopts)
363 formats = []
363 formats = []
364 pieces = []
364 pieces = []
365
365
366 for f, sep in funcmap:
366 for f, sep in funcmap:
367 l = [f(n) for n, dummy in lines]
367 l = [f(n) for n, dummy in lines]
368 if l:
368 if l:
369 if fm:
369 if fm:
370 formats.append(['%s' for x in l])
370 formats.append(['%s' for x in l])
371 else:
371 else:
372 sizes = [encoding.colwidth(x) for x in l]
372 sizes = [encoding.colwidth(x) for x in l]
373 ml = max(sizes)
373 ml = max(sizes)
374 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
374 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
375 pieces.append(l)
375 pieces.append(l)
376
376
377 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
377 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
378 fm.startitem()
378 fm.startitem()
379 fm.write(fields, "".join(f), *p)
379 fm.write(fields, "".join(f), *p)
380 fm.write('line', ": %s", l[1])
380 fm.write('line', ": %s", l[1])
381
381
382 if lines and not lines[-1][1].endswith('\n'):
382 if lines and not lines[-1][1].endswith('\n'):
383 fm.plain('\n')
383 fm.plain('\n')
384
384
385 fm.end()
385 fm.end()
386
386
387 @command('archive',
387 @command('archive',
388 [('', 'no-decode', None, _('do not pass files through decoders')),
388 [('', 'no-decode', None, _('do not pass files through decoders')),
389 ('p', 'prefix', '', _('directory prefix for files in archive'),
389 ('p', 'prefix', '', _('directory prefix for files in archive'),
390 _('PREFIX')),
390 _('PREFIX')),
391 ('r', 'rev', '', _('revision to distribute'), _('REV')),
391 ('r', 'rev', '', _('revision to distribute'), _('REV')),
392 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
392 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
393 ] + subrepoopts + walkopts,
393 ] + subrepoopts + walkopts,
394 _('[OPTION]... DEST'))
394 _('[OPTION]... DEST'))
395 def archive(ui, repo, dest, **opts):
395 def archive(ui, repo, dest, **opts):
396 '''create an unversioned archive of a repository revision
396 '''create an unversioned archive of a repository revision
397
397
398 By default, the revision used is the parent of the working
398 By default, the revision used is the parent of the working
399 directory; use -r/--rev to specify a different revision.
399 directory; use -r/--rev to specify a different revision.
400
400
401 The archive type is automatically detected based on file
401 The archive type is automatically detected based on file
402 extension (or override using -t/--type).
402 extension (or override using -t/--type).
403
403
404 .. container:: verbose
404 .. container:: verbose
405
405
406 Examples:
406 Examples:
407
407
408 - create a zip file containing the 1.0 release::
408 - create a zip file containing the 1.0 release::
409
409
410 hg archive -r 1.0 project-1.0.zip
410 hg archive -r 1.0 project-1.0.zip
411
411
412 - create a tarball excluding .hg files::
412 - create a tarball excluding .hg files::
413
413
414 hg archive project.tar.gz -X ".hg*"
414 hg archive project.tar.gz -X ".hg*"
415
415
416 Valid types are:
416 Valid types are:
417
417
418 :``files``: a directory full of files (default)
418 :``files``: a directory full of files (default)
419 :``tar``: tar archive, uncompressed
419 :``tar``: tar archive, uncompressed
420 :``tbz2``: tar archive, compressed using bzip2
420 :``tbz2``: tar archive, compressed using bzip2
421 :``tgz``: tar archive, compressed using gzip
421 :``tgz``: tar archive, compressed using gzip
422 :``uzip``: zip archive, uncompressed
422 :``uzip``: zip archive, uncompressed
423 :``zip``: zip archive, compressed using deflate
423 :``zip``: zip archive, compressed using deflate
424
424
425 The exact name of the destination archive or directory is given
425 The exact name of the destination archive or directory is given
426 using a format string; see :hg:`help export` for details.
426 using a format string; see :hg:`help export` for details.
427
427
428 Each member added to an archive file has a directory prefix
428 Each member added to an archive file has a directory prefix
429 prepended. Use -p/--prefix to specify a format string for the
429 prepended. Use -p/--prefix to specify a format string for the
430 prefix. The default is the basename of the archive, with suffixes
430 prefix. The default is the basename of the archive, with suffixes
431 removed.
431 removed.
432
432
433 Returns 0 on success.
433 Returns 0 on success.
434 '''
434 '''
435
435
436 ctx = scmutil.revsingle(repo, opts.get('rev'))
436 ctx = scmutil.revsingle(repo, opts.get('rev'))
437 if not ctx:
437 if not ctx:
438 raise util.Abort(_('no working directory: please specify a revision'))
438 raise util.Abort(_('no working directory: please specify a revision'))
439 node = ctx.node()
439 node = ctx.node()
440 dest = cmdutil.makefilename(repo, dest, node)
440 dest = cmdutil.makefilename(repo, dest, node)
441 if os.path.realpath(dest) == repo.root:
441 if os.path.realpath(dest) == repo.root:
442 raise util.Abort(_('repository root cannot be destination'))
442 raise util.Abort(_('repository root cannot be destination'))
443
443
444 kind = opts.get('type') or archival.guesskind(dest) or 'files'
444 kind = opts.get('type') or archival.guesskind(dest) or 'files'
445 prefix = opts.get('prefix')
445 prefix = opts.get('prefix')
446
446
447 if dest == '-':
447 if dest == '-':
448 if kind == 'files':
448 if kind == 'files':
449 raise util.Abort(_('cannot archive plain files to stdout'))
449 raise util.Abort(_('cannot archive plain files to stdout'))
450 dest = cmdutil.makefileobj(repo, dest)
450 dest = cmdutil.makefileobj(repo, dest)
451 if not prefix:
451 if not prefix:
452 prefix = os.path.basename(repo.root) + '-%h'
452 prefix = os.path.basename(repo.root) + '-%h'
453
453
454 prefix = cmdutil.makefilename(repo, prefix, node)
454 prefix = cmdutil.makefilename(repo, prefix, node)
455 matchfn = scmutil.match(ctx, [], opts)
455 matchfn = scmutil.match(ctx, [], opts)
456 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
456 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
457 matchfn, prefix, subrepos=opts.get('subrepos'))
457 matchfn, prefix, subrepos=opts.get('subrepos'))
458
458
459 @command('backout',
459 @command('backout',
460 [('', 'merge', None, _('merge with old dirstate parent after backout')),
460 [('', 'merge', None, _('merge with old dirstate parent after backout')),
461 ('', 'commit', None, _('commit if no conflicts were encountered')),
461 ('', 'commit', None, _('commit if no conflicts were encountered')),
462 ('', 'parent', '',
462 ('', 'parent', '',
463 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
463 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
464 ('r', 'rev', '', _('revision to backout'), _('REV')),
464 ('r', 'rev', '', _('revision to backout'), _('REV')),
465 ('e', 'edit', False, _('invoke editor on commit messages')),
465 ('e', 'edit', False, _('invoke editor on commit messages')),
466 ] + mergetoolopts + walkopts + commitopts + commitopts2,
466 ] + mergetoolopts + walkopts + commitopts + commitopts2,
467 _('[OPTION]... [-r] REV'))
467 _('[OPTION]... [-r] REV'))
468 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
468 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
469 '''reverse effect of earlier changeset
469 '''reverse effect of earlier changeset
470
470
471 Prepare a new changeset with the effect of REV undone in the
471 Prepare a new changeset with the effect of REV undone in the
472 current working directory.
472 current working directory.
473
473
474 If REV is the parent of the working directory, then this new changeset
474 If REV is the parent of the working directory, then this new changeset
475 is committed automatically. Otherwise, hg needs to merge the
475 is committed automatically. Otherwise, hg needs to merge the
476 changes and the merged result is left uncommitted.
476 changes and the merged result is left uncommitted.
477
477
478 .. note::
478 .. note::
479
479
480 backout cannot be used to fix either an unwanted or
480 backout cannot be used to fix either an unwanted or
481 incorrect merge.
481 incorrect merge.
482
482
483 .. container:: verbose
483 .. container:: verbose
484
484
485 By default, the pending changeset will have one parent,
485 By default, the pending changeset will have one parent,
486 maintaining a linear history. With --merge, the pending
486 maintaining a linear history. With --merge, the pending
487 changeset will instead have two parents: the old parent of the
487 changeset will instead have two parents: the old parent of the
488 working directory and a new child of REV that simply undoes REV.
488 working directory and a new child of REV that simply undoes REV.
489
489
490 Before version 1.7, the behavior without --merge was equivalent
490 Before version 1.7, the behavior without --merge was equivalent
491 to specifying --merge followed by :hg:`update --clean .` to
491 to specifying --merge followed by :hg:`update --clean .` to
492 cancel the merge and leave the child of REV as a head to be
492 cancel the merge and leave the child of REV as a head to be
493 merged separately.
493 merged separately.
494
494
495 See :hg:`help dates` for a list of formats valid for -d/--date.
495 See :hg:`help dates` for a list of formats valid for -d/--date.
496
496
497 Returns 0 on success, 1 if nothing to backout or there are unresolved
497 Returns 0 on success, 1 if nothing to backout or there are unresolved
498 files.
498 files.
499 '''
499 '''
500 if rev and node:
500 if rev and node:
501 raise util.Abort(_("please specify just one revision"))
501 raise util.Abort(_("please specify just one revision"))
502
502
503 if not rev:
503 if not rev:
504 rev = node
504 rev = node
505
505
506 if not rev:
506 if not rev:
507 raise util.Abort(_("please specify a revision to backout"))
507 raise util.Abort(_("please specify a revision to backout"))
508
508
509 date = opts.get('date')
509 date = opts.get('date')
510 if date:
510 if date:
511 opts['date'] = util.parsedate(date)
511 opts['date'] = util.parsedate(date)
512
512
513 cmdutil.checkunfinished(repo)
513 cmdutil.checkunfinished(repo)
514 cmdutil.bailifchanged(repo)
514 cmdutil.bailifchanged(repo)
515 node = scmutil.revsingle(repo, rev).node()
515 node = scmutil.revsingle(repo, rev).node()
516
516
517 op1, op2 = repo.dirstate.parents()
517 op1, op2 = repo.dirstate.parents()
518 if not repo.changelog.isancestor(node, op1):
518 if not repo.changelog.isancestor(node, op1):
519 raise util.Abort(_('cannot backout change that is not an ancestor'))
519 raise util.Abort(_('cannot backout change that is not an ancestor'))
520
520
521 p1, p2 = repo.changelog.parents(node)
521 p1, p2 = repo.changelog.parents(node)
522 if p1 == nullid:
522 if p1 == nullid:
523 raise util.Abort(_('cannot backout a change with no parents'))
523 raise util.Abort(_('cannot backout a change with no parents'))
524 if p2 != nullid:
524 if p2 != nullid:
525 if not opts.get('parent'):
525 if not opts.get('parent'):
526 raise util.Abort(_('cannot backout a merge changeset'))
526 raise util.Abort(_('cannot backout a merge changeset'))
527 p = repo.lookup(opts['parent'])
527 p = repo.lookup(opts['parent'])
528 if p not in (p1, p2):
528 if p not in (p1, p2):
529 raise util.Abort(_('%s is not a parent of %s') %
529 raise util.Abort(_('%s is not a parent of %s') %
530 (short(p), short(node)))
530 (short(p), short(node)))
531 parent = p
531 parent = p
532 else:
532 else:
533 if opts.get('parent'):
533 if opts.get('parent'):
534 raise util.Abort(_('cannot use --parent on non-merge changeset'))
534 raise util.Abort(_('cannot use --parent on non-merge changeset'))
535 parent = p1
535 parent = p1
536
536
537 # the backout should appear on the same branch
537 # the backout should appear on the same branch
538 wlock = repo.wlock()
538 wlock = repo.wlock()
539 try:
539 try:
540 branch = repo.dirstate.branch()
540 branch = repo.dirstate.branch()
541 bheads = repo.branchheads(branch)
541 bheads = repo.branchheads(branch)
542 rctx = scmutil.revsingle(repo, hex(parent))
542 rctx = scmutil.revsingle(repo, hex(parent))
543 if not opts.get('merge') and op1 != node:
543 if not opts.get('merge') and op1 != node:
544 try:
544 try:
545 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
545 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
546 'backout')
546 'backout')
547 repo.dirstate.beginparentchange()
547 repo.dirstate.beginparentchange()
548 stats = mergemod.update(repo, parent, True, True, False,
548 stats = mergemod.update(repo, parent, True, True, False,
549 node, False)
549 node, False)
550 repo.setparents(op1, op2)
550 repo.setparents(op1, op2)
551 repo.dirstate.endparentchange()
551 repo.dirstate.endparentchange()
552 hg._showstats(repo, stats)
552 hg._showstats(repo, stats)
553 if stats[3]:
553 if stats[3]:
554 repo.ui.status(_("use 'hg resolve' to retry unresolved "
554 repo.ui.status(_("use 'hg resolve' to retry unresolved "
555 "file merges\n"))
555 "file merges\n"))
556 return 1
556 return 1
557 elif not commit:
557 elif not commit:
558 msg = _("changeset %s backed out, "
558 msg = _("changeset %s backed out, "
559 "don't forget to commit.\n")
559 "don't forget to commit.\n")
560 ui.status(msg % short(node))
560 ui.status(msg % short(node))
561 return 0
561 return 0
562 finally:
562 finally:
563 ui.setconfig('ui', 'forcemerge', '', '')
563 ui.setconfig('ui', 'forcemerge', '', '')
564 else:
564 else:
565 hg.clean(repo, node, show_stats=False)
565 hg.clean(repo, node, show_stats=False)
566 repo.dirstate.setbranch(branch)
566 repo.dirstate.setbranch(branch)
567 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
567 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
568
568
569
569
570 def commitfunc(ui, repo, message, match, opts):
570 def commitfunc(ui, repo, message, match, opts):
571 editform = 'backout'
571 editform = 'backout'
572 e = cmdutil.getcommiteditor(editform=editform, **opts)
572 e = cmdutil.getcommiteditor(editform=editform, **opts)
573 if not message:
573 if not message:
574 # we don't translate commit messages
574 # we don't translate commit messages
575 message = "Backed out changeset %s" % short(node)
575 message = "Backed out changeset %s" % short(node)
576 e = cmdutil.getcommiteditor(edit=True, editform=editform)
576 e = cmdutil.getcommiteditor(edit=True, editform=editform)
577 return repo.commit(message, opts.get('user'), opts.get('date'),
577 return repo.commit(message, opts.get('user'), opts.get('date'),
578 match, editor=e)
578 match, editor=e)
579 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
579 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
580 if not newnode:
580 if not newnode:
581 ui.status(_("nothing changed\n"))
581 ui.status(_("nothing changed\n"))
582 return 1
582 return 1
583 cmdutil.commitstatus(repo, newnode, branch, bheads)
583 cmdutil.commitstatus(repo, newnode, branch, bheads)
584
584
585 def nice(node):
585 def nice(node):
586 return '%d:%s' % (repo.changelog.rev(node), short(node))
586 return '%d:%s' % (repo.changelog.rev(node), short(node))
587 ui.status(_('changeset %s backs out changeset %s\n') %
587 ui.status(_('changeset %s backs out changeset %s\n') %
588 (nice(repo.changelog.tip()), nice(node)))
588 (nice(repo.changelog.tip()), nice(node)))
589 if opts.get('merge') and op1 != node:
589 if opts.get('merge') and op1 != node:
590 hg.clean(repo, op1, show_stats=False)
590 hg.clean(repo, op1, show_stats=False)
591 ui.status(_('merging with changeset %s\n')
591 ui.status(_('merging with changeset %s\n')
592 % nice(repo.changelog.tip()))
592 % nice(repo.changelog.tip()))
593 try:
593 try:
594 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
594 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
595 'backout')
595 'backout')
596 return hg.merge(repo, hex(repo.changelog.tip()))
596 return hg.merge(repo, hex(repo.changelog.tip()))
597 finally:
597 finally:
598 ui.setconfig('ui', 'forcemerge', '', '')
598 ui.setconfig('ui', 'forcemerge', '', '')
599 finally:
599 finally:
600 wlock.release()
600 wlock.release()
601 return 0
601 return 0
602
602
603 @command('bisect',
603 @command('bisect',
604 [('r', 'reset', False, _('reset bisect state')),
604 [('r', 'reset', False, _('reset bisect state')),
605 ('g', 'good', False, _('mark changeset good')),
605 ('g', 'good', False, _('mark changeset good')),
606 ('b', 'bad', False, _('mark changeset bad')),
606 ('b', 'bad', False, _('mark changeset bad')),
607 ('s', 'skip', False, _('skip testing changeset')),
607 ('s', 'skip', False, _('skip testing changeset')),
608 ('e', 'extend', False, _('extend the bisect range')),
608 ('e', 'extend', False, _('extend the bisect range')),
609 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
609 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
610 ('U', 'noupdate', False, _('do not update to target'))],
610 ('U', 'noupdate', False, _('do not update to target'))],
611 _("[-gbsr] [-U] [-c CMD] [REV]"))
611 _("[-gbsr] [-U] [-c CMD] [REV]"))
612 def bisect(ui, repo, rev=None, extra=None, command=None,
612 def bisect(ui, repo, rev=None, extra=None, command=None,
613 reset=None, good=None, bad=None, skip=None, extend=None,
613 reset=None, good=None, bad=None, skip=None, extend=None,
614 noupdate=None):
614 noupdate=None):
615 """subdivision search of changesets
615 """subdivision search of changesets
616
616
617 This command helps to find changesets which introduce problems. To
617 This command helps to find changesets which introduce problems. To
618 use, mark the earliest changeset you know exhibits the problem as
618 use, mark the earliest changeset you know exhibits the problem as
619 bad, then mark the latest changeset which is free from the problem
619 bad, then mark the latest changeset which is free from the problem
620 as good. Bisect will update your working directory to a revision
620 as good. Bisect will update your working directory to a revision
621 for testing (unless the -U/--noupdate option is specified). Once
621 for testing (unless the -U/--noupdate option is specified). Once
622 you have performed tests, mark the working directory as good or
622 you have performed tests, mark the working directory as good or
623 bad, and bisect will either update to another candidate changeset
623 bad, and bisect will either update to another candidate changeset
624 or announce that it has found the bad revision.
624 or announce that it has found the bad revision.
625
625
626 As a shortcut, you can also use the revision argument to mark a
626 As a shortcut, you can also use the revision argument to mark a
627 revision as good or bad without checking it out first.
627 revision as good or bad without checking it out first.
628
628
629 If you supply a command, it will be used for automatic bisection.
629 If you supply a command, it will be used for automatic bisection.
630 The environment variable HG_NODE will contain the ID of the
630 The environment variable HG_NODE will contain the ID of the
631 changeset being tested. The exit status of the command will be
631 changeset being tested. The exit status of the command will be
632 used to mark revisions as good or bad: status 0 means good, 125
632 used to mark revisions as good or bad: status 0 means good, 125
633 means to skip the revision, 127 (command not found) will abort the
633 means to skip the revision, 127 (command not found) will abort the
634 bisection, and any other non-zero exit status means the revision
634 bisection, and any other non-zero exit status means the revision
635 is bad.
635 is bad.
636
636
637 .. container:: verbose
637 .. container:: verbose
638
638
639 Some examples:
639 Some examples:
640
640
641 - start a bisection with known bad revision 34, and good revision 12::
641 - start a bisection with known bad revision 34, and good revision 12::
642
642
643 hg bisect --bad 34
643 hg bisect --bad 34
644 hg bisect --good 12
644 hg bisect --good 12
645
645
646 - advance the current bisection by marking current revision as good or
646 - advance the current bisection by marking current revision as good or
647 bad::
647 bad::
648
648
649 hg bisect --good
649 hg bisect --good
650 hg bisect --bad
650 hg bisect --bad
651
651
652 - mark the current revision, or a known revision, to be skipped (e.g. if
652 - mark the current revision, or a known revision, to be skipped (e.g. if
653 that revision is not usable because of another issue)::
653 that revision is not usable because of another issue)::
654
654
655 hg bisect --skip
655 hg bisect --skip
656 hg bisect --skip 23
656 hg bisect --skip 23
657
657
658 - skip all revisions that do not touch directories ``foo`` or ``bar``::
658 - skip all revisions that do not touch directories ``foo`` or ``bar``::
659
659
660 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
660 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
661
661
662 - forget the current bisection::
662 - forget the current bisection::
663
663
664 hg bisect --reset
664 hg bisect --reset
665
665
666 - use 'make && make tests' to automatically find the first broken
666 - use 'make && make tests' to automatically find the first broken
667 revision::
667 revision::
668
668
669 hg bisect --reset
669 hg bisect --reset
670 hg bisect --bad 34
670 hg bisect --bad 34
671 hg bisect --good 12
671 hg bisect --good 12
672 hg bisect --command "make && make tests"
672 hg bisect --command "make && make tests"
673
673
674 - see all changesets whose states are already known in the current
674 - see all changesets whose states are already known in the current
675 bisection::
675 bisection::
676
676
677 hg log -r "bisect(pruned)"
677 hg log -r "bisect(pruned)"
678
678
679 - see the changeset currently being bisected (especially useful
679 - see the changeset currently being bisected (especially useful
680 if running with -U/--noupdate)::
680 if running with -U/--noupdate)::
681
681
682 hg log -r "bisect(current)"
682 hg log -r "bisect(current)"
683
683
684 - see all changesets that took part in the current bisection::
684 - see all changesets that took part in the current bisection::
685
685
686 hg log -r "bisect(range)"
686 hg log -r "bisect(range)"
687
687
688 - you can even get a nice graph::
688 - you can even get a nice graph::
689
689
690 hg log --graph -r "bisect(range)"
690 hg log --graph -r "bisect(range)"
691
691
692 See :hg:`help revsets` for more about the `bisect()` keyword.
692 See :hg:`help revsets` for more about the `bisect()` keyword.
693
693
694 Returns 0 on success.
694 Returns 0 on success.
695 """
695 """
696 def extendbisectrange(nodes, good):
696 def extendbisectrange(nodes, good):
697 # bisect is incomplete when it ends on a merge node and
697 # bisect is incomplete when it ends on a merge node and
698 # one of the parent was not checked.
698 # one of the parent was not checked.
699 parents = repo[nodes[0]].parents()
699 parents = repo[nodes[0]].parents()
700 if len(parents) > 1:
700 if len(parents) > 1:
701 if good:
701 if good:
702 side = state['bad']
702 side = state['bad']
703 else:
703 else:
704 side = state['good']
704 side = state['good']
705 num = len(set(i.node() for i in parents) & set(side))
705 num = len(set(i.node() for i in parents) & set(side))
706 if num == 1:
706 if num == 1:
707 return parents[0].ancestor(parents[1])
707 return parents[0].ancestor(parents[1])
708 return None
708 return None
709
709
710 def print_result(nodes, good):
710 def print_result(nodes, good):
711 displayer = cmdutil.show_changeset(ui, repo, {})
711 displayer = cmdutil.show_changeset(ui, repo, {})
712 if len(nodes) == 1:
712 if len(nodes) == 1:
713 # narrowed it down to a single revision
713 # narrowed it down to a single revision
714 if good:
714 if good:
715 ui.write(_("The first good revision is:\n"))
715 ui.write(_("The first good revision is:\n"))
716 else:
716 else:
717 ui.write(_("The first bad revision is:\n"))
717 ui.write(_("The first bad revision is:\n"))
718 displayer.show(repo[nodes[0]])
718 displayer.show(repo[nodes[0]])
719 extendnode = extendbisectrange(nodes, good)
719 extendnode = extendbisectrange(nodes, good)
720 if extendnode is not None:
720 if extendnode is not None:
721 ui.write(_('Not all ancestors of this changeset have been'
721 ui.write(_('Not all ancestors of this changeset have been'
722 ' checked.\nUse bisect --extend to continue the '
722 ' checked.\nUse bisect --extend to continue the '
723 'bisection from\nthe common ancestor, %s.\n')
723 'bisection from\nthe common ancestor, %s.\n')
724 % extendnode)
724 % extendnode)
725 else:
725 else:
726 # multiple possible revisions
726 # multiple possible revisions
727 if good:
727 if good:
728 ui.write(_("Due to skipped revisions, the first "
728 ui.write(_("Due to skipped revisions, the first "
729 "good revision could be any of:\n"))
729 "good revision could be any of:\n"))
730 else:
730 else:
731 ui.write(_("Due to skipped revisions, the first "
731 ui.write(_("Due to skipped revisions, the first "
732 "bad revision could be any of:\n"))
732 "bad revision could be any of:\n"))
733 for n in nodes:
733 for n in nodes:
734 displayer.show(repo[n])
734 displayer.show(repo[n])
735 displayer.close()
735 displayer.close()
736
736
737 def check_state(state, interactive=True):
737 def check_state(state, interactive=True):
738 if not state['good'] or not state['bad']:
738 if not state['good'] or not state['bad']:
739 if (good or bad or skip or reset) and interactive:
739 if (good or bad or skip or reset) and interactive:
740 return
740 return
741 if not state['good']:
741 if not state['good']:
742 raise util.Abort(_('cannot bisect (no known good revisions)'))
742 raise util.Abort(_('cannot bisect (no known good revisions)'))
743 else:
743 else:
744 raise util.Abort(_('cannot bisect (no known bad revisions)'))
744 raise util.Abort(_('cannot bisect (no known bad revisions)'))
745 return True
745 return True
746
746
747 # backward compatibility
747 # backward compatibility
748 if rev in "good bad reset init".split():
748 if rev in "good bad reset init".split():
749 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
749 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
750 cmd, rev, extra = rev, extra, None
750 cmd, rev, extra = rev, extra, None
751 if cmd == "good":
751 if cmd == "good":
752 good = True
752 good = True
753 elif cmd == "bad":
753 elif cmd == "bad":
754 bad = True
754 bad = True
755 else:
755 else:
756 reset = True
756 reset = True
757 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
757 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
758 raise util.Abort(_('incompatible arguments'))
758 raise util.Abort(_('incompatible arguments'))
759
759
760 cmdutil.checkunfinished(repo)
760 cmdutil.checkunfinished(repo)
761
761
762 if reset:
762 if reset:
763 p = repo.join("bisect.state")
763 p = repo.join("bisect.state")
764 if os.path.exists(p):
764 if os.path.exists(p):
765 os.unlink(p)
765 os.unlink(p)
766 return
766 return
767
767
768 state = hbisect.load_state(repo)
768 state = hbisect.load_state(repo)
769
769
770 if command:
770 if command:
771 changesets = 1
771 changesets = 1
772 if noupdate:
772 if noupdate:
773 try:
773 try:
774 node = state['current'][0]
774 node = state['current'][0]
775 except LookupError:
775 except LookupError:
776 raise util.Abort(_('current bisect revision is unknown - '
776 raise util.Abort(_('current bisect revision is unknown - '
777 'start a new bisect to fix'))
777 'start a new bisect to fix'))
778 else:
778 else:
779 node, p2 = repo.dirstate.parents()
779 node, p2 = repo.dirstate.parents()
780 if p2 != nullid:
780 if p2 != nullid:
781 raise util.Abort(_('current bisect revision is a merge'))
781 raise util.Abort(_('current bisect revision is a merge'))
782 try:
782 try:
783 while changesets:
783 while changesets:
784 # update state
784 # update state
785 state['current'] = [node]
785 state['current'] = [node]
786 hbisect.save_state(repo, state)
786 hbisect.save_state(repo, state)
787 status = ui.system(command, environ={'HG_NODE': hex(node)})
787 status = ui.system(command, environ={'HG_NODE': hex(node)})
788 if status == 125:
788 if status == 125:
789 transition = "skip"
789 transition = "skip"
790 elif status == 0:
790 elif status == 0:
791 transition = "good"
791 transition = "good"
792 # status < 0 means process was killed
792 # status < 0 means process was killed
793 elif status == 127:
793 elif status == 127:
794 raise util.Abort(_("failed to execute %s") % command)
794 raise util.Abort(_("failed to execute %s") % command)
795 elif status < 0:
795 elif status < 0:
796 raise util.Abort(_("%s killed") % command)
796 raise util.Abort(_("%s killed") % command)
797 else:
797 else:
798 transition = "bad"
798 transition = "bad"
799 ctx = scmutil.revsingle(repo, rev, node)
799 ctx = scmutil.revsingle(repo, rev, node)
800 rev = None # clear for future iterations
800 rev = None # clear for future iterations
801 state[transition].append(ctx.node())
801 state[transition].append(ctx.node())
802 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
802 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
803 check_state(state, interactive=False)
803 check_state(state, interactive=False)
804 # bisect
804 # bisect
805 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
805 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
806 # update to next check
806 # update to next check
807 node = nodes[0]
807 node = nodes[0]
808 if not noupdate:
808 if not noupdate:
809 cmdutil.bailifchanged(repo)
809 cmdutil.bailifchanged(repo)
810 hg.clean(repo, node, show_stats=False)
810 hg.clean(repo, node, show_stats=False)
811 finally:
811 finally:
812 state['current'] = [node]
812 state['current'] = [node]
813 hbisect.save_state(repo, state)
813 hbisect.save_state(repo, state)
814 print_result(nodes, bgood)
814 print_result(nodes, bgood)
815 return
815 return
816
816
817 # update state
817 # update state
818
818
819 if rev:
819 if rev:
820 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
820 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
821 else:
821 else:
822 nodes = [repo.lookup('.')]
822 nodes = [repo.lookup('.')]
823
823
824 if good or bad or skip:
824 if good or bad or skip:
825 if good:
825 if good:
826 state['good'] += nodes
826 state['good'] += nodes
827 elif bad:
827 elif bad:
828 state['bad'] += nodes
828 state['bad'] += nodes
829 elif skip:
829 elif skip:
830 state['skip'] += nodes
830 state['skip'] += nodes
831 hbisect.save_state(repo, state)
831 hbisect.save_state(repo, state)
832
832
833 if not check_state(state):
833 if not check_state(state):
834 return
834 return
835
835
836 # actually bisect
836 # actually bisect
837 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
837 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
838 if extend:
838 if extend:
839 if not changesets:
839 if not changesets:
840 extendnode = extendbisectrange(nodes, good)
840 extendnode = extendbisectrange(nodes, good)
841 if extendnode is not None:
841 if extendnode is not None:
842 ui.write(_("Extending search to changeset %d:%s\n")
842 ui.write(_("Extending search to changeset %d:%s\n")
843 % (extendnode.rev(), extendnode))
843 % (extendnode.rev(), extendnode))
844 state['current'] = [extendnode.node()]
844 state['current'] = [extendnode.node()]
845 hbisect.save_state(repo, state)
845 hbisect.save_state(repo, state)
846 if noupdate:
846 if noupdate:
847 return
847 return
848 cmdutil.bailifchanged(repo)
848 cmdutil.bailifchanged(repo)
849 return hg.clean(repo, extendnode.node())
849 return hg.clean(repo, extendnode.node())
850 raise util.Abort(_("nothing to extend"))
850 raise util.Abort(_("nothing to extend"))
851
851
852 if changesets == 0:
852 if changesets == 0:
853 print_result(nodes, good)
853 print_result(nodes, good)
854 else:
854 else:
855 assert len(nodes) == 1 # only a single node can be tested next
855 assert len(nodes) == 1 # only a single node can be tested next
856 node = nodes[0]
856 node = nodes[0]
857 # compute the approximate number of remaining tests
857 # compute the approximate number of remaining tests
858 tests, size = 0, 2
858 tests, size = 0, 2
859 while size <= changesets:
859 while size <= changesets:
860 tests, size = tests + 1, size * 2
860 tests, size = tests + 1, size * 2
861 rev = repo.changelog.rev(node)
861 rev = repo.changelog.rev(node)
862 ui.write(_("Testing changeset %d:%s "
862 ui.write(_("Testing changeset %d:%s "
863 "(%d changesets remaining, ~%d tests)\n")
863 "(%d changesets remaining, ~%d tests)\n")
864 % (rev, short(node), changesets, tests))
864 % (rev, short(node), changesets, tests))
865 state['current'] = [node]
865 state['current'] = [node]
866 hbisect.save_state(repo, state)
866 hbisect.save_state(repo, state)
867 if not noupdate:
867 if not noupdate:
868 cmdutil.bailifchanged(repo)
868 cmdutil.bailifchanged(repo)
869 return hg.clean(repo, node)
869 return hg.clean(repo, node)
870
870
871 @command('bookmarks|bookmark',
871 @command('bookmarks|bookmark',
872 [('f', 'force', False, _('force')),
872 [('f', 'force', False, _('force')),
873 ('r', 'rev', '', _('revision'), _('REV')),
873 ('r', 'rev', '', _('revision'), _('REV')),
874 ('d', 'delete', False, _('delete a given bookmark')),
874 ('d', 'delete', False, _('delete a given bookmark')),
875 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
875 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
876 ('i', 'inactive', False, _('mark a bookmark inactive')),
876 ('i', 'inactive', False, _('mark a bookmark inactive')),
877 ] + formatteropts,
877 ] + formatteropts,
878 _('hg bookmarks [OPTIONS]... [NAME]...'))
878 _('hg bookmarks [OPTIONS]... [NAME]...'))
879 def bookmark(ui, repo, *names, **opts):
879 def bookmark(ui, repo, *names, **opts):
880 '''create a new bookmark or list existing bookmarks
880 '''create a new bookmark or list existing bookmarks
881
881
882 Bookmarks are labels on changesets to help track lines of development.
882 Bookmarks are labels on changesets to help track lines of development.
883 Bookmarks are unversioned and can be moved, renamed and deleted.
883 Bookmarks are unversioned and can be moved, renamed and deleted.
884 Deleting or moving a bookmark has no effect on the associated changesets.
884 Deleting or moving a bookmark has no effect on the associated changesets.
885
885
886 Creating or updating to a bookmark causes it to be marked as 'active'.
886 Creating or updating to a bookmark causes it to be marked as 'active'.
887 The active bookmark is indicated with a '*'.
887 The active bookmark is indicated with a '*'.
888 When a commit is made, the active bookmark will advance to the new commit.
888 When a commit is made, the active bookmark will advance to the new commit.
889 A plain :hg:`update` will also advance an active bookmark, if possible.
889 A plain :hg:`update` will also advance an active bookmark, if possible.
890 Updating away from a bookmark will cause it to be deactivated.
890 Updating away from a bookmark will cause it to be deactivated.
891
891
892 Bookmarks can be pushed and pulled between repositories (see
892 Bookmarks can be pushed and pulled between repositories (see
893 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
893 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
894 diverged, a new 'divergent bookmark' of the form 'name@path' will
894 diverged, a new 'divergent bookmark' of the form 'name@path' will
895 be created. Using :hg:`merge` will resolve the divergence.
895 be created. Using :hg:`merge` will resolve the divergence.
896
896
897 A bookmark named '@' has the special property that :hg:`clone` will
897 A bookmark named '@' has the special property that :hg:`clone` will
898 check it out by default if it exists.
898 check it out by default if it exists.
899
899
900 .. container:: verbose
900 .. container:: verbose
901
901
902 Examples:
902 Examples:
903
903
904 - create an active bookmark for a new line of development::
904 - create an active bookmark for a new line of development::
905
905
906 hg book new-feature
906 hg book new-feature
907
907
908 - create an inactive bookmark as a place marker::
908 - create an inactive bookmark as a place marker::
909
909
910 hg book -i reviewed
910 hg book -i reviewed
911
911
912 - create an inactive bookmark on another changeset::
912 - create an inactive bookmark on another changeset::
913
913
914 hg book -r .^ tested
914 hg book -r .^ tested
915
915
916 - move the '@' bookmark from another branch::
916 - move the '@' bookmark from another branch::
917
917
918 hg book -f @
918 hg book -f @
919 '''
919 '''
920 force = opts.get('force')
920 force = opts.get('force')
921 rev = opts.get('rev')
921 rev = opts.get('rev')
922 delete = opts.get('delete')
922 delete = opts.get('delete')
923 rename = opts.get('rename')
923 rename = opts.get('rename')
924 inactive = opts.get('inactive')
924 inactive = opts.get('inactive')
925
925
926 def checkformat(mark):
926 def checkformat(mark):
927 mark = mark.strip()
927 mark = mark.strip()
928 if not mark:
928 if not mark:
929 raise util.Abort(_("bookmark names cannot consist entirely of "
929 raise util.Abort(_("bookmark names cannot consist entirely of "
930 "whitespace"))
930 "whitespace"))
931 scmutil.checknewlabel(repo, mark, 'bookmark')
931 scmutil.checknewlabel(repo, mark, 'bookmark')
932 return mark
932 return mark
933
933
934 def checkconflict(repo, mark, cur, force=False, target=None):
934 def checkconflict(repo, mark, cur, force=False, target=None):
935 if mark in marks and not force:
935 if mark in marks and not force:
936 if target:
936 if target:
937 if marks[mark] == target and target == cur:
937 if marks[mark] == target and target == cur:
938 # re-activating a bookmark
938 # re-activating a bookmark
939 return
939 return
940 anc = repo.changelog.ancestors([repo[target].rev()])
940 anc = repo.changelog.ancestors([repo[target].rev()])
941 bmctx = repo[marks[mark]]
941 bmctx = repo[marks[mark]]
942 divs = [repo[b].node() for b in marks
942 divs = [repo[b].node() for b in marks
943 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
943 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
944
944
945 # allow resolving a single divergent bookmark even if moving
945 # allow resolving a single divergent bookmark even if moving
946 # the bookmark across branches when a revision is specified
946 # the bookmark across branches when a revision is specified
947 # that contains a divergent bookmark
947 # that contains a divergent bookmark
948 if bmctx.rev() not in anc and target in divs:
948 if bmctx.rev() not in anc and target in divs:
949 bookmarks.deletedivergent(repo, [target], mark)
949 bookmarks.deletedivergent(repo, [target], mark)
950 return
950 return
951
951
952 deletefrom = [b for b in divs
952 deletefrom = [b for b in divs
953 if repo[b].rev() in anc or b == target]
953 if repo[b].rev() in anc or b == target]
954 bookmarks.deletedivergent(repo, deletefrom, mark)
954 bookmarks.deletedivergent(repo, deletefrom, mark)
955 if bookmarks.validdest(repo, bmctx, repo[target]):
955 if bookmarks.validdest(repo, bmctx, repo[target]):
956 ui.status(_("moving bookmark '%s' forward from %s\n") %
956 ui.status(_("moving bookmark '%s' forward from %s\n") %
957 (mark, short(bmctx.node())))
957 (mark, short(bmctx.node())))
958 return
958 return
959 raise util.Abort(_("bookmark '%s' already exists "
959 raise util.Abort(_("bookmark '%s' already exists "
960 "(use -f to force)") % mark)
960 "(use -f to force)") % mark)
961 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
961 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
962 and not force):
962 and not force):
963 raise util.Abort(
963 raise util.Abort(
964 _("a bookmark cannot have the name of an existing branch"))
964 _("a bookmark cannot have the name of an existing branch"))
965
965
966 if delete and rename:
966 if delete and rename:
967 raise util.Abort(_("--delete and --rename are incompatible"))
967 raise util.Abort(_("--delete and --rename are incompatible"))
968 if delete and rev:
968 if delete and rev:
969 raise util.Abort(_("--rev is incompatible with --delete"))
969 raise util.Abort(_("--rev is incompatible with --delete"))
970 if rename and rev:
970 if rename and rev:
971 raise util.Abort(_("--rev is incompatible with --rename"))
971 raise util.Abort(_("--rev is incompatible with --rename"))
972 if not names and (delete or rev):
972 if not names and (delete or rev):
973 raise util.Abort(_("bookmark name required"))
973 raise util.Abort(_("bookmark name required"))
974
974
975 if delete or rename or names or inactive:
975 if delete or rename or names or inactive:
976 wlock = repo.wlock()
976 wlock = repo.wlock()
977 try:
977 try:
978 cur = repo.changectx('.').node()
978 cur = repo.changectx('.').node()
979 marks = repo._bookmarks
979 marks = repo._bookmarks
980 if delete:
980 if delete:
981 for mark in names:
981 for mark in names:
982 if mark not in marks:
982 if mark not in marks:
983 raise util.Abort(_("bookmark '%s' does not exist") %
983 raise util.Abort(_("bookmark '%s' does not exist") %
984 mark)
984 mark)
985 if mark == repo._bookmarkcurrent:
985 if mark == repo._bookmarkcurrent:
986 bookmarks.unsetcurrent(repo)
986 bookmarks.unsetcurrent(repo)
987 del marks[mark]
987 del marks[mark]
988 marks.write()
988 marks.write()
989
989
990 elif rename:
990 elif rename:
991 if not names:
991 if not names:
992 raise util.Abort(_("new bookmark name required"))
992 raise util.Abort(_("new bookmark name required"))
993 elif len(names) > 1:
993 elif len(names) > 1:
994 raise util.Abort(_("only one new bookmark name allowed"))
994 raise util.Abort(_("only one new bookmark name allowed"))
995 mark = checkformat(names[0])
995 mark = checkformat(names[0])
996 if rename not in marks:
996 if rename not in marks:
997 raise util.Abort(_("bookmark '%s' does not exist") % rename)
997 raise util.Abort(_("bookmark '%s' does not exist") % rename)
998 checkconflict(repo, mark, cur, force)
998 checkconflict(repo, mark, cur, force)
999 marks[mark] = marks[rename]
999 marks[mark] = marks[rename]
1000 if repo._bookmarkcurrent == rename and not inactive:
1000 if repo._bookmarkcurrent == rename and not inactive:
1001 bookmarks.setcurrent(repo, mark)
1001 bookmarks.setcurrent(repo, mark)
1002 del marks[rename]
1002 del marks[rename]
1003 marks.write()
1003 marks.write()
1004
1004
1005 elif names:
1005 elif names:
1006 newact = None
1006 newact = None
1007 for mark in names:
1007 for mark in names:
1008 mark = checkformat(mark)
1008 mark = checkformat(mark)
1009 if newact is None:
1009 if newact is None:
1010 newact = mark
1010 newact = mark
1011 if inactive and mark == repo._bookmarkcurrent:
1011 if inactive and mark == repo._bookmarkcurrent:
1012 bookmarks.unsetcurrent(repo)
1012 bookmarks.unsetcurrent(repo)
1013 return
1013 return
1014 tgt = cur
1014 tgt = cur
1015 if rev:
1015 if rev:
1016 tgt = scmutil.revsingle(repo, rev).node()
1016 tgt = scmutil.revsingle(repo, rev).node()
1017 checkconflict(repo, mark, cur, force, tgt)
1017 checkconflict(repo, mark, cur, force, tgt)
1018 marks[mark] = tgt
1018 marks[mark] = tgt
1019 if not inactive and cur == marks[newact] and not rev:
1019 if not inactive and cur == marks[newact] and not rev:
1020 bookmarks.setcurrent(repo, newact)
1020 bookmarks.setcurrent(repo, newact)
1021 elif cur != tgt and newact == repo._bookmarkcurrent:
1021 elif cur != tgt and newact == repo._bookmarkcurrent:
1022 bookmarks.unsetcurrent(repo)
1022 bookmarks.unsetcurrent(repo)
1023 marks.write()
1023 marks.write()
1024
1024
1025 elif inactive:
1025 elif inactive:
1026 if len(marks) == 0:
1026 if len(marks) == 0:
1027 ui.status(_("no bookmarks set\n"))
1027 ui.status(_("no bookmarks set\n"))
1028 elif not repo._bookmarkcurrent:
1028 elif not repo._bookmarkcurrent:
1029 ui.status(_("no active bookmark\n"))
1029 ui.status(_("no active bookmark\n"))
1030 else:
1030 else:
1031 bookmarks.unsetcurrent(repo)
1031 bookmarks.unsetcurrent(repo)
1032 finally:
1032 finally:
1033 wlock.release()
1033 wlock.release()
1034 else: # show bookmarks
1034 else: # show bookmarks
1035 fm = ui.formatter('bookmarks', opts)
1035 fm = ui.formatter('bookmarks', opts)
1036 hexfn = fm.hexfunc
1036 hexfn = fm.hexfunc
1037 marks = repo._bookmarks
1037 marks = repo._bookmarks
1038 if len(marks) == 0 and not fm:
1038 if len(marks) == 0 and not fm:
1039 ui.status(_("no bookmarks set\n"))
1039 ui.status(_("no bookmarks set\n"))
1040 for bmark, n in sorted(marks.iteritems()):
1040 for bmark, n in sorted(marks.iteritems()):
1041 current = repo._bookmarkcurrent
1041 current = repo._bookmarkcurrent
1042 if bmark == current:
1042 if bmark == current:
1043 prefix, label = '*', 'bookmarks.current'
1043 prefix, label = '*', 'bookmarks.current'
1044 else:
1044 else:
1045 prefix, label = ' ', ''
1045 prefix, label = ' ', ''
1046
1046
1047 fm.startitem()
1047 fm.startitem()
1048 if not ui.quiet:
1048 if not ui.quiet:
1049 fm.plain(' %s ' % prefix, label=label)
1049 fm.plain(' %s ' % prefix, label=label)
1050 fm.write('bookmark', '%s', bmark, label=label)
1050 fm.write('bookmark', '%s', bmark, label=label)
1051 pad = " " * (25 - encoding.colwidth(bmark))
1051 pad = " " * (25 - encoding.colwidth(bmark))
1052 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1052 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1053 repo.changelog.rev(n), hexfn(n), label=label)
1053 repo.changelog.rev(n), hexfn(n), label=label)
1054 fm.data(active=(bmark == current))
1054 fm.data(active=(bmark == current))
1055 fm.plain('\n')
1055 fm.plain('\n')
1056 fm.end()
1056 fm.end()
1057
1057
1058 @command('branch',
1058 @command('branch',
1059 [('f', 'force', None,
1059 [('f', 'force', None,
1060 _('set branch name even if it shadows an existing branch')),
1060 _('set branch name even if it shadows an existing branch')),
1061 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1061 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1062 _('[-fC] [NAME]'))
1062 _('[-fC] [NAME]'))
1063 def branch(ui, repo, label=None, **opts):
1063 def branch(ui, repo, label=None, **opts):
1064 """set or show the current branch name
1064 """set or show the current branch name
1065
1065
1066 .. note::
1066 .. note::
1067
1067
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1070 information about named branches and bookmarks.
1070 information about named branches and bookmarks.
1071
1071
1072 With no argument, show the current branch name. With one argument,
1072 With no argument, show the current branch name. With one argument,
1073 set the working directory branch name (the branch will not exist
1073 set the working directory branch name (the branch will not exist
1074 in the repository until the next commit). Standard practice
1074 in the repository until the next commit). Standard practice
1075 recommends that primary development take place on the 'default'
1075 recommends that primary development take place on the 'default'
1076 branch.
1076 branch.
1077
1077
1078 Unless -f/--force is specified, branch will not let you set a
1078 Unless -f/--force is specified, branch will not let you set a
1079 branch name that already exists.
1079 branch name that already exists.
1080
1080
1081 Use -C/--clean to reset the working directory branch to that of
1081 Use -C/--clean to reset the working directory branch to that of
1082 the parent of the working directory, negating a previous branch
1082 the parent of the working directory, negating a previous branch
1083 change.
1083 change.
1084
1084
1085 Use the command :hg:`update` to switch to an existing branch. Use
1085 Use the command :hg:`update` to switch to an existing branch. Use
1086 :hg:`commit --close-branch` to mark this branch as closed.
1086 :hg:`commit --close-branch` to mark this branch as closed.
1087
1087
1088 Returns 0 on success.
1088 Returns 0 on success.
1089 """
1089 """
1090 if label:
1090 if label:
1091 label = label.strip()
1091 label = label.strip()
1092
1092
1093 if not opts.get('clean') and not label:
1093 if not opts.get('clean') and not label:
1094 ui.write("%s\n" % repo.dirstate.branch())
1094 ui.write("%s\n" % repo.dirstate.branch())
1095 return
1095 return
1096
1096
1097 wlock = repo.wlock()
1097 wlock = repo.wlock()
1098 try:
1098 try:
1099 if opts.get('clean'):
1099 if opts.get('clean'):
1100 label = repo[None].p1().branch()
1100 label = repo[None].p1().branch()
1101 repo.dirstate.setbranch(label)
1101 repo.dirstate.setbranch(label)
1102 ui.status(_('reset working directory to branch %s\n') % label)
1102 ui.status(_('reset working directory to branch %s\n') % label)
1103 elif label:
1103 elif label:
1104 if not opts.get('force') and label in repo.branchmap():
1104 if not opts.get('force') and label in repo.branchmap():
1105 if label not in [p.branch() for p in repo.parents()]:
1105 if label not in [p.branch() for p in repo.parents()]:
1106 raise util.Abort(_('a branch of the same name already'
1106 raise util.Abort(_('a branch of the same name already'
1107 ' exists'),
1107 ' exists'),
1108 # i18n: "it" refers to an existing branch
1108 # i18n: "it" refers to an existing branch
1109 hint=_("use 'hg update' to switch to it"))
1109 hint=_("use 'hg update' to switch to it"))
1110 scmutil.checknewlabel(repo, label, 'branch')
1110 scmutil.checknewlabel(repo, label, 'branch')
1111 repo.dirstate.setbranch(label)
1111 repo.dirstate.setbranch(label)
1112 ui.status(_('marked working directory as branch %s\n') % label)
1112 ui.status(_('marked working directory as branch %s\n') % label)
1113 ui.status(_('(branches are permanent and global, '
1113 ui.status(_('(branches are permanent and global, '
1114 'did you want a bookmark?)\n'))
1114 'did you want a bookmark?)\n'))
1115 finally:
1115 finally:
1116 wlock.release()
1116 wlock.release()
1117
1117
1118 @command('branches',
1118 @command('branches',
1119 [('a', 'active', False,
1119 [('a', 'active', False,
1120 _('show only branches that have unmerged heads (DEPRECATED)')),
1120 _('show only branches that have unmerged heads (DEPRECATED)')),
1121 ('c', 'closed', False, _('show normal and closed branches')),
1121 ('c', 'closed', False, _('show normal and closed branches')),
1122 ] + formatteropts,
1122 ] + formatteropts,
1123 _('[-ac]'))
1123 _('[-ac]'))
1124 def branches(ui, repo, active=False, closed=False, **opts):
1124 def branches(ui, repo, active=False, closed=False, **opts):
1125 """list repository named branches
1125 """list repository named branches
1126
1126
1127 List the repository's named branches, indicating which ones are
1127 List the repository's named branches, indicating which ones are
1128 inactive. If -c/--closed is specified, also list branches which have
1128 inactive. If -c/--closed is specified, also list branches which have
1129 been marked closed (see :hg:`commit --close-branch`).
1129 been marked closed (see :hg:`commit --close-branch`).
1130
1130
1131 Use the command :hg:`update` to switch to an existing branch.
1131 Use the command :hg:`update` to switch to an existing branch.
1132
1132
1133 Returns 0.
1133 Returns 0.
1134 """
1134 """
1135
1135
1136 fm = ui.formatter('branches', opts)
1136 fm = ui.formatter('branches', opts)
1137 hexfunc = fm.hexfunc
1137 hexfunc = fm.hexfunc
1138
1138
1139 allheads = set(repo.heads())
1139 allheads = set(repo.heads())
1140 branches = []
1140 branches = []
1141 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1141 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1142 isactive = not isclosed and bool(set(heads) & allheads)
1142 isactive = not isclosed and bool(set(heads) & allheads)
1143 branches.append((tag, repo[tip], isactive, not isclosed))
1143 branches.append((tag, repo[tip], isactive, not isclosed))
1144 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1144 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1145 reverse=True)
1145 reverse=True)
1146
1146
1147 for tag, ctx, isactive, isopen in branches:
1147 for tag, ctx, isactive, isopen in branches:
1148 if active and not isactive:
1148 if active and not isactive:
1149 continue
1149 continue
1150 if isactive:
1150 if isactive:
1151 label = 'branches.active'
1151 label = 'branches.active'
1152 notice = ''
1152 notice = ''
1153 elif not isopen:
1153 elif not isopen:
1154 if not closed:
1154 if not closed:
1155 continue
1155 continue
1156 label = 'branches.closed'
1156 label = 'branches.closed'
1157 notice = _(' (closed)')
1157 notice = _(' (closed)')
1158 else:
1158 else:
1159 label = 'branches.inactive'
1159 label = 'branches.inactive'
1160 notice = _(' (inactive)')
1160 notice = _(' (inactive)')
1161 current = (tag == repo.dirstate.branch())
1161 current = (tag == repo.dirstate.branch())
1162 if current:
1162 if current:
1163 label = 'branches.current'
1163 label = 'branches.current'
1164
1164
1165 fm.startitem()
1165 fm.startitem()
1166 fm.write('branch', '%s', tag, label=label)
1166 fm.write('branch', '%s', tag, label=label)
1167 rev = ctx.rev()
1167 rev = ctx.rev()
1168 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1168 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1169 fmt = ' ' * padsize + ' %d:%s'
1169 fmt = ' ' * padsize + ' %d:%s'
1170 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1170 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1171 label='log.changeset changeset.%s' % ctx.phasestr())
1171 label='log.changeset changeset.%s' % ctx.phasestr())
1172 fm.data(active=isactive, closed=not isopen, current=current)
1172 fm.data(active=isactive, closed=not isopen, current=current)
1173 if not ui.quiet:
1173 if not ui.quiet:
1174 fm.plain(notice)
1174 fm.plain(notice)
1175 fm.plain('\n')
1175 fm.plain('\n')
1176 fm.end()
1176 fm.end()
1177
1177
1178 @command('bundle',
1178 @command('bundle',
1179 [('f', 'force', None, _('run even when the destination is unrelated')),
1179 [('f', 'force', None, _('run even when the destination is unrelated')),
1180 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1180 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1181 _('REV')),
1181 _('REV')),
1182 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1182 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1183 _('BRANCH')),
1183 _('BRANCH')),
1184 ('', 'base', [],
1184 ('', 'base', [],
1185 _('a base changeset assumed to be available at the destination'),
1185 _('a base changeset assumed to be available at the destination'),
1186 _('REV')),
1186 _('REV')),
1187 ('a', 'all', None, _('bundle all changesets in the repository')),
1187 ('a', 'all', None, _('bundle all changesets in the repository')),
1188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1189 ] + remoteopts,
1189 ] + remoteopts,
1190 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1190 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1191 def bundle(ui, repo, fname, dest=None, **opts):
1191 def bundle(ui, repo, fname, dest=None, **opts):
1192 """create a changegroup file
1192 """create a changegroup file
1193
1193
1194 Generate a compressed changegroup file collecting changesets not
1194 Generate a compressed changegroup file collecting changesets not
1195 known to be in another repository.
1195 known to be in another repository.
1196
1196
1197 If you omit the destination repository, then hg assumes the
1197 If you omit the destination repository, then hg assumes the
1198 destination will have all the nodes you specify with --base
1198 destination will have all the nodes you specify with --base
1199 parameters. To create a bundle containing all changesets, use
1199 parameters. To create a bundle containing all changesets, use
1200 -a/--all (or --base null).
1200 -a/--all (or --base null).
1201
1201
1202 You can change compression method with the -t/--type option.
1202 You can change compression method with the -t/--type option.
1203 The available compression methods are: none, bzip2, and
1203 The available compression methods are: none, bzip2, and
1204 gzip (by default, bundles are compressed using bzip2).
1204 gzip (by default, bundles are compressed using bzip2).
1205
1205
1206 The bundle file can then be transferred using conventional means
1206 The bundle file can then be transferred using conventional means
1207 and applied to another repository with the unbundle or pull
1207 and applied to another repository with the unbundle or pull
1208 command. This is useful when direct push and pull are not
1208 command. This is useful when direct push and pull are not
1209 available or when exporting an entire repository is undesirable.
1209 available or when exporting an entire repository is undesirable.
1210
1210
1211 Applying bundles preserves all changeset contents including
1211 Applying bundles preserves all changeset contents including
1212 permissions, copy/rename information, and revision history.
1212 permissions, copy/rename information, and revision history.
1213
1213
1214 Returns 0 on success, 1 if no changes found.
1214 Returns 0 on success, 1 if no changes found.
1215 """
1215 """
1216 revs = None
1216 revs = None
1217 if 'rev' in opts:
1217 if 'rev' in opts:
1218 revs = scmutil.revrange(repo, opts['rev'])
1218 revs = scmutil.revrange(repo, opts['rev'])
1219
1219
1220 bundletype = opts.get('type', 'bzip2').lower()
1220 bundletype = opts.get('type', 'bzip2').lower()
1221 btypes = {'none': 'HG10UN',
1221 btypes = {'none': 'HG10UN',
1222 'bzip2': 'HG10BZ',
1222 'bzip2': 'HG10BZ',
1223 'gzip': 'HG10GZ',
1223 'gzip': 'HG10GZ',
1224 'bundle2': 'HG20'}
1224 'bundle2': 'HG20'}
1225 bundletype = btypes.get(bundletype)
1225 bundletype = btypes.get(bundletype)
1226 if bundletype not in changegroup.bundletypes:
1226 if bundletype not in changegroup.bundletypes:
1227 raise util.Abort(_('unknown bundle type specified with --type'))
1227 raise util.Abort(_('unknown bundle type specified with --type'))
1228
1228
1229 if opts.get('all'):
1229 if opts.get('all'):
1230 base = ['null']
1230 base = ['null']
1231 else:
1231 else:
1232 base = scmutil.revrange(repo, opts.get('base'))
1232 base = scmutil.revrange(repo, opts.get('base'))
1233 # TODO: get desired bundlecaps from command line.
1233 # TODO: get desired bundlecaps from command line.
1234 bundlecaps = None
1234 bundlecaps = None
1235 if base:
1235 if base:
1236 if dest:
1236 if dest:
1237 raise util.Abort(_("--base is incompatible with specifying "
1237 raise util.Abort(_("--base is incompatible with specifying "
1238 "a destination"))
1238 "a destination"))
1239 common = [repo.lookup(rev) for rev in base]
1239 common = [repo.lookup(rev) for rev in base]
1240 heads = revs and map(repo.lookup, revs) or revs
1240 heads = revs and map(repo.lookup, revs) or revs
1241 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1241 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1242 common=common, bundlecaps=bundlecaps)
1242 common=common, bundlecaps=bundlecaps)
1243 outgoing = None
1243 outgoing = None
1244 else:
1244 else:
1245 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1245 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1246 dest, branches = hg.parseurl(dest, opts.get('branch'))
1246 dest, branches = hg.parseurl(dest, opts.get('branch'))
1247 other = hg.peer(repo, opts, dest)
1247 other = hg.peer(repo, opts, dest)
1248 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1248 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1249 heads = revs and map(repo.lookup, revs) or revs
1249 heads = revs and map(repo.lookup, revs) or revs
1250 outgoing = discovery.findcommonoutgoing(repo, other,
1250 outgoing = discovery.findcommonoutgoing(repo, other,
1251 onlyheads=heads,
1251 onlyheads=heads,
1252 force=opts.get('force'),
1252 force=opts.get('force'),
1253 portable=True)
1253 portable=True)
1254 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1254 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1255 bundlecaps)
1255 bundlecaps)
1256 if not cg:
1256 if not cg:
1257 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1257 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1258 return 1
1258 return 1
1259
1259
1260 changegroup.writebundle(ui, cg, fname, bundletype)
1260 changegroup.writebundle(ui, cg, fname, bundletype)
1261
1261
1262 @command('cat',
1262 @command('cat',
1263 [('o', 'output', '',
1263 [('o', 'output', '',
1264 _('print output to file with formatted name'), _('FORMAT')),
1264 _('print output to file with formatted name'), _('FORMAT')),
1265 ('r', 'rev', '', _('print the given revision'), _('REV')),
1265 ('r', 'rev', '', _('print the given revision'), _('REV')),
1266 ('', 'decode', None, _('apply any matching decode filter')),
1266 ('', 'decode', None, _('apply any matching decode filter')),
1267 ] + walkopts,
1267 ] + walkopts,
1268 _('[OPTION]... FILE...'),
1268 _('[OPTION]... FILE...'),
1269 inferrepo=True)
1269 inferrepo=True)
1270 def cat(ui, repo, file1, *pats, **opts):
1270 def cat(ui, repo, file1, *pats, **opts):
1271 """output the current or given revision of files
1271 """output the current or given revision of files
1272
1272
1273 Print the specified files as they were at the given revision. If
1273 Print the specified files as they were at the given revision. If
1274 no revision is given, the parent of the working directory is used.
1274 no revision is given, the parent of the working directory is used.
1275
1275
1276 Output may be to a file, in which case the name of the file is
1276 Output may be to a file, in which case the name of the file is
1277 given using a format string. The formatting rules as follows:
1277 given using a format string. The formatting rules as follows:
1278
1278
1279 :``%%``: literal "%" character
1279 :``%%``: literal "%" character
1280 :``%s``: basename of file being printed
1280 :``%s``: basename of file being printed
1281 :``%d``: dirname of file being printed, or '.' if in repository root
1281 :``%d``: dirname of file being printed, or '.' if in repository root
1282 :``%p``: root-relative path name of file being printed
1282 :``%p``: root-relative path name of file being printed
1283 :``%H``: changeset hash (40 hexadecimal digits)
1283 :``%H``: changeset hash (40 hexadecimal digits)
1284 :``%R``: changeset revision number
1284 :``%R``: changeset revision number
1285 :``%h``: short-form changeset hash (12 hexadecimal digits)
1285 :``%h``: short-form changeset hash (12 hexadecimal digits)
1286 :``%r``: zero-padded changeset revision number
1286 :``%r``: zero-padded changeset revision number
1287 :``%b``: basename of the exporting repository
1287 :``%b``: basename of the exporting repository
1288
1288
1289 Returns 0 on success.
1289 Returns 0 on success.
1290 """
1290 """
1291 ctx = scmutil.revsingle(repo, opts.get('rev'))
1291 ctx = scmutil.revsingle(repo, opts.get('rev'))
1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1293
1293
1294 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1294 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1295
1295
1296 @command('^clone',
1296 @command('^clone',
1297 [('U', 'noupdate', None, _('the clone will include an empty working '
1297 [('U', 'noupdate', None, _('the clone will include an empty working '
1298 'directory (only a repository)')),
1298 'directory (only a repository)')),
1299 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1299 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1303 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1303 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1304 ] + remoteopts,
1304 ] + remoteopts,
1305 _('[OPTION]... SOURCE [DEST]'),
1305 _('[OPTION]... SOURCE [DEST]'),
1306 norepo=True)
1306 norepo=True)
1307 def clone(ui, source, dest=None, **opts):
1307 def clone(ui, source, dest=None, **opts):
1308 """make a copy of an existing repository
1308 """make a copy of an existing repository
1309
1309
1310 Create a copy of an existing repository in a new directory.
1310 Create a copy of an existing repository in a new directory.
1311
1311
1312 If no destination directory name is specified, it defaults to the
1312 If no destination directory name is specified, it defaults to the
1313 basename of the source.
1313 basename of the source.
1314
1314
1315 The location of the source is added to the new repository's
1315 The location of the source is added to the new repository's
1316 ``.hg/hgrc`` file, as the default to be used for future pulls.
1316 ``.hg/hgrc`` file, as the default to be used for future pulls.
1317
1317
1318 Only local paths and ``ssh://`` URLs are supported as
1318 Only local paths and ``ssh://`` URLs are supported as
1319 destinations. For ``ssh://`` destinations, no working directory or
1319 destinations. For ``ssh://`` destinations, no working directory or
1320 ``.hg/hgrc`` will be created on the remote side.
1320 ``.hg/hgrc`` will be created on the remote side.
1321
1321
1322 To pull only a subset of changesets, specify one or more revisions
1322 To pull only a subset of changesets, specify one or more revisions
1323 identifiers with -r/--rev or branches with -b/--branch. The
1323 identifiers with -r/--rev or branches with -b/--branch. The
1324 resulting clone will contain only the specified changesets and
1324 resulting clone will contain only the specified changesets and
1325 their ancestors. These options (or 'clone src#rev dest') imply
1325 their ancestors. These options (or 'clone src#rev dest') imply
1326 --pull, even for local source repositories. Note that specifying a
1326 --pull, even for local source repositories. Note that specifying a
1327 tag will include the tagged changeset but not the changeset
1327 tag will include the tagged changeset but not the changeset
1328 containing the tag.
1328 containing the tag.
1329
1329
1330 If the source repository has a bookmark called '@' set, that
1330 If the source repository has a bookmark called '@' set, that
1331 revision will be checked out in the new repository by default.
1331 revision will be checked out in the new repository by default.
1332
1332
1333 To check out a particular version, use -u/--update, or
1333 To check out a particular version, use -u/--update, or
1334 -U/--noupdate to create a clone with no working directory.
1334 -U/--noupdate to create a clone with no working directory.
1335
1335
1336 .. container:: verbose
1336 .. container:: verbose
1337
1337
1338 For efficiency, hardlinks are used for cloning whenever the
1338 For efficiency, hardlinks are used for cloning whenever the
1339 source and destination are on the same filesystem (note this
1339 source and destination are on the same filesystem (note this
1340 applies only to the repository data, not to the working
1340 applies only to the repository data, not to the working
1341 directory). Some filesystems, such as AFS, implement hardlinking
1341 directory). Some filesystems, such as AFS, implement hardlinking
1342 incorrectly, but do not report errors. In these cases, use the
1342 incorrectly, but do not report errors. In these cases, use the
1343 --pull option to avoid hardlinking.
1343 --pull option to avoid hardlinking.
1344
1344
1345 In some cases, you can clone repositories and the working
1345 In some cases, you can clone repositories and the working
1346 directory using full hardlinks with ::
1346 directory using full hardlinks with ::
1347
1347
1348 $ cp -al REPO REPOCLONE
1348 $ cp -al REPO REPOCLONE
1349
1349
1350 This is the fastest way to clone, but it is not always safe. The
1350 This is the fastest way to clone, but it is not always safe. The
1351 operation is not atomic (making sure REPO is not modified during
1351 operation is not atomic (making sure REPO is not modified during
1352 the operation is up to you) and you have to make sure your
1352 the operation is up to you) and you have to make sure your
1353 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1353 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1354 so). Also, this is not compatible with certain extensions that
1354 so). Also, this is not compatible with certain extensions that
1355 place their metadata under the .hg directory, such as mq.
1355 place their metadata under the .hg directory, such as mq.
1356
1356
1357 Mercurial will update the working directory to the first applicable
1357 Mercurial will update the working directory to the first applicable
1358 revision from this list:
1358 revision from this list:
1359
1359
1360 a) null if -U or the source repository has no changesets
1360 a) null if -U or the source repository has no changesets
1361 b) if -u . and the source repository is local, the first parent of
1361 b) if -u . and the source repository is local, the first parent of
1362 the source repository's working directory
1362 the source repository's working directory
1363 c) the changeset specified with -u (if a branch name, this means the
1363 c) the changeset specified with -u (if a branch name, this means the
1364 latest head of that branch)
1364 latest head of that branch)
1365 d) the changeset specified with -r
1365 d) the changeset specified with -r
1366 e) the tipmost head specified with -b
1366 e) the tipmost head specified with -b
1367 f) the tipmost head specified with the url#branch source syntax
1367 f) the tipmost head specified with the url#branch source syntax
1368 g) the revision marked with the '@' bookmark, if present
1368 g) the revision marked with the '@' bookmark, if present
1369 h) the tipmost head of the default branch
1369 h) the tipmost head of the default branch
1370 i) tip
1370 i) tip
1371
1371
1372 Examples:
1372 Examples:
1373
1373
1374 - clone a remote repository to a new directory named hg/::
1374 - clone a remote repository to a new directory named hg/::
1375
1375
1376 hg clone http://selenic.com/hg
1376 hg clone http://selenic.com/hg
1377
1377
1378 - create a lightweight local clone::
1378 - create a lightweight local clone::
1379
1379
1380 hg clone project/ project-feature/
1380 hg clone project/ project-feature/
1381
1381
1382 - clone from an absolute path on an ssh server (note double-slash)::
1382 - clone from an absolute path on an ssh server (note double-slash)::
1383
1383
1384 hg clone ssh://user@server//home/projects/alpha/
1384 hg clone ssh://user@server//home/projects/alpha/
1385
1385
1386 - do a high-speed clone over a LAN while checking out a
1386 - do a high-speed clone over a LAN while checking out a
1387 specified version::
1387 specified version::
1388
1388
1389 hg clone --uncompressed http://server/repo -u 1.5
1389 hg clone --uncompressed http://server/repo -u 1.5
1390
1390
1391 - create a repository without changesets after a particular revision::
1391 - create a repository without changesets after a particular revision::
1392
1392
1393 hg clone -r 04e544 experimental/ good/
1393 hg clone -r 04e544 experimental/ good/
1394
1394
1395 - clone (and track) a particular named branch::
1395 - clone (and track) a particular named branch::
1396
1396
1397 hg clone http://selenic.com/hg#stable
1397 hg clone http://selenic.com/hg#stable
1398
1398
1399 See :hg:`help urls` for details on specifying URLs.
1399 See :hg:`help urls` for details on specifying URLs.
1400
1400
1401 Returns 0 on success.
1401 Returns 0 on success.
1402 """
1402 """
1403 if opts.get('noupdate') and opts.get('updaterev'):
1403 if opts.get('noupdate') and opts.get('updaterev'):
1404 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1404 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1405
1405
1406 r = hg.clone(ui, opts, source, dest,
1406 r = hg.clone(ui, opts, source, dest,
1407 pull=opts.get('pull'),
1407 pull=opts.get('pull'),
1408 stream=opts.get('uncompressed'),
1408 stream=opts.get('uncompressed'),
1409 rev=opts.get('rev'),
1409 rev=opts.get('rev'),
1410 update=opts.get('updaterev') or not opts.get('noupdate'),
1410 update=opts.get('updaterev') or not opts.get('noupdate'),
1411 branch=opts.get('branch'))
1411 branch=opts.get('branch'))
1412
1412
1413 return r is None
1413 return r is None
1414
1414
1415 @command('^commit|ci',
1415 @command('^commit|ci',
1416 [('A', 'addremove', None,
1416 [('A', 'addremove', None,
1417 _('mark new/missing files as added/removed before committing')),
1417 _('mark new/missing files as added/removed before committing')),
1418 ('', 'close-branch', None,
1418 ('', 'close-branch', None,
1419 _('mark a branch as closed, hiding it from the branch list')),
1419 _('mark a branch as closed, hiding it from the branch list')),
1420 ('', 'amend', None, _('amend the parent of the working directory')),
1420 ('', 'amend', None, _('amend the parent of the working directory')),
1421 ('s', 'secret', None, _('use the secret phase for committing')),
1421 ('s', 'secret', None, _('use the secret phase for committing')),
1422 ('e', 'edit', None, _('invoke editor on commit messages')),
1422 ('e', 'edit', None, _('invoke editor on commit messages')),
1423 ('i', 'interactive', None, _('use interactive mode')),
1423 ('i', 'interactive', None, _('use interactive mode')),
1424 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1424 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1425 _('[OPTION]... [FILE]...'),
1425 _('[OPTION]... [FILE]...'),
1426 inferrepo=True)
1426 inferrepo=True)
1427 def commit(ui, repo, *pats, **opts):
1427 def commit(ui, repo, *pats, **opts):
1428 """commit the specified files or all outstanding changes
1428 """commit the specified files or all outstanding changes
1429
1429
1430 Commit changes to the given files into the repository. Unlike a
1430 Commit changes to the given files into the repository. Unlike a
1431 centralized SCM, this operation is a local operation. See
1431 centralized SCM, this operation is a local operation. See
1432 :hg:`push` for a way to actively distribute your changes.
1432 :hg:`push` for a way to actively distribute your changes.
1433
1433
1434 If a list of files is omitted, all changes reported by :hg:`status`
1434 If a list of files is omitted, all changes reported by :hg:`status`
1435 will be committed.
1435 will be committed.
1436
1436
1437 If you are committing the result of a merge, do not provide any
1437 If you are committing the result of a merge, do not provide any
1438 filenames or -I/-X filters.
1438 filenames or -I/-X filters.
1439
1439
1440 If no commit message is specified, Mercurial starts your
1440 If no commit message is specified, Mercurial starts your
1441 configured editor where you can enter a message. In case your
1441 configured editor where you can enter a message. In case your
1442 commit fails, you will find a backup of your message in
1442 commit fails, you will find a backup of your message in
1443 ``.hg/last-message.txt``.
1443 ``.hg/last-message.txt``.
1444
1444
1445 The --amend flag can be used to amend the parent of the
1445 The --amend flag can be used to amend the parent of the
1446 working directory with a new commit that contains the changes
1446 working directory with a new commit that contains the changes
1447 in the parent in addition to those currently reported by :hg:`status`,
1447 in the parent in addition to those currently reported by :hg:`status`,
1448 if there are any. The old commit is stored in a backup bundle in
1448 if there are any. The old commit is stored in a backup bundle in
1449 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1449 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1450 on how to restore it).
1450 on how to restore it).
1451
1451
1452 Message, user and date are taken from the amended commit unless
1452 Message, user and date are taken from the amended commit unless
1453 specified. When a message isn't specified on the command line,
1453 specified. When a message isn't specified on the command line,
1454 the editor will open with the message of the amended commit.
1454 the editor will open with the message of the amended commit.
1455
1455
1456 It is not possible to amend public changesets (see :hg:`help phases`)
1456 It is not possible to amend public changesets (see :hg:`help phases`)
1457 or changesets that have children.
1457 or changesets that have children.
1458
1458
1459 See :hg:`help dates` for a list of formats valid for -d/--date.
1459 See :hg:`help dates` for a list of formats valid for -d/--date.
1460
1460
1461 Returns 0 on success, 1 if nothing changed.
1461 Returns 0 on success, 1 if nothing changed.
1462 """
1462 """
1463 if opts.get('interactive'):
1463 if opts.get('interactive'):
1464 opts.pop('interactive')
1464 opts.pop('interactive')
1465 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1465 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1466 cmdutil.recordfilter, *pats, **opts)
1466 cmdutil.recordfilter, *pats, **opts)
1467 return
1467 return
1468
1468
1469 if opts.get('subrepos'):
1469 if opts.get('subrepos'):
1470 if opts.get('amend'):
1470 if opts.get('amend'):
1471 raise util.Abort(_('cannot amend with --subrepos'))
1471 raise util.Abort(_('cannot amend with --subrepos'))
1472 # Let --subrepos on the command line override config setting.
1472 # Let --subrepos on the command line override config setting.
1473 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1473 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1474
1474
1475 cmdutil.checkunfinished(repo, commit=True)
1475 cmdutil.checkunfinished(repo, commit=True)
1476
1476
1477 branch = repo[None].branch()
1477 branch = repo[None].branch()
1478 bheads = repo.branchheads(branch)
1478 bheads = repo.branchheads(branch)
1479
1479
1480 extra = {}
1480 extra = {}
1481 if opts.get('close_branch'):
1481 if opts.get('close_branch'):
1482 extra['close'] = 1
1482 extra['close'] = 1
1483
1483
1484 if not bheads:
1484 if not bheads:
1485 raise util.Abort(_('can only close branch heads'))
1485 raise util.Abort(_('can only close branch heads'))
1486 elif opts.get('amend'):
1486 elif opts.get('amend'):
1487 if repo.parents()[0].p1().branch() != branch and \
1487 if repo.parents()[0].p1().branch() != branch and \
1488 repo.parents()[0].p2().branch() != branch:
1488 repo.parents()[0].p2().branch() != branch:
1489 raise util.Abort(_('can only close branch heads'))
1489 raise util.Abort(_('can only close branch heads'))
1490
1490
1491 if opts.get('amend'):
1491 if opts.get('amend'):
1492 if ui.configbool('ui', 'commitsubrepos'):
1492 if ui.configbool('ui', 'commitsubrepos'):
1493 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1493 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1494
1494
1495 old = repo['.']
1495 old = repo['.']
1496 if not old.mutable():
1496 if not old.mutable():
1497 raise util.Abort(_('cannot amend public changesets'))
1497 raise util.Abort(_('cannot amend public changesets'))
1498 if len(repo[None].parents()) > 1:
1498 if len(repo[None].parents()) > 1:
1499 raise util.Abort(_('cannot amend while merging'))
1499 raise util.Abort(_('cannot amend while merging'))
1500 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1500 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1501 if not allowunstable and old.children():
1501 if not allowunstable and old.children():
1502 raise util.Abort(_('cannot amend changeset with children'))
1502 raise util.Abort(_('cannot amend changeset with children'))
1503
1503
1504 # commitfunc is used only for temporary amend commit by cmdutil.amend
1504 # commitfunc is used only for temporary amend commit by cmdutil.amend
1505 def commitfunc(ui, repo, message, match, opts):
1505 def commitfunc(ui, repo, message, match, opts):
1506 return repo.commit(message,
1506 return repo.commit(message,
1507 opts.get('user') or old.user(),
1507 opts.get('user') or old.user(),
1508 opts.get('date') or old.date(),
1508 opts.get('date') or old.date(),
1509 match,
1509 match,
1510 extra=extra)
1510 extra=extra)
1511
1511
1512 current = repo._bookmarkcurrent
1512 current = repo._bookmarkcurrent
1513 marks = old.bookmarks()
1513 marks = old.bookmarks()
1514 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1514 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1515 if node == old.node():
1515 if node == old.node():
1516 ui.status(_("nothing changed\n"))
1516 ui.status(_("nothing changed\n"))
1517 return 1
1517 return 1
1518 elif marks:
1518 elif marks:
1519 ui.debug('moving bookmarks %r from %s to %s\n' %
1519 ui.debug('moving bookmarks %r from %s to %s\n' %
1520 (marks, old.hex(), hex(node)))
1520 (marks, old.hex(), hex(node)))
1521 newmarks = repo._bookmarks
1521 newmarks = repo._bookmarks
1522 for bm in marks:
1522 for bm in marks:
1523 newmarks[bm] = node
1523 newmarks[bm] = node
1524 if bm == current:
1524 if bm == current:
1525 bookmarks.setcurrent(repo, bm)
1525 bookmarks.setcurrent(repo, bm)
1526 newmarks.write()
1526 newmarks.write()
1527 else:
1527 else:
1528 def commitfunc(ui, repo, message, match, opts):
1528 def commitfunc(ui, repo, message, match, opts):
1529 backup = ui.backupconfig('phases', 'new-commit')
1529 backup = ui.backupconfig('phases', 'new-commit')
1530 baseui = repo.baseui
1530 baseui = repo.baseui
1531 basebackup = baseui.backupconfig('phases', 'new-commit')
1531 basebackup = baseui.backupconfig('phases', 'new-commit')
1532 try:
1532 try:
1533 if opts.get('secret'):
1533 if opts.get('secret'):
1534 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1534 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1535 # Propagate to subrepos
1535 # Propagate to subrepos
1536 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1536 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1537
1537
1538 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1538 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1539 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1539 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1540 return repo.commit(message, opts.get('user'), opts.get('date'),
1540 return repo.commit(message, opts.get('user'), opts.get('date'),
1541 match,
1541 match,
1542 editor=editor,
1542 editor=editor,
1543 extra=extra)
1543 extra=extra)
1544 finally:
1544 finally:
1545 ui.restoreconfig(backup)
1545 ui.restoreconfig(backup)
1546 repo.baseui.restoreconfig(basebackup)
1546 repo.baseui.restoreconfig(basebackup)
1547
1547
1548
1548
1549 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1549 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1550
1550
1551 if not node:
1551 if not node:
1552 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1552 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1553 if stat[3]:
1553 if stat[3]:
1554 ui.status(_("nothing changed (%d missing files, see "
1554 ui.status(_("nothing changed (%d missing files, see "
1555 "'hg status')\n") % len(stat[3]))
1555 "'hg status')\n") % len(stat[3]))
1556 else:
1556 else:
1557 ui.status(_("nothing changed\n"))
1557 ui.status(_("nothing changed\n"))
1558 return 1
1558 return 1
1559
1559
1560 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1560 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1561
1561
1562 @command('config|showconfig|debugconfig',
1562 @command('config|showconfig|debugconfig',
1563 [('u', 'untrusted', None, _('show untrusted configuration options')),
1563 [('u', 'untrusted', None, _('show untrusted configuration options')),
1564 ('e', 'edit', None, _('edit user config')),
1564 ('e', 'edit', None, _('edit user config')),
1565 ('l', 'local', None, _('edit repository config')),
1565 ('l', 'local', None, _('edit repository config')),
1566 ('g', 'global', None, _('edit global config'))],
1566 ('g', 'global', None, _('edit global config'))],
1567 _('[-u] [NAME]...'),
1567 _('[-u] [NAME]...'),
1568 optionalrepo=True)
1568 optionalrepo=True)
1569 def config(ui, repo, *values, **opts):
1569 def config(ui, repo, *values, **opts):
1570 """show combined config settings from all hgrc files
1570 """show combined config settings from all hgrc files
1571
1571
1572 With no arguments, print names and values of all config items.
1572 With no arguments, print names and values of all config items.
1573
1573
1574 With one argument of the form section.name, print just the value
1574 With one argument of the form section.name, print just the value
1575 of that config item.
1575 of that config item.
1576
1576
1577 With multiple arguments, print names and values of all config
1577 With multiple arguments, print names and values of all config
1578 items with matching section names.
1578 items with matching section names.
1579
1579
1580 With --edit, start an editor on the user-level config file. With
1580 With --edit, start an editor on the user-level config file. With
1581 --global, edit the system-wide config file. With --local, edit the
1581 --global, edit the system-wide config file. With --local, edit the
1582 repository-level config file.
1582 repository-level config file.
1583
1583
1584 With --debug, the source (filename and line number) is printed
1584 With --debug, the source (filename and line number) is printed
1585 for each config item.
1585 for each config item.
1586
1586
1587 See :hg:`help config` for more information about config files.
1587 See :hg:`help config` for more information about config files.
1588
1588
1589 Returns 0 on success, 1 if NAME does not exist.
1589 Returns 0 on success, 1 if NAME does not exist.
1590
1590
1591 """
1591 """
1592
1592
1593 if opts.get('edit') or opts.get('local') or opts.get('global'):
1593 if opts.get('edit') or opts.get('local') or opts.get('global'):
1594 if opts.get('local') and opts.get('global'):
1594 if opts.get('local') and opts.get('global'):
1595 raise util.Abort(_("can't use --local and --global together"))
1595 raise util.Abort(_("can't use --local and --global together"))
1596
1596
1597 if opts.get('local'):
1597 if opts.get('local'):
1598 if not repo:
1598 if not repo:
1599 raise util.Abort(_("can't use --local outside a repository"))
1599 raise util.Abort(_("can't use --local outside a repository"))
1600 paths = [repo.join('hgrc')]
1600 paths = [repo.join('hgrc')]
1601 elif opts.get('global'):
1601 elif opts.get('global'):
1602 paths = scmutil.systemrcpath()
1602 paths = scmutil.systemrcpath()
1603 else:
1603 else:
1604 paths = scmutil.userrcpath()
1604 paths = scmutil.userrcpath()
1605
1605
1606 for f in paths:
1606 for f in paths:
1607 if os.path.exists(f):
1607 if os.path.exists(f):
1608 break
1608 break
1609 else:
1609 else:
1610 if opts.get('global'):
1610 if opts.get('global'):
1611 samplehgrc = uimod.samplehgrcs['global']
1611 samplehgrc = uimod.samplehgrcs['global']
1612 elif opts.get('local'):
1612 elif opts.get('local'):
1613 samplehgrc = uimod.samplehgrcs['local']
1613 samplehgrc = uimod.samplehgrcs['local']
1614 else:
1614 else:
1615 samplehgrc = uimod.samplehgrcs['user']
1615 samplehgrc = uimod.samplehgrcs['user']
1616
1616
1617 f = paths[0]
1617 f = paths[0]
1618 fp = open(f, "w")
1618 fp = open(f, "w")
1619 fp.write(samplehgrc)
1619 fp.write(samplehgrc)
1620 fp.close()
1620 fp.close()
1621
1621
1622 editor = ui.geteditor()
1622 editor = ui.geteditor()
1623 ui.system("%s \"%s\"" % (editor, f),
1623 ui.system("%s \"%s\"" % (editor, f),
1624 onerr=util.Abort, errprefix=_("edit failed"))
1624 onerr=util.Abort, errprefix=_("edit failed"))
1625 return
1625 return
1626
1626
1627 for f in scmutil.rcpath():
1627 for f in scmutil.rcpath():
1628 ui.debug('read config from: %s\n' % f)
1628 ui.debug('read config from: %s\n' % f)
1629 untrusted = bool(opts.get('untrusted'))
1629 untrusted = bool(opts.get('untrusted'))
1630 if values:
1630 if values:
1631 sections = [v for v in values if '.' not in v]
1631 sections = [v for v in values if '.' not in v]
1632 items = [v for v in values if '.' in v]
1632 items = [v for v in values if '.' in v]
1633 if len(items) > 1 or items and sections:
1633 if len(items) > 1 or items and sections:
1634 raise util.Abort(_('only one config item permitted'))
1634 raise util.Abort(_('only one config item permitted'))
1635 matched = False
1635 matched = False
1636 for section, name, value in ui.walkconfig(untrusted=untrusted):
1636 for section, name, value in ui.walkconfig(untrusted=untrusted):
1637 value = str(value).replace('\n', '\\n')
1637 value = str(value).replace('\n', '\\n')
1638 sectname = section + '.' + name
1638 sectname = section + '.' + name
1639 if values:
1639 if values:
1640 for v in values:
1640 for v in values:
1641 if v == section:
1641 if v == section:
1642 ui.debug('%s: ' %
1642 ui.debug('%s: ' %
1643 ui.configsource(section, name, untrusted))
1643 ui.configsource(section, name, untrusted))
1644 ui.write('%s=%s\n' % (sectname, value))
1644 ui.write('%s=%s\n' % (sectname, value))
1645 matched = True
1645 matched = True
1646 elif v == sectname:
1646 elif v == sectname:
1647 ui.debug('%s: ' %
1647 ui.debug('%s: ' %
1648 ui.configsource(section, name, untrusted))
1648 ui.configsource(section, name, untrusted))
1649 ui.write(value, '\n')
1649 ui.write(value, '\n')
1650 matched = True
1650 matched = True
1651 else:
1651 else:
1652 ui.debug('%s: ' %
1652 ui.debug('%s: ' %
1653 ui.configsource(section, name, untrusted))
1653 ui.configsource(section, name, untrusted))
1654 ui.write('%s=%s\n' % (sectname, value))
1654 ui.write('%s=%s\n' % (sectname, value))
1655 matched = True
1655 matched = True
1656 if matched:
1656 if matched:
1657 return 0
1657 return 0
1658 return 1
1658 return 1
1659
1659
1660 @command('copy|cp',
1660 @command('copy|cp',
1661 [('A', 'after', None, _('record a copy that has already occurred')),
1661 [('A', 'after', None, _('record a copy that has already occurred')),
1662 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1662 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1663 ] + walkopts + dryrunopts,
1663 ] + walkopts + dryrunopts,
1664 _('[OPTION]... [SOURCE]... DEST'))
1664 _('[OPTION]... [SOURCE]... DEST'))
1665 def copy(ui, repo, *pats, **opts):
1665 def copy(ui, repo, *pats, **opts):
1666 """mark files as copied for the next commit
1666 """mark files as copied for the next commit
1667
1667
1668 Mark dest as having copies of source files. If dest is a
1668 Mark dest as having copies of source files. If dest is a
1669 directory, copies are put in that directory. If dest is a file,
1669 directory, copies are put in that directory. If dest is a file,
1670 the source must be a single file.
1670 the source must be a single file.
1671
1671
1672 By default, this command copies the contents of files as they
1672 By default, this command copies the contents of files as they
1673 exist in the working directory. If invoked with -A/--after, the
1673 exist in the working directory. If invoked with -A/--after, the
1674 operation is recorded, but no copying is performed.
1674 operation is recorded, but no copying is performed.
1675
1675
1676 This command takes effect with the next commit. To undo a copy
1676 This command takes effect with the next commit. To undo a copy
1677 before that, see :hg:`revert`.
1677 before that, see :hg:`revert`.
1678
1678
1679 Returns 0 on success, 1 if errors are encountered.
1679 Returns 0 on success, 1 if errors are encountered.
1680 """
1680 """
1681 wlock = repo.wlock(False)
1681 wlock = repo.wlock(False)
1682 try:
1682 try:
1683 return cmdutil.copy(ui, repo, pats, opts)
1683 return cmdutil.copy(ui, repo, pats, opts)
1684 finally:
1684 finally:
1685 wlock.release()
1685 wlock.release()
1686
1686
1687 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1687 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1688 def debugancestor(ui, repo, *args):
1688 def debugancestor(ui, repo, *args):
1689 """find the ancestor revision of two revisions in a given index"""
1689 """find the ancestor revision of two revisions in a given index"""
1690 if len(args) == 3:
1690 if len(args) == 3:
1691 index, rev1, rev2 = args
1691 index, rev1, rev2 = args
1692 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1692 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1693 lookup = r.lookup
1693 lookup = r.lookup
1694 elif len(args) == 2:
1694 elif len(args) == 2:
1695 if not repo:
1695 if not repo:
1696 raise util.Abort(_("there is no Mercurial repository here "
1696 raise util.Abort(_("there is no Mercurial repository here "
1697 "(.hg not found)"))
1697 "(.hg not found)"))
1698 rev1, rev2 = args
1698 rev1, rev2 = args
1699 r = repo.changelog
1699 r = repo.changelog
1700 lookup = repo.lookup
1700 lookup = repo.lookup
1701 else:
1701 else:
1702 raise util.Abort(_('either two or three arguments required'))
1702 raise util.Abort(_('either two or three arguments required'))
1703 a = r.ancestor(lookup(rev1), lookup(rev2))
1703 a = r.ancestor(lookup(rev1), lookup(rev2))
1704 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1704 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1705
1705
1706 @command('debugbuilddag',
1706 @command('debugbuilddag',
1707 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1707 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1708 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1708 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1709 ('n', 'new-file', None, _('add new file at each rev'))],
1709 ('n', 'new-file', None, _('add new file at each rev'))],
1710 _('[OPTION]... [TEXT]'))
1710 _('[OPTION]... [TEXT]'))
1711 def debugbuilddag(ui, repo, text=None,
1711 def debugbuilddag(ui, repo, text=None,
1712 mergeable_file=False,
1712 mergeable_file=False,
1713 overwritten_file=False,
1713 overwritten_file=False,
1714 new_file=False):
1714 new_file=False):
1715 """builds a repo with a given DAG from scratch in the current empty repo
1715 """builds a repo with a given DAG from scratch in the current empty repo
1716
1716
1717 The description of the DAG is read from stdin if not given on the
1717 The description of the DAG is read from stdin if not given on the
1718 command line.
1718 command line.
1719
1719
1720 Elements:
1720 Elements:
1721
1721
1722 - "+n" is a linear run of n nodes based on the current default parent
1722 - "+n" is a linear run of n nodes based on the current default parent
1723 - "." is a single node based on the current default parent
1723 - "." is a single node based on the current default parent
1724 - "$" resets the default parent to null (implied at the start);
1724 - "$" resets the default parent to null (implied at the start);
1725 otherwise the default parent is always the last node created
1725 otherwise the default parent is always the last node created
1726 - "<p" sets the default parent to the backref p
1726 - "<p" sets the default parent to the backref p
1727 - "*p" is a fork at parent p, which is a backref
1727 - "*p" is a fork at parent p, which is a backref
1728 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1728 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1729 - "/p2" is a merge of the preceding node and p2
1729 - "/p2" is a merge of the preceding node and p2
1730 - ":tag" defines a local tag for the preceding node
1730 - ":tag" defines a local tag for the preceding node
1731 - "@branch" sets the named branch for subsequent nodes
1731 - "@branch" sets the named branch for subsequent nodes
1732 - "#...\\n" is a comment up to the end of the line
1732 - "#...\\n" is a comment up to the end of the line
1733
1733
1734 Whitespace between the above elements is ignored.
1734 Whitespace between the above elements is ignored.
1735
1735
1736 A backref is either
1736 A backref is either
1737
1737
1738 - a number n, which references the node curr-n, where curr is the current
1738 - a number n, which references the node curr-n, where curr is the current
1739 node, or
1739 node, or
1740 - the name of a local tag you placed earlier using ":tag", or
1740 - the name of a local tag you placed earlier using ":tag", or
1741 - empty to denote the default parent.
1741 - empty to denote the default parent.
1742
1742
1743 All string valued-elements are either strictly alphanumeric, or must
1743 All string valued-elements are either strictly alphanumeric, or must
1744 be enclosed in double quotes ("..."), with "\\" as escape character.
1744 be enclosed in double quotes ("..."), with "\\" as escape character.
1745 """
1745 """
1746
1746
1747 if text is None:
1747 if text is None:
1748 ui.status(_("reading DAG from stdin\n"))
1748 ui.status(_("reading DAG from stdin\n"))
1749 text = ui.fin.read()
1749 text = ui.fin.read()
1750
1750
1751 cl = repo.changelog
1751 cl = repo.changelog
1752 if len(cl) > 0:
1752 if len(cl) > 0:
1753 raise util.Abort(_('repository is not empty'))
1753 raise util.Abort(_('repository is not empty'))
1754
1754
1755 # determine number of revs in DAG
1755 # determine number of revs in DAG
1756 total = 0
1756 total = 0
1757 for type, data in dagparser.parsedag(text):
1757 for type, data in dagparser.parsedag(text):
1758 if type == 'n':
1758 if type == 'n':
1759 total += 1
1759 total += 1
1760
1760
1761 if mergeable_file:
1761 if mergeable_file:
1762 linesperrev = 2
1762 linesperrev = 2
1763 # make a file with k lines per rev
1763 # make a file with k lines per rev
1764 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1764 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1765 initialmergedlines.append("")
1765 initialmergedlines.append("")
1766
1766
1767 tags = []
1767 tags = []
1768
1768
1769 lock = tr = None
1769 lock = tr = None
1770 try:
1770 try:
1771 lock = repo.lock()
1771 lock = repo.lock()
1772 tr = repo.transaction("builddag")
1772 tr = repo.transaction("builddag")
1773
1773
1774 at = -1
1774 at = -1
1775 atbranch = 'default'
1775 atbranch = 'default'
1776 nodeids = []
1776 nodeids = []
1777 id = 0
1777 id = 0
1778 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1778 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1779 for type, data in dagparser.parsedag(text):
1779 for type, data in dagparser.parsedag(text):
1780 if type == 'n':
1780 if type == 'n':
1781 ui.note(('node %s\n' % str(data)))
1781 ui.note(('node %s\n' % str(data)))
1782 id, ps = data
1782 id, ps = data
1783
1783
1784 files = []
1784 files = []
1785 fctxs = {}
1785 fctxs = {}
1786
1786
1787 p2 = None
1787 p2 = None
1788 if mergeable_file:
1788 if mergeable_file:
1789 fn = "mf"
1789 fn = "mf"
1790 p1 = repo[ps[0]]
1790 p1 = repo[ps[0]]
1791 if len(ps) > 1:
1791 if len(ps) > 1:
1792 p2 = repo[ps[1]]
1792 p2 = repo[ps[1]]
1793 pa = p1.ancestor(p2)
1793 pa = p1.ancestor(p2)
1794 base, local, other = [x[fn].data() for x in (pa, p1,
1794 base, local, other = [x[fn].data() for x in (pa, p1,
1795 p2)]
1795 p2)]
1796 m3 = simplemerge.Merge3Text(base, local, other)
1796 m3 = simplemerge.Merge3Text(base, local, other)
1797 ml = [l.strip() for l in m3.merge_lines()]
1797 ml = [l.strip() for l in m3.merge_lines()]
1798 ml.append("")
1798 ml.append("")
1799 elif at > 0:
1799 elif at > 0:
1800 ml = p1[fn].data().split("\n")
1800 ml = p1[fn].data().split("\n")
1801 else:
1801 else:
1802 ml = initialmergedlines
1802 ml = initialmergedlines
1803 ml[id * linesperrev] += " r%i" % id
1803 ml[id * linesperrev] += " r%i" % id
1804 mergedtext = "\n".join(ml)
1804 mergedtext = "\n".join(ml)
1805 files.append(fn)
1805 files.append(fn)
1806 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1806 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1807
1807
1808 if overwritten_file:
1808 if overwritten_file:
1809 fn = "of"
1809 fn = "of"
1810 files.append(fn)
1810 files.append(fn)
1811 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1811 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1812
1812
1813 if new_file:
1813 if new_file:
1814 fn = "nf%i" % id
1814 fn = "nf%i" % id
1815 files.append(fn)
1815 files.append(fn)
1816 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1816 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1817 if len(ps) > 1:
1817 if len(ps) > 1:
1818 if not p2:
1818 if not p2:
1819 p2 = repo[ps[1]]
1819 p2 = repo[ps[1]]
1820 for fn in p2:
1820 for fn in p2:
1821 if fn.startswith("nf"):
1821 if fn.startswith("nf"):
1822 files.append(fn)
1822 files.append(fn)
1823 fctxs[fn] = p2[fn]
1823 fctxs[fn] = p2[fn]
1824
1824
1825 def fctxfn(repo, cx, path):
1825 def fctxfn(repo, cx, path):
1826 return fctxs.get(path)
1826 return fctxs.get(path)
1827
1827
1828 if len(ps) == 0 or ps[0] < 0:
1828 if len(ps) == 0 or ps[0] < 0:
1829 pars = [None, None]
1829 pars = [None, None]
1830 elif len(ps) == 1:
1830 elif len(ps) == 1:
1831 pars = [nodeids[ps[0]], None]
1831 pars = [nodeids[ps[0]], None]
1832 else:
1832 else:
1833 pars = [nodeids[p] for p in ps]
1833 pars = [nodeids[p] for p in ps]
1834 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1834 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1835 date=(id, 0),
1835 date=(id, 0),
1836 user="debugbuilddag",
1836 user="debugbuilddag",
1837 extra={'branch': atbranch})
1837 extra={'branch': atbranch})
1838 nodeid = repo.commitctx(cx)
1838 nodeid = repo.commitctx(cx)
1839 nodeids.append(nodeid)
1839 nodeids.append(nodeid)
1840 at = id
1840 at = id
1841 elif type == 'l':
1841 elif type == 'l':
1842 id, name = data
1842 id, name = data
1843 ui.note(('tag %s\n' % name))
1843 ui.note(('tag %s\n' % name))
1844 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1844 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1845 elif type == 'a':
1845 elif type == 'a':
1846 ui.note(('branch %s\n' % data))
1846 ui.note(('branch %s\n' % data))
1847 atbranch = data
1847 atbranch = data
1848 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1848 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1849 tr.close()
1849 tr.close()
1850
1850
1851 if tags:
1851 if tags:
1852 repo.vfs.write("localtags", "".join(tags))
1852 repo.vfs.write("localtags", "".join(tags))
1853 finally:
1853 finally:
1854 ui.progress(_('building'), None)
1854 ui.progress(_('building'), None)
1855 release(tr, lock)
1855 release(tr, lock)
1856
1856
1857 @command('debugbundle',
1857 @command('debugbundle',
1858 [('a', 'all', None, _('show all details'))],
1858 [('a', 'all', None, _('show all details'))],
1859 _('FILE'),
1859 _('FILE'),
1860 norepo=True)
1860 norepo=True)
1861 def debugbundle(ui, bundlepath, all=None, **opts):
1861 def debugbundle(ui, bundlepath, all=None, **opts):
1862 """lists the contents of a bundle"""
1862 """lists the contents of a bundle"""
1863 f = hg.openpath(ui, bundlepath)
1863 f = hg.openpath(ui, bundlepath)
1864 try:
1864 try:
1865 gen = exchange.readbundle(ui, f, bundlepath)
1865 gen = exchange.readbundle(ui, f, bundlepath)
1866 if isinstance(gen, bundle2.unbundle20):
1866 if isinstance(gen, bundle2.unbundle20):
1867 return _debugbundle2(ui, gen, all=all, **opts)
1867 return _debugbundle2(ui, gen, all=all, **opts)
1868 if all:
1868 if all:
1869 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1869 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1870
1870
1871 def showchunks(named):
1871 def showchunks(named):
1872 ui.write("\n%s\n" % named)
1872 ui.write("\n%s\n" % named)
1873 chain = None
1873 chain = None
1874 while True:
1874 while True:
1875 chunkdata = gen.deltachunk(chain)
1875 chunkdata = gen.deltachunk(chain)
1876 if not chunkdata:
1876 if not chunkdata:
1877 break
1877 break
1878 node = chunkdata['node']
1878 node = chunkdata['node']
1879 p1 = chunkdata['p1']
1879 p1 = chunkdata['p1']
1880 p2 = chunkdata['p2']
1880 p2 = chunkdata['p2']
1881 cs = chunkdata['cs']
1881 cs = chunkdata['cs']
1882 deltabase = chunkdata['deltabase']
1882 deltabase = chunkdata['deltabase']
1883 delta = chunkdata['delta']
1883 delta = chunkdata['delta']
1884 ui.write("%s %s %s %s %s %s\n" %
1884 ui.write("%s %s %s %s %s %s\n" %
1885 (hex(node), hex(p1), hex(p2),
1885 (hex(node), hex(p1), hex(p2),
1886 hex(cs), hex(deltabase), len(delta)))
1886 hex(cs), hex(deltabase), len(delta)))
1887 chain = node
1887 chain = node
1888
1888
1889 chunkdata = gen.changelogheader()
1889 chunkdata = gen.changelogheader()
1890 showchunks("changelog")
1890 showchunks("changelog")
1891 chunkdata = gen.manifestheader()
1891 chunkdata = gen.manifestheader()
1892 showchunks("manifest")
1892 showchunks("manifest")
1893 while True:
1893 while True:
1894 chunkdata = gen.filelogheader()
1894 chunkdata = gen.filelogheader()
1895 if not chunkdata:
1895 if not chunkdata:
1896 break
1896 break
1897 fname = chunkdata['filename']
1897 fname = chunkdata['filename']
1898 showchunks(fname)
1898 showchunks(fname)
1899 else:
1899 else:
1900 if isinstance(gen, bundle2.unbundle20):
1900 if isinstance(gen, bundle2.unbundle20):
1901 raise util.Abort(_('use debugbundle2 for this file'))
1901 raise util.Abort(_('use debugbundle2 for this file'))
1902 chunkdata = gen.changelogheader()
1902 chunkdata = gen.changelogheader()
1903 chain = None
1903 chain = None
1904 while True:
1904 while True:
1905 chunkdata = gen.deltachunk(chain)
1905 chunkdata = gen.deltachunk(chain)
1906 if not chunkdata:
1906 if not chunkdata:
1907 break
1907 break
1908 node = chunkdata['node']
1908 node = chunkdata['node']
1909 ui.write("%s\n" % hex(node))
1909 ui.write("%s\n" % hex(node))
1910 chain = node
1910 chain = node
1911 finally:
1911 finally:
1912 f.close()
1912 f.close()
1913
1913
1914 def _debugbundle2(ui, gen, **opts):
1914 def _debugbundle2(ui, gen, **opts):
1915 """lists the contents of a bundle2"""
1915 """lists the contents of a bundle2"""
1916 if not isinstance(gen, bundle2.unbundle20):
1916 if not isinstance(gen, bundle2.unbundle20):
1917 raise util.Abort(_('not a bundle2 file'))
1917 raise util.Abort(_('not a bundle2 file'))
1918 ui.write(('Stream params: %s\n' % repr(gen.params)))
1918 ui.write(('Stream params: %s\n' % repr(gen.params)))
1919 for part in gen.iterparts():
1919 for part in gen.iterparts():
1920 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1920 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1921 if part.type == 'changegroup':
1921 if part.type == 'changegroup':
1922 version = part.params.get('version', '01')
1922 version = part.params.get('version', '01')
1923 cg = changegroup.packermap[version][1](part, 'UN')
1923 cg = changegroup.packermap[version][1](part, 'UN')
1924 chunkdata = cg.changelogheader()
1924 chunkdata = cg.changelogheader()
1925 chain = None
1925 chain = None
1926 while True:
1926 while True:
1927 chunkdata = cg.deltachunk(chain)
1927 chunkdata = cg.deltachunk(chain)
1928 if not chunkdata:
1928 if not chunkdata:
1929 break
1929 break
1930 node = chunkdata['node']
1930 node = chunkdata['node']
1931 ui.write(" %s\n" % hex(node))
1931 ui.write(" %s\n" % hex(node))
1932 chain = node
1932 chain = node
1933
1933
1934 @command('debugcheckstate', [], '')
1934 @command('debugcheckstate', [], '')
1935 def debugcheckstate(ui, repo):
1935 def debugcheckstate(ui, repo):
1936 """validate the correctness of the current dirstate"""
1936 """validate the correctness of the current dirstate"""
1937 parent1, parent2 = repo.dirstate.parents()
1937 parent1, parent2 = repo.dirstate.parents()
1938 m1 = repo[parent1].manifest()
1938 m1 = repo[parent1].manifest()
1939 m2 = repo[parent2].manifest()
1939 m2 = repo[parent2].manifest()
1940 errors = 0
1940 errors = 0
1941 for f in repo.dirstate:
1941 for f in repo.dirstate:
1942 state = repo.dirstate[f]
1942 state = repo.dirstate[f]
1943 if state in "nr" and f not in m1:
1943 if state in "nr" and f not in m1:
1944 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1944 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1945 errors += 1
1945 errors += 1
1946 if state in "a" and f in m1:
1946 if state in "a" and f in m1:
1947 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1947 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1948 errors += 1
1948 errors += 1
1949 if state in "m" and f not in m1 and f not in m2:
1949 if state in "m" and f not in m1 and f not in m2:
1950 ui.warn(_("%s in state %s, but not in either manifest\n") %
1950 ui.warn(_("%s in state %s, but not in either manifest\n") %
1951 (f, state))
1951 (f, state))
1952 errors += 1
1952 errors += 1
1953 for f in m1:
1953 for f in m1:
1954 state = repo.dirstate[f]
1954 state = repo.dirstate[f]
1955 if state not in "nrm":
1955 if state not in "nrm":
1956 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1956 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1957 errors += 1
1957 errors += 1
1958 if errors:
1958 if errors:
1959 error = _(".hg/dirstate inconsistent with current parent's manifest")
1959 error = _(".hg/dirstate inconsistent with current parent's manifest")
1960 raise util.Abort(error)
1960 raise util.Abort(error)
1961
1961
1962 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1962 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1963 def debugcommands(ui, cmd='', *args):
1963 def debugcommands(ui, cmd='', *args):
1964 """list all available commands and options"""
1964 """list all available commands and options"""
1965 for cmd, vals in sorted(table.iteritems()):
1965 for cmd, vals in sorted(table.iteritems()):
1966 cmd = cmd.split('|')[0].strip('^')
1966 cmd = cmd.split('|')[0].strip('^')
1967 opts = ', '.join([i[1] for i in vals[1]])
1967 opts = ', '.join([i[1] for i in vals[1]])
1968 ui.write('%s: %s\n' % (cmd, opts))
1968 ui.write('%s: %s\n' % (cmd, opts))
1969
1969
1970 @command('debugcomplete',
1970 @command('debugcomplete',
1971 [('o', 'options', None, _('show the command options'))],
1971 [('o', 'options', None, _('show the command options'))],
1972 _('[-o] CMD'),
1972 _('[-o] CMD'),
1973 norepo=True)
1973 norepo=True)
1974 def debugcomplete(ui, cmd='', **opts):
1974 def debugcomplete(ui, cmd='', **opts):
1975 """returns the completion list associated with the given command"""
1975 """returns the completion list associated with the given command"""
1976
1976
1977 if opts.get('options'):
1977 if opts.get('options'):
1978 options = []
1978 options = []
1979 otables = [globalopts]
1979 otables = [globalopts]
1980 if cmd:
1980 if cmd:
1981 aliases, entry = cmdutil.findcmd(cmd, table, False)
1981 aliases, entry = cmdutil.findcmd(cmd, table, False)
1982 otables.append(entry[1])
1982 otables.append(entry[1])
1983 for t in otables:
1983 for t in otables:
1984 for o in t:
1984 for o in t:
1985 if "(DEPRECATED)" in o[3]:
1985 if "(DEPRECATED)" in o[3]:
1986 continue
1986 continue
1987 if o[0]:
1987 if o[0]:
1988 options.append('-%s' % o[0])
1988 options.append('-%s' % o[0])
1989 options.append('--%s' % o[1])
1989 options.append('--%s' % o[1])
1990 ui.write("%s\n" % "\n".join(options))
1990 ui.write("%s\n" % "\n".join(options))
1991 return
1991 return
1992
1992
1993 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1993 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1994 if ui.verbose:
1994 if ui.verbose:
1995 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1995 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1996 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1996 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1997
1997
1998 @command('debugdag',
1998 @command('debugdag',
1999 [('t', 'tags', None, _('use tags as labels')),
1999 [('t', 'tags', None, _('use tags as labels')),
2000 ('b', 'branches', None, _('annotate with branch names')),
2000 ('b', 'branches', None, _('annotate with branch names')),
2001 ('', 'dots', None, _('use dots for runs')),
2001 ('', 'dots', None, _('use dots for runs')),
2002 ('s', 'spaces', None, _('separate elements by spaces'))],
2002 ('s', 'spaces', None, _('separate elements by spaces'))],
2003 _('[OPTION]... [FILE [REV]...]'),
2003 _('[OPTION]... [FILE [REV]...]'),
2004 optionalrepo=True)
2004 optionalrepo=True)
2005 def debugdag(ui, repo, file_=None, *revs, **opts):
2005 def debugdag(ui, repo, file_=None, *revs, **opts):
2006 """format the changelog or an index DAG as a concise textual description
2006 """format the changelog or an index DAG as a concise textual description
2007
2007
2008 If you pass a revlog index, the revlog's DAG is emitted. If you list
2008 If you pass a revlog index, the revlog's DAG is emitted. If you list
2009 revision numbers, they get labeled in the output as rN.
2009 revision numbers, they get labeled in the output as rN.
2010
2010
2011 Otherwise, the changelog DAG of the current repo is emitted.
2011 Otherwise, the changelog DAG of the current repo is emitted.
2012 """
2012 """
2013 spaces = opts.get('spaces')
2013 spaces = opts.get('spaces')
2014 dots = opts.get('dots')
2014 dots = opts.get('dots')
2015 if file_:
2015 if file_:
2016 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2016 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2017 revs = set((int(r) for r in revs))
2017 revs = set((int(r) for r in revs))
2018 def events():
2018 def events():
2019 for r in rlog:
2019 for r in rlog:
2020 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2020 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2021 if p != -1))
2021 if p != -1))
2022 if r in revs:
2022 if r in revs:
2023 yield 'l', (r, "r%i" % r)
2023 yield 'l', (r, "r%i" % r)
2024 elif repo:
2024 elif repo:
2025 cl = repo.changelog
2025 cl = repo.changelog
2026 tags = opts.get('tags')
2026 tags = opts.get('tags')
2027 branches = opts.get('branches')
2027 branches = opts.get('branches')
2028 if tags:
2028 if tags:
2029 labels = {}
2029 labels = {}
2030 for l, n in repo.tags().items():
2030 for l, n in repo.tags().items():
2031 labels.setdefault(cl.rev(n), []).append(l)
2031 labels.setdefault(cl.rev(n), []).append(l)
2032 def events():
2032 def events():
2033 b = "default"
2033 b = "default"
2034 for r in cl:
2034 for r in cl:
2035 if branches:
2035 if branches:
2036 newb = cl.read(cl.node(r))[5]['branch']
2036 newb = cl.read(cl.node(r))[5]['branch']
2037 if newb != b:
2037 if newb != b:
2038 yield 'a', newb
2038 yield 'a', newb
2039 b = newb
2039 b = newb
2040 yield 'n', (r, list(p for p in cl.parentrevs(r)
2040 yield 'n', (r, list(p for p in cl.parentrevs(r)
2041 if p != -1))
2041 if p != -1))
2042 if tags:
2042 if tags:
2043 ls = labels.get(r)
2043 ls = labels.get(r)
2044 if ls:
2044 if ls:
2045 for l in ls:
2045 for l in ls:
2046 yield 'l', (r, l)
2046 yield 'l', (r, l)
2047 else:
2047 else:
2048 raise util.Abort(_('need repo for changelog dag'))
2048 raise util.Abort(_('need repo for changelog dag'))
2049
2049
2050 for line in dagparser.dagtextlines(events(),
2050 for line in dagparser.dagtextlines(events(),
2051 addspaces=spaces,
2051 addspaces=spaces,
2052 wraplabels=True,
2052 wraplabels=True,
2053 wrapannotations=True,
2053 wrapannotations=True,
2054 wrapnonlinear=dots,
2054 wrapnonlinear=dots,
2055 usedots=dots,
2055 usedots=dots,
2056 maxlinewidth=70):
2056 maxlinewidth=70):
2057 ui.write(line)
2057 ui.write(line)
2058 ui.write("\n")
2058 ui.write("\n")
2059
2059
2060 @command('debugdata',
2060 @command('debugdata',
2061 [('c', 'changelog', False, _('open changelog')),
2061 [('c', 'changelog', False, _('open changelog')),
2062 ('m', 'manifest', False, _('open manifest'))],
2062 ('m', 'manifest', False, _('open manifest'))],
2063 _('-c|-m|FILE REV'))
2063 _('-c|-m|FILE REV'))
2064 def debugdata(ui, repo, file_, rev=None, **opts):
2064 def debugdata(ui, repo, file_, rev=None, **opts):
2065 """dump the contents of a data file revision"""
2065 """dump the contents of a data file revision"""
2066 if opts.get('changelog') or opts.get('manifest'):
2066 if opts.get('changelog') or opts.get('manifest'):
2067 file_, rev = None, file_
2067 file_, rev = None, file_
2068 elif rev is None:
2068 elif rev is None:
2069 raise error.CommandError('debugdata', _('invalid arguments'))
2069 raise error.CommandError('debugdata', _('invalid arguments'))
2070 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2070 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2071 try:
2071 try:
2072 ui.write(r.revision(r.lookup(rev)))
2072 ui.write(r.revision(r.lookup(rev)))
2073 except KeyError:
2073 except KeyError:
2074 raise util.Abort(_('invalid revision identifier %s') % rev)
2074 raise util.Abort(_('invalid revision identifier %s') % rev)
2075
2075
2076 @command('debugdate',
2076 @command('debugdate',
2077 [('e', 'extended', None, _('try extended date formats'))],
2077 [('e', 'extended', None, _('try extended date formats'))],
2078 _('[-e] DATE [RANGE]'),
2078 _('[-e] DATE [RANGE]'),
2079 norepo=True, optionalrepo=True)
2079 norepo=True, optionalrepo=True)
2080 def debugdate(ui, date, range=None, **opts):
2080 def debugdate(ui, date, range=None, **opts):
2081 """parse and display a date"""
2081 """parse and display a date"""
2082 if opts["extended"]:
2082 if opts["extended"]:
2083 d = util.parsedate(date, util.extendeddateformats)
2083 d = util.parsedate(date, util.extendeddateformats)
2084 else:
2084 else:
2085 d = util.parsedate(date)
2085 d = util.parsedate(date)
2086 ui.write(("internal: %s %s\n") % d)
2086 ui.write(("internal: %s %s\n") % d)
2087 ui.write(("standard: %s\n") % util.datestr(d))
2087 ui.write(("standard: %s\n") % util.datestr(d))
2088 if range:
2088 if range:
2089 m = util.matchdate(range)
2089 m = util.matchdate(range)
2090 ui.write(("match: %s\n") % m(d[0]))
2090 ui.write(("match: %s\n") % m(d[0]))
2091
2091
2092 @command('debugdiscovery',
2092 @command('debugdiscovery',
2093 [('', 'old', None, _('use old-style discovery')),
2093 [('', 'old', None, _('use old-style discovery')),
2094 ('', 'nonheads', None,
2094 ('', 'nonheads', None,
2095 _('use old-style discovery with non-heads included')),
2095 _('use old-style discovery with non-heads included')),
2096 ] + remoteopts,
2096 ] + remoteopts,
2097 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2097 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2098 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2098 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2099 """runs the changeset discovery protocol in isolation"""
2099 """runs the changeset discovery protocol in isolation"""
2100 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2100 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2101 opts.get('branch'))
2101 opts.get('branch'))
2102 remote = hg.peer(repo, opts, remoteurl)
2102 remote = hg.peer(repo, opts, remoteurl)
2103 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2103 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2104
2104
2105 # make sure tests are repeatable
2105 # make sure tests are repeatable
2106 random.seed(12323)
2106 random.seed(12323)
2107
2107
2108 def doit(localheads, remoteheads, remote=remote):
2108 def doit(localheads, remoteheads, remote=remote):
2109 if opts.get('old'):
2109 if opts.get('old'):
2110 if localheads:
2110 if localheads:
2111 raise util.Abort('cannot use localheads with old style '
2111 raise util.Abort('cannot use localheads with old style '
2112 'discovery')
2112 'discovery')
2113 if not util.safehasattr(remote, 'branches'):
2113 if not util.safehasattr(remote, 'branches'):
2114 # enable in-client legacy support
2114 # enable in-client legacy support
2115 remote = localrepo.locallegacypeer(remote.local())
2115 remote = localrepo.locallegacypeer(remote.local())
2116 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2116 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2117 force=True)
2117 force=True)
2118 common = set(common)
2118 common = set(common)
2119 if not opts.get('nonheads'):
2119 if not opts.get('nonheads'):
2120 ui.write(("unpruned common: %s\n") %
2120 ui.write(("unpruned common: %s\n") %
2121 " ".join(sorted(short(n) for n in common)))
2121 " ".join(sorted(short(n) for n in common)))
2122 dag = dagutil.revlogdag(repo.changelog)
2122 dag = dagutil.revlogdag(repo.changelog)
2123 all = dag.ancestorset(dag.internalizeall(common))
2123 all = dag.ancestorset(dag.internalizeall(common))
2124 common = dag.externalizeall(dag.headsetofconnecteds(all))
2124 common = dag.externalizeall(dag.headsetofconnecteds(all))
2125 else:
2125 else:
2126 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2126 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2127 common = set(common)
2127 common = set(common)
2128 rheads = set(hds)
2128 rheads = set(hds)
2129 lheads = set(repo.heads())
2129 lheads = set(repo.heads())
2130 ui.write(("common heads: %s\n") %
2130 ui.write(("common heads: %s\n") %
2131 " ".join(sorted(short(n) for n in common)))
2131 " ".join(sorted(short(n) for n in common)))
2132 if lheads <= common:
2132 if lheads <= common:
2133 ui.write(("local is subset\n"))
2133 ui.write(("local is subset\n"))
2134 elif rheads <= common:
2134 elif rheads <= common:
2135 ui.write(("remote is subset\n"))
2135 ui.write(("remote is subset\n"))
2136
2136
2137 serverlogs = opts.get('serverlog')
2137 serverlogs = opts.get('serverlog')
2138 if serverlogs:
2138 if serverlogs:
2139 for filename in serverlogs:
2139 for filename in serverlogs:
2140 logfile = open(filename, 'r')
2140 logfile = open(filename, 'r')
2141 try:
2141 try:
2142 line = logfile.readline()
2142 line = logfile.readline()
2143 while line:
2143 while line:
2144 parts = line.strip().split(';')
2144 parts = line.strip().split(';')
2145 op = parts[1]
2145 op = parts[1]
2146 if op == 'cg':
2146 if op == 'cg':
2147 pass
2147 pass
2148 elif op == 'cgss':
2148 elif op == 'cgss':
2149 doit(parts[2].split(' '), parts[3].split(' '))
2149 doit(parts[2].split(' '), parts[3].split(' '))
2150 elif op == 'unb':
2150 elif op == 'unb':
2151 doit(parts[3].split(' '), parts[2].split(' '))
2151 doit(parts[3].split(' '), parts[2].split(' '))
2152 line = logfile.readline()
2152 line = logfile.readline()
2153 finally:
2153 finally:
2154 logfile.close()
2154 logfile.close()
2155
2155
2156 else:
2156 else:
2157 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2157 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2158 opts.get('remote_head'))
2158 opts.get('remote_head'))
2159 localrevs = opts.get('local_head')
2159 localrevs = opts.get('local_head')
2160 doit(localrevs, remoterevs)
2160 doit(localrevs, remoterevs)
2161
2161
2162 @command('debugfileset',
2162 @command('debugfileset',
2163 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2163 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2164 _('[-r REV] FILESPEC'))
2164 _('[-r REV] FILESPEC'))
2165 def debugfileset(ui, repo, expr, **opts):
2165 def debugfileset(ui, repo, expr, **opts):
2166 '''parse and apply a fileset specification'''
2166 '''parse and apply a fileset specification'''
2167 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2167 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2168 if ui.verbose:
2168 if ui.verbose:
2169 tree = fileset.parse(expr)[0]
2169 tree = fileset.parse(expr)[0]
2170 ui.note(tree, "\n")
2170 ui.note(tree, "\n")
2171
2171
2172 for f in ctx.getfileset(expr):
2172 for f in ctx.getfileset(expr):
2173 ui.write("%s\n" % f)
2173 ui.write("%s\n" % f)
2174
2174
2175 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2175 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2176 def debugfsinfo(ui, path="."):
2176 def debugfsinfo(ui, path="."):
2177 """show information detected about current filesystem"""
2177 """show information detected about current filesystem"""
2178 util.writefile('.debugfsinfo', '')
2178 util.writefile('.debugfsinfo', '')
2179 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2179 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2180 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2180 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2181 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2181 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2182 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2182 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2183 and 'yes' or 'no'))
2183 and 'yes' or 'no'))
2184 os.unlink('.debugfsinfo')
2184 os.unlink('.debugfsinfo')
2185
2185
2186 @command('debuggetbundle',
2186 @command('debuggetbundle',
2187 [('H', 'head', [], _('id of head node'), _('ID')),
2187 [('H', 'head', [], _('id of head node'), _('ID')),
2188 ('C', 'common', [], _('id of common node'), _('ID')),
2188 ('C', 'common', [], _('id of common node'), _('ID')),
2189 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2189 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2190 _('REPO FILE [-H|-C ID]...'),
2190 _('REPO FILE [-H|-C ID]...'),
2191 norepo=True)
2191 norepo=True)
2192 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2192 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2193 """retrieves a bundle from a repo
2193 """retrieves a bundle from a repo
2194
2194
2195 Every ID must be a full-length hex node id string. Saves the bundle to the
2195 Every ID must be a full-length hex node id string. Saves the bundle to the
2196 given file.
2196 given file.
2197 """
2197 """
2198 repo = hg.peer(ui, opts, repopath)
2198 repo = hg.peer(ui, opts, repopath)
2199 if not repo.capable('getbundle'):
2199 if not repo.capable('getbundle'):
2200 raise util.Abort("getbundle() not supported by target repository")
2200 raise util.Abort("getbundle() not supported by target repository")
2201 args = {}
2201 args = {}
2202 if common:
2202 if common:
2203 args['common'] = [bin(s) for s in common]
2203 args['common'] = [bin(s) for s in common]
2204 if head:
2204 if head:
2205 args['heads'] = [bin(s) for s in head]
2205 args['heads'] = [bin(s) for s in head]
2206 # TODO: get desired bundlecaps from command line.
2206 # TODO: get desired bundlecaps from command line.
2207 args['bundlecaps'] = None
2207 args['bundlecaps'] = None
2208 bundle = repo.getbundle('debug', **args)
2208 bundle = repo.getbundle('debug', **args)
2209
2209
2210 bundletype = opts.get('type', 'bzip2').lower()
2210 bundletype = opts.get('type', 'bzip2').lower()
2211 btypes = {'none': 'HG10UN',
2211 btypes = {'none': 'HG10UN',
2212 'bzip2': 'HG10BZ',
2212 'bzip2': 'HG10BZ',
2213 'gzip': 'HG10GZ',
2213 'gzip': 'HG10GZ',
2214 'bundle2': 'HG20'}
2214 'bundle2': 'HG20'}
2215 bundletype = btypes.get(bundletype)
2215 bundletype = btypes.get(bundletype)
2216 if bundletype not in changegroup.bundletypes:
2216 if bundletype not in changegroup.bundletypes:
2217 raise util.Abort(_('unknown bundle type specified with --type'))
2217 raise util.Abort(_('unknown bundle type specified with --type'))
2218 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2218 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2219
2219
2220 @command('debugignore', [], '')
2220 @command('debugignore', [], '')
2221 def debugignore(ui, repo, *values, **opts):
2221 def debugignore(ui, repo, *values, **opts):
2222 """display the combined ignore pattern"""
2222 """display the combined ignore pattern"""
2223 ignore = repo.dirstate._ignore
2223 ignore = repo.dirstate._ignore
2224 includepat = getattr(ignore, 'includepat', None)
2224 includepat = getattr(ignore, 'includepat', None)
2225 if includepat is not None:
2225 if includepat is not None:
2226 ui.write("%s\n" % includepat)
2226 ui.write("%s\n" % includepat)
2227 else:
2227 else:
2228 raise util.Abort(_("no ignore patterns found"))
2228 raise util.Abort(_("no ignore patterns found"))
2229
2229
2230 @command('debugindex',
2230 @command('debugindex',
2231 [('c', 'changelog', False, _('open changelog')),
2231 [('c', 'changelog', False, _('open changelog')),
2232 ('m', 'manifest', False, _('open manifest')),
2232 ('m', 'manifest', False, _('open manifest')),
2233 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2233 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2234 _('[-f FORMAT] -c|-m|FILE'),
2234 _('[-f FORMAT] -c|-m|FILE'),
2235 optionalrepo=True)
2235 optionalrepo=True)
2236 def debugindex(ui, repo, file_=None, **opts):
2236 def debugindex(ui, repo, file_=None, **opts):
2237 """dump the contents of an index file"""
2237 """dump the contents of an index file"""
2238 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2238 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2239 format = opts.get('format', 0)
2239 format = opts.get('format', 0)
2240 if format not in (0, 1):
2240 if format not in (0, 1):
2241 raise util.Abort(_("unknown format %d") % format)
2241 raise util.Abort(_("unknown format %d") % format)
2242
2242
2243 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2243 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2244 if generaldelta:
2244 if generaldelta:
2245 basehdr = ' delta'
2245 basehdr = ' delta'
2246 else:
2246 else:
2247 basehdr = ' base'
2247 basehdr = ' base'
2248
2248
2249 if ui.debugflag:
2249 if ui.debugflag:
2250 shortfn = hex
2250 shortfn = hex
2251 else:
2251 else:
2252 shortfn = short
2252 shortfn = short
2253
2253
2254 # There might not be anything in r, so have a sane default
2254 # There might not be anything in r, so have a sane default
2255 idlen = 12
2255 idlen = 12
2256 for i in r:
2256 for i in r:
2257 idlen = len(shortfn(r.node(i)))
2257 idlen = len(shortfn(r.node(i)))
2258 break
2258 break
2259
2259
2260 if format == 0:
2260 if format == 0:
2261 ui.write(" rev offset length " + basehdr + " linkrev"
2261 ui.write(" rev offset length " + basehdr + " linkrev"
2262 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2262 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2263 elif format == 1:
2263 elif format == 1:
2264 ui.write(" rev flag offset length"
2264 ui.write(" rev flag offset length"
2265 " size " + basehdr + " link p1 p2"
2265 " size " + basehdr + " link p1 p2"
2266 " %s\n" % "nodeid".rjust(idlen))
2266 " %s\n" % "nodeid".rjust(idlen))
2267
2267
2268 for i in r:
2268 for i in r:
2269 node = r.node(i)
2269 node = r.node(i)
2270 if generaldelta:
2270 if generaldelta:
2271 base = r.deltaparent(i)
2271 base = r.deltaparent(i)
2272 else:
2272 else:
2273 base = r.chainbase(i)
2273 base = r.chainbase(i)
2274 if format == 0:
2274 if format == 0:
2275 try:
2275 try:
2276 pp = r.parents(node)
2276 pp = r.parents(node)
2277 except Exception:
2277 except Exception:
2278 pp = [nullid, nullid]
2278 pp = [nullid, nullid]
2279 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2279 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2280 i, r.start(i), r.length(i), base, r.linkrev(i),
2280 i, r.start(i), r.length(i), base, r.linkrev(i),
2281 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2281 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2282 elif format == 1:
2282 elif format == 1:
2283 pr = r.parentrevs(i)
2283 pr = r.parentrevs(i)
2284 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2284 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2285 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2285 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2286 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2286 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2287
2287
2288 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2288 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2289 def debugindexdot(ui, repo, file_):
2289 def debugindexdot(ui, repo, file_):
2290 """dump an index DAG as a graphviz dot file"""
2290 """dump an index DAG as a graphviz dot file"""
2291 r = None
2291 r = None
2292 if repo:
2292 if repo:
2293 filelog = repo.file(file_)
2293 filelog = repo.file(file_)
2294 if len(filelog):
2294 if len(filelog):
2295 r = filelog
2295 r = filelog
2296 if not r:
2296 if not r:
2297 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2297 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2298 ui.write(("digraph G {\n"))
2298 ui.write(("digraph G {\n"))
2299 for i in r:
2299 for i in r:
2300 node = r.node(i)
2300 node = r.node(i)
2301 pp = r.parents(node)
2301 pp = r.parents(node)
2302 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2302 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2303 if pp[1] != nullid:
2303 if pp[1] != nullid:
2304 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2304 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2305 ui.write("}\n")
2305 ui.write("}\n")
2306
2306
2307 @command('debuginstall', [], '', norepo=True)
2307 @command('debuginstall', [], '', norepo=True)
2308 def debuginstall(ui):
2308 def debuginstall(ui):
2309 '''test Mercurial installation
2309 '''test Mercurial installation
2310
2310
2311 Returns 0 on success.
2311 Returns 0 on success.
2312 '''
2312 '''
2313
2313
2314 def writetemp(contents):
2314 def writetemp(contents):
2315 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2315 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2316 f = os.fdopen(fd, "wb")
2316 f = os.fdopen(fd, "wb")
2317 f.write(contents)
2317 f.write(contents)
2318 f.close()
2318 f.close()
2319 return name
2319 return name
2320
2320
2321 problems = 0
2321 problems = 0
2322
2322
2323 # encoding
2323 # encoding
2324 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2324 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2325 try:
2325 try:
2326 encoding.fromlocal("test")
2326 encoding.fromlocal("test")
2327 except util.Abort, inst:
2327 except util.Abort, inst:
2328 ui.write(" %s\n" % inst)
2328 ui.write(" %s\n" % inst)
2329 ui.write(_(" (check that your locale is properly set)\n"))
2329 ui.write(_(" (check that your locale is properly set)\n"))
2330 problems += 1
2330 problems += 1
2331
2331
2332 # Python
2332 # Python
2333 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2333 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2334 ui.status(_("checking Python version (%s)\n")
2334 ui.status(_("checking Python version (%s)\n")
2335 % ("%s.%s.%s" % sys.version_info[:3]))
2335 % ("%s.%s.%s" % sys.version_info[:3]))
2336 ui.status(_("checking Python lib (%s)...\n")
2336 ui.status(_("checking Python lib (%s)...\n")
2337 % os.path.dirname(os.__file__))
2337 % os.path.dirname(os.__file__))
2338
2338
2339 # compiled modules
2339 # compiled modules
2340 ui.status(_("checking installed modules (%s)...\n")
2340 ui.status(_("checking installed modules (%s)...\n")
2341 % os.path.dirname(__file__))
2341 % os.path.dirname(__file__))
2342 try:
2342 try:
2343 import bdiff, mpatch, base85, osutil
2343 import bdiff, mpatch, base85, osutil
2344 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2344 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2345 except Exception, inst:
2345 except Exception, inst:
2346 ui.write(" %s\n" % inst)
2346 ui.write(" %s\n" % inst)
2347 ui.write(_(" One or more extensions could not be found"))
2347 ui.write(_(" One or more extensions could not be found"))
2348 ui.write(_(" (check that you compiled the extensions)\n"))
2348 ui.write(_(" (check that you compiled the extensions)\n"))
2349 problems += 1
2349 problems += 1
2350
2350
2351 # templates
2351 # templates
2352 import templater
2352 import templater
2353 p = templater.templatepaths()
2353 p = templater.templatepaths()
2354 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2354 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2355 if p:
2355 if p:
2356 m = templater.templatepath("map-cmdline.default")
2356 m = templater.templatepath("map-cmdline.default")
2357 if m:
2357 if m:
2358 # template found, check if it is working
2358 # template found, check if it is working
2359 try:
2359 try:
2360 templater.templater(m)
2360 templater.templater(m)
2361 except Exception, inst:
2361 except Exception, inst:
2362 ui.write(" %s\n" % inst)
2362 ui.write(" %s\n" % inst)
2363 p = None
2363 p = None
2364 else:
2364 else:
2365 ui.write(_(" template 'default' not found\n"))
2365 ui.write(_(" template 'default' not found\n"))
2366 p = None
2366 p = None
2367 else:
2367 else:
2368 ui.write(_(" no template directories found\n"))
2368 ui.write(_(" no template directories found\n"))
2369 if not p:
2369 if not p:
2370 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2370 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2371 problems += 1
2371 problems += 1
2372
2372
2373 # editor
2373 # editor
2374 ui.status(_("checking commit editor...\n"))
2374 ui.status(_("checking commit editor...\n"))
2375 editor = ui.geteditor()
2375 editor = ui.geteditor()
2376 cmdpath = util.findexe(shlex.split(editor)[0])
2376 cmdpath = util.findexe(shlex.split(editor)[0])
2377 if not cmdpath:
2377 if not cmdpath:
2378 if editor == 'vi':
2378 if editor == 'vi':
2379 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2379 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2380 ui.write(_(" (specify a commit editor in your configuration"
2380 ui.write(_(" (specify a commit editor in your configuration"
2381 " file)\n"))
2381 " file)\n"))
2382 else:
2382 else:
2383 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2383 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2384 ui.write(_(" (specify a commit editor in your configuration"
2384 ui.write(_(" (specify a commit editor in your configuration"
2385 " file)\n"))
2385 " file)\n"))
2386 problems += 1
2386 problems += 1
2387
2387
2388 # check username
2388 # check username
2389 ui.status(_("checking username...\n"))
2389 ui.status(_("checking username...\n"))
2390 try:
2390 try:
2391 ui.username()
2391 ui.username()
2392 except util.Abort, e:
2392 except util.Abort, e:
2393 ui.write(" %s\n" % e)
2393 ui.write(" %s\n" % e)
2394 ui.write(_(" (specify a username in your configuration file)\n"))
2394 ui.write(_(" (specify a username in your configuration file)\n"))
2395 problems += 1
2395 problems += 1
2396
2396
2397 if not problems:
2397 if not problems:
2398 ui.status(_("no problems detected\n"))
2398 ui.status(_("no problems detected\n"))
2399 else:
2399 else:
2400 ui.write(_("%s problems detected,"
2400 ui.write(_("%s problems detected,"
2401 " please check your install!\n") % problems)
2401 " please check your install!\n") % problems)
2402
2402
2403 return problems
2403 return problems
2404
2404
2405 @command('debugknown', [], _('REPO ID...'), norepo=True)
2405 @command('debugknown', [], _('REPO ID...'), norepo=True)
2406 def debugknown(ui, repopath, *ids, **opts):
2406 def debugknown(ui, repopath, *ids, **opts):
2407 """test whether node ids are known to a repo
2407 """test whether node ids are known to a repo
2408
2408
2409 Every ID must be a full-length hex node id string. Returns a list of 0s
2409 Every ID must be a full-length hex node id string. Returns a list of 0s
2410 and 1s indicating unknown/known.
2410 and 1s indicating unknown/known.
2411 """
2411 """
2412 repo = hg.peer(ui, opts, repopath)
2412 repo = hg.peer(ui, opts, repopath)
2413 if not repo.capable('known'):
2413 if not repo.capable('known'):
2414 raise util.Abort("known() not supported by target repository")
2414 raise util.Abort("known() not supported by target repository")
2415 flags = repo.known([bin(s) for s in ids])
2415 flags = repo.known([bin(s) for s in ids])
2416 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2416 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2417
2417
2418 @command('debuglabelcomplete', [], _('LABEL...'))
2418 @command('debuglabelcomplete', [], _('LABEL...'))
2419 def debuglabelcomplete(ui, repo, *args):
2419 def debuglabelcomplete(ui, repo, *args):
2420 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2420 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2421 debugnamecomplete(ui, repo, *args)
2421 debugnamecomplete(ui, repo, *args)
2422
2422
2423 @command('debugnamecomplete', [], _('NAME...'))
2423 @command('debugnamecomplete', [], _('NAME...'))
2424 def debugnamecomplete(ui, repo, *args):
2424 def debugnamecomplete(ui, repo, *args):
2425 '''complete "names" - tags, open branch names, bookmark names'''
2425 '''complete "names" - tags, open branch names, bookmark names'''
2426
2426
2427 names = set()
2427 names = set()
2428 # since we previously only listed open branches, we will handle that
2428 # since we previously only listed open branches, we will handle that
2429 # specially (after this for loop)
2429 # specially (after this for loop)
2430 for name, ns in repo.names.iteritems():
2430 for name, ns in repo.names.iteritems():
2431 if name != 'branches':
2431 if name != 'branches':
2432 names.update(ns.listnames(repo))
2432 names.update(ns.listnames(repo))
2433 names.update(tag for (tag, heads, tip, closed)
2433 names.update(tag for (tag, heads, tip, closed)
2434 in repo.branchmap().iterbranches() if not closed)
2434 in repo.branchmap().iterbranches() if not closed)
2435 completions = set()
2435 completions = set()
2436 if not args:
2436 if not args:
2437 args = ['']
2437 args = ['']
2438 for a in args:
2438 for a in args:
2439 completions.update(n for n in names if n.startswith(a))
2439 completions.update(n for n in names if n.startswith(a))
2440 ui.write('\n'.join(sorted(completions)))
2440 ui.write('\n'.join(sorted(completions)))
2441 ui.write('\n')
2441 ui.write('\n')
2442
2442
2443 @command('debuglocks',
2443 @command('debuglocks',
2444 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2444 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2445 ('W', 'force-wlock', None,
2445 ('W', 'force-wlock', None,
2446 _('free the working state lock (DANGEROUS)'))],
2446 _('free the working state lock (DANGEROUS)'))],
2447 _('[OPTION]...'))
2447 _('[OPTION]...'))
2448 def debuglocks(ui, repo, **opts):
2448 def debuglocks(ui, repo, **opts):
2449 """show or modify state of locks
2449 """show or modify state of locks
2450
2450
2451 By default, this command will show which locks are held. This
2451 By default, this command will show which locks are held. This
2452 includes the user and process holding the lock, the amount of time
2452 includes the user and process holding the lock, the amount of time
2453 the lock has been held, and the machine name where the process is
2453 the lock has been held, and the machine name where the process is
2454 running if it's not local.
2454 running if it's not local.
2455
2455
2456 Locks protect the integrity of Mercurial's data, so should be
2456 Locks protect the integrity of Mercurial's data, so should be
2457 treated with care. System crashes or other interruptions may cause
2457 treated with care. System crashes or other interruptions may cause
2458 locks to not be properly released, though Mercurial will usually
2458 locks to not be properly released, though Mercurial will usually
2459 detect and remove such stale locks automatically.
2459 detect and remove such stale locks automatically.
2460
2460
2461 However, detecting stale locks may not always be possible (for
2461 However, detecting stale locks may not always be possible (for
2462 instance, on a shared filesystem). Removing locks may also be
2462 instance, on a shared filesystem). Removing locks may also be
2463 blocked by filesystem permissions.
2463 blocked by filesystem permissions.
2464
2464
2465 Returns 0 if no locks are held.
2465 Returns 0 if no locks are held.
2466
2466
2467 """
2467 """
2468
2468
2469 if opts.get('force_lock'):
2469 if opts.get('force_lock'):
2470 repo.svfs.unlink('lock')
2470 repo.svfs.unlink('lock')
2471 if opts.get('force_wlock'):
2471 if opts.get('force_wlock'):
2472 repo.vfs.unlink('wlock')
2472 repo.vfs.unlink('wlock')
2473 if opts.get('force_lock') or opts.get('force_lock'):
2473 if opts.get('force_lock') or opts.get('force_lock'):
2474 return 0
2474 return 0
2475
2475
2476 now = time.time()
2476 now = time.time()
2477 held = 0
2477 held = 0
2478
2478
2479 def report(vfs, name, method):
2479 def report(vfs, name, method):
2480 # this causes stale locks to get reaped for more accurate reporting
2480 # this causes stale locks to get reaped for more accurate reporting
2481 try:
2481 try:
2482 l = method(False)
2482 l = method(False)
2483 except error.LockHeld:
2483 except error.LockHeld:
2484 l = None
2484 l = None
2485
2485
2486 if l:
2486 if l:
2487 l.release()
2487 l.release()
2488 else:
2488 else:
2489 try:
2489 try:
2490 stat = repo.svfs.lstat(name)
2490 stat = repo.svfs.lstat(name)
2491 age = now - stat.st_mtime
2491 age = now - stat.st_mtime
2492 user = util.username(stat.st_uid)
2492 user = util.username(stat.st_uid)
2493 locker = vfs.readlock(name)
2493 locker = vfs.readlock(name)
2494 if ":" in locker:
2494 if ":" in locker:
2495 host, pid = locker.split(':')
2495 host, pid = locker.split(':')
2496 if host == socket.gethostname():
2496 if host == socket.gethostname():
2497 locker = 'user %s, process %s' % (user, pid)
2497 locker = 'user %s, process %s' % (user, pid)
2498 else:
2498 else:
2499 locker = 'user %s, process %s, host %s' \
2499 locker = 'user %s, process %s, host %s' \
2500 % (user, pid, host)
2500 % (user, pid, host)
2501 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2501 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2502 return 1
2502 return 1
2503 except OSError, e:
2503 except OSError, e:
2504 if e.errno != errno.ENOENT:
2504 if e.errno != errno.ENOENT:
2505 raise
2505 raise
2506
2506
2507 ui.write("%-6s free\n" % (name + ":"))
2507 ui.write("%-6s free\n" % (name + ":"))
2508 return 0
2508 return 0
2509
2509
2510 held += report(repo.svfs, "lock", repo.lock)
2510 held += report(repo.svfs, "lock", repo.lock)
2511 held += report(repo.vfs, "wlock", repo.wlock)
2511 held += report(repo.vfs, "wlock", repo.wlock)
2512
2512
2513 return held
2513 return held
2514
2514
2515 @command('debugobsolete',
2515 @command('debugobsolete',
2516 [('', 'flags', 0, _('markers flag')),
2516 [('', 'flags', 0, _('markers flag')),
2517 ('', 'record-parents', False,
2517 ('', 'record-parents', False,
2518 _('record parent information for the precursor')),
2518 _('record parent information for the precursor')),
2519 ('r', 'rev', [], _('display markers relevant to REV')),
2519 ('r', 'rev', [], _('display markers relevant to REV')),
2520 ] + commitopts2,
2520 ] + commitopts2,
2521 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2521 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2522 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2522 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2523 """create arbitrary obsolete marker
2523 """create arbitrary obsolete marker
2524
2524
2525 With no arguments, displays the list of obsolescence markers."""
2525 With no arguments, displays the list of obsolescence markers."""
2526
2526
2527 def parsenodeid(s):
2527 def parsenodeid(s):
2528 try:
2528 try:
2529 # We do not use revsingle/revrange functions here to accept
2529 # We do not use revsingle/revrange functions here to accept
2530 # arbitrary node identifiers, possibly not present in the
2530 # arbitrary node identifiers, possibly not present in the
2531 # local repository.
2531 # local repository.
2532 n = bin(s)
2532 n = bin(s)
2533 if len(n) != len(nullid):
2533 if len(n) != len(nullid):
2534 raise TypeError()
2534 raise TypeError()
2535 return n
2535 return n
2536 except TypeError:
2536 except TypeError:
2537 raise util.Abort('changeset references must be full hexadecimal '
2537 raise util.Abort('changeset references must be full hexadecimal '
2538 'node identifiers')
2538 'node identifiers')
2539
2539
2540 if precursor is not None:
2540 if precursor is not None:
2541 if opts['rev']:
2541 if opts['rev']:
2542 raise util.Abort('cannot select revision when creating marker')
2542 raise util.Abort('cannot select revision when creating marker')
2543 metadata = {}
2543 metadata = {}
2544 metadata['user'] = opts['user'] or ui.username()
2544 metadata['user'] = opts['user'] or ui.username()
2545 succs = tuple(parsenodeid(succ) for succ in successors)
2545 succs = tuple(parsenodeid(succ) for succ in successors)
2546 l = repo.lock()
2546 l = repo.lock()
2547 try:
2547 try:
2548 tr = repo.transaction('debugobsolete')
2548 tr = repo.transaction('debugobsolete')
2549 try:
2549 try:
2550 try:
2550 try:
2551 date = opts.get('date')
2551 date = opts.get('date')
2552 if date:
2552 if date:
2553 date = util.parsedate(date)
2553 date = util.parsedate(date)
2554 else:
2554 else:
2555 date = None
2555 date = None
2556 prec = parsenodeid(precursor)
2556 prec = parsenodeid(precursor)
2557 parents = None
2557 parents = None
2558 if opts['record_parents']:
2558 if opts['record_parents']:
2559 if prec not in repo.unfiltered():
2559 if prec not in repo.unfiltered():
2560 raise util.Abort('cannot used --record-parents on '
2560 raise util.Abort('cannot used --record-parents on '
2561 'unknown changesets')
2561 'unknown changesets')
2562 parents = repo.unfiltered()[prec].parents()
2562 parents = repo.unfiltered()[prec].parents()
2563 parents = tuple(p.node() for p in parents)
2563 parents = tuple(p.node() for p in parents)
2564 repo.obsstore.create(tr, prec, succs, opts['flags'],
2564 repo.obsstore.create(tr, prec, succs, opts['flags'],
2565 parents=parents, date=date,
2565 parents=parents, date=date,
2566 metadata=metadata)
2566 metadata=metadata)
2567 tr.close()
2567 tr.close()
2568 except ValueError, exc:
2568 except ValueError, exc:
2569 raise util.Abort(_('bad obsmarker input: %s') % exc)
2569 raise util.Abort(_('bad obsmarker input: %s') % exc)
2570 finally:
2570 finally:
2571 tr.release()
2571 tr.release()
2572 finally:
2572 finally:
2573 l.release()
2573 l.release()
2574 else:
2574 else:
2575 if opts['rev']:
2575 if opts['rev']:
2576 revs = scmutil.revrange(repo, opts['rev'])
2576 revs = scmutil.revrange(repo, opts['rev'])
2577 nodes = [repo[r].node() for r in revs]
2577 nodes = [repo[r].node() for r in revs]
2578 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2578 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2579 markers.sort(key=lambda x: x._data)
2579 markers.sort(key=lambda x: x._data)
2580 else:
2580 else:
2581 markers = obsolete.getmarkers(repo)
2581 markers = obsolete.getmarkers(repo)
2582
2582
2583 for m in markers:
2583 for m in markers:
2584 cmdutil.showmarker(ui, m)
2584 cmdutil.showmarker(ui, m)
2585
2585
2586 @command('debugpathcomplete',
2586 @command('debugpathcomplete',
2587 [('f', 'full', None, _('complete an entire path')),
2587 [('f', 'full', None, _('complete an entire path')),
2588 ('n', 'normal', None, _('show only normal files')),
2588 ('n', 'normal', None, _('show only normal files')),
2589 ('a', 'added', None, _('show only added files')),
2589 ('a', 'added', None, _('show only added files')),
2590 ('r', 'removed', None, _('show only removed files'))],
2590 ('r', 'removed', None, _('show only removed files'))],
2591 _('FILESPEC...'))
2591 _('FILESPEC...'))
2592 def debugpathcomplete(ui, repo, *specs, **opts):
2592 def debugpathcomplete(ui, repo, *specs, **opts):
2593 '''complete part or all of a tracked path
2593 '''complete part or all of a tracked path
2594
2594
2595 This command supports shells that offer path name completion. It
2595 This command supports shells that offer path name completion. It
2596 currently completes only files already known to the dirstate.
2596 currently completes only files already known to the dirstate.
2597
2597
2598 Completion extends only to the next path segment unless
2598 Completion extends only to the next path segment unless
2599 --full is specified, in which case entire paths are used.'''
2599 --full is specified, in which case entire paths are used.'''
2600
2600
2601 def complete(path, acceptable):
2601 def complete(path, acceptable):
2602 dirstate = repo.dirstate
2602 dirstate = repo.dirstate
2603 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2603 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2604 rootdir = repo.root + os.sep
2604 rootdir = repo.root + os.sep
2605 if spec != repo.root and not spec.startswith(rootdir):
2605 if spec != repo.root and not spec.startswith(rootdir):
2606 return [], []
2606 return [], []
2607 if os.path.isdir(spec):
2607 if os.path.isdir(spec):
2608 spec += '/'
2608 spec += '/'
2609 spec = spec[len(rootdir):]
2609 spec = spec[len(rootdir):]
2610 fixpaths = os.sep != '/'
2610 fixpaths = os.sep != '/'
2611 if fixpaths:
2611 if fixpaths:
2612 spec = spec.replace(os.sep, '/')
2612 spec = spec.replace(os.sep, '/')
2613 speclen = len(spec)
2613 speclen = len(spec)
2614 fullpaths = opts['full']
2614 fullpaths = opts['full']
2615 files, dirs = set(), set()
2615 files, dirs = set(), set()
2616 adddir, addfile = dirs.add, files.add
2616 adddir, addfile = dirs.add, files.add
2617 for f, st in dirstate.iteritems():
2617 for f, st in dirstate.iteritems():
2618 if f.startswith(spec) and st[0] in acceptable:
2618 if f.startswith(spec) and st[0] in acceptable:
2619 if fixpaths:
2619 if fixpaths:
2620 f = f.replace('/', os.sep)
2620 f = f.replace('/', os.sep)
2621 if fullpaths:
2621 if fullpaths:
2622 addfile(f)
2622 addfile(f)
2623 continue
2623 continue
2624 s = f.find(os.sep, speclen)
2624 s = f.find(os.sep, speclen)
2625 if s >= 0:
2625 if s >= 0:
2626 adddir(f[:s])
2626 adddir(f[:s])
2627 else:
2627 else:
2628 addfile(f)
2628 addfile(f)
2629 return files, dirs
2629 return files, dirs
2630
2630
2631 acceptable = ''
2631 acceptable = ''
2632 if opts['normal']:
2632 if opts['normal']:
2633 acceptable += 'nm'
2633 acceptable += 'nm'
2634 if opts['added']:
2634 if opts['added']:
2635 acceptable += 'a'
2635 acceptable += 'a'
2636 if opts['removed']:
2636 if opts['removed']:
2637 acceptable += 'r'
2637 acceptable += 'r'
2638 cwd = repo.getcwd()
2638 cwd = repo.getcwd()
2639 if not specs:
2639 if not specs:
2640 specs = ['.']
2640 specs = ['.']
2641
2641
2642 files, dirs = set(), set()
2642 files, dirs = set(), set()
2643 for spec in specs:
2643 for spec in specs:
2644 f, d = complete(spec, acceptable or 'nmar')
2644 f, d = complete(spec, acceptable or 'nmar')
2645 files.update(f)
2645 files.update(f)
2646 dirs.update(d)
2646 dirs.update(d)
2647 files.update(dirs)
2647 files.update(dirs)
2648 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2648 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2649 ui.write('\n')
2649 ui.write('\n')
2650
2650
2651 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2651 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2652 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2652 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2653 '''access the pushkey key/value protocol
2653 '''access the pushkey key/value protocol
2654
2654
2655 With two args, list the keys in the given namespace.
2655 With two args, list the keys in the given namespace.
2656
2656
2657 With five args, set a key to new if it currently is set to old.
2657 With five args, set a key to new if it currently is set to old.
2658 Reports success or failure.
2658 Reports success or failure.
2659 '''
2659 '''
2660
2660
2661 target = hg.peer(ui, {}, repopath)
2661 target = hg.peer(ui, {}, repopath)
2662 if keyinfo:
2662 if keyinfo:
2663 key, old, new = keyinfo
2663 key, old, new = keyinfo
2664 r = target.pushkey(namespace, key, old, new)
2664 r = target.pushkey(namespace, key, old, new)
2665 ui.status(str(r) + '\n')
2665 ui.status(str(r) + '\n')
2666 return not r
2666 return not r
2667 else:
2667 else:
2668 for k, v in sorted(target.listkeys(namespace).iteritems()):
2668 for k, v in sorted(target.listkeys(namespace).iteritems()):
2669 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2669 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2670 v.encode('string-escape')))
2670 v.encode('string-escape')))
2671
2671
2672 @command('debugpvec', [], _('A B'))
2672 @command('debugpvec', [], _('A B'))
2673 def debugpvec(ui, repo, a, b=None):
2673 def debugpvec(ui, repo, a, b=None):
2674 ca = scmutil.revsingle(repo, a)
2674 ca = scmutil.revsingle(repo, a)
2675 cb = scmutil.revsingle(repo, b)
2675 cb = scmutil.revsingle(repo, b)
2676 pa = pvec.ctxpvec(ca)
2676 pa = pvec.ctxpvec(ca)
2677 pb = pvec.ctxpvec(cb)
2677 pb = pvec.ctxpvec(cb)
2678 if pa == pb:
2678 if pa == pb:
2679 rel = "="
2679 rel = "="
2680 elif pa > pb:
2680 elif pa > pb:
2681 rel = ">"
2681 rel = ">"
2682 elif pa < pb:
2682 elif pa < pb:
2683 rel = "<"
2683 rel = "<"
2684 elif pa | pb:
2684 elif pa | pb:
2685 rel = "|"
2685 rel = "|"
2686 ui.write(_("a: %s\n") % pa)
2686 ui.write(_("a: %s\n") % pa)
2687 ui.write(_("b: %s\n") % pb)
2687 ui.write(_("b: %s\n") % pb)
2688 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2688 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2689 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2689 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2690 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2690 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2691 pa.distance(pb), rel))
2691 pa.distance(pb), rel))
2692
2692
2693 @command('debugrebuilddirstate|debugrebuildstate',
2693 @command('debugrebuilddirstate|debugrebuildstate',
2694 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2694 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2695 _('[-r REV]'))
2695 _('[-r REV]'))
2696 def debugrebuilddirstate(ui, repo, rev):
2696 def debugrebuilddirstate(ui, repo, rev):
2697 """rebuild the dirstate as it would look like for the given revision
2697 """rebuild the dirstate as it would look like for the given revision
2698
2698
2699 If no revision is specified the first current parent will be used.
2699 If no revision is specified the first current parent will be used.
2700
2700
2701 The dirstate will be set to the files of the given revision.
2701 The dirstate will be set to the files of the given revision.
2702 The actual working directory content or existing dirstate
2702 The actual working directory content or existing dirstate
2703 information such as adds or removes is not considered.
2703 information such as adds or removes is not considered.
2704
2704
2705 One use of this command is to make the next :hg:`status` invocation
2705 One use of this command is to make the next :hg:`status` invocation
2706 check the actual file content.
2706 check the actual file content.
2707 """
2707 """
2708 ctx = scmutil.revsingle(repo, rev)
2708 ctx = scmutil.revsingle(repo, rev)
2709 wlock = repo.wlock()
2709 wlock = repo.wlock()
2710 try:
2710 try:
2711 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2711 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2712 finally:
2712 finally:
2713 wlock.release()
2713 wlock.release()
2714
2714
2715 @command('debugrename',
2715 @command('debugrename',
2716 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2716 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2717 _('[-r REV] FILE'))
2717 _('[-r REV] FILE'))
2718 def debugrename(ui, repo, file1, *pats, **opts):
2718 def debugrename(ui, repo, file1, *pats, **opts):
2719 """dump rename information"""
2719 """dump rename information"""
2720
2720
2721 ctx = scmutil.revsingle(repo, opts.get('rev'))
2721 ctx = scmutil.revsingle(repo, opts.get('rev'))
2722 m = scmutil.match(ctx, (file1,) + pats, opts)
2722 m = scmutil.match(ctx, (file1,) + pats, opts)
2723 for abs in ctx.walk(m):
2723 for abs in ctx.walk(m):
2724 fctx = ctx[abs]
2724 fctx = ctx[abs]
2725 o = fctx.filelog().renamed(fctx.filenode())
2725 o = fctx.filelog().renamed(fctx.filenode())
2726 rel = m.rel(abs)
2726 rel = m.rel(abs)
2727 if o:
2727 if o:
2728 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2728 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2729 else:
2729 else:
2730 ui.write(_("%s not renamed\n") % rel)
2730 ui.write(_("%s not renamed\n") % rel)
2731
2731
2732 @command('debugrevlog',
2732 @command('debugrevlog',
2733 [('c', 'changelog', False, _('open changelog')),
2733 [('c', 'changelog', False, _('open changelog')),
2734 ('m', 'manifest', False, _('open manifest')),
2734 ('m', 'manifest', False, _('open manifest')),
2735 ('d', 'dump', False, _('dump index data'))],
2735 ('d', 'dump', False, _('dump index data'))],
2736 _('-c|-m|FILE'),
2736 _('-c|-m|FILE'),
2737 optionalrepo=True)
2737 optionalrepo=True)
2738 def debugrevlog(ui, repo, file_=None, **opts):
2738 def debugrevlog(ui, repo, file_=None, **opts):
2739 """show data and statistics about a revlog"""
2739 """show data and statistics about a revlog"""
2740 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2740 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2741
2741
2742 if opts.get("dump"):
2742 if opts.get("dump"):
2743 numrevs = len(r)
2743 numrevs = len(r)
2744 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2744 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2745 " rawsize totalsize compression heads chainlen\n")
2745 " rawsize totalsize compression heads chainlen\n")
2746 ts = 0
2746 ts = 0
2747 heads = set()
2747 heads = set()
2748
2748
2749 for rev in xrange(numrevs):
2749 for rev in xrange(numrevs):
2750 dbase = r.deltaparent(rev)
2750 dbase = r.deltaparent(rev)
2751 if dbase == -1:
2751 if dbase == -1:
2752 dbase = rev
2752 dbase = rev
2753 cbase = r.chainbase(rev)
2753 cbase = r.chainbase(rev)
2754 clen = r.chainlen(rev)
2754 clen = r.chainlen(rev)
2755 p1, p2 = r.parentrevs(rev)
2755 p1, p2 = r.parentrevs(rev)
2756 rs = r.rawsize(rev)
2756 rs = r.rawsize(rev)
2757 ts = ts + rs
2757 ts = ts + rs
2758 heads -= set(r.parentrevs(rev))
2758 heads -= set(r.parentrevs(rev))
2759 heads.add(rev)
2759 heads.add(rev)
2760 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2760 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2761 "%11d %5d %8d\n" %
2761 "%11d %5d %8d\n" %
2762 (rev, p1, p2, r.start(rev), r.end(rev),
2762 (rev, p1, p2, r.start(rev), r.end(rev),
2763 r.start(dbase), r.start(cbase),
2763 r.start(dbase), r.start(cbase),
2764 r.start(p1), r.start(p2),
2764 r.start(p1), r.start(p2),
2765 rs, ts, ts / r.end(rev), len(heads), clen))
2765 rs, ts, ts / r.end(rev), len(heads), clen))
2766 return 0
2766 return 0
2767
2767
2768 v = r.version
2768 v = r.version
2769 format = v & 0xFFFF
2769 format = v & 0xFFFF
2770 flags = []
2770 flags = []
2771 gdelta = False
2771 gdelta = False
2772 if v & revlog.REVLOGNGINLINEDATA:
2772 if v & revlog.REVLOGNGINLINEDATA:
2773 flags.append('inline')
2773 flags.append('inline')
2774 if v & revlog.REVLOGGENERALDELTA:
2774 if v & revlog.REVLOGGENERALDELTA:
2775 gdelta = True
2775 gdelta = True
2776 flags.append('generaldelta')
2776 flags.append('generaldelta')
2777 if not flags:
2777 if not flags:
2778 flags = ['(none)']
2778 flags = ['(none)']
2779
2779
2780 nummerges = 0
2780 nummerges = 0
2781 numfull = 0
2781 numfull = 0
2782 numprev = 0
2782 numprev = 0
2783 nump1 = 0
2783 nump1 = 0
2784 nump2 = 0
2784 nump2 = 0
2785 numother = 0
2785 numother = 0
2786 nump1prev = 0
2786 nump1prev = 0
2787 nump2prev = 0
2787 nump2prev = 0
2788 chainlengths = []
2788 chainlengths = []
2789
2789
2790 datasize = [None, 0, 0L]
2790 datasize = [None, 0, 0L]
2791 fullsize = [None, 0, 0L]
2791 fullsize = [None, 0, 0L]
2792 deltasize = [None, 0, 0L]
2792 deltasize = [None, 0, 0L]
2793
2793
2794 def addsize(size, l):
2794 def addsize(size, l):
2795 if l[0] is None or size < l[0]:
2795 if l[0] is None or size < l[0]:
2796 l[0] = size
2796 l[0] = size
2797 if size > l[1]:
2797 if size > l[1]:
2798 l[1] = size
2798 l[1] = size
2799 l[2] += size
2799 l[2] += size
2800
2800
2801 numrevs = len(r)
2801 numrevs = len(r)
2802 for rev in xrange(numrevs):
2802 for rev in xrange(numrevs):
2803 p1, p2 = r.parentrevs(rev)
2803 p1, p2 = r.parentrevs(rev)
2804 delta = r.deltaparent(rev)
2804 delta = r.deltaparent(rev)
2805 if format > 0:
2805 if format > 0:
2806 addsize(r.rawsize(rev), datasize)
2806 addsize(r.rawsize(rev), datasize)
2807 if p2 != nullrev:
2807 if p2 != nullrev:
2808 nummerges += 1
2808 nummerges += 1
2809 size = r.length(rev)
2809 size = r.length(rev)
2810 if delta == nullrev:
2810 if delta == nullrev:
2811 chainlengths.append(0)
2811 chainlengths.append(0)
2812 numfull += 1
2812 numfull += 1
2813 addsize(size, fullsize)
2813 addsize(size, fullsize)
2814 else:
2814 else:
2815 chainlengths.append(chainlengths[delta] + 1)
2815 chainlengths.append(chainlengths[delta] + 1)
2816 addsize(size, deltasize)
2816 addsize(size, deltasize)
2817 if delta == rev - 1:
2817 if delta == rev - 1:
2818 numprev += 1
2818 numprev += 1
2819 if delta == p1:
2819 if delta == p1:
2820 nump1prev += 1
2820 nump1prev += 1
2821 elif delta == p2:
2821 elif delta == p2:
2822 nump2prev += 1
2822 nump2prev += 1
2823 elif delta == p1:
2823 elif delta == p1:
2824 nump1 += 1
2824 nump1 += 1
2825 elif delta == p2:
2825 elif delta == p2:
2826 nump2 += 1
2826 nump2 += 1
2827 elif delta != nullrev:
2827 elif delta != nullrev:
2828 numother += 1
2828 numother += 1
2829
2829
2830 # Adjust size min value for empty cases
2830 # Adjust size min value for empty cases
2831 for size in (datasize, fullsize, deltasize):
2831 for size in (datasize, fullsize, deltasize):
2832 if size[0] is None:
2832 if size[0] is None:
2833 size[0] = 0
2833 size[0] = 0
2834
2834
2835 numdeltas = numrevs - numfull
2835 numdeltas = numrevs - numfull
2836 numoprev = numprev - nump1prev - nump2prev
2836 numoprev = numprev - nump1prev - nump2prev
2837 totalrawsize = datasize[2]
2837 totalrawsize = datasize[2]
2838 datasize[2] /= numrevs
2838 datasize[2] /= numrevs
2839 fulltotal = fullsize[2]
2839 fulltotal = fullsize[2]
2840 fullsize[2] /= numfull
2840 fullsize[2] /= numfull
2841 deltatotal = deltasize[2]
2841 deltatotal = deltasize[2]
2842 if numrevs - numfull > 0:
2842 if numrevs - numfull > 0:
2843 deltasize[2] /= numrevs - numfull
2843 deltasize[2] /= numrevs - numfull
2844 totalsize = fulltotal + deltatotal
2844 totalsize = fulltotal + deltatotal
2845 avgchainlen = sum(chainlengths) / numrevs
2845 avgchainlen = sum(chainlengths) / numrevs
2846 maxchainlen = max(chainlengths)
2846 maxchainlen = max(chainlengths)
2847 compratio = totalrawsize / totalsize
2847 compratio = totalrawsize / totalsize
2848
2848
2849 basedfmtstr = '%%%dd\n'
2849 basedfmtstr = '%%%dd\n'
2850 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2850 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2851
2851
2852 def dfmtstr(max):
2852 def dfmtstr(max):
2853 return basedfmtstr % len(str(max))
2853 return basedfmtstr % len(str(max))
2854 def pcfmtstr(max, padding=0):
2854 def pcfmtstr(max, padding=0):
2855 return basepcfmtstr % (len(str(max)), ' ' * padding)
2855 return basepcfmtstr % (len(str(max)), ' ' * padding)
2856
2856
2857 def pcfmt(value, total):
2857 def pcfmt(value, total):
2858 return (value, 100 * float(value) / total)
2858 return (value, 100 * float(value) / total)
2859
2859
2860 ui.write(('format : %d\n') % format)
2860 ui.write(('format : %d\n') % format)
2861 ui.write(('flags : %s\n') % ', '.join(flags))
2861 ui.write(('flags : %s\n') % ', '.join(flags))
2862
2862
2863 ui.write('\n')
2863 ui.write('\n')
2864 fmt = pcfmtstr(totalsize)
2864 fmt = pcfmtstr(totalsize)
2865 fmt2 = dfmtstr(totalsize)
2865 fmt2 = dfmtstr(totalsize)
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2867 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2867 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2868 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2868 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2869 ui.write(('revisions : ') + fmt2 % numrevs)
2869 ui.write(('revisions : ') + fmt2 % numrevs)
2870 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2870 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2871 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2871 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2872 ui.write(('revision size : ') + fmt2 % totalsize)
2872 ui.write(('revision size : ') + fmt2 % totalsize)
2873 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2873 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2874 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2874 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2875
2875
2876 ui.write('\n')
2876 ui.write('\n')
2877 fmt = dfmtstr(max(avgchainlen, compratio))
2877 fmt = dfmtstr(max(avgchainlen, compratio))
2878 ui.write(('avg chain length : ') + fmt % avgchainlen)
2878 ui.write(('avg chain length : ') + fmt % avgchainlen)
2879 ui.write(('max chain length : ') + fmt % maxchainlen)
2879 ui.write(('max chain length : ') + fmt % maxchainlen)
2880 ui.write(('compression ratio : ') + fmt % compratio)
2880 ui.write(('compression ratio : ') + fmt % compratio)
2881
2881
2882 if format > 0:
2882 if format > 0:
2883 ui.write('\n')
2883 ui.write('\n')
2884 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2884 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2885 % tuple(datasize))
2885 % tuple(datasize))
2886 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2886 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2887 % tuple(fullsize))
2887 % tuple(fullsize))
2888 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2888 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2889 % tuple(deltasize))
2889 % tuple(deltasize))
2890
2890
2891 if numdeltas > 0:
2891 if numdeltas > 0:
2892 ui.write('\n')
2892 ui.write('\n')
2893 fmt = pcfmtstr(numdeltas)
2893 fmt = pcfmtstr(numdeltas)
2894 fmt2 = pcfmtstr(numdeltas, 4)
2894 fmt2 = pcfmtstr(numdeltas, 4)
2895 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2895 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2896 if numprev > 0:
2896 if numprev > 0:
2897 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2897 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2898 numprev))
2898 numprev))
2899 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2899 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2900 numprev))
2900 numprev))
2901 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2901 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2902 numprev))
2902 numprev))
2903 if gdelta:
2903 if gdelta:
2904 ui.write(('deltas against p1 : ')
2904 ui.write(('deltas against p1 : ')
2905 + fmt % pcfmt(nump1, numdeltas))
2905 + fmt % pcfmt(nump1, numdeltas))
2906 ui.write(('deltas against p2 : ')
2906 ui.write(('deltas against p2 : ')
2907 + fmt % pcfmt(nump2, numdeltas))
2907 + fmt % pcfmt(nump2, numdeltas))
2908 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2908 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2909 numdeltas))
2909 numdeltas))
2910
2910
2911 @command('debugrevspec',
2911 @command('debugrevspec',
2912 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2912 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2913 ('REVSPEC'))
2913 ('REVSPEC'))
2914 def debugrevspec(ui, repo, expr, **opts):
2914 def debugrevspec(ui, repo, expr, **opts):
2915 """parse and apply a revision specification
2915 """parse and apply a revision specification
2916
2916
2917 Use --verbose to print the parsed tree before and after aliases
2917 Use --verbose to print the parsed tree before and after aliases
2918 expansion.
2918 expansion.
2919 """
2919 """
2920 if ui.verbose:
2920 if ui.verbose:
2921 tree = revset.parse(expr)[0]
2921 tree = revset.parse(expr)[0]
2922 ui.note(revset.prettyformat(tree), "\n")
2922 ui.note(revset.prettyformat(tree), "\n")
2923 newtree = revset.findaliases(ui, tree)
2923 newtree = revset.findaliases(ui, tree)
2924 if newtree != tree:
2924 if newtree != tree:
2925 ui.note(revset.prettyformat(newtree), "\n")
2925 ui.note(revset.prettyformat(newtree), "\n")
2926 tree = newtree
2926 tree = newtree
2927 newtree = revset.foldconcat(tree)
2927 newtree = revset.foldconcat(tree)
2928 if newtree != tree:
2928 if newtree != tree:
2929 ui.note(revset.prettyformat(newtree), "\n")
2929 ui.note(revset.prettyformat(newtree), "\n")
2930 if opts["optimize"]:
2930 if opts["optimize"]:
2931 weight, optimizedtree = revset.optimize(newtree, True)
2931 weight, optimizedtree = revset.optimize(newtree, True)
2932 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2932 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2933 func = revset.match(ui, expr)
2933 func = revset.match(ui, expr)
2934 revs = func(repo)
2934 revs = func(repo)
2935 if ui.verbose:
2935 if ui.verbose:
2936 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2936 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2937 for c in revs:
2937 for c in revs:
2938 ui.write("%s\n" % c)
2938 ui.write("%s\n" % c)
2939
2939
2940 @command('debugsetparents', [], _('REV1 [REV2]'))
2940 @command('debugsetparents', [], _('REV1 [REV2]'))
2941 def debugsetparents(ui, repo, rev1, rev2=None):
2941 def debugsetparents(ui, repo, rev1, rev2=None):
2942 """manually set the parents of the current working directory
2942 """manually set the parents of the current working directory
2943
2943
2944 This is useful for writing repository conversion tools, but should
2944 This is useful for writing repository conversion tools, but should
2945 be used with care. For example, neither the working directory nor the
2945 be used with care. For example, neither the working directory nor the
2946 dirstate is updated, so file status may be incorrect after running this
2946 dirstate is updated, so file status may be incorrect after running this
2947 command.
2947 command.
2948
2948
2949 Returns 0 on success.
2949 Returns 0 on success.
2950 """
2950 """
2951
2951
2952 r1 = scmutil.revsingle(repo, rev1).node()
2952 r1 = scmutil.revsingle(repo, rev1).node()
2953 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2953 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2954
2954
2955 wlock = repo.wlock()
2955 wlock = repo.wlock()
2956 try:
2956 try:
2957 repo.dirstate.beginparentchange()
2957 repo.dirstate.beginparentchange()
2958 repo.setparents(r1, r2)
2958 repo.setparents(r1, r2)
2959 repo.dirstate.endparentchange()
2959 repo.dirstate.endparentchange()
2960 finally:
2960 finally:
2961 wlock.release()
2961 wlock.release()
2962
2962
2963 @command('debugdirstate|debugstate',
2963 @command('debugdirstate|debugstate',
2964 [('', 'nodates', None, _('do not display the saved mtime')),
2964 [('', 'nodates', None, _('do not display the saved mtime')),
2965 ('', 'datesort', None, _('sort by saved mtime'))],
2965 ('', 'datesort', None, _('sort by saved mtime'))],
2966 _('[OPTION]...'))
2966 _('[OPTION]...'))
2967 def debugstate(ui, repo, nodates=None, datesort=None):
2967 def debugstate(ui, repo, nodates=None, datesort=None):
2968 """show the contents of the current dirstate"""
2968 """show the contents of the current dirstate"""
2969 timestr = ""
2969 timestr = ""
2970 if datesort:
2970 if datesort:
2971 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2971 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2972 else:
2972 else:
2973 keyfunc = None # sort by filename
2973 keyfunc = None # sort by filename
2974 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2974 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2975 if ent[3] == -1:
2975 if ent[3] == -1:
2976 timestr = 'unset '
2976 timestr = 'unset '
2977 elif nodates:
2977 elif nodates:
2978 timestr = 'set '
2978 timestr = 'set '
2979 else:
2979 else:
2980 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2980 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2981 time.localtime(ent[3]))
2981 time.localtime(ent[3]))
2982 if ent[1] & 020000:
2982 if ent[1] & 020000:
2983 mode = 'lnk'
2983 mode = 'lnk'
2984 else:
2984 else:
2985 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2985 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2986 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2986 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2987 for f in repo.dirstate.copies():
2987 for f in repo.dirstate.copies():
2988 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2988 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2989
2989
2990 @command('debugsub',
2990 @command('debugsub',
2991 [('r', 'rev', '',
2991 [('r', 'rev', '',
2992 _('revision to check'), _('REV'))],
2992 _('revision to check'), _('REV'))],
2993 _('[-r REV] [REV]'))
2993 _('[-r REV] [REV]'))
2994 def debugsub(ui, repo, rev=None):
2994 def debugsub(ui, repo, rev=None):
2995 ctx = scmutil.revsingle(repo, rev, None)
2995 ctx = scmutil.revsingle(repo, rev, None)
2996 for k, v in sorted(ctx.substate.items()):
2996 for k, v in sorted(ctx.substate.items()):
2997 ui.write(('path %s\n') % k)
2997 ui.write(('path %s\n') % k)
2998 ui.write((' source %s\n') % v[0])
2998 ui.write((' source %s\n') % v[0])
2999 ui.write((' revision %s\n') % v[1])
2999 ui.write((' revision %s\n') % v[1])
3000
3000
3001 @command('debugsuccessorssets',
3001 @command('debugsuccessorssets',
3002 [],
3002 [],
3003 _('[REV]'))
3003 _('[REV]'))
3004 def debugsuccessorssets(ui, repo, *revs):
3004 def debugsuccessorssets(ui, repo, *revs):
3005 """show set of successors for revision
3005 """show set of successors for revision
3006
3006
3007 A successors set of changeset A is a consistent group of revisions that
3007 A successors set of changeset A is a consistent group of revisions that
3008 succeed A. It contains non-obsolete changesets only.
3008 succeed A. It contains non-obsolete changesets only.
3009
3009
3010 In most cases a changeset A has a single successors set containing a single
3010 In most cases a changeset A has a single successors set containing a single
3011 successor (changeset A replaced by A').
3011 successor (changeset A replaced by A').
3012
3012
3013 A changeset that is made obsolete with no successors are called "pruned".
3013 A changeset that is made obsolete with no successors are called "pruned".
3014 Such changesets have no successors sets at all.
3014 Such changesets have no successors sets at all.
3015
3015
3016 A changeset that has been "split" will have a successors set containing
3016 A changeset that has been "split" will have a successors set containing
3017 more than one successor.
3017 more than one successor.
3018
3018
3019 A changeset that has been rewritten in multiple different ways is called
3019 A changeset that has been rewritten in multiple different ways is called
3020 "divergent". Such changesets have multiple successor sets (each of which
3020 "divergent". Such changesets have multiple successor sets (each of which
3021 may also be split, i.e. have multiple successors).
3021 may also be split, i.e. have multiple successors).
3022
3022
3023 Results are displayed as follows::
3023 Results are displayed as follows::
3024
3024
3025 <rev1>
3025 <rev1>
3026 <successors-1A>
3026 <successors-1A>
3027 <rev2>
3027 <rev2>
3028 <successors-2A>
3028 <successors-2A>
3029 <successors-2B1> <successors-2B2> <successors-2B3>
3029 <successors-2B1> <successors-2B2> <successors-2B3>
3030
3030
3031 Here rev2 has two possible (i.e. divergent) successors sets. The first
3031 Here rev2 has two possible (i.e. divergent) successors sets. The first
3032 holds one element, whereas the second holds three (i.e. the changeset has
3032 holds one element, whereas the second holds three (i.e. the changeset has
3033 been split).
3033 been split).
3034 """
3034 """
3035 # passed to successorssets caching computation from one call to another
3035 # passed to successorssets caching computation from one call to another
3036 cache = {}
3036 cache = {}
3037 ctx2str = str
3037 ctx2str = str
3038 node2str = short
3038 node2str = short
3039 if ui.debug():
3039 if ui.debug():
3040 def ctx2str(ctx):
3040 def ctx2str(ctx):
3041 return ctx.hex()
3041 return ctx.hex()
3042 node2str = hex
3042 node2str = hex
3043 for rev in scmutil.revrange(repo, revs):
3043 for rev in scmutil.revrange(repo, revs):
3044 ctx = repo[rev]
3044 ctx = repo[rev]
3045 ui.write('%s\n'% ctx2str(ctx))
3045 ui.write('%s\n'% ctx2str(ctx))
3046 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3046 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3047 if succsset:
3047 if succsset:
3048 ui.write(' ')
3048 ui.write(' ')
3049 ui.write(node2str(succsset[0]))
3049 ui.write(node2str(succsset[0]))
3050 for node in succsset[1:]:
3050 for node in succsset[1:]:
3051 ui.write(' ')
3051 ui.write(' ')
3052 ui.write(node2str(node))
3052 ui.write(node2str(node))
3053 ui.write('\n')
3053 ui.write('\n')
3054
3054
3055 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3055 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3056 def debugwalk(ui, repo, *pats, **opts):
3056 def debugwalk(ui, repo, *pats, **opts):
3057 """show how files match on given patterns"""
3057 """show how files match on given patterns"""
3058 m = scmutil.match(repo[None], pats, opts)
3058 m = scmutil.match(repo[None], pats, opts)
3059 items = list(repo.walk(m))
3059 items = list(repo.walk(m))
3060 if not items:
3060 if not items:
3061 return
3061 return
3062 f = lambda fn: fn
3062 f = lambda fn: fn
3063 if ui.configbool('ui', 'slash') and os.sep != '/':
3063 if ui.configbool('ui', 'slash') and os.sep != '/':
3064 f = lambda fn: util.normpath(fn)
3064 f = lambda fn: util.normpath(fn)
3065 fmt = 'f %%-%ds %%-%ds %%s' % (
3065 fmt = 'f %%-%ds %%-%ds %%s' % (
3066 max([len(abs) for abs in items]),
3066 max([len(abs) for abs in items]),
3067 max([len(m.rel(abs)) for abs in items]))
3067 max([len(m.rel(abs)) for abs in items]))
3068 for abs in items:
3068 for abs in items:
3069 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3069 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3070 ui.write("%s\n" % line.rstrip())
3070 ui.write("%s\n" % line.rstrip())
3071
3071
3072 @command('debugwireargs',
3072 @command('debugwireargs',
3073 [('', 'three', '', 'three'),
3073 [('', 'three', '', 'three'),
3074 ('', 'four', '', 'four'),
3074 ('', 'four', '', 'four'),
3075 ('', 'five', '', 'five'),
3075 ('', 'five', '', 'five'),
3076 ] + remoteopts,
3076 ] + remoteopts,
3077 _('REPO [OPTIONS]... [ONE [TWO]]'),
3077 _('REPO [OPTIONS]... [ONE [TWO]]'),
3078 norepo=True)
3078 norepo=True)
3079 def debugwireargs(ui, repopath, *vals, **opts):
3079 def debugwireargs(ui, repopath, *vals, **opts):
3080 repo = hg.peer(ui, opts, repopath)
3080 repo = hg.peer(ui, opts, repopath)
3081 for opt in remoteopts:
3081 for opt in remoteopts:
3082 del opts[opt[1]]
3082 del opts[opt[1]]
3083 args = {}
3083 args = {}
3084 for k, v in opts.iteritems():
3084 for k, v in opts.iteritems():
3085 if v:
3085 if v:
3086 args[k] = v
3086 args[k] = v
3087 # run twice to check that we don't mess up the stream for the next command
3087 # run twice to check that we don't mess up the stream for the next command
3088 res1 = repo.debugwireargs(*vals, **args)
3088 res1 = repo.debugwireargs(*vals, **args)
3089 res2 = repo.debugwireargs(*vals, **args)
3089 res2 = repo.debugwireargs(*vals, **args)
3090 ui.write("%s\n" % res1)
3090 ui.write("%s\n" % res1)
3091 if res1 != res2:
3091 if res1 != res2:
3092 ui.warn("%s\n" % res2)
3092 ui.warn("%s\n" % res2)
3093
3093
3094 @command('^diff',
3094 @command('^diff',
3095 [('r', 'rev', [], _('revision'), _('REV')),
3095 [('r', 'rev', [], _('revision'), _('REV')),
3096 ('c', 'change', '', _('change made by revision'), _('REV'))
3096 ('c', 'change', '', _('change made by revision'), _('REV'))
3097 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3097 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3098 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3098 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3099 inferrepo=True)
3099 inferrepo=True)
3100 def diff(ui, repo, *pats, **opts):
3100 def diff(ui, repo, *pats, **opts):
3101 """diff repository (or selected files)
3101 """diff repository (or selected files)
3102
3102
3103 Show differences between revisions for the specified files.
3103 Show differences between revisions for the specified files.
3104
3104
3105 Differences between files are shown using the unified diff format.
3105 Differences between files are shown using the unified diff format.
3106
3106
3107 .. note::
3107 .. note::
3108
3108
3109 diff may generate unexpected results for merges, as it will
3109 diff may generate unexpected results for merges, as it will
3110 default to comparing against the working directory's first
3110 default to comparing against the working directory's first
3111 parent changeset if no revisions are specified.
3111 parent changeset if no revisions are specified.
3112
3112
3113 When two revision arguments are given, then changes are shown
3113 When two revision arguments are given, then changes are shown
3114 between those revisions. If only one revision is specified then
3114 between those revisions. If only one revision is specified then
3115 that revision is compared to the working directory, and, when no
3115 that revision is compared to the working directory, and, when no
3116 revisions are specified, the working directory files are compared
3116 revisions are specified, the working directory files are compared
3117 to its parent.
3117 to its parent.
3118
3118
3119 Alternatively you can specify -c/--change with a revision to see
3119 Alternatively you can specify -c/--change with a revision to see
3120 the changes in that changeset relative to its first parent.
3120 the changes in that changeset relative to its first parent.
3121
3121
3122 Without the -a/--text option, diff will avoid generating diffs of
3122 Without the -a/--text option, diff will avoid generating diffs of
3123 files it detects as binary. With -a, diff will generate a diff
3123 files it detects as binary. With -a, diff will generate a diff
3124 anyway, probably with undesirable results.
3124 anyway, probably with undesirable results.
3125
3125
3126 Use the -g/--git option to generate diffs in the git extended diff
3126 Use the -g/--git option to generate diffs in the git extended diff
3127 format. For more information, read :hg:`help diffs`.
3127 format. For more information, read :hg:`help diffs`.
3128
3128
3129 .. container:: verbose
3129 .. container:: verbose
3130
3130
3131 Examples:
3131 Examples:
3132
3132
3133 - compare a file in the current working directory to its parent::
3133 - compare a file in the current working directory to its parent::
3134
3134
3135 hg diff foo.c
3135 hg diff foo.c
3136
3136
3137 - compare two historical versions of a directory, with rename info::
3137 - compare two historical versions of a directory, with rename info::
3138
3138
3139 hg diff --git -r 1.0:1.2 lib/
3139 hg diff --git -r 1.0:1.2 lib/
3140
3140
3141 - get change stats relative to the last change on some date::
3141 - get change stats relative to the last change on some date::
3142
3142
3143 hg diff --stat -r "date('may 2')"
3143 hg diff --stat -r "date('may 2')"
3144
3144
3145 - diff all newly-added files that contain a keyword::
3145 - diff all newly-added files that contain a keyword::
3146
3146
3147 hg diff "set:added() and grep(GNU)"
3147 hg diff "set:added() and grep(GNU)"
3148
3148
3149 - compare a revision and its parents::
3149 - compare a revision and its parents::
3150
3150
3151 hg diff -c 9353 # compare against first parent
3151 hg diff -c 9353 # compare against first parent
3152 hg diff -r 9353^:9353 # same using revset syntax
3152 hg diff -r 9353^:9353 # same using revset syntax
3153 hg diff -r 9353^2:9353 # compare against the second parent
3153 hg diff -r 9353^2:9353 # compare against the second parent
3154
3154
3155 Returns 0 on success.
3155 Returns 0 on success.
3156 """
3156 """
3157
3157
3158 revs = opts.get('rev')
3158 revs = opts.get('rev')
3159 change = opts.get('change')
3159 change = opts.get('change')
3160 stat = opts.get('stat')
3160 stat = opts.get('stat')
3161 reverse = opts.get('reverse')
3161 reverse = opts.get('reverse')
3162
3162
3163 if revs and change:
3163 if revs and change:
3164 msg = _('cannot specify --rev and --change at the same time')
3164 msg = _('cannot specify --rev and --change at the same time')
3165 raise util.Abort(msg)
3165 raise util.Abort(msg)
3166 elif change:
3166 elif change:
3167 node2 = scmutil.revsingle(repo, change, None).node()
3167 node2 = scmutil.revsingle(repo, change, None).node()
3168 node1 = repo[node2].p1().node()
3168 node1 = repo[node2].p1().node()
3169 else:
3169 else:
3170 node1, node2 = scmutil.revpair(repo, revs)
3170 node1, node2 = scmutil.revpair(repo, revs)
3171
3171
3172 if reverse:
3172 if reverse:
3173 node1, node2 = node2, node1
3173 node1, node2 = node2, node1
3174
3174
3175 diffopts = patch.diffallopts(ui, opts)
3175 diffopts = patch.diffallopts(ui, opts)
3176 m = scmutil.match(repo[node2], pats, opts)
3176 m = scmutil.match(repo[node2], pats, opts)
3177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3178 listsubrepos=opts.get('subrepos'),
3178 listsubrepos=opts.get('subrepos'),
3179 root=opts.get('root'))
3179 root=opts.get('root'))
3180
3180
3181 @command('^export',
3181 @command('^export',
3182 [('o', 'output', '',
3182 [('o', 'output', '',
3183 _('print output to file with formatted name'), _('FORMAT')),
3183 _('print output to file with formatted name'), _('FORMAT')),
3184 ('', 'switch-parent', None, _('diff against the second parent')),
3184 ('', 'switch-parent', None, _('diff against the second parent')),
3185 ('r', 'rev', [], _('revisions to export'), _('REV')),
3185 ('r', 'rev', [], _('revisions to export'), _('REV')),
3186 ] + diffopts,
3186 ] + diffopts,
3187 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3187 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3188 def export(ui, repo, *changesets, **opts):
3188 def export(ui, repo, *changesets, **opts):
3189 """dump the header and diffs for one or more changesets
3189 """dump the header and diffs for one or more changesets
3190
3190
3191 Print the changeset header and diffs for one or more revisions.
3191 Print the changeset header and diffs for one or more revisions.
3192 If no revision is given, the parent of the working directory is used.
3192 If no revision is given, the parent of the working directory is used.
3193
3193
3194 The information shown in the changeset header is: author, date,
3194 The information shown in the changeset header is: author, date,
3195 branch name (if non-default), changeset hash, parent(s) and commit
3195 branch name (if non-default), changeset hash, parent(s) and commit
3196 comment.
3196 comment.
3197
3197
3198 .. note::
3198 .. note::
3199
3199
3200 export may generate unexpected diff output for merge
3200 export may generate unexpected diff output for merge
3201 changesets, as it will compare the merge changeset against its
3201 changesets, as it will compare the merge changeset against its
3202 first parent only.
3202 first parent only.
3203
3203
3204 Output may be to a file, in which case the name of the file is
3204 Output may be to a file, in which case the name of the file is
3205 given using a format string. The formatting rules are as follows:
3205 given using a format string. The formatting rules are as follows:
3206
3206
3207 :``%%``: literal "%" character
3207 :``%%``: literal "%" character
3208 :``%H``: changeset hash (40 hexadecimal digits)
3208 :``%H``: changeset hash (40 hexadecimal digits)
3209 :``%N``: number of patches being generated
3209 :``%N``: number of patches being generated
3210 :``%R``: changeset revision number
3210 :``%R``: changeset revision number
3211 :``%b``: basename of the exporting repository
3211 :``%b``: basename of the exporting repository
3212 :``%h``: short-form changeset hash (12 hexadecimal digits)
3212 :``%h``: short-form changeset hash (12 hexadecimal digits)
3213 :``%m``: first line of the commit message (only alphanumeric characters)
3213 :``%m``: first line of the commit message (only alphanumeric characters)
3214 :``%n``: zero-padded sequence number, starting at 1
3214 :``%n``: zero-padded sequence number, starting at 1
3215 :``%r``: zero-padded changeset revision number
3215 :``%r``: zero-padded changeset revision number
3216
3216
3217 Without the -a/--text option, export will avoid generating diffs
3217 Without the -a/--text option, export will avoid generating diffs
3218 of files it detects as binary. With -a, export will generate a
3218 of files it detects as binary. With -a, export will generate a
3219 diff anyway, probably with undesirable results.
3219 diff anyway, probably with undesirable results.
3220
3220
3221 Use the -g/--git option to generate diffs in the git extended diff
3221 Use the -g/--git option to generate diffs in the git extended diff
3222 format. See :hg:`help diffs` for more information.
3222 format. See :hg:`help diffs` for more information.
3223
3223
3224 With the --switch-parent option, the diff will be against the
3224 With the --switch-parent option, the diff will be against the
3225 second parent. It can be useful to review a merge.
3225 second parent. It can be useful to review a merge.
3226
3226
3227 .. container:: verbose
3227 .. container:: verbose
3228
3228
3229 Examples:
3229 Examples:
3230
3230
3231 - use export and import to transplant a bugfix to the current
3231 - use export and import to transplant a bugfix to the current
3232 branch::
3232 branch::
3233
3233
3234 hg export -r 9353 | hg import -
3234 hg export -r 9353 | hg import -
3235
3235
3236 - export all the changesets between two revisions to a file with
3236 - export all the changesets between two revisions to a file with
3237 rename information::
3237 rename information::
3238
3238
3239 hg export --git -r 123:150 > changes.txt
3239 hg export --git -r 123:150 > changes.txt
3240
3240
3241 - split outgoing changes into a series of patches with
3241 - split outgoing changes into a series of patches with
3242 descriptive names::
3242 descriptive names::
3243
3243
3244 hg export -r "outgoing()" -o "%n-%m.patch"
3244 hg export -r "outgoing()" -o "%n-%m.patch"
3245
3245
3246 Returns 0 on success.
3246 Returns 0 on success.
3247 """
3247 """
3248 changesets += tuple(opts.get('rev', []))
3248 changesets += tuple(opts.get('rev', []))
3249 if not changesets:
3249 if not changesets:
3250 changesets = ['.']
3250 changesets = ['.']
3251 revs = scmutil.revrange(repo, changesets)
3251 revs = scmutil.revrange(repo, changesets)
3252 if not revs:
3252 if not revs:
3253 raise util.Abort(_("export requires at least one changeset"))
3253 raise util.Abort(_("export requires at least one changeset"))
3254 if len(revs) > 1:
3254 if len(revs) > 1:
3255 ui.note(_('exporting patches:\n'))
3255 ui.note(_('exporting patches:\n'))
3256 else:
3256 else:
3257 ui.note(_('exporting patch:\n'))
3257 ui.note(_('exporting patch:\n'))
3258 cmdutil.export(repo, revs, template=opts.get('output'),
3258 cmdutil.export(repo, revs, template=opts.get('output'),
3259 switch_parent=opts.get('switch_parent'),
3259 switch_parent=opts.get('switch_parent'),
3260 opts=patch.diffallopts(ui, opts))
3260 opts=patch.diffallopts(ui, opts))
3261
3261
3262 @command('files',
3262 @command('files',
3263 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3263 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3265 ] + walkopts + formatteropts + subrepoopts,
3265 ] + walkopts + formatteropts + subrepoopts,
3266 _('[OPTION]... [PATTERN]...'))
3266 _('[OPTION]... [PATTERN]...'))
3267 def files(ui, repo, *pats, **opts):
3267 def files(ui, repo, *pats, **opts):
3268 """list tracked files
3268 """list tracked files
3269
3269
3270 Print files under Mercurial control in the working directory or
3270 Print files under Mercurial control in the working directory or
3271 specified revision whose names match the given patterns (excluding
3271 specified revision whose names match the given patterns (excluding
3272 removed files).
3272 removed files).
3273
3273
3274 If no patterns are given to match, this command prints the names
3274 If no patterns are given to match, this command prints the names
3275 of all files under Mercurial control in the working directory.
3275 of all files under Mercurial control in the working directory.
3276
3276
3277 .. container:: verbose
3277 .. container:: verbose
3278
3278
3279 Examples:
3279 Examples:
3280
3280
3281 - list all files under the current directory::
3281 - list all files under the current directory::
3282
3282
3283 hg files .
3283 hg files .
3284
3284
3285 - shows sizes and flags for current revision::
3285 - shows sizes and flags for current revision::
3286
3286
3287 hg files -vr .
3287 hg files -vr .
3288
3288
3289 - list all files named README::
3289 - list all files named README::
3290
3290
3291 hg files -I "**/README"
3291 hg files -I "**/README"
3292
3292
3293 - list all binary files::
3293 - list all binary files::
3294
3294
3295 hg files "set:binary()"
3295 hg files "set:binary()"
3296
3296
3297 - find files containing a regular expression::
3297 - find files containing a regular expression::
3298
3298
3299 hg files "set:grep('bob')"
3299 hg files "set:grep('bob')"
3300
3300
3301 - search tracked file contents with xargs and grep::
3301 - search tracked file contents with xargs and grep::
3302
3302
3303 hg files -0 | xargs -0 grep foo
3303 hg files -0 | xargs -0 grep foo
3304
3304
3305 See :hg:`help patterns` and :hg:`help filesets` for more information
3305 See :hg:`help patterns` and :hg:`help filesets` for more information
3306 on specifying file patterns.
3306 on specifying file patterns.
3307
3307
3308 Returns 0 if a match is found, 1 otherwise.
3308 Returns 0 if a match is found, 1 otherwise.
3309
3309
3310 """
3310 """
3311 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3311 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3312
3312
3313 end = '\n'
3313 end = '\n'
3314 if opts.get('print0'):
3314 if opts.get('print0'):
3315 end = '\0'
3315 end = '\0'
3316 fm = ui.formatter('files', opts)
3316 fm = ui.formatter('files', opts)
3317 fmt = '%s' + end
3317 fmt = '%s' + end
3318
3318
3319 m = scmutil.match(ctx, pats, opts)
3319 m = scmutil.match(ctx, pats, opts)
3320 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3320 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3321
3321
3322 fm.end()
3322 fm.end()
3323
3323
3324 return ret
3324 return ret
3325
3325
3326 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3326 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3327 def forget(ui, repo, *pats, **opts):
3327 def forget(ui, repo, *pats, **opts):
3328 """forget the specified files on the next commit
3328 """forget the specified files on the next commit
3329
3329
3330 Mark the specified files so they will no longer be tracked
3330 Mark the specified files so they will no longer be tracked
3331 after the next commit.
3331 after the next commit.
3332
3332
3333 This only removes files from the current branch, not from the
3333 This only removes files from the current branch, not from the
3334 entire project history, and it does not delete them from the
3334 entire project history, and it does not delete them from the
3335 working directory.
3335 working directory.
3336
3336
3337 To undo a forget before the next commit, see :hg:`add`.
3337 To undo a forget before the next commit, see :hg:`add`.
3338
3338
3339 .. container:: verbose
3339 .. container:: verbose
3340
3340
3341 Examples:
3341 Examples:
3342
3342
3343 - forget newly-added binary files::
3343 - forget newly-added binary files::
3344
3344
3345 hg forget "set:added() and binary()"
3345 hg forget "set:added() and binary()"
3346
3346
3347 - forget files that would be excluded by .hgignore::
3347 - forget files that would be excluded by .hgignore::
3348
3348
3349 hg forget "set:hgignore()"
3349 hg forget "set:hgignore()"
3350
3350
3351 Returns 0 on success.
3351 Returns 0 on success.
3352 """
3352 """
3353
3353
3354 if not pats:
3354 if not pats:
3355 raise util.Abort(_('no files specified'))
3355 raise util.Abort(_('no files specified'))
3356
3356
3357 m = scmutil.match(repo[None], pats, opts)
3357 m = scmutil.match(repo[None], pats, opts)
3358 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3358 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3359 return rejected and 1 or 0
3359 return rejected and 1 or 0
3360
3360
3361 @command(
3361 @command(
3362 'graft',
3362 'graft',
3363 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3363 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3364 ('c', 'continue', False, _('resume interrupted graft')),
3364 ('c', 'continue', False, _('resume interrupted graft')),
3365 ('e', 'edit', False, _('invoke editor on commit messages')),
3365 ('e', 'edit', False, _('invoke editor on commit messages')),
3366 ('', 'log', None, _('append graft info to log message')),
3366 ('', 'log', None, _('append graft info to log message')),
3367 ('f', 'force', False, _('force graft')),
3367 ('f', 'force', False, _('force graft')),
3368 ('D', 'currentdate', False,
3368 ('D', 'currentdate', False,
3369 _('record the current date as commit date')),
3369 _('record the current date as commit date')),
3370 ('U', 'currentuser', False,
3370 ('U', 'currentuser', False,
3371 _('record the current user as committer'), _('DATE'))]
3371 _('record the current user as committer'), _('DATE'))]
3372 + commitopts2 + mergetoolopts + dryrunopts,
3372 + commitopts2 + mergetoolopts + dryrunopts,
3373 _('[OPTION]... [-r] REV...'))
3373 _('[OPTION]... [-r] REV...'))
3374 def graft(ui, repo, *revs, **opts):
3374 def graft(ui, repo, *revs, **opts):
3375 '''copy changes from other branches onto the current branch
3375 '''copy changes from other branches onto the current branch
3376
3376
3377 This command uses Mercurial's merge logic to copy individual
3377 This command uses Mercurial's merge logic to copy individual
3378 changes from other branches without merging branches in the
3378 changes from other branches without merging branches in the
3379 history graph. This is sometimes known as 'backporting' or
3379 history graph. This is sometimes known as 'backporting' or
3380 'cherry-picking'. By default, graft will copy user, date, and
3380 'cherry-picking'. By default, graft will copy user, date, and
3381 description from the source changesets.
3381 description from the source changesets.
3382
3382
3383 Changesets that are ancestors of the current revision, that have
3383 Changesets that are ancestors of the current revision, that have
3384 already been grafted, or that are merges will be skipped.
3384 already been grafted, or that are merges will be skipped.
3385
3385
3386 If --log is specified, log messages will have a comment appended
3386 If --log is specified, log messages will have a comment appended
3387 of the form::
3387 of the form::
3388
3388
3389 (grafted from CHANGESETHASH)
3389 (grafted from CHANGESETHASH)
3390
3390
3391 If --force is specified, revisions will be grafted even if they
3391 If --force is specified, revisions will be grafted even if they
3392 are already ancestors of or have been grafted to the destination.
3392 are already ancestors of or have been grafted to the destination.
3393 This is useful when the revisions have since been backed out.
3393 This is useful when the revisions have since been backed out.
3394
3394
3395 If a graft merge results in conflicts, the graft process is
3395 If a graft merge results in conflicts, the graft process is
3396 interrupted so that the current merge can be manually resolved.
3396 interrupted so that the current merge can be manually resolved.
3397 Once all conflicts are addressed, the graft process can be
3397 Once all conflicts are addressed, the graft process can be
3398 continued with the -c/--continue option.
3398 continued with the -c/--continue option.
3399
3399
3400 .. note::
3400 .. note::
3401
3401
3402 The -c/--continue option does not reapply earlier options, except
3402 The -c/--continue option does not reapply earlier options, except
3403 for --force.
3403 for --force.
3404
3404
3405 .. container:: verbose
3405 .. container:: verbose
3406
3406
3407 Examples:
3407 Examples:
3408
3408
3409 - copy a single change to the stable branch and edit its description::
3409 - copy a single change to the stable branch and edit its description::
3410
3410
3411 hg update stable
3411 hg update stable
3412 hg graft --edit 9393
3412 hg graft --edit 9393
3413
3413
3414 - graft a range of changesets with one exception, updating dates::
3414 - graft a range of changesets with one exception, updating dates::
3415
3415
3416 hg graft -D "2085::2093 and not 2091"
3416 hg graft -D "2085::2093 and not 2091"
3417
3417
3418 - continue a graft after resolving conflicts::
3418 - continue a graft after resolving conflicts::
3419
3419
3420 hg graft -c
3420 hg graft -c
3421
3421
3422 - show the source of a grafted changeset::
3422 - show the source of a grafted changeset::
3423
3423
3424 hg log --debug -r .
3424 hg log --debug -r .
3425
3425
3426 See :hg:`help revisions` and :hg:`help revsets` for more about
3426 See :hg:`help revisions` and :hg:`help revsets` for more about
3427 specifying revisions.
3427 specifying revisions.
3428
3428
3429 Returns 0 on successful completion.
3429 Returns 0 on successful completion.
3430 '''
3430 '''
3431
3431
3432 revs = list(revs)
3432 revs = list(revs)
3433 revs.extend(opts['rev'])
3433 revs.extend(opts['rev'])
3434
3434
3435 if not opts.get('user') and opts.get('currentuser'):
3435 if not opts.get('user') and opts.get('currentuser'):
3436 opts['user'] = ui.username()
3436 opts['user'] = ui.username()
3437 if not opts.get('date') and opts.get('currentdate'):
3437 if not opts.get('date') and opts.get('currentdate'):
3438 opts['date'] = "%d %d" % util.makedate()
3438 opts['date'] = "%d %d" % util.makedate()
3439
3439
3440 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3440 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3441
3441
3442 cont = False
3442 cont = False
3443 if opts['continue']:
3443 if opts['continue']:
3444 cont = True
3444 cont = True
3445 if revs:
3445 if revs:
3446 raise util.Abort(_("can't specify --continue and revisions"))
3446 raise util.Abort(_("can't specify --continue and revisions"))
3447 # read in unfinished revisions
3447 # read in unfinished revisions
3448 try:
3448 try:
3449 nodes = repo.vfs.read('graftstate').splitlines()
3449 nodes = repo.vfs.read('graftstate').splitlines()
3450 revs = [repo[node].rev() for node in nodes]
3450 revs = [repo[node].rev() for node in nodes]
3451 except IOError, inst:
3451 except IOError, inst:
3452 if inst.errno != errno.ENOENT:
3452 if inst.errno != errno.ENOENT:
3453 raise
3453 raise
3454 raise util.Abort(_("no graft state found, can't continue"))
3454 raise util.Abort(_("no graft state found, can't continue"))
3455 else:
3455 else:
3456 cmdutil.checkunfinished(repo)
3456 cmdutil.checkunfinished(repo)
3457 cmdutil.bailifchanged(repo)
3457 cmdutil.bailifchanged(repo)
3458 if not revs:
3458 if not revs:
3459 raise util.Abort(_('no revisions specified'))
3459 raise util.Abort(_('no revisions specified'))
3460 revs = scmutil.revrange(repo, revs)
3460 revs = scmutil.revrange(repo, revs)
3461
3461
3462 skipped = set()
3462 skipped = set()
3463 # check for merges
3463 # check for merges
3464 for rev in repo.revs('%ld and merge()', revs):
3464 for rev in repo.revs('%ld and merge()', revs):
3465 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3465 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3466 skipped.add(rev)
3466 skipped.add(rev)
3467 revs = [r for r in revs if r not in skipped]
3467 revs = [r for r in revs if r not in skipped]
3468 if not revs:
3468 if not revs:
3469 return -1
3469 return -1
3470
3470
3471 # Don't check in the --continue case, in effect retaining --force across
3471 # Don't check in the --continue case, in effect retaining --force across
3472 # --continues. That's because without --force, any revisions we decided to
3472 # --continues. That's because without --force, any revisions we decided to
3473 # skip would have been filtered out here, so they wouldn't have made their
3473 # skip would have been filtered out here, so they wouldn't have made their
3474 # way to the graftstate. With --force, any revisions we would have otherwise
3474 # way to the graftstate. With --force, any revisions we would have otherwise
3475 # skipped would not have been filtered out, and if they hadn't been applied
3475 # skipped would not have been filtered out, and if they hadn't been applied
3476 # already, they'd have been in the graftstate.
3476 # already, they'd have been in the graftstate.
3477 if not (cont or opts.get('force')):
3477 if not (cont or opts.get('force')):
3478 # check for ancestors of dest branch
3478 # check for ancestors of dest branch
3479 crev = repo['.'].rev()
3479 crev = repo['.'].rev()
3480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3481 # Cannot use x.remove(y) on smart set, this has to be a list.
3481 # Cannot use x.remove(y) on smart set, this has to be a list.
3482 # XXX make this lazy in the future
3482 # XXX make this lazy in the future
3483 revs = list(revs)
3483 revs = list(revs)
3484 # don't mutate while iterating, create a copy
3484 # don't mutate while iterating, create a copy
3485 for rev in list(revs):
3485 for rev in list(revs):
3486 if rev in ancestors:
3486 if rev in ancestors:
3487 ui.warn(_('skipping ancestor revision %d:%s\n') %
3487 ui.warn(_('skipping ancestor revision %d:%s\n') %
3488 (rev, repo[rev]))
3488 (rev, repo[rev]))
3489 # XXX remove on list is slow
3489 # XXX remove on list is slow
3490 revs.remove(rev)
3490 revs.remove(rev)
3491 if not revs:
3491 if not revs:
3492 return -1
3492 return -1
3493
3493
3494 # analyze revs for earlier grafts
3494 # analyze revs for earlier grafts
3495 ids = {}
3495 ids = {}
3496 for ctx in repo.set("%ld", revs):
3496 for ctx in repo.set("%ld", revs):
3497 ids[ctx.hex()] = ctx.rev()
3497 ids[ctx.hex()] = ctx.rev()
3498 n = ctx.extra().get('source')
3498 n = ctx.extra().get('source')
3499 if n:
3499 if n:
3500 ids[n] = ctx.rev()
3500 ids[n] = ctx.rev()
3501
3501
3502 # check ancestors for earlier grafts
3502 # check ancestors for earlier grafts
3503 ui.debug('scanning for duplicate grafts\n')
3503 ui.debug('scanning for duplicate grafts\n')
3504
3504
3505 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3505 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3506 ctx = repo[rev]
3506 ctx = repo[rev]
3507 n = ctx.extra().get('source')
3507 n = ctx.extra().get('source')
3508 if n in ids:
3508 if n in ids:
3509 try:
3509 try:
3510 r = repo[n].rev()
3510 r = repo[n].rev()
3511 except error.RepoLookupError:
3511 except error.RepoLookupError:
3512 r = None
3512 r = None
3513 if r in revs:
3513 if r in revs:
3514 ui.warn(_('skipping revision %d:%s '
3514 ui.warn(_('skipping revision %d:%s '
3515 '(already grafted to %d:%s)\n')
3515 '(already grafted to %d:%s)\n')
3516 % (r, repo[r], rev, ctx))
3516 % (r, repo[r], rev, ctx))
3517 revs.remove(r)
3517 revs.remove(r)
3518 elif ids[n] in revs:
3518 elif ids[n] in revs:
3519 if r is None:
3519 if r is None:
3520 ui.warn(_('skipping already grafted revision %d:%s '
3520 ui.warn(_('skipping already grafted revision %d:%s '
3521 '(%d:%s also has unknown origin %s)\n')
3521 '(%d:%s also has unknown origin %s)\n')
3522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3523 else:
3523 else:
3524 ui.warn(_('skipping already grafted revision %d:%s '
3524 ui.warn(_('skipping already grafted revision %d:%s '
3525 '(%d:%s also has origin %d:%s)\n')
3525 '(%d:%s also has origin %d:%s)\n')
3526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3527 revs.remove(ids[n])
3527 revs.remove(ids[n])
3528 elif ctx.hex() in ids:
3528 elif ctx.hex() in ids:
3529 r = ids[ctx.hex()]
3529 r = ids[ctx.hex()]
3530 ui.warn(_('skipping already grafted revision %d:%s '
3530 ui.warn(_('skipping already grafted revision %d:%s '
3531 '(was grafted from %d:%s)\n') %
3531 '(was grafted from %d:%s)\n') %
3532 (r, repo[r], rev, ctx))
3532 (r, repo[r], rev, ctx))
3533 revs.remove(r)
3533 revs.remove(r)
3534 if not revs:
3534 if not revs:
3535 return -1
3535 return -1
3536
3536
3537 wlock = repo.wlock()
3537 wlock = repo.wlock()
3538 try:
3538 try:
3539 for pos, ctx in enumerate(repo.set("%ld", revs)):
3539 for pos, ctx in enumerate(repo.set("%ld", revs)):
3540 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3540 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3541 ctx.description().split('\n', 1)[0])
3541 ctx.description().split('\n', 1)[0])
3542 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3542 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3543 if names:
3543 if names:
3544 desc += ' (%s)' % ' '.join(names)
3544 desc += ' (%s)' % ' '.join(names)
3545 ui.status(_('grafting %s\n') % desc)
3545 ui.status(_('grafting %s\n') % desc)
3546 if opts.get('dry_run'):
3546 if opts.get('dry_run'):
3547 continue
3547 continue
3548
3548
3549 source = ctx.extra().get('source')
3549 source = ctx.extra().get('source')
3550 extra = {}
3550 extra = {}
3551 if source:
3551 if source:
3552 extra['source'] = source
3552 extra['source'] = source
3553 extra['intermediate-source'] = ctx.hex()
3553 extra['intermediate-source'] = ctx.hex()
3554 else:
3554 else:
3555 extra['source'] = ctx.hex()
3555 extra['source'] = ctx.hex()
3556 user = ctx.user()
3556 user = ctx.user()
3557 if opts.get('user'):
3557 if opts.get('user'):
3558 user = opts['user']
3558 user = opts['user']
3559 date = ctx.date()
3559 date = ctx.date()
3560 if opts.get('date'):
3560 if opts.get('date'):
3561 date = opts['date']
3561 date = opts['date']
3562 message = ctx.description()
3562 message = ctx.description()
3563 if opts.get('log'):
3563 if opts.get('log'):
3564 message += '\n(grafted from %s)' % ctx.hex()
3564 message += '\n(grafted from %s)' % ctx.hex()
3565
3565
3566 # we don't merge the first commit when continuing
3566 # we don't merge the first commit when continuing
3567 if not cont:
3567 if not cont:
3568 # perform the graft merge with p1(rev) as 'ancestor'
3568 # perform the graft merge with p1(rev) as 'ancestor'
3569 try:
3569 try:
3570 # ui.forcemerge is an internal variable, do not document
3570 # ui.forcemerge is an internal variable, do not document
3571 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3571 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3572 'graft')
3572 'graft')
3573 stats = mergemod.graft(repo, ctx, ctx.p1(),
3573 stats = mergemod.graft(repo, ctx, ctx.p1(),
3574 ['local', 'graft'])
3574 ['local', 'graft'])
3575 finally:
3575 finally:
3576 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3576 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3577 # report any conflicts
3577 # report any conflicts
3578 if stats and stats[3] > 0:
3578 if stats and stats[3] > 0:
3579 # write out state for --continue
3579 # write out state for --continue
3580 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3580 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3581 repo.vfs.write('graftstate', ''.join(nodelines))
3581 repo.vfs.write('graftstate', ''.join(nodelines))
3582 raise util.Abort(
3582 raise util.Abort(
3583 _("unresolved conflicts, can't continue"),
3583 _("unresolved conflicts, can't continue"),
3584 hint=_('use hg resolve and hg graft --continue'))
3584 hint=_('use hg resolve and hg graft --continue'))
3585 else:
3585 else:
3586 cont = False
3586 cont = False
3587
3587
3588 # commit
3588 # commit
3589 node = repo.commit(text=message, user=user,
3589 node = repo.commit(text=message, user=user,
3590 date=date, extra=extra, editor=editor)
3590 date=date, extra=extra, editor=editor)
3591 if node is None:
3591 if node is None:
3592 ui.warn(
3592 ui.warn(
3593 _('note: graft of %d:%s created no changes to commit\n') %
3593 _('note: graft of %d:%s created no changes to commit\n') %
3594 (ctx.rev(), ctx))
3594 (ctx.rev(), ctx))
3595 finally:
3595 finally:
3596 wlock.release()
3596 wlock.release()
3597
3597
3598 # remove state when we complete successfully
3598 # remove state when we complete successfully
3599 if not opts.get('dry_run'):
3599 if not opts.get('dry_run'):
3600 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3600 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3601
3601
3602 return 0
3602 return 0
3603
3603
3604 @command('grep',
3604 @command('grep',
3605 [('0', 'print0', None, _('end fields with NUL')),
3605 [('0', 'print0', None, _('end fields with NUL')),
3606 ('', 'all', None, _('print all revisions that match')),
3606 ('', 'all', None, _('print all revisions that match')),
3607 ('a', 'text', None, _('treat all files as text')),
3607 ('a', 'text', None, _('treat all files as text')),
3608 ('f', 'follow', None,
3608 ('f', 'follow', None,
3609 _('follow changeset history,'
3609 _('follow changeset history,'
3610 ' or file history across copies and renames')),
3610 ' or file history across copies and renames')),
3611 ('i', 'ignore-case', None, _('ignore case when matching')),
3611 ('i', 'ignore-case', None, _('ignore case when matching')),
3612 ('l', 'files-with-matches', None,
3612 ('l', 'files-with-matches', None,
3613 _('print only filenames and revisions that match')),
3613 _('print only filenames and revisions that match')),
3614 ('n', 'line-number', None, _('print matching line numbers')),
3614 ('n', 'line-number', None, _('print matching line numbers')),
3615 ('r', 'rev', [],
3615 ('r', 'rev', [],
3616 _('only search files changed within revision range'), _('REV')),
3616 _('only search files changed within revision range'), _('REV')),
3617 ('u', 'user', None, _('list the author (long with -v)')),
3617 ('u', 'user', None, _('list the author (long with -v)')),
3618 ('d', 'date', None, _('list the date (short with -q)')),
3618 ('d', 'date', None, _('list the date (short with -q)')),
3619 ] + walkopts,
3619 ] + walkopts,
3620 _('[OPTION]... PATTERN [FILE]...'),
3620 _('[OPTION]... PATTERN [FILE]...'),
3621 inferrepo=True)
3621 inferrepo=True)
3622 def grep(ui, repo, pattern, *pats, **opts):
3622 def grep(ui, repo, pattern, *pats, **opts):
3623 """search for a pattern in specified files and revisions
3623 """search for a pattern in specified files and revisions
3624
3624
3625 Search revisions of files for a regular expression.
3625 Search revisions of files for a regular expression.
3626
3626
3627 This command behaves differently than Unix grep. It only accepts
3627 This command behaves differently than Unix grep. It only accepts
3628 Python/Perl regexps. It searches repository history, not the
3628 Python/Perl regexps. It searches repository history, not the
3629 working directory. It always prints the revision number in which a
3629 working directory. It always prints the revision number in which a
3630 match appears.
3630 match appears.
3631
3631
3632 By default, grep only prints output for the first revision of a
3632 By default, grep only prints output for the first revision of a
3633 file in which it finds a match. To get it to print every revision
3633 file in which it finds a match. To get it to print every revision
3634 that contains a change in match status ("-" for a match that
3634 that contains a change in match status ("-" for a match that
3635 becomes a non-match, or "+" for a non-match that becomes a match),
3635 becomes a non-match, or "+" for a non-match that becomes a match),
3636 use the --all flag.
3636 use the --all flag.
3637
3637
3638 Returns 0 if a match is found, 1 otherwise.
3638 Returns 0 if a match is found, 1 otherwise.
3639 """
3639 """
3640 reflags = re.M
3640 reflags = re.M
3641 if opts.get('ignore_case'):
3641 if opts.get('ignore_case'):
3642 reflags |= re.I
3642 reflags |= re.I
3643 try:
3643 try:
3644 regexp = util.re.compile(pattern, reflags)
3644 regexp = util.re.compile(pattern, reflags)
3645 except re.error, inst:
3645 except re.error, inst:
3646 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3646 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3647 return 1
3647 return 1
3648 sep, eol = ':', '\n'
3648 sep, eol = ':', '\n'
3649 if opts.get('print0'):
3649 if opts.get('print0'):
3650 sep = eol = '\0'
3650 sep = eol = '\0'
3651
3651
3652 getfile = util.lrucachefunc(repo.file)
3652 getfile = util.lrucachefunc(repo.file)
3653
3653
3654 def matchlines(body):
3654 def matchlines(body):
3655 begin = 0
3655 begin = 0
3656 linenum = 0
3656 linenum = 0
3657 while begin < len(body):
3657 while begin < len(body):
3658 match = regexp.search(body, begin)
3658 match = regexp.search(body, begin)
3659 if not match:
3659 if not match:
3660 break
3660 break
3661 mstart, mend = match.span()
3661 mstart, mend = match.span()
3662 linenum += body.count('\n', begin, mstart) + 1
3662 linenum += body.count('\n', begin, mstart) + 1
3663 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3663 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3664 begin = body.find('\n', mend) + 1 or len(body) + 1
3664 begin = body.find('\n', mend) + 1 or len(body) + 1
3665 lend = begin - 1
3665 lend = begin - 1
3666 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3666 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3667
3667
3668 class linestate(object):
3668 class linestate(object):
3669 def __init__(self, line, linenum, colstart, colend):
3669 def __init__(self, line, linenum, colstart, colend):
3670 self.line = line
3670 self.line = line
3671 self.linenum = linenum
3671 self.linenum = linenum
3672 self.colstart = colstart
3672 self.colstart = colstart
3673 self.colend = colend
3673 self.colend = colend
3674
3674
3675 def __hash__(self):
3675 def __hash__(self):
3676 return hash((self.linenum, self.line))
3676 return hash((self.linenum, self.line))
3677
3677
3678 def __eq__(self, other):
3678 def __eq__(self, other):
3679 return self.line == other.line
3679 return self.line == other.line
3680
3680
3681 def __iter__(self):
3681 def __iter__(self):
3682 yield (self.line[:self.colstart], '')
3682 yield (self.line[:self.colstart], '')
3683 yield (self.line[self.colstart:self.colend], 'grep.match')
3683 yield (self.line[self.colstart:self.colend], 'grep.match')
3684 rest = self.line[self.colend:]
3684 rest = self.line[self.colend:]
3685 while rest != '':
3685 while rest != '':
3686 match = regexp.search(rest)
3686 match = regexp.search(rest)
3687 if not match:
3687 if not match:
3688 yield (rest, '')
3688 yield (rest, '')
3689 break
3689 break
3690 mstart, mend = match.span()
3690 mstart, mend = match.span()
3691 yield (rest[:mstart], '')
3691 yield (rest[:mstart], '')
3692 yield (rest[mstart:mend], 'grep.match')
3692 yield (rest[mstart:mend], 'grep.match')
3693 rest = rest[mend:]
3693 rest = rest[mend:]
3694
3694
3695 matches = {}
3695 matches = {}
3696 copies = {}
3696 copies = {}
3697 def grepbody(fn, rev, body):
3697 def grepbody(fn, rev, body):
3698 matches[rev].setdefault(fn, [])
3698 matches[rev].setdefault(fn, [])
3699 m = matches[rev][fn]
3699 m = matches[rev][fn]
3700 for lnum, cstart, cend, line in matchlines(body):
3700 for lnum, cstart, cend, line in matchlines(body):
3701 s = linestate(line, lnum, cstart, cend)
3701 s = linestate(line, lnum, cstart, cend)
3702 m.append(s)
3702 m.append(s)
3703
3703
3704 def difflinestates(a, b):
3704 def difflinestates(a, b):
3705 sm = difflib.SequenceMatcher(None, a, b)
3705 sm = difflib.SequenceMatcher(None, a, b)
3706 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3706 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3707 if tag == 'insert':
3707 if tag == 'insert':
3708 for i in xrange(blo, bhi):
3708 for i in xrange(blo, bhi):
3709 yield ('+', b[i])
3709 yield ('+', b[i])
3710 elif tag == 'delete':
3710 elif tag == 'delete':
3711 for i in xrange(alo, ahi):
3711 for i in xrange(alo, ahi):
3712 yield ('-', a[i])
3712 yield ('-', a[i])
3713 elif tag == 'replace':
3713 elif tag == 'replace':
3714 for i in xrange(alo, ahi):
3714 for i in xrange(alo, ahi):
3715 yield ('-', a[i])
3715 yield ('-', a[i])
3716 for i in xrange(blo, bhi):
3716 for i in xrange(blo, bhi):
3717 yield ('+', b[i])
3717 yield ('+', b[i])
3718
3718
3719 def display(fn, ctx, pstates, states):
3719 def display(fn, ctx, pstates, states):
3720 rev = ctx.rev()
3720 rev = ctx.rev()
3721 if ui.quiet:
3721 if ui.quiet:
3722 datefunc = util.shortdate
3722 datefunc = util.shortdate
3723 else:
3723 else:
3724 datefunc = util.datestr
3724 datefunc = util.datestr
3725 found = False
3725 found = False
3726 @util.cachefunc
3726 @util.cachefunc
3727 def binary():
3727 def binary():
3728 flog = getfile(fn)
3728 flog = getfile(fn)
3729 return util.binary(flog.read(ctx.filenode(fn)))
3729 return util.binary(flog.read(ctx.filenode(fn)))
3730
3730
3731 if opts.get('all'):
3731 if opts.get('all'):
3732 iter = difflinestates(pstates, states)
3732 iter = difflinestates(pstates, states)
3733 else:
3733 else:
3734 iter = [('', l) for l in states]
3734 iter = [('', l) for l in states]
3735 for change, l in iter:
3735 for change, l in iter:
3736 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3736 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3737
3737
3738 if opts.get('line_number'):
3738 if opts.get('line_number'):
3739 cols.append((str(l.linenum), 'grep.linenumber'))
3739 cols.append((str(l.linenum), 'grep.linenumber'))
3740 if opts.get('all'):
3740 if opts.get('all'):
3741 cols.append((change, 'grep.change'))
3741 cols.append((change, 'grep.change'))
3742 if opts.get('user'):
3742 if opts.get('user'):
3743 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3743 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3744 if opts.get('date'):
3744 if opts.get('date'):
3745 cols.append((datefunc(ctx.date()), 'grep.date'))
3745 cols.append((datefunc(ctx.date()), 'grep.date'))
3746 for col, label in cols[:-1]:
3746 for col, label in cols[:-1]:
3747 ui.write(col, label=label)
3747 ui.write(col, label=label)
3748 ui.write(sep, label='grep.sep')
3748 ui.write(sep, label='grep.sep')
3749 ui.write(cols[-1][0], label=cols[-1][1])
3749 ui.write(cols[-1][0], label=cols[-1][1])
3750 if not opts.get('files_with_matches'):
3750 if not opts.get('files_with_matches'):
3751 ui.write(sep, label='grep.sep')
3751 ui.write(sep, label='grep.sep')
3752 if not opts.get('text') and binary():
3752 if not opts.get('text') and binary():
3753 ui.write(" Binary file matches")
3753 ui.write(" Binary file matches")
3754 else:
3754 else:
3755 for s, label in l:
3755 for s, label in l:
3756 ui.write(s, label=label)
3756 ui.write(s, label=label)
3757 ui.write(eol)
3757 ui.write(eol)
3758 found = True
3758 found = True
3759 if opts.get('files_with_matches'):
3759 if opts.get('files_with_matches'):
3760 break
3760 break
3761 return found
3761 return found
3762
3762
3763 skip = {}
3763 skip = {}
3764 revfiles = {}
3764 revfiles = {}
3765 matchfn = scmutil.match(repo[None], pats, opts)
3765 matchfn = scmutil.match(repo[None], pats, opts)
3766 found = False
3766 found = False
3767 follow = opts.get('follow')
3767 follow = opts.get('follow')
3768
3768
3769 def prep(ctx, fns):
3769 def prep(ctx, fns):
3770 rev = ctx.rev()
3770 rev = ctx.rev()
3771 pctx = ctx.p1()
3771 pctx = ctx.p1()
3772 parent = pctx.rev()
3772 parent = pctx.rev()
3773 matches.setdefault(rev, {})
3773 matches.setdefault(rev, {})
3774 matches.setdefault(parent, {})
3774 matches.setdefault(parent, {})
3775 files = revfiles.setdefault(rev, [])
3775 files = revfiles.setdefault(rev, [])
3776 for fn in fns:
3776 for fn in fns:
3777 flog = getfile(fn)
3777 flog = getfile(fn)
3778 try:
3778 try:
3779 fnode = ctx.filenode(fn)
3779 fnode = ctx.filenode(fn)
3780 except error.LookupError:
3780 except error.LookupError:
3781 continue
3781 continue
3782
3782
3783 copied = flog.renamed(fnode)
3783 copied = flog.renamed(fnode)
3784 copy = follow and copied and copied[0]
3784 copy = follow and copied and copied[0]
3785 if copy:
3785 if copy:
3786 copies.setdefault(rev, {})[fn] = copy
3786 copies.setdefault(rev, {})[fn] = copy
3787 if fn in skip:
3787 if fn in skip:
3788 if copy:
3788 if copy:
3789 skip[copy] = True
3789 skip[copy] = True
3790 continue
3790 continue
3791 files.append(fn)
3791 files.append(fn)
3792
3792
3793 if fn not in matches[rev]:
3793 if fn not in matches[rev]:
3794 grepbody(fn, rev, flog.read(fnode))
3794 grepbody(fn, rev, flog.read(fnode))
3795
3795
3796 pfn = copy or fn
3796 pfn = copy or fn
3797 if pfn not in matches[parent]:
3797 if pfn not in matches[parent]:
3798 try:
3798 try:
3799 fnode = pctx.filenode(pfn)
3799 fnode = pctx.filenode(pfn)
3800 grepbody(pfn, parent, flog.read(fnode))
3800 grepbody(pfn, parent, flog.read(fnode))
3801 except error.LookupError:
3801 except error.LookupError:
3802 pass
3802 pass
3803
3803
3804 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3804 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3805 rev = ctx.rev()
3805 rev = ctx.rev()
3806 parent = ctx.p1().rev()
3806 parent = ctx.p1().rev()
3807 for fn in sorted(revfiles.get(rev, [])):
3807 for fn in sorted(revfiles.get(rev, [])):
3808 states = matches[rev][fn]
3808 states = matches[rev][fn]
3809 copy = copies.get(rev, {}).get(fn)
3809 copy = copies.get(rev, {}).get(fn)
3810 if fn in skip:
3810 if fn in skip:
3811 if copy:
3811 if copy:
3812 skip[copy] = True
3812 skip[copy] = True
3813 continue
3813 continue
3814 pstates = matches.get(parent, {}).get(copy or fn, [])
3814 pstates = matches.get(parent, {}).get(copy or fn, [])
3815 if pstates or states:
3815 if pstates or states:
3816 r = display(fn, ctx, pstates, states)
3816 r = display(fn, ctx, pstates, states)
3817 found = found or r
3817 found = found or r
3818 if r and not opts.get('all'):
3818 if r and not opts.get('all'):
3819 skip[fn] = True
3819 skip[fn] = True
3820 if copy:
3820 if copy:
3821 skip[copy] = True
3821 skip[copy] = True
3822 del matches[rev]
3822 del matches[rev]
3823 del revfiles[rev]
3823 del revfiles[rev]
3824
3824
3825 return not found
3825 return not found
3826
3826
3827 @command('heads',
3827 @command('heads',
3828 [('r', 'rev', '',
3828 [('r', 'rev', '',
3829 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3829 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3830 ('t', 'topo', False, _('show topological heads only')),
3830 ('t', 'topo', False, _('show topological heads only')),
3831 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3831 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3832 ('c', 'closed', False, _('show normal and closed branch heads')),
3832 ('c', 'closed', False, _('show normal and closed branch heads')),
3833 ] + templateopts,
3833 ] + templateopts,
3834 _('[-ct] [-r STARTREV] [REV]...'))
3834 _('[-ct] [-r STARTREV] [REV]...'))
3835 def heads(ui, repo, *branchrevs, **opts):
3835 def heads(ui, repo, *branchrevs, **opts):
3836 """show branch heads
3836 """show branch heads
3837
3837
3838 With no arguments, show all open branch heads in the repository.
3838 With no arguments, show all open branch heads in the repository.
3839 Branch heads are changesets that have no descendants on the
3839 Branch heads are changesets that have no descendants on the
3840 same branch. They are where development generally takes place and
3840 same branch. They are where development generally takes place and
3841 are the usual targets for update and merge operations.
3841 are the usual targets for update and merge operations.
3842
3842
3843 If one or more REVs are given, only open branch heads on the
3843 If one or more REVs are given, only open branch heads on the
3844 branches associated with the specified changesets are shown. This
3844 branches associated with the specified changesets are shown. This
3845 means that you can use :hg:`heads .` to see the heads on the
3845 means that you can use :hg:`heads .` to see the heads on the
3846 currently checked-out branch.
3846 currently checked-out branch.
3847
3847
3848 If -c/--closed is specified, also show branch heads marked closed
3848 If -c/--closed is specified, also show branch heads marked closed
3849 (see :hg:`commit --close-branch`).
3849 (see :hg:`commit --close-branch`).
3850
3850
3851 If STARTREV is specified, only those heads that are descendants of
3851 If STARTREV is specified, only those heads that are descendants of
3852 STARTREV will be displayed.
3852 STARTREV will be displayed.
3853
3853
3854 If -t/--topo is specified, named branch mechanics will be ignored and only
3854 If -t/--topo is specified, named branch mechanics will be ignored and only
3855 topological heads (changesets with no children) will be shown.
3855 topological heads (changesets with no children) will be shown.
3856
3856
3857 Returns 0 if matching heads are found, 1 if not.
3857 Returns 0 if matching heads are found, 1 if not.
3858 """
3858 """
3859
3859
3860 start = None
3860 start = None
3861 if 'rev' in opts:
3861 if 'rev' in opts:
3862 start = scmutil.revsingle(repo, opts['rev'], None).node()
3862 start = scmutil.revsingle(repo, opts['rev'], None).node()
3863
3863
3864 if opts.get('topo'):
3864 if opts.get('topo'):
3865 heads = [repo[h] for h in repo.heads(start)]
3865 heads = [repo[h] for h in repo.heads(start)]
3866 else:
3866 else:
3867 heads = []
3867 heads = []
3868 for branch in repo.branchmap():
3868 for branch in repo.branchmap():
3869 heads += repo.branchheads(branch, start, opts.get('closed'))
3869 heads += repo.branchheads(branch, start, opts.get('closed'))
3870 heads = [repo[h] for h in heads]
3870 heads = [repo[h] for h in heads]
3871
3871
3872 if branchrevs:
3872 if branchrevs:
3873 branches = set(repo[br].branch() for br in branchrevs)
3873 branches = set(repo[br].branch() for br in branchrevs)
3874 heads = [h for h in heads if h.branch() in branches]
3874 heads = [h for h in heads if h.branch() in branches]
3875
3875
3876 if opts.get('active') and branchrevs:
3876 if opts.get('active') and branchrevs:
3877 dagheads = repo.heads(start)
3877 dagheads = repo.heads(start)
3878 heads = [h for h in heads if h.node() in dagheads]
3878 heads = [h for h in heads if h.node() in dagheads]
3879
3879
3880 if branchrevs:
3880 if branchrevs:
3881 haveheads = set(h.branch() for h in heads)
3881 haveheads = set(h.branch() for h in heads)
3882 if branches - haveheads:
3882 if branches - haveheads:
3883 headless = ', '.join(b for b in branches - haveheads)
3883 headless = ', '.join(b for b in branches - haveheads)
3884 msg = _('no open branch heads found on branches %s')
3884 msg = _('no open branch heads found on branches %s')
3885 if opts.get('rev'):
3885 if opts.get('rev'):
3886 msg += _(' (started at %s)') % opts['rev']
3886 msg += _(' (started at %s)') % opts['rev']
3887 ui.warn((msg + '\n') % headless)
3887 ui.warn((msg + '\n') % headless)
3888
3888
3889 if not heads:
3889 if not heads:
3890 return 1
3890 return 1
3891
3891
3892 heads = sorted(heads, key=lambda x: -x.rev())
3892 heads = sorted(heads, key=lambda x: -x.rev())
3893 displayer = cmdutil.show_changeset(ui, repo, opts)
3893 displayer = cmdutil.show_changeset(ui, repo, opts)
3894 for ctx in heads:
3894 for ctx in heads:
3895 displayer.show(ctx)
3895 displayer.show(ctx)
3896 displayer.close()
3896 displayer.close()
3897
3897
3898 @command('help',
3898 @command('help',
3899 [('e', 'extension', None, _('show only help for extensions')),
3899 [('e', 'extension', None, _('show only help for extensions')),
3900 ('c', 'command', None, _('show only help for commands')),
3900 ('c', 'command', None, _('show only help for commands')),
3901 ('k', 'keyword', '', _('show topics matching keyword')),
3901 ('k', 'keyword', '', _('show topics matching keyword')),
3902 ],
3902 ],
3903 _('[-ec] [TOPIC]'),
3903 _('[-ec] [TOPIC]'),
3904 norepo=True)
3904 norepo=True)
3905 def help_(ui, name=None, **opts):
3905 def help_(ui, name=None, **opts):
3906 """show help for a given topic or a help overview
3906 """show help for a given topic or a help overview
3907
3907
3908 With no arguments, print a list of commands with short help messages.
3908 With no arguments, print a list of commands with short help messages.
3909
3909
3910 Given a topic, extension, or command name, print help for that
3910 Given a topic, extension, or command name, print help for that
3911 topic.
3911 topic.
3912
3912
3913 Returns 0 if successful.
3913 Returns 0 if successful.
3914 """
3914 """
3915
3915
3916 textwidth = min(ui.termwidth(), 80) - 2
3916 textwidth = min(ui.termwidth(), 80) - 2
3917
3917
3918 keep = []
3918 keep = []
3919 if ui.verbose:
3919 if ui.verbose:
3920 keep.append('verbose')
3920 keep.append('verbose')
3921 if sys.platform.startswith('win'):
3921 if sys.platform.startswith('win'):
3922 keep.append('windows')
3922 keep.append('windows')
3923 elif sys.platform == 'OpenVMS':
3923 elif sys.platform == 'OpenVMS':
3924 keep.append('vms')
3924 keep.append('vms')
3925 elif sys.platform == 'plan9':
3925 elif sys.platform == 'plan9':
3926 keep.append('plan9')
3926 keep.append('plan9')
3927 else:
3927 else:
3928 keep.append('unix')
3928 keep.append('unix')
3929 keep.append(sys.platform.lower())
3929 keep.append(sys.platform.lower())
3930
3930
3931 section = None
3931 section = None
3932 if name and '.' in name:
3932 if name and '.' in name:
3933 name, section = name.split('.', 1)
3933 name, section = name.split('.', 1)
3934
3934
3935 text = help.help_(ui, name, **opts)
3935 text = help.help_(ui, name, **opts)
3936
3936
3937 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3937 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3938 section=section)
3938 section=section)
3939 if section and not formatted:
3939 if section and not formatted:
3940 raise util.Abort(_("help section not found"))
3940 raise util.Abort(_("help section not found"))
3941
3941
3942 if 'verbose' in pruned:
3942 if 'verbose' in pruned:
3943 keep.append('omitted')
3943 keep.append('omitted')
3944 else:
3944 else:
3945 keep.append('notomitted')
3945 keep.append('notomitted')
3946 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3946 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3947 section=section)
3947 section=section)
3948 ui.write(formatted)
3948 ui.write(formatted)
3949
3949
3950
3950
3951 @command('identify|id',
3951 @command('identify|id',
3952 [('r', 'rev', '',
3952 [('r', 'rev', '',
3953 _('identify the specified revision'), _('REV')),
3953 _('identify the specified revision'), _('REV')),
3954 ('n', 'num', None, _('show local revision number')),
3954 ('n', 'num', None, _('show local revision number')),
3955 ('i', 'id', None, _('show global revision id')),
3955 ('i', 'id', None, _('show global revision id')),
3956 ('b', 'branch', None, _('show branch')),
3956 ('b', 'branch', None, _('show branch')),
3957 ('t', 'tags', None, _('show tags')),
3957 ('t', 'tags', None, _('show tags')),
3958 ('B', 'bookmarks', None, _('show bookmarks')),
3958 ('B', 'bookmarks', None, _('show bookmarks')),
3959 ] + remoteopts,
3959 ] + remoteopts,
3960 _('[-nibtB] [-r REV] [SOURCE]'),
3960 _('[-nibtB] [-r REV] [SOURCE]'),
3961 optionalrepo=True)
3961 optionalrepo=True)
3962 def identify(ui, repo, source=None, rev=None,
3962 def identify(ui, repo, source=None, rev=None,
3963 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3963 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3964 """identify the working directory or specified revision
3964 """identify the working directory or specified revision
3965
3965
3966 Print a summary identifying the repository state at REV using one or
3966 Print a summary identifying the repository state at REV using one or
3967 two parent hash identifiers, followed by a "+" if the working
3967 two parent hash identifiers, followed by a "+" if the working
3968 directory has uncommitted changes, the branch name (if not default),
3968 directory has uncommitted changes, the branch name (if not default),
3969 a list of tags, and a list of bookmarks.
3969 a list of tags, and a list of bookmarks.
3970
3970
3971 When REV is not given, print a summary of the current state of the
3971 When REV is not given, print a summary of the current state of the
3972 repository.
3972 repository.
3973
3973
3974 Specifying a path to a repository root or Mercurial bundle will
3974 Specifying a path to a repository root or Mercurial bundle will
3975 cause lookup to operate on that repository/bundle.
3975 cause lookup to operate on that repository/bundle.
3976
3976
3977 .. container:: verbose
3977 .. container:: verbose
3978
3978
3979 Examples:
3979 Examples:
3980
3980
3981 - generate a build identifier for the working directory::
3981 - generate a build identifier for the working directory::
3982
3982
3983 hg id --id > build-id.dat
3983 hg id --id > build-id.dat
3984
3984
3985 - find the revision corresponding to a tag::
3985 - find the revision corresponding to a tag::
3986
3986
3987 hg id -n -r 1.3
3987 hg id -n -r 1.3
3988
3988
3989 - check the most recent revision of a remote repository::
3989 - check the most recent revision of a remote repository::
3990
3990
3991 hg id -r tip http://selenic.com/hg/
3991 hg id -r tip http://selenic.com/hg/
3992
3992
3993 Returns 0 if successful.
3993 Returns 0 if successful.
3994 """
3994 """
3995
3995
3996 if not repo and not source:
3996 if not repo and not source:
3997 raise util.Abort(_("there is no Mercurial repository here "
3997 raise util.Abort(_("there is no Mercurial repository here "
3998 "(.hg not found)"))
3998 "(.hg not found)"))
3999
3999
4000 if ui.debugflag:
4000 if ui.debugflag:
4001 hexfunc = hex
4001 hexfunc = hex
4002 else:
4002 else:
4003 hexfunc = short
4003 hexfunc = short
4004 default = not (num or id or branch or tags or bookmarks)
4004 default = not (num or id or branch or tags or bookmarks)
4005 output = []
4005 output = []
4006 revs = []
4006 revs = []
4007
4007
4008 if source:
4008 if source:
4009 source, branches = hg.parseurl(ui.expandpath(source))
4009 source, branches = hg.parseurl(ui.expandpath(source))
4010 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4010 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4011 repo = peer.local()
4011 repo = peer.local()
4012 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4012 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4013
4013
4014 if not repo:
4014 if not repo:
4015 if num or branch or tags:
4015 if num or branch or tags:
4016 raise util.Abort(
4016 raise util.Abort(
4017 _("can't query remote revision number, branch, or tags"))
4017 _("can't query remote revision number, branch, or tags"))
4018 if not rev and revs:
4018 if not rev and revs:
4019 rev = revs[0]
4019 rev = revs[0]
4020 if not rev:
4020 if not rev:
4021 rev = "tip"
4021 rev = "tip"
4022
4022
4023 remoterev = peer.lookup(rev)
4023 remoterev = peer.lookup(rev)
4024 if default or id:
4024 if default or id:
4025 output = [hexfunc(remoterev)]
4025 output = [hexfunc(remoterev)]
4026
4026
4027 def getbms():
4027 def getbms():
4028 bms = []
4028 bms = []
4029
4029
4030 if 'bookmarks' in peer.listkeys('namespaces'):
4030 if 'bookmarks' in peer.listkeys('namespaces'):
4031 hexremoterev = hex(remoterev)
4031 hexremoterev = hex(remoterev)
4032 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4032 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4033 if bmr == hexremoterev]
4033 if bmr == hexremoterev]
4034
4034
4035 return sorted(bms)
4035 return sorted(bms)
4036
4036
4037 if bookmarks:
4037 if bookmarks:
4038 output.extend(getbms())
4038 output.extend(getbms())
4039 elif default and not ui.quiet:
4039 elif default and not ui.quiet:
4040 # multiple bookmarks for a single parent separated by '/'
4040 # multiple bookmarks for a single parent separated by '/'
4041 bm = '/'.join(getbms())
4041 bm = '/'.join(getbms())
4042 if bm:
4042 if bm:
4043 output.append(bm)
4043 output.append(bm)
4044 else:
4044 else:
4045 if not rev:
4045 if not rev:
4046 ctx = repo[None]
4046 ctx = repo[None]
4047 parents = ctx.parents()
4047 parents = ctx.parents()
4048 changed = ""
4048 changed = ""
4049 if default or id or num:
4049 if default or id or num:
4050 if (util.any(repo.status())
4050 if (util.any(repo.status())
4051 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4051 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4052 changed = '+'
4052 changed = '+'
4053 if default or id:
4053 if default or id:
4054 output = ["%s%s" %
4054 output = ["%s%s" %
4055 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4055 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4056 if num:
4056 if num:
4057 output.append("%s%s" %
4057 output.append("%s%s" %
4058 ('+'.join([str(p.rev()) for p in parents]), changed))
4058 ('+'.join([str(p.rev()) for p in parents]), changed))
4059 else:
4059 else:
4060 ctx = scmutil.revsingle(repo, rev)
4060 ctx = scmutil.revsingle(repo, rev)
4061 if default or id:
4061 if default or id:
4062 output = [hexfunc(ctx.node())]
4062 output = [hexfunc(ctx.node())]
4063 if num:
4063 if num:
4064 output.append(str(ctx.rev()))
4064 output.append(str(ctx.rev()))
4065
4065
4066 if default and not ui.quiet:
4066 if default and not ui.quiet:
4067 b = ctx.branch()
4067 b = ctx.branch()
4068 if b != 'default':
4068 if b != 'default':
4069 output.append("(%s)" % b)
4069 output.append("(%s)" % b)
4070
4070
4071 # multiple tags for a single parent separated by '/'
4071 # multiple tags for a single parent separated by '/'
4072 t = '/'.join(ctx.tags())
4072 t = '/'.join(ctx.tags())
4073 if t:
4073 if t:
4074 output.append(t)
4074 output.append(t)
4075
4075
4076 # multiple bookmarks for a single parent separated by '/'
4076 # multiple bookmarks for a single parent separated by '/'
4077 bm = '/'.join(ctx.bookmarks())
4077 bm = '/'.join(ctx.bookmarks())
4078 if bm:
4078 if bm:
4079 output.append(bm)
4079 output.append(bm)
4080 else:
4080 else:
4081 if branch:
4081 if branch:
4082 output.append(ctx.branch())
4082 output.append(ctx.branch())
4083
4083
4084 if tags:
4084 if tags:
4085 output.extend(ctx.tags())
4085 output.extend(ctx.tags())
4086
4086
4087 if bookmarks:
4087 if bookmarks:
4088 output.extend(ctx.bookmarks())
4088 output.extend(ctx.bookmarks())
4089
4089
4090 ui.write("%s\n" % ' '.join(output))
4090 ui.write("%s\n" % ' '.join(output))
4091
4091
4092 @command('import|patch',
4092 @command('import|patch',
4093 [('p', 'strip', 1,
4093 [('p', 'strip', 1,
4094 _('directory strip option for patch. This has the same '
4094 _('directory strip option for patch. This has the same '
4095 'meaning as the corresponding patch option'), _('NUM')),
4095 'meaning as the corresponding patch option'), _('NUM')),
4096 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4096 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4097 ('e', 'edit', False, _('invoke editor on commit messages')),
4097 ('e', 'edit', False, _('invoke editor on commit messages')),
4098 ('f', 'force', None,
4098 ('f', 'force', None,
4099 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4099 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4100 ('', 'no-commit', None,
4100 ('', 'no-commit', None,
4101 _("don't commit, just update the working directory")),
4101 _("don't commit, just update the working directory")),
4102 ('', 'bypass', None,
4102 ('', 'bypass', None,
4103 _("apply patch without touching the working directory")),
4103 _("apply patch without touching the working directory")),
4104 ('', 'partial', None,
4104 ('', 'partial', None,
4105 _('commit even if some hunks fail')),
4105 _('commit even if some hunks fail')),
4106 ('', 'exact', None,
4106 ('', 'exact', None,
4107 _('apply patch to the nodes from which it was generated')),
4107 _('apply patch to the nodes from which it was generated')),
4108 ('', 'prefix', '',
4108 ('', 'prefix', '',
4109 _('apply patch to subdirectory'), _('DIR')),
4109 _('apply patch to subdirectory'), _('DIR')),
4110 ('', 'import-branch', None,
4110 ('', 'import-branch', None,
4111 _('use any branch information in patch (implied by --exact)'))] +
4111 _('use any branch information in patch (implied by --exact)'))] +
4112 commitopts + commitopts2 + similarityopts,
4112 commitopts + commitopts2 + similarityopts,
4113 _('[OPTION]... PATCH...'))
4113 _('[OPTION]... PATCH...'))
4114 def import_(ui, repo, patch1=None, *patches, **opts):
4114 def import_(ui, repo, patch1=None, *patches, **opts):
4115 """import an ordered set of patches
4115 """import an ordered set of patches
4116
4116
4117 Import a list of patches and commit them individually (unless
4117 Import a list of patches and commit them individually (unless
4118 --no-commit is specified).
4118 --no-commit is specified).
4119
4119
4120 Because import first applies changes to the working directory,
4120 Because import first applies changes to the working directory,
4121 import will abort if there are outstanding changes.
4121 import will abort if there are outstanding changes.
4122
4122
4123 You can import a patch straight from a mail message. Even patches
4123 You can import a patch straight from a mail message. Even patches
4124 as attachments work (to use the body part, it must have type
4124 as attachments work (to use the body part, it must have type
4125 text/plain or text/x-patch). From and Subject headers of email
4125 text/plain or text/x-patch). From and Subject headers of email
4126 message are used as default committer and commit message. All
4126 message are used as default committer and commit message. All
4127 text/plain body parts before first diff are added to commit
4127 text/plain body parts before first diff are added to commit
4128 message.
4128 message.
4129
4129
4130 If the imported patch was generated by :hg:`export`, user and
4130 If the imported patch was generated by :hg:`export`, user and
4131 description from patch override values from message headers and
4131 description from patch override values from message headers and
4132 body. Values given on command line with -m/--message and -u/--user
4132 body. Values given on command line with -m/--message and -u/--user
4133 override these.
4133 override these.
4134
4134
4135 If --exact is specified, import will set the working directory to
4135 If --exact is specified, import will set the working directory to
4136 the parent of each patch before applying it, and will abort if the
4136 the parent of each patch before applying it, and will abort if the
4137 resulting changeset has a different ID than the one recorded in
4137 resulting changeset has a different ID than the one recorded in
4138 the patch. This may happen due to character set problems or other
4138 the patch. This may happen due to character set problems or other
4139 deficiencies in the text patch format.
4139 deficiencies in the text patch format.
4140
4140
4141 Use --bypass to apply and commit patches directly to the
4141 Use --bypass to apply and commit patches directly to the
4142 repository, not touching the working directory. Without --exact,
4142 repository, not touching the working directory. Without --exact,
4143 patches will be applied on top of the working directory parent
4143 patches will be applied on top of the working directory parent
4144 revision.
4144 revision.
4145
4145
4146 With -s/--similarity, hg will attempt to discover renames and
4146 With -s/--similarity, hg will attempt to discover renames and
4147 copies in the patch in the same way as :hg:`addremove`.
4147 copies in the patch in the same way as :hg:`addremove`.
4148
4148
4149 Use --partial to ensure a changeset will be created from the patch
4149 Use --partial to ensure a changeset will be created from the patch
4150 even if some hunks fail to apply. Hunks that fail to apply will be
4150 even if some hunks fail to apply. Hunks that fail to apply will be
4151 written to a <target-file>.rej file. Conflicts can then be resolved
4151 written to a <target-file>.rej file. Conflicts can then be resolved
4152 by hand before :hg:`commit --amend` is run to update the created
4152 by hand before :hg:`commit --amend` is run to update the created
4153 changeset. This flag exists to let people import patches that
4153 changeset. This flag exists to let people import patches that
4154 partially apply without losing the associated metadata (author,
4154 partially apply without losing the associated metadata (author,
4155 date, description, ...). Note that when none of the hunk applies
4155 date, description, ...). Note that when none of the hunk applies
4156 cleanly, :hg:`import --partial` will create an empty changeset,
4156 cleanly, :hg:`import --partial` will create an empty changeset,
4157 importing only the patch metadata.
4157 importing only the patch metadata.
4158
4158
4159 To read a patch from standard input, use "-" as the patch name. If
4159 To read a patch from standard input, use "-" as the patch name. If
4160 a URL is specified, the patch will be downloaded from it.
4160 a URL is specified, the patch will be downloaded from it.
4161 See :hg:`help dates` for a list of formats valid for -d/--date.
4161 See :hg:`help dates` for a list of formats valid for -d/--date.
4162
4162
4163 .. container:: verbose
4163 .. container:: verbose
4164
4164
4165 Examples:
4165 Examples:
4166
4166
4167 - import a traditional patch from a website and detect renames::
4167 - import a traditional patch from a website and detect renames::
4168
4168
4169 hg import -s 80 http://example.com/bugfix.patch
4169 hg import -s 80 http://example.com/bugfix.patch
4170
4170
4171 - import a changeset from an hgweb server::
4171 - import a changeset from an hgweb server::
4172
4172
4173 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4173 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4174
4174
4175 - import all the patches in an Unix-style mbox::
4175 - import all the patches in an Unix-style mbox::
4176
4176
4177 hg import incoming-patches.mbox
4177 hg import incoming-patches.mbox
4178
4178
4179 - attempt to exactly restore an exported changeset (not always
4179 - attempt to exactly restore an exported changeset (not always
4180 possible)::
4180 possible)::
4181
4181
4182 hg import --exact proposed-fix.patch
4182 hg import --exact proposed-fix.patch
4183
4183
4184 Returns 0 on success, 1 on partial success (see --partial).
4184 Returns 0 on success, 1 on partial success (see --partial).
4185 """
4185 """
4186
4186
4187 if not patch1:
4187 if not patch1:
4188 raise util.Abort(_('need at least one patch to import'))
4188 raise util.Abort(_('need at least one patch to import'))
4189
4189
4190 patches = (patch1,) + patches
4190 patches = (patch1,) + patches
4191
4191
4192 date = opts.get('date')
4192 date = opts.get('date')
4193 if date:
4193 if date:
4194 opts['date'] = util.parsedate(date)
4194 opts['date'] = util.parsedate(date)
4195
4195
4196 update = not opts.get('bypass')
4196 update = not opts.get('bypass')
4197 if not update and opts.get('no_commit'):
4197 if not update and opts.get('no_commit'):
4198 raise util.Abort(_('cannot use --no-commit with --bypass'))
4198 raise util.Abort(_('cannot use --no-commit with --bypass'))
4199 try:
4199 try:
4200 sim = float(opts.get('similarity') or 0)
4200 sim = float(opts.get('similarity') or 0)
4201 except ValueError:
4201 except ValueError:
4202 raise util.Abort(_('similarity must be a number'))
4202 raise util.Abort(_('similarity must be a number'))
4203 if sim < 0 or sim > 100:
4203 if sim < 0 or sim > 100:
4204 raise util.Abort(_('similarity must be between 0 and 100'))
4204 raise util.Abort(_('similarity must be between 0 and 100'))
4205 if sim and not update:
4205 if sim and not update:
4206 raise util.Abort(_('cannot use --similarity with --bypass'))
4206 raise util.Abort(_('cannot use --similarity with --bypass'))
4207 if opts.get('exact') and opts.get('edit'):
4207 if opts.get('exact') and opts.get('edit'):
4208 raise util.Abort(_('cannot use --exact with --edit'))
4208 raise util.Abort(_('cannot use --exact with --edit'))
4209 if opts.get('exact') and opts.get('prefix'):
4209 if opts.get('exact') and opts.get('prefix'):
4210 raise util.Abort(_('cannot use --exact with --prefix'))
4210 raise util.Abort(_('cannot use --exact with --prefix'))
4211
4211
4212 if update:
4212 if update:
4213 cmdutil.checkunfinished(repo)
4213 cmdutil.checkunfinished(repo)
4214 if (opts.get('exact') or not opts.get('force')) and update:
4214 if (opts.get('exact') or not opts.get('force')) and update:
4215 cmdutil.bailifchanged(repo)
4215 cmdutil.bailifchanged(repo)
4216
4216
4217 base = opts["base"]
4217 base = opts["base"]
4218 wlock = lock = tr = None
4218 wlock = lock = tr = None
4219 msgs = []
4219 msgs = []
4220 ret = 0
4220 ret = 0
4221
4221
4222
4222
4223 try:
4223 try:
4224 try:
4224 try:
4225 wlock = repo.wlock()
4225 wlock = repo.wlock()
4226 repo.dirstate.beginparentchange()
4226 repo.dirstate.beginparentchange()
4227 if not opts.get('no_commit'):
4227 if not opts.get('no_commit'):
4228 lock = repo.lock()
4228 lock = repo.lock()
4229 tr = repo.transaction('import')
4229 tr = repo.transaction('import')
4230 parents = repo.parents()
4230 parents = repo.parents()
4231 for patchurl in patches:
4231 for patchurl in patches:
4232 if patchurl == '-':
4232 if patchurl == '-':
4233 ui.status(_('applying patch from stdin\n'))
4233 ui.status(_('applying patch from stdin\n'))
4234 patchfile = ui.fin
4234 patchfile = ui.fin
4235 patchurl = 'stdin' # for error message
4235 patchurl = 'stdin' # for error message
4236 else:
4236 else:
4237 patchurl = os.path.join(base, patchurl)
4237 patchurl = os.path.join(base, patchurl)
4238 ui.status(_('applying %s\n') % patchurl)
4238 ui.status(_('applying %s\n') % patchurl)
4239 patchfile = hg.openpath(ui, patchurl)
4239 patchfile = hg.openpath(ui, patchurl)
4240
4240
4241 haspatch = False
4241 haspatch = False
4242 for hunk in patch.split(patchfile):
4242 for hunk in patch.split(patchfile):
4243 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4243 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4244 parents, opts,
4244 parents, opts,
4245 msgs, hg.clean)
4245 msgs, hg.clean)
4246 if msg:
4246 if msg:
4247 haspatch = True
4247 haspatch = True
4248 ui.note(msg + '\n')
4248 ui.note(msg + '\n')
4249 if update or opts.get('exact'):
4249 if update or opts.get('exact'):
4250 parents = repo.parents()
4250 parents = repo.parents()
4251 else:
4251 else:
4252 parents = [repo[node]]
4252 parents = [repo[node]]
4253 if rej:
4253 if rej:
4254 ui.write_err(_("patch applied partially\n"))
4254 ui.write_err(_("patch applied partially\n"))
4255 ui.write_err(_("(fix the .rej files and run "
4255 ui.write_err(_("(fix the .rej files and run "
4256 "`hg commit --amend`)\n"))
4256 "`hg commit --amend`)\n"))
4257 ret = 1
4257 ret = 1
4258 break
4258 break
4259
4259
4260 if not haspatch:
4260 if not haspatch:
4261 raise util.Abort(_('%s: no diffs found') % patchurl)
4261 raise util.Abort(_('%s: no diffs found') % patchurl)
4262
4262
4263 if tr:
4263 if tr:
4264 tr.close()
4264 tr.close()
4265 if msgs:
4265 if msgs:
4266 repo.savecommitmessage('\n* * *\n'.join(msgs))
4266 repo.savecommitmessage('\n* * *\n'.join(msgs))
4267 repo.dirstate.endparentchange()
4267 repo.dirstate.endparentchange()
4268 return ret
4268 return ret
4269 except: # re-raises
4269 except: # re-raises
4270 # wlock.release() indirectly calls dirstate.write(): since
4270 # wlock.release() indirectly calls dirstate.write(): since
4271 # we're crashing, we do not want to change the working dir
4271 # we're crashing, we do not want to change the working dir
4272 # parent after all, so make sure it writes nothing
4272 # parent after all, so make sure it writes nothing
4273 repo.dirstate.invalidate()
4273 repo.dirstate.invalidate()
4274 raise
4274 raise
4275 finally:
4275 finally:
4276 if tr:
4276 if tr:
4277 tr.release()
4277 tr.release()
4278 release(lock, wlock)
4278 release(lock, wlock)
4279
4279
4280 @command('incoming|in',
4280 @command('incoming|in',
4281 [('f', 'force', None,
4281 [('f', 'force', None,
4282 _('run even if remote repository is unrelated')),
4282 _('run even if remote repository is unrelated')),
4283 ('n', 'newest-first', None, _('show newest record first')),
4283 ('n', 'newest-first', None, _('show newest record first')),
4284 ('', 'bundle', '',
4284 ('', 'bundle', '',
4285 _('file to store the bundles into'), _('FILE')),
4285 _('file to store the bundles into'), _('FILE')),
4286 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4286 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4287 ('B', 'bookmarks', False, _("compare bookmarks")),
4287 ('B', 'bookmarks', False, _("compare bookmarks")),
4288 ('b', 'branch', [],
4288 ('b', 'branch', [],
4289 _('a specific branch you would like to pull'), _('BRANCH')),
4289 _('a specific branch you would like to pull'), _('BRANCH')),
4290 ] + logopts + remoteopts + subrepoopts,
4290 ] + logopts + remoteopts + subrepoopts,
4291 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4291 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4292 def incoming(ui, repo, source="default", **opts):
4292 def incoming(ui, repo, source="default", **opts):
4293 """show new changesets found in source
4293 """show new changesets found in source
4294
4294
4295 Show new changesets found in the specified path/URL or the default
4295 Show new changesets found in the specified path/URL or the default
4296 pull location. These are the changesets that would have been pulled
4296 pull location. These are the changesets that would have been pulled
4297 if a pull at the time you issued this command.
4297 if a pull at the time you issued this command.
4298
4298
4299 See pull for valid source format details.
4299 See pull for valid source format details.
4300
4300
4301 .. container:: verbose
4301 .. container:: verbose
4302
4302
4303 With -B/--bookmarks, the result of bookmark comparison between
4303 With -B/--bookmarks, the result of bookmark comparison between
4304 local and remote repositories is displayed. With -v/--verbose,
4304 local and remote repositories is displayed. With -v/--verbose,
4305 status is also displayed for each bookmark like below::
4305 status is also displayed for each bookmark like below::
4306
4306
4307 BM1 01234567890a added
4307 BM1 01234567890a added
4308 BM2 1234567890ab advanced
4308 BM2 1234567890ab advanced
4309 BM3 234567890abc diverged
4309 BM3 234567890abc diverged
4310 BM4 34567890abcd changed
4310 BM4 34567890abcd changed
4311
4311
4312 The action taken locally when pulling depends on the
4312 The action taken locally when pulling depends on the
4313 status of each bookmark:
4313 status of each bookmark:
4314
4314
4315 :``added``: pull will create it
4315 :``added``: pull will create it
4316 :``advanced``: pull will update it
4316 :``advanced``: pull will update it
4317 :``diverged``: pull will create a divergent bookmark
4317 :``diverged``: pull will create a divergent bookmark
4318 :``changed``: result depends on remote changesets
4318 :``changed``: result depends on remote changesets
4319
4319
4320 From the point of view of pulling behavior, bookmark
4320 From the point of view of pulling behavior, bookmark
4321 existing only in the remote repository are treated as ``added``,
4321 existing only in the remote repository are treated as ``added``,
4322 even if it is in fact locally deleted.
4322 even if it is in fact locally deleted.
4323
4323
4324 .. container:: verbose
4324 .. container:: verbose
4325
4325
4326 For remote repository, using --bundle avoids downloading the
4326 For remote repository, using --bundle avoids downloading the
4327 changesets twice if the incoming is followed by a pull.
4327 changesets twice if the incoming is followed by a pull.
4328
4328
4329 Examples:
4329 Examples:
4330
4330
4331 - show incoming changes with patches and full description::
4331 - show incoming changes with patches and full description::
4332
4332
4333 hg incoming -vp
4333 hg incoming -vp
4334
4334
4335 - show incoming changes excluding merges, store a bundle::
4335 - show incoming changes excluding merges, store a bundle::
4336
4336
4337 hg in -vpM --bundle incoming.hg
4337 hg in -vpM --bundle incoming.hg
4338 hg pull incoming.hg
4338 hg pull incoming.hg
4339
4339
4340 - briefly list changes inside a bundle::
4340 - briefly list changes inside a bundle::
4341
4341
4342 hg in changes.hg -T "{desc|firstline}\\n"
4342 hg in changes.hg -T "{desc|firstline}\\n"
4343
4343
4344 Returns 0 if there are incoming changes, 1 otherwise.
4344 Returns 0 if there are incoming changes, 1 otherwise.
4345 """
4345 """
4346 if opts.get('graph'):
4346 if opts.get('graph'):
4347 cmdutil.checkunsupportedgraphflags([], opts)
4347 cmdutil.checkunsupportedgraphflags([], opts)
4348 def display(other, chlist, displayer):
4348 def display(other, chlist, displayer):
4349 revdag = cmdutil.graphrevs(other, chlist, opts)
4349 revdag = cmdutil.graphrevs(other, chlist, opts)
4350 showparents = [ctx.node() for ctx in repo[None].parents()]
4350 showparents = [ctx.node() for ctx in repo[None].parents()]
4351 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4351 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4352 graphmod.asciiedges)
4352 graphmod.asciiedges)
4353
4353
4354 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4354 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4355 return 0
4355 return 0
4356
4356
4357 if opts.get('bundle') and opts.get('subrepos'):
4357 if opts.get('bundle') and opts.get('subrepos'):
4358 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4358 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4359
4359
4360 if opts.get('bookmarks'):
4360 if opts.get('bookmarks'):
4361 source, branches = hg.parseurl(ui.expandpath(source),
4361 source, branches = hg.parseurl(ui.expandpath(source),
4362 opts.get('branch'))
4362 opts.get('branch'))
4363 other = hg.peer(repo, opts, source)
4363 other = hg.peer(repo, opts, source)
4364 if 'bookmarks' not in other.listkeys('namespaces'):
4364 if 'bookmarks' not in other.listkeys('namespaces'):
4365 ui.warn(_("remote doesn't support bookmarks\n"))
4365 ui.warn(_("remote doesn't support bookmarks\n"))
4366 return 0
4366 return 0
4367 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4367 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4368 return bookmarks.incoming(ui, repo, other)
4368 return bookmarks.incoming(ui, repo, other)
4369
4369
4370 repo._subtoppath = ui.expandpath(source)
4370 repo._subtoppath = ui.expandpath(source)
4371 try:
4371 try:
4372 return hg.incoming(ui, repo, source, opts)
4372 return hg.incoming(ui, repo, source, opts)
4373 finally:
4373 finally:
4374 del repo._subtoppath
4374 del repo._subtoppath
4375
4375
4376
4376
4377 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4377 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4378 norepo=True)
4378 norepo=True)
4379 def init(ui, dest=".", **opts):
4379 def init(ui, dest=".", **opts):
4380 """create a new repository in the given directory
4380 """create a new repository in the given directory
4381
4381
4382 Initialize a new repository in the given directory. If the given
4382 Initialize a new repository in the given directory. If the given
4383 directory does not exist, it will be created.
4383 directory does not exist, it will be created.
4384
4384
4385 If no directory is given, the current directory is used.
4385 If no directory is given, the current directory is used.
4386
4386
4387 It is possible to specify an ``ssh://`` URL as the destination.
4387 It is possible to specify an ``ssh://`` URL as the destination.
4388 See :hg:`help urls` for more information.
4388 See :hg:`help urls` for more information.
4389
4389
4390 Returns 0 on success.
4390 Returns 0 on success.
4391 """
4391 """
4392 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4392 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4393
4393
4394 @command('locate',
4394 @command('locate',
4395 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4395 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4396 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4396 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4397 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4397 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4398 ] + walkopts,
4398 ] + walkopts,
4399 _('[OPTION]... [PATTERN]...'))
4399 _('[OPTION]... [PATTERN]...'))
4400 def locate(ui, repo, *pats, **opts):
4400 def locate(ui, repo, *pats, **opts):
4401 """locate files matching specific patterns (DEPRECATED)
4401 """locate files matching specific patterns (DEPRECATED)
4402
4402
4403 Print files under Mercurial control in the working directory whose
4403 Print files under Mercurial control in the working directory whose
4404 names match the given patterns.
4404 names match the given patterns.
4405
4405
4406 By default, this command searches all directories in the working
4406 By default, this command searches all directories in the working
4407 directory. To search just the current directory and its
4407 directory. To search just the current directory and its
4408 subdirectories, use "--include .".
4408 subdirectories, use "--include .".
4409
4409
4410 If no patterns are given to match, this command prints the names
4410 If no patterns are given to match, this command prints the names
4411 of all files under Mercurial control in the working directory.
4411 of all files under Mercurial control in the working directory.
4412
4412
4413 If you want to feed the output of this command into the "xargs"
4413 If you want to feed the output of this command into the "xargs"
4414 command, use the -0 option to both this command and "xargs". This
4414 command, use the -0 option to both this command and "xargs". This
4415 will avoid the problem of "xargs" treating single filenames that
4415 will avoid the problem of "xargs" treating single filenames that
4416 contain whitespace as multiple filenames.
4416 contain whitespace as multiple filenames.
4417
4417
4418 See :hg:`help files` for a more versatile command.
4418 See :hg:`help files` for a more versatile command.
4419
4419
4420 Returns 0 if a match is found, 1 otherwise.
4420 Returns 0 if a match is found, 1 otherwise.
4421 """
4421 """
4422 if opts.get('print0'):
4422 if opts.get('print0'):
4423 end = '\0'
4423 end = '\0'
4424 else:
4424 else:
4425 end = '\n'
4425 end = '\n'
4426 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4426 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4427
4427
4428 ret = 1
4428 ret = 1
4429 ctx = repo[rev]
4429 ctx = repo[rev]
4430 m = scmutil.match(ctx, pats, opts, default='relglob')
4430 m = scmutil.match(ctx, pats, opts, default='relglob')
4431 m.bad = lambda x, y: False
4431 m.bad = lambda x, y: False
4432
4432
4433 for abs in ctx.matches(m):
4433 for abs in ctx.matches(m):
4434 if opts.get('fullpath'):
4434 if opts.get('fullpath'):
4435 ui.write(repo.wjoin(abs), end)
4435 ui.write(repo.wjoin(abs), end)
4436 else:
4436 else:
4437 ui.write(((pats and m.rel(abs)) or abs), end)
4437 ui.write(((pats and m.rel(abs)) or abs), end)
4438 ret = 0
4438 ret = 0
4439
4439
4440 return ret
4440 return ret
4441
4441
4442 @command('^log|history',
4442 @command('^log|history',
4443 [('f', 'follow', None,
4443 [('f', 'follow', None,
4444 _('follow changeset history, or file history across copies and renames')),
4444 _('follow changeset history, or file history across copies and renames')),
4445 ('', 'follow-first', None,
4445 ('', 'follow-first', None,
4446 _('only follow the first parent of merge changesets (DEPRECATED)')),
4446 _('only follow the first parent of merge changesets (DEPRECATED)')),
4447 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4447 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4448 ('C', 'copies', None, _('show copied files')),
4448 ('C', 'copies', None, _('show copied files')),
4449 ('k', 'keyword', [],
4449 ('k', 'keyword', [],
4450 _('do case-insensitive search for a given text'), _('TEXT')),
4450 _('do case-insensitive search for a given text'), _('TEXT')),
4451 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4451 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4452 ('', 'removed', None, _('include revisions where files were removed')),
4452 ('', 'removed', None, _('include revisions where files were removed')),
4453 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4453 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4454 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4454 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4455 ('', 'only-branch', [],
4455 ('', 'only-branch', [],
4456 _('show only changesets within the given named branch (DEPRECATED)'),
4456 _('show only changesets within the given named branch (DEPRECATED)'),
4457 _('BRANCH')),
4457 _('BRANCH')),
4458 ('b', 'branch', [],
4458 ('b', 'branch', [],
4459 _('show changesets within the given named branch'), _('BRANCH')),
4459 _('show changesets within the given named branch'), _('BRANCH')),
4460 ('P', 'prune', [],
4460 ('P', 'prune', [],
4461 _('do not display revision or any of its ancestors'), _('REV')),
4461 _('do not display revision or any of its ancestors'), _('REV')),
4462 ] + logopts + walkopts,
4462 ] + logopts + walkopts,
4463 _('[OPTION]... [FILE]'),
4463 _('[OPTION]... [FILE]'),
4464 inferrepo=True)
4464 inferrepo=True)
4465 def log(ui, repo, *pats, **opts):
4465 def log(ui, repo, *pats, **opts):
4466 """show revision history of entire repository or files
4466 """show revision history of entire repository or files
4467
4467
4468 Print the revision history of the specified files or the entire
4468 Print the revision history of the specified files or the entire
4469 project.
4469 project.
4470
4470
4471 If no revision range is specified, the default is ``tip:0`` unless
4471 If no revision range is specified, the default is ``tip:0`` unless
4472 --follow is set, in which case the working directory parent is
4472 --follow is set, in which case the working directory parent is
4473 used as the starting revision.
4473 used as the starting revision.
4474
4474
4475 File history is shown without following rename or copy history of
4475 File history is shown without following rename or copy history of
4476 files. Use -f/--follow with a filename to follow history across
4476 files. Use -f/--follow with a filename to follow history across
4477 renames and copies. --follow without a filename will only show
4477 renames and copies. --follow without a filename will only show
4478 ancestors or descendants of the starting revision.
4478 ancestors or descendants of the starting revision.
4479
4479
4480 By default this command prints revision number and changeset id,
4480 By default this command prints revision number and changeset id,
4481 tags, non-trivial parents, user, date and time, and a summary for
4481 tags, non-trivial parents, user, date and time, and a summary for
4482 each commit. When the -v/--verbose switch is used, the list of
4482 each commit. When the -v/--verbose switch is used, the list of
4483 changed files and full commit message are shown.
4483 changed files and full commit message are shown.
4484
4484
4485 With --graph the revisions are shown as an ASCII art DAG with the most
4485 With --graph the revisions are shown as an ASCII art DAG with the most
4486 recent changeset at the top.
4486 recent changeset at the top.
4487 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4487 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4488 and '+' represents a fork where the changeset from the lines below is a
4488 and '+' represents a fork where the changeset from the lines below is a
4489 parent of the 'o' merge on the same line.
4489 parent of the 'o' merge on the same line.
4490
4490
4491 .. note::
4491 .. note::
4492
4492
4493 log -p/--patch may generate unexpected diff output for merge
4493 log -p/--patch may generate unexpected diff output for merge
4494 changesets, as it will only compare the merge changeset against
4494 changesets, as it will only compare the merge changeset against
4495 its first parent. Also, only files different from BOTH parents
4495 its first parent. Also, only files different from BOTH parents
4496 will appear in files:.
4496 will appear in files:.
4497
4497
4498 .. note::
4498 .. note::
4499
4499
4500 for performance reasons, log FILE may omit duplicate changes
4500 for performance reasons, log FILE may omit duplicate changes
4501 made on branches and will not show removals or mode changes. To
4501 made on branches and will not show removals or mode changes. To
4502 see all such changes, use the --removed switch.
4502 see all such changes, use the --removed switch.
4503
4503
4504 .. container:: verbose
4504 .. container:: verbose
4505
4505
4506 Some examples:
4506 Some examples:
4507
4507
4508 - changesets with full descriptions and file lists::
4508 - changesets with full descriptions and file lists::
4509
4509
4510 hg log -v
4510 hg log -v
4511
4511
4512 - changesets ancestral to the working directory::
4512 - changesets ancestral to the working directory::
4513
4513
4514 hg log -f
4514 hg log -f
4515
4515
4516 - last 10 commits on the current branch::
4516 - last 10 commits on the current branch::
4517
4517
4518 hg log -l 10 -b .
4518 hg log -l 10 -b .
4519
4519
4520 - changesets showing all modifications of a file, including removals::
4520 - changesets showing all modifications of a file, including removals::
4521
4521
4522 hg log --removed file.c
4522 hg log --removed file.c
4523
4523
4524 - all changesets that touch a directory, with diffs, excluding merges::
4524 - all changesets that touch a directory, with diffs, excluding merges::
4525
4525
4526 hg log -Mp lib/
4526 hg log -Mp lib/
4527
4527
4528 - all revision numbers that match a keyword::
4528 - all revision numbers that match a keyword::
4529
4529
4530 hg log -k bug --template "{rev}\\n"
4530 hg log -k bug --template "{rev}\\n"
4531
4531
4532 - list available log templates::
4532 - list available log templates::
4533
4533
4534 hg log -T list
4534 hg log -T list
4535
4535
4536 - check if a given changeset is included in a tagged release::
4536 - check if a given changeset is included in a tagged release::
4537
4537
4538 hg log -r "a21ccf and ancestor(1.9)"
4538 hg log -r "a21ccf and ancestor(1.9)"
4539
4539
4540 - find all changesets by some user in a date range::
4540 - find all changesets by some user in a date range::
4541
4541
4542 hg log -k alice -d "may 2008 to jul 2008"
4542 hg log -k alice -d "may 2008 to jul 2008"
4543
4543
4544 - summary of all changesets after the last tag::
4544 - summary of all changesets after the last tag::
4545
4545
4546 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4546 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4547
4547
4548 See :hg:`help dates` for a list of formats valid for -d/--date.
4548 See :hg:`help dates` for a list of formats valid for -d/--date.
4549
4549
4550 See :hg:`help revisions` and :hg:`help revsets` for more about
4550 See :hg:`help revisions` and :hg:`help revsets` for more about
4551 specifying revisions.
4551 specifying revisions.
4552
4552
4553 See :hg:`help templates` for more about pre-packaged styles and
4553 See :hg:`help templates` for more about pre-packaged styles and
4554 specifying custom templates.
4554 specifying custom templates.
4555
4555
4556 Returns 0 on success.
4556 Returns 0 on success.
4557
4557
4558 """
4558 """
4559 if opts.get('follow') and opts.get('rev'):
4559 if opts.get('follow') and opts.get('rev'):
4560 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4560 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4561 del opts['follow']
4561 del opts['follow']
4562
4562
4563 if opts.get('graph'):
4563 if opts.get('graph'):
4564 return cmdutil.graphlog(ui, repo, *pats, **opts)
4564 return cmdutil.graphlog(ui, repo, *pats, **opts)
4565
4565
4566 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4566 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4567 limit = cmdutil.loglimit(opts)
4567 limit = cmdutil.loglimit(opts)
4568 count = 0
4568 count = 0
4569
4569
4570 getrenamed = None
4570 getrenamed = None
4571 if opts.get('copies'):
4571 if opts.get('copies'):
4572 endrev = None
4572 endrev = None
4573 if opts.get('rev'):
4573 if opts.get('rev'):
4574 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4574 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4575 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4575 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4576
4576
4577 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4577 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4578 for rev in revs:
4578 for rev in revs:
4579 if count == limit:
4579 if count == limit:
4580 break
4580 break
4581 ctx = repo[rev]
4581 ctx = repo[rev]
4582 copies = None
4582 copies = None
4583 if getrenamed is not None and rev:
4583 if getrenamed is not None and rev:
4584 copies = []
4584 copies = []
4585 for fn in ctx.files():
4585 for fn in ctx.files():
4586 rename = getrenamed(fn, rev)
4586 rename = getrenamed(fn, rev)
4587 if rename:
4587 if rename:
4588 copies.append((fn, rename[0]))
4588 copies.append((fn, rename[0]))
4589 if filematcher:
4589 if filematcher:
4590 revmatchfn = filematcher(ctx.rev())
4590 revmatchfn = filematcher(ctx.rev())
4591 else:
4591 else:
4592 revmatchfn = None
4592 revmatchfn = None
4593 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4593 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4594 if displayer.flush(rev):
4594 if displayer.flush(rev):
4595 count += 1
4595 count += 1
4596
4596
4597 displayer.close()
4597 displayer.close()
4598
4598
4599 @command('manifest',
4599 @command('manifest',
4600 [('r', 'rev', '', _('revision to display'), _('REV')),
4600 [('r', 'rev', '', _('revision to display'), _('REV')),
4601 ('', 'all', False, _("list files from all revisions"))]
4601 ('', 'all', False, _("list files from all revisions"))]
4602 + formatteropts,
4602 + formatteropts,
4603 _('[-r REV]'))
4603 _('[-r REV]'))
4604 def manifest(ui, repo, node=None, rev=None, **opts):
4604 def manifest(ui, repo, node=None, rev=None, **opts):
4605 """output the current or given revision of the project manifest
4605 """output the current or given revision of the project manifest
4606
4606
4607 Print a list of version controlled files for the given revision.
4607 Print a list of version controlled files for the given revision.
4608 If no revision is given, the first parent of the working directory
4608 If no revision is given, the first parent of the working directory
4609 is used, or the null revision if no revision is checked out.
4609 is used, or the null revision if no revision is checked out.
4610
4610
4611 With -v, print file permissions, symlink and executable bits.
4611 With -v, print file permissions, symlink and executable bits.
4612 With --debug, print file revision hashes.
4612 With --debug, print file revision hashes.
4613
4613
4614 If option --all is specified, the list of all files from all revisions
4614 If option --all is specified, the list of all files from all revisions
4615 is printed. This includes deleted and renamed files.
4615 is printed. This includes deleted and renamed files.
4616
4616
4617 Returns 0 on success.
4617 Returns 0 on success.
4618 """
4618 """
4619
4619
4620 fm = ui.formatter('manifest', opts)
4620 fm = ui.formatter('manifest', opts)
4621
4621
4622 if opts.get('all'):
4622 if opts.get('all'):
4623 if rev or node:
4623 if rev or node:
4624 raise util.Abort(_("can't specify a revision with --all"))
4624 raise util.Abort(_("can't specify a revision with --all"))
4625
4625
4626 res = []
4626 res = []
4627 prefix = "data/"
4627 prefix = "data/"
4628 suffix = ".i"
4628 suffix = ".i"
4629 plen = len(prefix)
4629 plen = len(prefix)
4630 slen = len(suffix)
4630 slen = len(suffix)
4631 lock = repo.lock()
4631 lock = repo.lock()
4632 try:
4632 try:
4633 for fn, b, size in repo.store.datafiles():
4633 for fn, b, size in repo.store.datafiles():
4634 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4634 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4635 res.append(fn[plen:-slen])
4635 res.append(fn[plen:-slen])
4636 finally:
4636 finally:
4637 lock.release()
4637 lock.release()
4638 for f in res:
4638 for f in res:
4639 fm.startitem()
4639 fm.startitem()
4640 fm.write("path", '%s\n', f)
4640 fm.write("path", '%s\n', f)
4641 fm.end()
4641 fm.end()
4642 return
4642 return
4643
4643
4644 if rev and node:
4644 if rev and node:
4645 raise util.Abort(_("please specify just one revision"))
4645 raise util.Abort(_("please specify just one revision"))
4646
4646
4647 if not node:
4647 if not node:
4648 node = rev
4648 node = rev
4649
4649
4650 char = {'l': '@', 'x': '*', '': ''}
4650 char = {'l': '@', 'x': '*', '': ''}
4651 mode = {'l': '644', 'x': '755', '': '644'}
4651 mode = {'l': '644', 'x': '755', '': '644'}
4652 ctx = scmutil.revsingle(repo, node)
4652 ctx = scmutil.revsingle(repo, node)
4653 mf = ctx.manifest()
4653 mf = ctx.manifest()
4654 for f in ctx:
4654 for f in ctx:
4655 fm.startitem()
4655 fm.startitem()
4656 fl = ctx[f].flags()
4656 fl = ctx[f].flags()
4657 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4657 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4658 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4658 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4659 fm.write('path', '%s\n', f)
4659 fm.write('path', '%s\n', f)
4660 fm.end()
4660 fm.end()
4661
4661
4662 @command('^merge',
4662 @command('^merge',
4663 [('f', 'force', None,
4663 [('f', 'force', None,
4664 _('force a merge including outstanding changes (DEPRECATED)')),
4664 _('force a merge including outstanding changes (DEPRECATED)')),
4665 ('r', 'rev', '', _('revision to merge'), _('REV')),
4665 ('r', 'rev', '', _('revision to merge'), _('REV')),
4666 ('P', 'preview', None,
4666 ('P', 'preview', None,
4667 _('review revisions to merge (no merge is performed)'))
4667 _('review revisions to merge (no merge is performed)'))
4668 ] + mergetoolopts,
4668 ] + mergetoolopts,
4669 _('[-P] [-f] [[-r] REV]'))
4669 _('[-P] [-f] [[-r] REV]'))
4670 def merge(ui, repo, node=None, **opts):
4670 def merge(ui, repo, node=None, **opts):
4671 """merge another revision into working directory
4671 """merge another revision into working directory
4672
4672
4673 The current working directory is updated with all changes made in
4673 The current working directory is updated with all changes made in
4674 the requested revision since the last common predecessor revision.
4674 the requested revision since the last common predecessor revision.
4675
4675
4676 Files that changed between either parent are marked as changed for
4676 Files that changed between either parent are marked as changed for
4677 the next commit and a commit must be performed before any further
4677 the next commit and a commit must be performed before any further
4678 updates to the repository are allowed. The next commit will have
4678 updates to the repository are allowed. The next commit will have
4679 two parents.
4679 two parents.
4680
4680
4681 ``--tool`` can be used to specify the merge tool used for file
4681 ``--tool`` can be used to specify the merge tool used for file
4682 merges. It overrides the HGMERGE environment variable and your
4682 merges. It overrides the HGMERGE environment variable and your
4683 configuration files. See :hg:`help merge-tools` for options.
4683 configuration files. See :hg:`help merge-tools` for options.
4684
4684
4685 If no revision is specified, the working directory's parent is a
4685 If no revision is specified, the working directory's parent is a
4686 head revision, and the current branch contains exactly one other
4686 head revision, and the current branch contains exactly one other
4687 head, the other head is merged with by default. Otherwise, an
4687 head, the other head is merged with by default. Otherwise, an
4688 explicit revision with which to merge with must be provided.
4688 explicit revision with which to merge with must be provided.
4689
4689
4690 :hg:`resolve` must be used to resolve unresolved files.
4690 :hg:`resolve` must be used to resolve unresolved files.
4691
4691
4692 To undo an uncommitted merge, use :hg:`update --clean .` which
4692 To undo an uncommitted merge, use :hg:`update --clean .` which
4693 will check out a clean copy of the original merge parent, losing
4693 will check out a clean copy of the original merge parent, losing
4694 all changes.
4694 all changes.
4695
4695
4696 Returns 0 on success, 1 if there are unresolved files.
4696 Returns 0 on success, 1 if there are unresolved files.
4697 """
4697 """
4698
4698
4699 if opts.get('rev') and node:
4699 if opts.get('rev') and node:
4700 raise util.Abort(_("please specify just one revision"))
4700 raise util.Abort(_("please specify just one revision"))
4701 if not node:
4701 if not node:
4702 node = opts.get('rev')
4702 node = opts.get('rev')
4703
4703
4704 if node:
4704 if node:
4705 node = scmutil.revsingle(repo, node).node()
4705 node = scmutil.revsingle(repo, node).node()
4706
4706
4707 if not node and repo._bookmarkcurrent:
4707 if not node and repo._bookmarkcurrent:
4708 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4708 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4709 curhead = repo[repo._bookmarkcurrent].node()
4709 curhead = repo[repo._bookmarkcurrent].node()
4710 if len(bmheads) == 2:
4710 if len(bmheads) == 2:
4711 if curhead == bmheads[0]:
4711 if curhead == bmheads[0]:
4712 node = bmheads[1]
4712 node = bmheads[1]
4713 else:
4713 else:
4714 node = bmheads[0]
4714 node = bmheads[0]
4715 elif len(bmheads) > 2:
4715 elif len(bmheads) > 2:
4716 raise util.Abort(_("multiple matching bookmarks to merge - "
4716 raise util.Abort(_("multiple matching bookmarks to merge - "
4717 "please merge with an explicit rev or bookmark"),
4717 "please merge with an explicit rev or bookmark"),
4718 hint=_("run 'hg heads' to see all heads"))
4718 hint=_("run 'hg heads' to see all heads"))
4719 elif len(bmheads) <= 1:
4719 elif len(bmheads) <= 1:
4720 raise util.Abort(_("no matching bookmark to merge - "
4720 raise util.Abort(_("no matching bookmark to merge - "
4721 "please merge with an explicit rev or bookmark"),
4721 "please merge with an explicit rev or bookmark"),
4722 hint=_("run 'hg heads' to see all heads"))
4722 hint=_("run 'hg heads' to see all heads"))
4723
4723
4724 if not node and not repo._bookmarkcurrent:
4724 if not node and not repo._bookmarkcurrent:
4725 branch = repo[None].branch()
4725 branch = repo[None].branch()
4726 bheads = repo.branchheads(branch)
4726 bheads = repo.branchheads(branch)
4727 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4727 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4728
4728
4729 if len(nbhs) > 2:
4729 if len(nbhs) > 2:
4730 raise util.Abort(_("branch '%s' has %d heads - "
4730 raise util.Abort(_("branch '%s' has %d heads - "
4731 "please merge with an explicit rev")
4731 "please merge with an explicit rev")
4732 % (branch, len(bheads)),
4732 % (branch, len(bheads)),
4733 hint=_("run 'hg heads .' to see heads"))
4733 hint=_("run 'hg heads .' to see heads"))
4734
4734
4735 parent = repo.dirstate.p1()
4735 parent = repo.dirstate.p1()
4736 if len(nbhs) <= 1:
4736 if len(nbhs) <= 1:
4737 if len(bheads) > 1:
4737 if len(bheads) > 1:
4738 raise util.Abort(_("heads are bookmarked - "
4738 raise util.Abort(_("heads are bookmarked - "
4739 "please merge with an explicit rev"),
4739 "please merge with an explicit rev"),
4740 hint=_("run 'hg heads' to see all heads"))
4740 hint=_("run 'hg heads' to see all heads"))
4741 if len(repo.heads()) > 1:
4741 if len(repo.heads()) > 1:
4742 raise util.Abort(_("branch '%s' has one head - "
4742 raise util.Abort(_("branch '%s' has one head - "
4743 "please merge with an explicit rev")
4743 "please merge with an explicit rev")
4744 % branch,
4744 % branch,
4745 hint=_("run 'hg heads' to see all heads"))
4745 hint=_("run 'hg heads' to see all heads"))
4746 msg, hint = _('nothing to merge'), None
4746 msg, hint = _('nothing to merge'), None
4747 if parent != repo.lookup(branch):
4747 if parent != repo.lookup(branch):
4748 hint = _("use 'hg update' instead")
4748 hint = _("use 'hg update' instead")
4749 raise util.Abort(msg, hint=hint)
4749 raise util.Abort(msg, hint=hint)
4750
4750
4751 if parent not in bheads:
4751 if parent not in bheads:
4752 raise util.Abort(_('working directory not at a head revision'),
4752 raise util.Abort(_('working directory not at a head revision'),
4753 hint=_("use 'hg update' or merge with an "
4753 hint=_("use 'hg update' or merge with an "
4754 "explicit revision"))
4754 "explicit revision"))
4755 if parent == nbhs[0]:
4755 if parent == nbhs[0]:
4756 node = nbhs[-1]
4756 node = nbhs[-1]
4757 else:
4757 else:
4758 node = nbhs[0]
4758 node = nbhs[0]
4759
4759
4760 if opts.get('preview'):
4760 if opts.get('preview'):
4761 # find nodes that are ancestors of p2 but not of p1
4761 # find nodes that are ancestors of p2 but not of p1
4762 p1 = repo.lookup('.')
4762 p1 = repo.lookup('.')
4763 p2 = repo.lookup(node)
4763 p2 = repo.lookup(node)
4764 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4764 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4765
4765
4766 displayer = cmdutil.show_changeset(ui, repo, opts)
4766 displayer = cmdutil.show_changeset(ui, repo, opts)
4767 for node in nodes:
4767 for node in nodes:
4768 displayer.show(repo[node])
4768 displayer.show(repo[node])
4769 displayer.close()
4769 displayer.close()
4770 return 0
4770 return 0
4771
4771
4772 try:
4772 try:
4773 # ui.forcemerge is an internal variable, do not document
4773 # ui.forcemerge is an internal variable, do not document
4774 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4774 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4775 return hg.merge(repo, node, force=opts.get('force'))
4775 return hg.merge(repo, node, force=opts.get('force'))
4776 finally:
4776 finally:
4777 ui.setconfig('ui', 'forcemerge', '', 'merge')
4777 ui.setconfig('ui', 'forcemerge', '', 'merge')
4778
4778
4779 @command('outgoing|out',
4779 @command('outgoing|out',
4780 [('f', 'force', None, _('run even when the destination is unrelated')),
4780 [('f', 'force', None, _('run even when the destination is unrelated')),
4781 ('r', 'rev', [],
4781 ('r', 'rev', [],
4782 _('a changeset intended to be included in the destination'), _('REV')),
4782 _('a changeset intended to be included in the destination'), _('REV')),
4783 ('n', 'newest-first', None, _('show newest record first')),
4783 ('n', 'newest-first', None, _('show newest record first')),
4784 ('B', 'bookmarks', False, _('compare bookmarks')),
4784 ('B', 'bookmarks', False, _('compare bookmarks')),
4785 ('b', 'branch', [], _('a specific branch you would like to push'),
4785 ('b', 'branch', [], _('a specific branch you would like to push'),
4786 _('BRANCH')),
4786 _('BRANCH')),
4787 ] + logopts + remoteopts + subrepoopts,
4787 ] + logopts + remoteopts + subrepoopts,
4788 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4788 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4789 def outgoing(ui, repo, dest=None, **opts):
4789 def outgoing(ui, repo, dest=None, **opts):
4790 """show changesets not found in the destination
4790 """show changesets not found in the destination
4791
4791
4792 Show changesets not found in the specified destination repository
4792 Show changesets not found in the specified destination repository
4793 or the default push location. These are the changesets that would
4793 or the default push location. These are the changesets that would
4794 be pushed if a push was requested.
4794 be pushed if a push was requested.
4795
4795
4796 See pull for details of valid destination formats.
4796 See pull for details of valid destination formats.
4797
4797
4798 .. container:: verbose
4798 .. container:: verbose
4799
4799
4800 With -B/--bookmarks, the result of bookmark comparison between
4800 With -B/--bookmarks, the result of bookmark comparison between
4801 local and remote repositories is displayed. With -v/--verbose,
4801 local and remote repositories is displayed. With -v/--verbose,
4802 status is also displayed for each bookmark like below::
4802 status is also displayed for each bookmark like below::
4803
4803
4804 BM1 01234567890a added
4804 BM1 01234567890a added
4805 BM2 deleted
4805 BM2 deleted
4806 BM3 234567890abc advanced
4806 BM3 234567890abc advanced
4807 BM4 34567890abcd diverged
4807 BM4 34567890abcd diverged
4808 BM5 4567890abcde changed
4808 BM5 4567890abcde changed
4809
4809
4810 The action taken when pushing depends on the
4810 The action taken when pushing depends on the
4811 status of each bookmark:
4811 status of each bookmark:
4812
4812
4813 :``added``: push with ``-B`` will create it
4813 :``added``: push with ``-B`` will create it
4814 :``deleted``: push with ``-B`` will delete it
4814 :``deleted``: push with ``-B`` will delete it
4815 :``advanced``: push will update it
4815 :``advanced``: push will update it
4816 :``diverged``: push with ``-B`` will update it
4816 :``diverged``: push with ``-B`` will update it
4817 :``changed``: push with ``-B`` will update it
4817 :``changed``: push with ``-B`` will update it
4818
4818
4819 From the point of view of pushing behavior, bookmarks
4819 From the point of view of pushing behavior, bookmarks
4820 existing only in the remote repository are treated as
4820 existing only in the remote repository are treated as
4821 ``deleted``, even if it is in fact added remotely.
4821 ``deleted``, even if it is in fact added remotely.
4822
4822
4823 Returns 0 if there are outgoing changes, 1 otherwise.
4823 Returns 0 if there are outgoing changes, 1 otherwise.
4824 """
4824 """
4825 if opts.get('graph'):
4825 if opts.get('graph'):
4826 cmdutil.checkunsupportedgraphflags([], opts)
4826 cmdutil.checkunsupportedgraphflags([], opts)
4827 o, other = hg._outgoing(ui, repo, dest, opts)
4827 o, other = hg._outgoing(ui, repo, dest, opts)
4828 if not o:
4828 if not o:
4829 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4829 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4830 return
4830 return
4831
4831
4832 revdag = cmdutil.graphrevs(repo, o, opts)
4832 revdag = cmdutil.graphrevs(repo, o, opts)
4833 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4833 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4834 showparents = [ctx.node() for ctx in repo[None].parents()]
4834 showparents = [ctx.node() for ctx in repo[None].parents()]
4835 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4835 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4836 graphmod.asciiedges)
4836 graphmod.asciiedges)
4837 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4837 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4838 return 0
4838 return 0
4839
4839
4840 if opts.get('bookmarks'):
4840 if opts.get('bookmarks'):
4841 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4841 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4842 dest, branches = hg.parseurl(dest, opts.get('branch'))
4842 dest, branches = hg.parseurl(dest, opts.get('branch'))
4843 other = hg.peer(repo, opts, dest)
4843 other = hg.peer(repo, opts, dest)
4844 if 'bookmarks' not in other.listkeys('namespaces'):
4844 if 'bookmarks' not in other.listkeys('namespaces'):
4845 ui.warn(_("remote doesn't support bookmarks\n"))
4845 ui.warn(_("remote doesn't support bookmarks\n"))
4846 return 0
4846 return 0
4847 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4847 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4848 return bookmarks.outgoing(ui, repo, other)
4848 return bookmarks.outgoing(ui, repo, other)
4849
4849
4850 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4850 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4851 try:
4851 try:
4852 return hg.outgoing(ui, repo, dest, opts)
4852 return hg.outgoing(ui, repo, dest, opts)
4853 finally:
4853 finally:
4854 del repo._subtoppath
4854 del repo._subtoppath
4855
4855
4856 @command('parents',
4856 @command('parents',
4857 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4857 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4858 ] + templateopts,
4858 ] + templateopts,
4859 _('[-r REV] [FILE]'),
4859 _('[-r REV] [FILE]'),
4860 inferrepo=True)
4860 inferrepo=True)
4861 def parents(ui, repo, file_=None, **opts):
4861 def parents(ui, repo, file_=None, **opts):
4862 """show the parents of the working directory or revision (DEPRECATED)
4862 """show the parents of the working directory or revision (DEPRECATED)
4863
4863
4864 Print the working directory's parent revisions. If a revision is
4864 Print the working directory's parent revisions. If a revision is
4865 given via -r/--rev, the parent of that revision will be printed.
4865 given via -r/--rev, the parent of that revision will be printed.
4866 If a file argument is given, the revision in which the file was
4866 If a file argument is given, the revision in which the file was
4867 last changed (before the working directory revision or the
4867 last changed (before the working directory revision or the
4868 argument to --rev if given) is printed.
4868 argument to --rev if given) is printed.
4869
4869
4870 See :hg:`summary` and :hg:`help revsets` for related information.
4870 See :hg:`summary` and :hg:`help revsets` for related information.
4871
4871
4872 Returns 0 on success.
4872 Returns 0 on success.
4873 """
4873 """
4874
4874
4875 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4875 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4876
4876
4877 if file_:
4877 if file_:
4878 m = scmutil.match(ctx, (file_,), opts)
4878 m = scmutil.match(ctx, (file_,), opts)
4879 if m.anypats() or len(m.files()) != 1:
4879 if m.anypats() or len(m.files()) != 1:
4880 raise util.Abort(_('can only specify an explicit filename'))
4880 raise util.Abort(_('can only specify an explicit filename'))
4881 file_ = m.files()[0]
4881 file_ = m.files()[0]
4882 filenodes = []
4882 filenodes = []
4883 for cp in ctx.parents():
4883 for cp in ctx.parents():
4884 if not cp:
4884 if not cp:
4885 continue
4885 continue
4886 try:
4886 try:
4887 filenodes.append(cp.filenode(file_))
4887 filenodes.append(cp.filenode(file_))
4888 except error.LookupError:
4888 except error.LookupError:
4889 pass
4889 pass
4890 if not filenodes:
4890 if not filenodes:
4891 raise util.Abort(_("'%s' not found in manifest!") % file_)
4891 raise util.Abort(_("'%s' not found in manifest!") % file_)
4892 p = []
4892 p = []
4893 for fn in filenodes:
4893 for fn in filenodes:
4894 fctx = repo.filectx(file_, fileid=fn)
4894 fctx = repo.filectx(file_, fileid=fn)
4895 p.append(fctx.node())
4895 p.append(fctx.node())
4896 else:
4896 else:
4897 p = [cp.node() for cp in ctx.parents()]
4897 p = [cp.node() for cp in ctx.parents()]
4898
4898
4899 displayer = cmdutil.show_changeset(ui, repo, opts)
4899 displayer = cmdutil.show_changeset(ui, repo, opts)
4900 for n in p:
4900 for n in p:
4901 if n != nullid:
4901 if n != nullid:
4902 displayer.show(repo[n])
4902 displayer.show(repo[n])
4903 displayer.close()
4903 displayer.close()
4904
4904
4905 @command('paths', [], _('[NAME]'), optionalrepo=True)
4905 @command('paths', [], _('[NAME]'), optionalrepo=True)
4906 def paths(ui, repo, search=None):
4906 def paths(ui, repo, search=None):
4907 """show aliases for remote repositories
4907 """show aliases for remote repositories
4908
4908
4909 Show definition of symbolic path name NAME. If no name is given,
4909 Show definition of symbolic path name NAME. If no name is given,
4910 show definition of all available names.
4910 show definition of all available names.
4911
4911
4912 Option -q/--quiet suppresses all output when searching for NAME
4912 Option -q/--quiet suppresses all output when searching for NAME
4913 and shows only the path names when listing all definitions.
4913 and shows only the path names when listing all definitions.
4914
4914
4915 Path names are defined in the [paths] section of your
4915 Path names are defined in the [paths] section of your
4916 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4916 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4917 repository, ``.hg/hgrc`` is used, too.
4917 repository, ``.hg/hgrc`` is used, too.
4918
4918
4919 The path names ``default`` and ``default-push`` have a special
4919 The path names ``default`` and ``default-push`` have a special
4920 meaning. When performing a push or pull operation, they are used
4920 meaning. When performing a push or pull operation, they are used
4921 as fallbacks if no location is specified on the command-line.
4921 as fallbacks if no location is specified on the command-line.
4922 When ``default-push`` is set, it will be used for push and
4922 When ``default-push`` is set, it will be used for push and
4923 ``default`` will be used for pull; otherwise ``default`` is used
4923 ``default`` will be used for pull; otherwise ``default`` is used
4924 as the fallback for both. When cloning a repository, the clone
4924 as the fallback for both. When cloning a repository, the clone
4925 source is written as ``default`` in ``.hg/hgrc``. Note that
4925 source is written as ``default`` in ``.hg/hgrc``. Note that
4926 ``default`` and ``default-push`` apply to all inbound (e.g.
4926 ``default`` and ``default-push`` apply to all inbound (e.g.
4927 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4927 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4928 :hg:`bundle`) operations.
4928 :hg:`bundle`) operations.
4929
4929
4930 See :hg:`help urls` for more information.
4930 See :hg:`help urls` for more information.
4931
4931
4932 Returns 0 on success.
4932 Returns 0 on success.
4933 """
4933 """
4934 if search:
4934 if search:
4935 for name, path in sorted(ui.paths.iteritems()):
4935 for name, path in sorted(ui.paths.iteritems()):
4936 if name == search:
4936 if name == search:
4937 ui.status("%s\n" % util.hidepassword(path.loc))
4937 ui.status("%s\n" % util.hidepassword(path.loc))
4938 return
4938 return
4939 if not ui.quiet:
4939 if not ui.quiet:
4940 ui.warn(_("not found!\n"))
4940 ui.warn(_("not found!\n"))
4941 return 1
4941 return 1
4942 else:
4942 else:
4943 for name, path in sorted(ui.paths.iteritems()):
4943 for name, path in sorted(ui.paths.iteritems()):
4944 if ui.quiet:
4944 if ui.quiet:
4945 ui.write("%s\n" % name)
4945 ui.write("%s\n" % name)
4946 else:
4946 else:
4947 ui.write("%s = %s\n" % (name,
4947 ui.write("%s = %s\n" % (name,
4948 util.hidepassword(path.loc)))
4948 util.hidepassword(path.loc)))
4949
4949
4950 @command('phase',
4950 @command('phase',
4951 [('p', 'public', False, _('set changeset phase to public')),
4951 [('p', 'public', False, _('set changeset phase to public')),
4952 ('d', 'draft', False, _('set changeset phase to draft')),
4952 ('d', 'draft', False, _('set changeset phase to draft')),
4953 ('s', 'secret', False, _('set changeset phase to secret')),
4953 ('s', 'secret', False, _('set changeset phase to secret')),
4954 ('f', 'force', False, _('allow to move boundary backward')),
4954 ('f', 'force', False, _('allow to move boundary backward')),
4955 ('r', 'rev', [], _('target revision'), _('REV')),
4955 ('r', 'rev', [], _('target revision'), _('REV')),
4956 ],
4956 ],
4957 _('[-p|-d|-s] [-f] [-r] REV...'))
4957 _('[-p|-d|-s] [-f] [-r] REV...'))
4958 def phase(ui, repo, *revs, **opts):
4958 def phase(ui, repo, *revs, **opts):
4959 """set or show the current phase name
4959 """set or show the current phase name
4960
4960
4961 With no argument, show the phase name of specified revisions.
4961 With no argument, show the phase name of specified revisions.
4962
4962
4963 With one of -p/--public, -d/--draft or -s/--secret, change the
4963 With one of -p/--public, -d/--draft or -s/--secret, change the
4964 phase value of the specified revisions.
4964 phase value of the specified revisions.
4965
4965
4966 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4966 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4967 lower phase to an higher phase. Phases are ordered as follows::
4967 lower phase to an higher phase. Phases are ordered as follows::
4968
4968
4969 public < draft < secret
4969 public < draft < secret
4970
4970
4971 Returns 0 on success, 1 if no phases were changed or some could not
4971 Returns 0 on success, 1 if no phases were changed or some could not
4972 be changed.
4972 be changed.
4973 """
4973 """
4974 # search for a unique phase argument
4974 # search for a unique phase argument
4975 targetphase = None
4975 targetphase = None
4976 for idx, name in enumerate(phases.phasenames):
4976 for idx, name in enumerate(phases.phasenames):
4977 if opts[name]:
4977 if opts[name]:
4978 if targetphase is not None:
4978 if targetphase is not None:
4979 raise util.Abort(_('only one phase can be specified'))
4979 raise util.Abort(_('only one phase can be specified'))
4980 targetphase = idx
4980 targetphase = idx
4981
4981
4982 # look for specified revision
4982 # look for specified revision
4983 revs = list(revs)
4983 revs = list(revs)
4984 revs.extend(opts['rev'])
4984 revs.extend(opts['rev'])
4985 if not revs:
4985 if not revs:
4986 raise util.Abort(_('no revisions specified'))
4986 raise util.Abort(_('no revisions specified'))
4987
4987
4988 revs = scmutil.revrange(repo, revs)
4988 revs = scmutil.revrange(repo, revs)
4989
4989
4990 lock = None
4990 lock = None
4991 ret = 0
4991 ret = 0
4992 if targetphase is None:
4992 if targetphase is None:
4993 # display
4993 # display
4994 for r in revs:
4994 for r in revs:
4995 ctx = repo[r]
4995 ctx = repo[r]
4996 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4996 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4997 else:
4997 else:
4998 tr = None
4998 tr = None
4999 lock = repo.lock()
4999 lock = repo.lock()
5000 try:
5000 try:
5001 tr = repo.transaction("phase")
5001 tr = repo.transaction("phase")
5002 # set phase
5002 # set phase
5003 if not revs:
5003 if not revs:
5004 raise util.Abort(_('empty revision set'))
5004 raise util.Abort(_('empty revision set'))
5005 nodes = [repo[r].node() for r in revs]
5005 nodes = [repo[r].node() for r in revs]
5006 # moving revision from public to draft may hide them
5006 # moving revision from public to draft may hide them
5007 # We have to check result on an unfiltered repository
5007 # We have to check result on an unfiltered repository
5008 unfi = repo.unfiltered()
5008 unfi = repo.unfiltered()
5009 getphase = unfi._phasecache.phase
5009 getphase = unfi._phasecache.phase
5010 olddata = [getphase(unfi, r) for r in unfi]
5010 olddata = [getphase(unfi, r) for r in unfi]
5011 phases.advanceboundary(repo, tr, targetphase, nodes)
5011 phases.advanceboundary(repo, tr, targetphase, nodes)
5012 if opts['force']:
5012 if opts['force']:
5013 phases.retractboundary(repo, tr, targetphase, nodes)
5013 phases.retractboundary(repo, tr, targetphase, nodes)
5014 tr.close()
5014 tr.close()
5015 finally:
5015 finally:
5016 if tr is not None:
5016 if tr is not None:
5017 tr.release()
5017 tr.release()
5018 lock.release()
5018 lock.release()
5019 getphase = unfi._phasecache.phase
5019 getphase = unfi._phasecache.phase
5020 newdata = [getphase(unfi, r) for r in unfi]
5020 newdata = [getphase(unfi, r) for r in unfi]
5021 changes = sum(newdata[r] != olddata[r] for r in unfi)
5021 changes = sum(newdata[r] != olddata[r] for r in unfi)
5022 cl = unfi.changelog
5022 cl = unfi.changelog
5023 rejected = [n for n in nodes
5023 rejected = [n for n in nodes
5024 if newdata[cl.rev(n)] < targetphase]
5024 if newdata[cl.rev(n)] < targetphase]
5025 if rejected:
5025 if rejected:
5026 ui.warn(_('cannot move %i changesets to a higher '
5026 ui.warn(_('cannot move %i changesets to a higher '
5027 'phase, use --force\n') % len(rejected))
5027 'phase, use --force\n') % len(rejected))
5028 ret = 1
5028 ret = 1
5029 if changes:
5029 if changes:
5030 msg = _('phase changed for %i changesets\n') % changes
5030 msg = _('phase changed for %i changesets\n') % changes
5031 if ret:
5031 if ret:
5032 ui.status(msg)
5032 ui.status(msg)
5033 else:
5033 else:
5034 ui.note(msg)
5034 ui.note(msg)
5035 else:
5035 else:
5036 ui.warn(_('no phases changed\n'))
5036 ui.warn(_('no phases changed\n'))
5037 ret = 1
5037 ret = 1
5038 return ret
5038 return ret
5039
5039
5040 def postincoming(ui, repo, modheads, optupdate, checkout):
5040 def postincoming(ui, repo, modheads, optupdate, checkout):
5041 if modheads == 0:
5041 if modheads == 0:
5042 return
5042 return
5043 if optupdate:
5043 if optupdate:
5044 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5044 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5045 try:
5045 try:
5046 ret = hg.update(repo, checkout)
5046 ret = hg.update(repo, checkout)
5047 except util.Abort, inst:
5047 except util.Abort, inst:
5048 ui.warn(_("not updating: %s\n") % str(inst))
5048 ui.warn(_("not updating: %s\n") % str(inst))
5049 if inst.hint:
5049 if inst.hint:
5050 ui.warn(_("(%s)\n") % inst.hint)
5050 ui.warn(_("(%s)\n") % inst.hint)
5051 return 0
5051 return 0
5052 if not ret and not checkout:
5052 if not ret and not checkout:
5053 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5053 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5054 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5054 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5055 return ret
5055 return ret
5056 if modheads > 1:
5056 if modheads > 1:
5057 currentbranchheads = len(repo.branchheads())
5057 currentbranchheads = len(repo.branchheads())
5058 if currentbranchheads == modheads:
5058 if currentbranchheads == modheads:
5059 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5059 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5060 elif currentbranchheads > 1:
5060 elif currentbranchheads > 1:
5061 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5061 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5062 "merge)\n"))
5062 "merge)\n"))
5063 else:
5063 else:
5064 ui.status(_("(run 'hg heads' to see heads)\n"))
5064 ui.status(_("(run 'hg heads' to see heads)\n"))
5065 else:
5065 else:
5066 ui.status(_("(run 'hg update' to get a working copy)\n"))
5066 ui.status(_("(run 'hg update' to get a working copy)\n"))
5067
5067
5068 @command('^pull',
5068 @command('^pull',
5069 [('u', 'update', None,
5069 [('u', 'update', None,
5070 _('update to new branch head if changesets were pulled')),
5070 _('update to new branch head if changesets were pulled')),
5071 ('f', 'force', None, _('run even when remote repository is unrelated')),
5071 ('f', 'force', None, _('run even when remote repository is unrelated')),
5072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5073 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5073 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5074 ('b', 'branch', [], _('a specific branch you would like to pull'),
5074 ('b', 'branch', [], _('a specific branch you would like to pull'),
5075 _('BRANCH')),
5075 _('BRANCH')),
5076 ] + remoteopts,
5076 ] + remoteopts,
5077 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5077 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5078 def pull(ui, repo, source="default", **opts):
5078 def pull(ui, repo, source="default", **opts):
5079 """pull changes from the specified source
5079 """pull changes from the specified source
5080
5080
5081 Pull changes from a remote repository to a local one.
5081 Pull changes from a remote repository to a local one.
5082
5082
5083 This finds all changes from the repository at the specified path
5083 This finds all changes from the repository at the specified path
5084 or URL and adds them to a local repository (the current one unless
5084 or URL and adds them to a local repository (the current one unless
5085 -R is specified). By default, this does not update the copy of the
5085 -R is specified). By default, this does not update the copy of the
5086 project in the working directory.
5086 project in the working directory.
5087
5087
5088 Use :hg:`incoming` if you want to see what would have been added
5088 Use :hg:`incoming` if you want to see what would have been added
5089 by a pull at the time you issued this command. If you then decide
5089 by a pull at the time you issued this command. If you then decide
5090 to add those changes to the repository, you should use :hg:`pull
5090 to add those changes to the repository, you should use :hg:`pull
5091 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5091 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5092
5092
5093 If SOURCE is omitted, the 'default' path will be used.
5093 If SOURCE is omitted, the 'default' path will be used.
5094 See :hg:`help urls` for more information.
5094 See :hg:`help urls` for more information.
5095
5095
5096 Returns 0 on success, 1 if an update had unresolved files.
5096 Returns 0 on success, 1 if an update had unresolved files.
5097 """
5097 """
5098 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5098 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5099 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5099 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5100 other = hg.peer(repo, opts, source)
5100 other = hg.peer(repo, opts, source)
5101 try:
5101 try:
5102 revs, checkout = hg.addbranchrevs(repo, other, branches,
5102 revs, checkout = hg.addbranchrevs(repo, other, branches,
5103 opts.get('rev'))
5103 opts.get('rev'))
5104
5104
5105 remotebookmarks = other.listkeys('bookmarks')
5105 remotebookmarks = other.listkeys('bookmarks')
5106
5106
5107 if opts.get('bookmark'):
5107 if opts.get('bookmark'):
5108 if not revs:
5108 if not revs:
5109 revs = []
5109 revs = []
5110 for b in opts['bookmark']:
5110 for b in opts['bookmark']:
5111 if b not in remotebookmarks:
5111 if b not in remotebookmarks:
5112 raise util.Abort(_('remote bookmark %s not found!') % b)
5112 raise util.Abort(_('remote bookmark %s not found!') % b)
5113 revs.append(remotebookmarks[b])
5113 revs.append(remotebookmarks[b])
5114
5114
5115 if revs:
5115 if revs:
5116 try:
5116 try:
5117 revs = [other.lookup(rev) for rev in revs]
5117 revs = [other.lookup(rev) for rev in revs]
5118 except error.CapabilityError:
5118 except error.CapabilityError:
5119 err = _("other repository doesn't support revision lookup, "
5119 err = _("other repository doesn't support revision lookup, "
5120 "so a rev cannot be specified.")
5120 "so a rev cannot be specified.")
5121 raise util.Abort(err)
5121 raise util.Abort(err)
5122
5122
5123 modheads = exchange.pull(repo, other, heads=revs,
5123 modheads = exchange.pull(repo, other, heads=revs,
5124 force=opts.get('force'),
5124 force=opts.get('force'),
5125 bookmarks=opts.get('bookmark', ())).cgresult
5125 bookmarks=opts.get('bookmark', ())).cgresult
5126 if checkout:
5126 if checkout:
5127 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5127 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5128 repo._subtoppath = source
5128 repo._subtoppath = source
5129 try:
5129 try:
5130 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5130 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5131
5131
5132 finally:
5132 finally:
5133 del repo._subtoppath
5133 del repo._subtoppath
5134
5134
5135 finally:
5135 finally:
5136 other.close()
5136 other.close()
5137 return ret
5137 return ret
5138
5138
5139 @command('^push',
5139 @command('^push',
5140 [('f', 'force', None, _('force push')),
5140 [('f', 'force', None, _('force push')),
5141 ('r', 'rev', [],
5141 ('r', 'rev', [],
5142 _('a changeset intended to be included in the destination'),
5142 _('a changeset intended to be included in the destination'),
5143 _('REV')),
5143 _('REV')),
5144 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5144 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5145 ('b', 'branch', [],
5145 ('b', 'branch', [],
5146 _('a specific branch you would like to push'), _('BRANCH')),
5146 _('a specific branch you would like to push'), _('BRANCH')),
5147 ('', 'new-branch', False, _('allow pushing a new branch')),
5147 ('', 'new-branch', False, _('allow pushing a new branch')),
5148 ] + remoteopts,
5148 ] + remoteopts,
5149 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5149 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5150 def push(ui, repo, dest=None, **opts):
5150 def push(ui, repo, dest=None, **opts):
5151 """push changes to the specified destination
5151 """push changes to the specified destination
5152
5152
5153 Push changesets from the local repository to the specified
5153 Push changesets from the local repository to the specified
5154 destination.
5154 destination.
5155
5155
5156 This operation is symmetrical to pull: it is identical to a pull
5156 This operation is symmetrical to pull: it is identical to a pull
5157 in the destination repository from the current one.
5157 in the destination repository from the current one.
5158
5158
5159 By default, push will not allow creation of new heads at the
5159 By default, push will not allow creation of new heads at the
5160 destination, since multiple heads would make it unclear which head
5160 destination, since multiple heads would make it unclear which head
5161 to use. In this situation, it is recommended to pull and merge
5161 to use. In this situation, it is recommended to pull and merge
5162 before pushing.
5162 before pushing.
5163
5163
5164 Use --new-branch if you want to allow push to create a new named
5164 Use --new-branch if you want to allow push to create a new named
5165 branch that is not present at the destination. This allows you to
5165 branch that is not present at the destination. This allows you to
5166 only create a new branch without forcing other changes.
5166 only create a new branch without forcing other changes.
5167
5167
5168 .. note::
5168 .. note::
5169
5169
5170 Extra care should be taken with the -f/--force option,
5170 Extra care should be taken with the -f/--force option,
5171 which will push all new heads on all branches, an action which will
5171 which will push all new heads on all branches, an action which will
5172 almost always cause confusion for collaborators.
5172 almost always cause confusion for collaborators.
5173
5173
5174 If -r/--rev is used, the specified revision and all its ancestors
5174 If -r/--rev is used, the specified revision and all its ancestors
5175 will be pushed to the remote repository.
5175 will be pushed to the remote repository.
5176
5176
5177 If -B/--bookmark is used, the specified bookmarked revision, its
5177 If -B/--bookmark is used, the specified bookmarked revision, its
5178 ancestors, and the bookmark will be pushed to the remote
5178 ancestors, and the bookmark will be pushed to the remote
5179 repository.
5179 repository.
5180
5180
5181 Please see :hg:`help urls` for important details about ``ssh://``
5181 Please see :hg:`help urls` for important details about ``ssh://``
5182 URLs. If DESTINATION is omitted, a default path will be used.
5182 URLs. If DESTINATION is omitted, a default path will be used.
5183
5183
5184 Returns 0 if push was successful, 1 if nothing to push.
5184 Returns 0 if push was successful, 1 if nothing to push.
5185 """
5185 """
5186
5186
5187 if opts.get('bookmark'):
5187 if opts.get('bookmark'):
5188 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5188 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5189 for b in opts['bookmark']:
5189 for b in opts['bookmark']:
5190 # translate -B options to -r so changesets get pushed
5190 # translate -B options to -r so changesets get pushed
5191 if b in repo._bookmarks:
5191 if b in repo._bookmarks:
5192 opts.setdefault('rev', []).append(b)
5192 opts.setdefault('rev', []).append(b)
5193 else:
5193 else:
5194 # if we try to push a deleted bookmark, translate it to null
5194 # if we try to push a deleted bookmark, translate it to null
5195 # this lets simultaneous -r, -b options continue working
5195 # this lets simultaneous -r, -b options continue working
5196 opts.setdefault('rev', []).append("null")
5196 opts.setdefault('rev', []).append("null")
5197
5197
5198 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5198 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5199 dest, branches = hg.parseurl(dest, opts.get('branch'))
5199 dest, branches = hg.parseurl(dest, opts.get('branch'))
5200 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5200 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5201 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5201 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5202 try:
5202 try:
5203 other = hg.peer(repo, opts, dest)
5203 other = hg.peer(repo, opts, dest)
5204 except error.RepoError:
5204 except error.RepoError:
5205 if dest == "default-push":
5205 if dest == "default-push":
5206 raise util.Abort(_("default repository not configured!"),
5206 raise util.Abort(_("default repository not configured!"),
5207 hint=_('see the "path" section in "hg help config"'))
5207 hint=_('see the "path" section in "hg help config"'))
5208 else:
5208 else:
5209 raise
5209 raise
5210
5210
5211 if revs:
5211 if revs:
5212 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5212 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5213 if not revs:
5213 if not revs:
5214 raise util.Abort(_("specified revisions evaluate to an empty set"),
5214 raise util.Abort(_("specified revisions evaluate to an empty set"),
5215 hint=_("use different revision arguments"))
5215 hint=_("use different revision arguments"))
5216
5216
5217 repo._subtoppath = dest
5217 repo._subtoppath = dest
5218 try:
5218 try:
5219 # push subrepos depth-first for coherent ordering
5219 # push subrepos depth-first for coherent ordering
5220 c = repo['']
5220 c = repo['']
5221 subs = c.substate # only repos that are committed
5221 subs = c.substate # only repos that are committed
5222 for s in sorted(subs):
5222 for s in sorted(subs):
5223 result = c.sub(s).push(opts)
5223 result = c.sub(s).push(opts)
5224 if result == 0:
5224 if result == 0:
5225 return not result
5225 return not result
5226 finally:
5226 finally:
5227 del repo._subtoppath
5227 del repo._subtoppath
5228 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5228 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5229 newbranch=opts.get('new_branch'),
5229 newbranch=opts.get('new_branch'),
5230 bookmarks=opts.get('bookmark', ()))
5230 bookmarks=opts.get('bookmark', ()))
5231
5231
5232 result = not pushop.cgresult
5232 result = not pushop.cgresult
5233
5233
5234 if pushop.bkresult is not None:
5234 if pushop.bkresult is not None:
5235 if pushop.bkresult == 2:
5235 if pushop.bkresult == 2:
5236 result = 2
5236 result = 2
5237 elif not result and pushop.bkresult:
5237 elif not result and pushop.bkresult:
5238 result = 2
5238 result = 2
5239
5239
5240 return result
5240 return result
5241
5241
5242 @command('recover', [])
5242 @command('recover', [])
5243 def recover(ui, repo):
5243 def recover(ui, repo):
5244 """roll back an interrupted transaction
5244 """roll back an interrupted transaction
5245
5245
5246 Recover from an interrupted commit or pull.
5246 Recover from an interrupted commit or pull.
5247
5247
5248 This command tries to fix the repository status after an
5248 This command tries to fix the repository status after an
5249 interrupted operation. It should only be necessary when Mercurial
5249 interrupted operation. It should only be necessary when Mercurial
5250 suggests it.
5250 suggests it.
5251
5251
5252 Returns 0 if successful, 1 if nothing to recover or verify fails.
5252 Returns 0 if successful, 1 if nothing to recover or verify fails.
5253 """
5253 """
5254 if repo.recover():
5254 if repo.recover():
5255 return hg.verify(repo)
5255 return hg.verify(repo)
5256 return 1
5256 return 1
5257
5257
5258 @command('^remove|rm',
5258 @command('^remove|rm',
5259 [('A', 'after', None, _('record delete for missing files')),
5259 [('A', 'after', None, _('record delete for missing files')),
5260 ('f', 'force', None,
5260 ('f', 'force', None,
5261 _('remove (and delete) file even if added or modified')),
5261 _('remove (and delete) file even if added or modified')),
5262 ] + subrepoopts + walkopts,
5262 ] + subrepoopts + walkopts,
5263 _('[OPTION]... FILE...'),
5263 _('[OPTION]... FILE...'),
5264 inferrepo=True)
5264 inferrepo=True)
5265 def remove(ui, repo, *pats, **opts):
5265 def remove(ui, repo, *pats, **opts):
5266 """remove the specified files on the next commit
5266 """remove the specified files on the next commit
5267
5267
5268 Schedule the indicated files for removal from the current branch.
5268 Schedule the indicated files for removal from the current branch.
5269
5269
5270 This command schedules the files to be removed at the next commit.
5270 This command schedules the files to be removed at the next commit.
5271 To undo a remove before that, see :hg:`revert`. To undo added
5271 To undo a remove before that, see :hg:`revert`. To undo added
5272 files, see :hg:`forget`.
5272 files, see :hg:`forget`.
5273
5273
5274 .. container:: verbose
5274 .. container:: verbose
5275
5275
5276 -A/--after can be used to remove only files that have already
5276 -A/--after can be used to remove only files that have already
5277 been deleted, -f/--force can be used to force deletion, and -Af
5277 been deleted, -f/--force can be used to force deletion, and -Af
5278 can be used to remove files from the next revision without
5278 can be used to remove files from the next revision without
5279 deleting them from the working directory.
5279 deleting them from the working directory.
5280
5280
5281 The following table details the behavior of remove for different
5281 The following table details the behavior of remove for different
5282 file states (columns) and option combinations (rows). The file
5282 file states (columns) and option combinations (rows). The file
5283 states are Added [A], Clean [C], Modified [M] and Missing [!]
5283 states are Added [A], Clean [C], Modified [M] and Missing [!]
5284 (as reported by :hg:`status`). The actions are Warn, Remove
5284 (as reported by :hg:`status`). The actions are Warn, Remove
5285 (from branch) and Delete (from disk):
5285 (from branch) and Delete (from disk):
5286
5286
5287 ========= == == == ==
5287 ========= == == == ==
5288 opt/state A C M !
5288 opt/state A C M !
5289 ========= == == == ==
5289 ========= == == == ==
5290 none W RD W R
5290 none W RD W R
5291 -f R RD RD R
5291 -f R RD RD R
5292 -A W W W R
5292 -A W W W R
5293 -Af R R R R
5293 -Af R R R R
5294 ========= == == == ==
5294 ========= == == == ==
5295
5295
5296 Note that remove never deletes files in Added [A] state from the
5296 Note that remove never deletes files in Added [A] state from the
5297 working directory, not even if option --force is specified.
5297 working directory, not even if option --force is specified.
5298
5298
5299 Returns 0 on success, 1 if any warnings encountered.
5299 Returns 0 on success, 1 if any warnings encountered.
5300 """
5300 """
5301
5301
5302 after, force = opts.get('after'), opts.get('force')
5302 after, force = opts.get('after'), opts.get('force')
5303 if not pats and not after:
5303 if not pats and not after:
5304 raise util.Abort(_('no files specified'))
5304 raise util.Abort(_('no files specified'))
5305
5305
5306 m = scmutil.match(repo[None], pats, opts)
5306 m = scmutil.match(repo[None], pats, opts)
5307 subrepos = opts.get('subrepos')
5307 subrepos = opts.get('subrepos')
5308 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5308 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5309
5309
5310 @command('rename|move|mv',
5310 @command('rename|move|mv',
5311 [('A', 'after', None, _('record a rename that has already occurred')),
5311 [('A', 'after', None, _('record a rename that has already occurred')),
5312 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5312 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5313 ] + walkopts + dryrunopts,
5313 ] + walkopts + dryrunopts,
5314 _('[OPTION]... SOURCE... DEST'))
5314 _('[OPTION]... SOURCE... DEST'))
5315 def rename(ui, repo, *pats, **opts):
5315 def rename(ui, repo, *pats, **opts):
5316 """rename files; equivalent of copy + remove
5316 """rename files; equivalent of copy + remove
5317
5317
5318 Mark dest as copies of sources; mark sources for deletion. If dest
5318 Mark dest as copies of sources; mark sources for deletion. If dest
5319 is a directory, copies are put in that directory. If dest is a
5319 is a directory, copies are put in that directory. If dest is a
5320 file, there can only be one source.
5320 file, there can only be one source.
5321
5321
5322 By default, this command copies the contents of files as they
5322 By default, this command copies the contents of files as they
5323 exist in the working directory. If invoked with -A/--after, the
5323 exist in the working directory. If invoked with -A/--after, the
5324 operation is recorded, but no copying is performed.
5324 operation is recorded, but no copying is performed.
5325
5325
5326 This command takes effect at the next commit. To undo a rename
5326 This command takes effect at the next commit. To undo a rename
5327 before that, see :hg:`revert`.
5327 before that, see :hg:`revert`.
5328
5328
5329 Returns 0 on success, 1 if errors are encountered.
5329 Returns 0 on success, 1 if errors are encountered.
5330 """
5330 """
5331 wlock = repo.wlock(False)
5331 wlock = repo.wlock(False)
5332 try:
5332 try:
5333 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5333 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5334 finally:
5334 finally:
5335 wlock.release()
5335 wlock.release()
5336
5336
5337 @command('resolve',
5337 @command('resolve',
5338 [('a', 'all', None, _('select all unresolved files')),
5338 [('a', 'all', None, _('select all unresolved files')),
5339 ('l', 'list', None, _('list state of files needing merge')),
5339 ('l', 'list', None, _('list state of files needing merge')),
5340 ('m', 'mark', None, _('mark files as resolved')),
5340 ('m', 'mark', None, _('mark files as resolved')),
5341 ('u', 'unmark', None, _('mark files as unresolved')),
5341 ('u', 'unmark', None, _('mark files as unresolved')),
5342 ('n', 'no-status', None, _('hide status prefix'))]
5342 ('n', 'no-status', None, _('hide status prefix'))]
5343 + mergetoolopts + walkopts + formatteropts,
5343 + mergetoolopts + walkopts + formatteropts,
5344 _('[OPTION]... [FILE]...'),
5344 _('[OPTION]... [FILE]...'),
5345 inferrepo=True)
5345 inferrepo=True)
5346 def resolve(ui, repo, *pats, **opts):
5346 def resolve(ui, repo, *pats, **opts):
5347 """redo merges or set/view the merge status of files
5347 """redo merges or set/view the merge status of files
5348
5348
5349 Merges with unresolved conflicts are often the result of
5349 Merges with unresolved conflicts are often the result of
5350 non-interactive merging using the ``internal:merge`` configuration
5350 non-interactive merging using the ``internal:merge`` configuration
5351 setting, or a command-line merge tool like ``diff3``. The resolve
5351 setting, or a command-line merge tool like ``diff3``. The resolve
5352 command is used to manage the files involved in a merge, after
5352 command is used to manage the files involved in a merge, after
5353 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5353 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5354 working directory must have two parents). See :hg:`help
5354 working directory must have two parents). See :hg:`help
5355 merge-tools` for information on configuring merge tools.
5355 merge-tools` for information on configuring merge tools.
5356
5356
5357 The resolve command can be used in the following ways:
5357 The resolve command can be used in the following ways:
5358
5358
5359 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5359 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5360 files, discarding any previous merge attempts. Re-merging is not
5360 files, discarding any previous merge attempts. Re-merging is not
5361 performed for files already marked as resolved. Use ``--all/-a``
5361 performed for files already marked as resolved. Use ``--all/-a``
5362 to select all unresolved files. ``--tool`` can be used to specify
5362 to select all unresolved files. ``--tool`` can be used to specify
5363 the merge tool used for the given files. It overrides the HGMERGE
5363 the merge tool used for the given files. It overrides the HGMERGE
5364 environment variable and your configuration files. Previous file
5364 environment variable and your configuration files. Previous file
5365 contents are saved with a ``.orig`` suffix.
5365 contents are saved with a ``.orig`` suffix.
5366
5366
5367 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5367 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5368 (e.g. after having manually fixed-up the files). The default is
5368 (e.g. after having manually fixed-up the files). The default is
5369 to mark all unresolved files.
5369 to mark all unresolved files.
5370
5370
5371 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5371 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5372 default is to mark all resolved files.
5372 default is to mark all resolved files.
5373
5373
5374 - :hg:`resolve -l`: list files which had or still have conflicts.
5374 - :hg:`resolve -l`: list files which had or still have conflicts.
5375 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5375 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5376
5376
5377 Note that Mercurial will not let you commit files with unresolved
5377 Note that Mercurial will not let you commit files with unresolved
5378 merge conflicts. You must use :hg:`resolve -m ...` before you can
5378 merge conflicts. You must use :hg:`resolve -m ...` before you can
5379 commit after a conflicting merge.
5379 commit after a conflicting merge.
5380
5380
5381 Returns 0 on success, 1 if any files fail a resolve attempt.
5381 Returns 0 on success, 1 if any files fail a resolve attempt.
5382 """
5382 """
5383
5383
5384 all, mark, unmark, show, nostatus = \
5384 all, mark, unmark, show, nostatus = \
5385 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5385 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5386
5386
5387 if (show and (mark or unmark)) or (mark and unmark):
5387 if (show and (mark or unmark)) or (mark and unmark):
5388 raise util.Abort(_("too many options specified"))
5388 raise util.Abort(_("too many options specified"))
5389 if pats and all:
5389 if pats and all:
5390 raise util.Abort(_("can't specify --all and patterns"))
5390 raise util.Abort(_("can't specify --all and patterns"))
5391 if not (all or pats or show or mark or unmark):
5391 if not (all or pats or show or mark or unmark):
5392 raise util.Abort(_('no files or directories specified'),
5392 raise util.Abort(_('no files or directories specified'),
5393 hint=('use --all to remerge all files'))
5393 hint=('use --all to remerge all files'))
5394
5394
5395 if show:
5395 if show:
5396 fm = ui.formatter('resolve', opts)
5396 fm = ui.formatter('resolve', opts)
5397 ms = mergemod.mergestate(repo)
5397 ms = mergemod.mergestate(repo)
5398 m = scmutil.match(repo[None], pats, opts)
5398 m = scmutil.match(repo[None], pats, opts)
5399 for f in ms:
5399 for f in ms:
5400 if not m(f):
5400 if not m(f):
5401 continue
5401 continue
5402 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5402 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5403 fm.startitem()
5403 fm.startitem()
5404 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5404 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5405 fm.write('path', '%s\n', f, label=l)
5405 fm.write('path', '%s\n', f, label=l)
5406 fm.end()
5406 fm.end()
5407 return 0
5407 return 0
5408
5408
5409 wlock = repo.wlock()
5409 wlock = repo.wlock()
5410 try:
5410 try:
5411 ms = mergemod.mergestate(repo)
5411 ms = mergemod.mergestate(repo)
5412
5412
5413 if not (ms.active() or repo.dirstate.p2() != nullid):
5413 if not (ms.active() or repo.dirstate.p2() != nullid):
5414 raise util.Abort(
5414 raise util.Abort(
5415 _('resolve command not applicable when not merging'))
5415 _('resolve command not applicable when not merging'))
5416
5416
5417 m = scmutil.match(repo[None], pats, opts)
5417 m = scmutil.match(repo[None], pats, opts)
5418 ret = 0
5418 ret = 0
5419 didwork = False
5419 didwork = False
5420
5420
5421 for f in ms:
5421 for f in ms:
5422 if not m(f):
5422 if not m(f):
5423 continue
5423 continue
5424
5424
5425 didwork = True
5425 didwork = True
5426
5426
5427 if mark:
5427 if mark:
5428 ms.mark(f, "r")
5428 ms.mark(f, "r")
5429 elif unmark:
5429 elif unmark:
5430 ms.mark(f, "u")
5430 ms.mark(f, "u")
5431 else:
5431 else:
5432 wctx = repo[None]
5432 wctx = repo[None]
5433
5433
5434 # backup pre-resolve (merge uses .orig for its own purposes)
5434 # backup pre-resolve (merge uses .orig for its own purposes)
5435 a = repo.wjoin(f)
5435 a = repo.wjoin(f)
5436 util.copyfile(a, a + ".resolve")
5436 util.copyfile(a, a + ".resolve")
5437
5437
5438 try:
5438 try:
5439 # resolve file
5439 # resolve file
5440 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5440 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5441 'resolve')
5441 'resolve')
5442 if ms.resolve(f, wctx):
5442 if ms.resolve(f, wctx):
5443 ret = 1
5443 ret = 1
5444 finally:
5444 finally:
5445 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5445 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5446 ms.commit()
5446 ms.commit()
5447
5447
5448 # replace filemerge's .orig file with our resolve file
5448 # replace filemerge's .orig file with our resolve file
5449 util.rename(a + ".resolve", a + ".orig")
5449 util.rename(a + ".resolve", a + ".orig")
5450
5450
5451 ms.commit()
5451 ms.commit()
5452
5452
5453 if not didwork and pats:
5453 if not didwork and pats:
5454 ui.warn(_("arguments do not match paths that need resolving\n"))
5454 ui.warn(_("arguments do not match paths that need resolving\n"))
5455
5455
5456 finally:
5456 finally:
5457 wlock.release()
5457 wlock.release()
5458
5458
5459 # Nudge users into finishing an unfinished operation
5459 # Nudge users into finishing an unfinished operation
5460 if not list(ms.unresolved()):
5460 if not list(ms.unresolved()):
5461 ui.status(_('(no more unresolved files)\n'))
5461 ui.status(_('(no more unresolved files)\n'))
5462
5462
5463 return ret
5463 return ret
5464
5464
5465 @command('revert',
5465 @command('revert',
5466 [('a', 'all', None, _('revert all changes when no arguments given')),
5466 [('a', 'all', None, _('revert all changes when no arguments given')),
5467 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5467 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5468 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5468 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5469 ('C', 'no-backup', None, _('do not save backup copies of files')),
5469 ('C', 'no-backup', None, _('do not save backup copies of files')),
5470 ('i', 'interactive', None, _('interactively select the changes')),
5470 ('i', 'interactive', None, _('interactively select the changes')),
5471 ] + walkopts + dryrunopts,
5471 ] + walkopts + dryrunopts,
5472 _('[OPTION]... [-r REV] [NAME]...'))
5472 _('[OPTION]... [-r REV] [NAME]...'))
5473 def revert(ui, repo, *pats, **opts):
5473 def revert(ui, repo, *pats, **opts):
5474 """restore files to their checkout state
5474 """restore files to their checkout state
5475
5475
5476 .. note::
5476 .. note::
5477
5477
5478 To check out earlier revisions, you should use :hg:`update REV`.
5478 To check out earlier revisions, you should use :hg:`update REV`.
5479 To cancel an uncommitted merge (and lose your changes),
5479 To cancel an uncommitted merge (and lose your changes),
5480 use :hg:`update --clean .`.
5480 use :hg:`update --clean .`.
5481
5481
5482 With no revision specified, revert the specified files or directories
5482 With no revision specified, revert the specified files or directories
5483 to the contents they had in the parent of the working directory.
5483 to the contents they had in the parent of the working directory.
5484 This restores the contents of files to an unmodified
5484 This restores the contents of files to an unmodified
5485 state and unschedules adds, removes, copies, and renames. If the
5485 state and unschedules adds, removes, copies, and renames. If the
5486 working directory has two parents, you must explicitly specify a
5486 working directory has two parents, you must explicitly specify a
5487 revision.
5487 revision.
5488
5488
5489 Using the -r/--rev or -d/--date options, revert the given files or
5489 Using the -r/--rev or -d/--date options, revert the given files or
5490 directories to their states as of a specific revision. Because
5490 directories to their states as of a specific revision. Because
5491 revert does not change the working directory parents, this will
5491 revert does not change the working directory parents, this will
5492 cause these files to appear modified. This can be helpful to "back
5492 cause these files to appear modified. This can be helpful to "back
5493 out" some or all of an earlier change. See :hg:`backout` for a
5493 out" some or all of an earlier change. See :hg:`backout` for a
5494 related method.
5494 related method.
5495
5495
5496 Modified files are saved with a .orig suffix before reverting.
5496 Modified files are saved with a .orig suffix before reverting.
5497 To disable these backups, use --no-backup.
5497 To disable these backups, use --no-backup.
5498
5498
5499 See :hg:`help dates` for a list of formats valid for -d/--date.
5499 See :hg:`help dates` for a list of formats valid for -d/--date.
5500
5500
5501 Returns 0 on success.
5501 Returns 0 on success.
5502 """
5502 """
5503
5503
5504 if opts.get("date"):
5504 if opts.get("date"):
5505 if opts.get("rev"):
5505 if opts.get("rev"):
5506 raise util.Abort(_("you can't specify a revision and a date"))
5506 raise util.Abort(_("you can't specify a revision and a date"))
5507 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5507 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5508
5508
5509 parent, p2 = repo.dirstate.parents()
5509 parent, p2 = repo.dirstate.parents()
5510 if not opts.get('rev') and p2 != nullid:
5510 if not opts.get('rev') and p2 != nullid:
5511 # revert after merge is a trap for new users (issue2915)
5511 # revert after merge is a trap for new users (issue2915)
5512 raise util.Abort(_('uncommitted merge with no revision specified'),
5512 raise util.Abort(_('uncommitted merge with no revision specified'),
5513 hint=_('use "hg update" or see "hg help revert"'))
5513 hint=_('use "hg update" or see "hg help revert"'))
5514
5514
5515 ctx = scmutil.revsingle(repo, opts.get('rev'))
5515 ctx = scmutil.revsingle(repo, opts.get('rev'))
5516
5516
5517 if not pats and not opts.get('all'):
5517 if not pats and not (opts.get('all') or opts.get('interactive')):
5518 msg = _("no files or directories specified")
5518 msg = _("no files or directories specified")
5519 if p2 != nullid:
5519 if p2 != nullid:
5520 hint = _("uncommitted merge, use --all to discard all changes,"
5520 hint = _("uncommitted merge, use --all to discard all changes,"
5521 " or 'hg update -C .' to abort the merge")
5521 " or 'hg update -C .' to abort the merge")
5522 raise util.Abort(msg, hint=hint)
5522 raise util.Abort(msg, hint=hint)
5523 dirty = util.any(repo.status())
5523 dirty = util.any(repo.status())
5524 node = ctx.node()
5524 node = ctx.node()
5525 if node != parent:
5525 if node != parent:
5526 if dirty:
5526 if dirty:
5527 hint = _("uncommitted changes, use --all to discard all"
5527 hint = _("uncommitted changes, use --all to discard all"
5528 " changes, or 'hg update %s' to update") % ctx.rev()
5528 " changes, or 'hg update %s' to update") % ctx.rev()
5529 else:
5529 else:
5530 hint = _("use --all to revert all files,"
5530 hint = _("use --all to revert all files,"
5531 " or 'hg update %s' to update") % ctx.rev()
5531 " or 'hg update %s' to update") % ctx.rev()
5532 elif dirty:
5532 elif dirty:
5533 hint = _("uncommitted changes, use --all to discard all changes")
5533 hint = _("uncommitted changes, use --all to discard all changes")
5534 else:
5534 else:
5535 hint = _("use --all to revert all files")
5535 hint = _("use --all to revert all files")
5536 raise util.Abort(msg, hint=hint)
5536 raise util.Abort(msg, hint=hint)
5537
5537
5538 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5538 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5539
5539
5540 @command('rollback', dryrunopts +
5540 @command('rollback', dryrunopts +
5541 [('f', 'force', False, _('ignore safety measures'))])
5541 [('f', 'force', False, _('ignore safety measures'))])
5542 def rollback(ui, repo, **opts):
5542 def rollback(ui, repo, **opts):
5543 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5543 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5544
5544
5545 Please use :hg:`commit --amend` instead of rollback to correct
5545 Please use :hg:`commit --amend` instead of rollback to correct
5546 mistakes in the last commit.
5546 mistakes in the last commit.
5547
5547
5548 This command should be used with care. There is only one level of
5548 This command should be used with care. There is only one level of
5549 rollback, and there is no way to undo a rollback. It will also
5549 rollback, and there is no way to undo a rollback. It will also
5550 restore the dirstate at the time of the last transaction, losing
5550 restore the dirstate at the time of the last transaction, losing
5551 any dirstate changes since that time. This command does not alter
5551 any dirstate changes since that time. This command does not alter
5552 the working directory.
5552 the working directory.
5553
5553
5554 Transactions are used to encapsulate the effects of all commands
5554 Transactions are used to encapsulate the effects of all commands
5555 that create new changesets or propagate existing changesets into a
5555 that create new changesets or propagate existing changesets into a
5556 repository.
5556 repository.
5557
5557
5558 .. container:: verbose
5558 .. container:: verbose
5559
5559
5560 For example, the following commands are transactional, and their
5560 For example, the following commands are transactional, and their
5561 effects can be rolled back:
5561 effects can be rolled back:
5562
5562
5563 - commit
5563 - commit
5564 - import
5564 - import
5565 - pull
5565 - pull
5566 - push (with this repository as the destination)
5566 - push (with this repository as the destination)
5567 - unbundle
5567 - unbundle
5568
5568
5569 To avoid permanent data loss, rollback will refuse to rollback a
5569 To avoid permanent data loss, rollback will refuse to rollback a
5570 commit transaction if it isn't checked out. Use --force to
5570 commit transaction if it isn't checked out. Use --force to
5571 override this protection.
5571 override this protection.
5572
5572
5573 This command is not intended for use on public repositories. Once
5573 This command is not intended for use on public repositories. Once
5574 changes are visible for pull by other users, rolling a transaction
5574 changes are visible for pull by other users, rolling a transaction
5575 back locally is ineffective (someone else may already have pulled
5575 back locally is ineffective (someone else may already have pulled
5576 the changes). Furthermore, a race is possible with readers of the
5576 the changes). Furthermore, a race is possible with readers of the
5577 repository; for example an in-progress pull from the repository
5577 repository; for example an in-progress pull from the repository
5578 may fail if a rollback is performed.
5578 may fail if a rollback is performed.
5579
5579
5580 Returns 0 on success, 1 if no rollback data is available.
5580 Returns 0 on success, 1 if no rollback data is available.
5581 """
5581 """
5582 return repo.rollback(dryrun=opts.get('dry_run'),
5582 return repo.rollback(dryrun=opts.get('dry_run'),
5583 force=opts.get('force'))
5583 force=opts.get('force'))
5584
5584
5585 @command('root', [])
5585 @command('root', [])
5586 def root(ui, repo):
5586 def root(ui, repo):
5587 """print the root (top) of the current working directory
5587 """print the root (top) of the current working directory
5588
5588
5589 Print the root directory of the current repository.
5589 Print the root directory of the current repository.
5590
5590
5591 Returns 0 on success.
5591 Returns 0 on success.
5592 """
5592 """
5593 ui.write(repo.root + "\n")
5593 ui.write(repo.root + "\n")
5594
5594
5595 @command('^serve',
5595 @command('^serve',
5596 [('A', 'accesslog', '', _('name of access log file to write to'),
5596 [('A', 'accesslog', '', _('name of access log file to write to'),
5597 _('FILE')),
5597 _('FILE')),
5598 ('d', 'daemon', None, _('run server in background')),
5598 ('d', 'daemon', None, _('run server in background')),
5599 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5599 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5600 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5600 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5601 # use string type, then we can check if something was passed
5601 # use string type, then we can check if something was passed
5602 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5602 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5603 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5603 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5604 _('ADDR')),
5604 _('ADDR')),
5605 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5605 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5606 _('PREFIX')),
5606 _('PREFIX')),
5607 ('n', 'name', '',
5607 ('n', 'name', '',
5608 _('name to show in web pages (default: working directory)'), _('NAME')),
5608 _('name to show in web pages (default: working directory)'), _('NAME')),
5609 ('', 'web-conf', '',
5609 ('', 'web-conf', '',
5610 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5610 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5611 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5611 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5612 _('FILE')),
5612 _('FILE')),
5613 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5613 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5614 ('', 'stdio', None, _('for remote clients')),
5614 ('', 'stdio', None, _('for remote clients')),
5615 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5615 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5616 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5616 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5617 ('', 'style', '', _('template style to use'), _('STYLE')),
5617 ('', 'style', '', _('template style to use'), _('STYLE')),
5618 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5618 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5619 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5619 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5620 _('[OPTION]...'),
5620 _('[OPTION]...'),
5621 optionalrepo=True)
5621 optionalrepo=True)
5622 def serve(ui, repo, **opts):
5622 def serve(ui, repo, **opts):
5623 """start stand-alone webserver
5623 """start stand-alone webserver
5624
5624
5625 Start a local HTTP repository browser and pull server. You can use
5625 Start a local HTTP repository browser and pull server. You can use
5626 this for ad-hoc sharing and browsing of repositories. It is
5626 this for ad-hoc sharing and browsing of repositories. It is
5627 recommended to use a real web server to serve a repository for
5627 recommended to use a real web server to serve a repository for
5628 longer periods of time.
5628 longer periods of time.
5629
5629
5630 Please note that the server does not implement access control.
5630 Please note that the server does not implement access control.
5631 This means that, by default, anybody can read from the server and
5631 This means that, by default, anybody can read from the server and
5632 nobody can write to it by default. Set the ``web.allow_push``
5632 nobody can write to it by default. Set the ``web.allow_push``
5633 option to ``*`` to allow everybody to push to the server. You
5633 option to ``*`` to allow everybody to push to the server. You
5634 should use a real web server if you need to authenticate users.
5634 should use a real web server if you need to authenticate users.
5635
5635
5636 By default, the server logs accesses to stdout and errors to
5636 By default, the server logs accesses to stdout and errors to
5637 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5637 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5638 files.
5638 files.
5639
5639
5640 To have the server choose a free port number to listen on, specify
5640 To have the server choose a free port number to listen on, specify
5641 a port number of 0; in this case, the server will print the port
5641 a port number of 0; in this case, the server will print the port
5642 number it uses.
5642 number it uses.
5643
5643
5644 Returns 0 on success.
5644 Returns 0 on success.
5645 """
5645 """
5646
5646
5647 if opts["stdio"] and opts["cmdserver"]:
5647 if opts["stdio"] and opts["cmdserver"]:
5648 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5648 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5649
5649
5650 if opts["stdio"]:
5650 if opts["stdio"]:
5651 if repo is None:
5651 if repo is None:
5652 raise error.RepoError(_("there is no Mercurial repository here"
5652 raise error.RepoError(_("there is no Mercurial repository here"
5653 " (.hg not found)"))
5653 " (.hg not found)"))
5654 s = sshserver.sshserver(ui, repo)
5654 s = sshserver.sshserver(ui, repo)
5655 s.serve_forever()
5655 s.serve_forever()
5656
5656
5657 if opts["cmdserver"]:
5657 if opts["cmdserver"]:
5658 service = commandserver.createservice(ui, repo, opts)
5658 service = commandserver.createservice(ui, repo, opts)
5659 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5659 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5660
5660
5661 # this way we can check if something was given in the command-line
5661 # this way we can check if something was given in the command-line
5662 if opts.get('port'):
5662 if opts.get('port'):
5663 opts['port'] = util.getport(opts.get('port'))
5663 opts['port'] = util.getport(opts.get('port'))
5664
5664
5665 if repo:
5665 if repo:
5666 baseui = repo.baseui
5666 baseui = repo.baseui
5667 else:
5667 else:
5668 baseui = ui
5668 baseui = ui
5669 optlist = ("name templates style address port prefix ipv6"
5669 optlist = ("name templates style address port prefix ipv6"
5670 " accesslog errorlog certificate encoding")
5670 " accesslog errorlog certificate encoding")
5671 for o in optlist.split():
5671 for o in optlist.split():
5672 val = opts.get(o, '')
5672 val = opts.get(o, '')
5673 if val in (None, ''): # should check against default options instead
5673 if val in (None, ''): # should check against default options instead
5674 continue
5674 continue
5675 baseui.setconfig("web", o, val, 'serve')
5675 baseui.setconfig("web", o, val, 'serve')
5676 if repo and repo.ui != baseui:
5676 if repo and repo.ui != baseui:
5677 repo.ui.setconfig("web", o, val, 'serve')
5677 repo.ui.setconfig("web", o, val, 'serve')
5678
5678
5679 o = opts.get('web_conf') or opts.get('webdir_conf')
5679 o = opts.get('web_conf') or opts.get('webdir_conf')
5680 if not o:
5680 if not o:
5681 if not repo:
5681 if not repo:
5682 raise error.RepoError(_("there is no Mercurial repository"
5682 raise error.RepoError(_("there is no Mercurial repository"
5683 " here (.hg not found)"))
5683 " here (.hg not found)"))
5684 o = repo
5684 o = repo
5685
5685
5686 app = hgweb.hgweb(o, baseui=baseui)
5686 app = hgweb.hgweb(o, baseui=baseui)
5687 service = httpservice(ui, app, opts)
5687 service = httpservice(ui, app, opts)
5688 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5688 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5689
5689
5690 class httpservice(object):
5690 class httpservice(object):
5691 def __init__(self, ui, app, opts):
5691 def __init__(self, ui, app, opts):
5692 self.ui = ui
5692 self.ui = ui
5693 self.app = app
5693 self.app = app
5694 self.opts = opts
5694 self.opts = opts
5695
5695
5696 def init(self):
5696 def init(self):
5697 util.setsignalhandler()
5697 util.setsignalhandler()
5698 self.httpd = hgweb_server.create_server(self.ui, self.app)
5698 self.httpd = hgweb_server.create_server(self.ui, self.app)
5699
5699
5700 if self.opts['port'] and not self.ui.verbose:
5700 if self.opts['port'] and not self.ui.verbose:
5701 return
5701 return
5702
5702
5703 if self.httpd.prefix:
5703 if self.httpd.prefix:
5704 prefix = self.httpd.prefix.strip('/') + '/'
5704 prefix = self.httpd.prefix.strip('/') + '/'
5705 else:
5705 else:
5706 prefix = ''
5706 prefix = ''
5707
5707
5708 port = ':%d' % self.httpd.port
5708 port = ':%d' % self.httpd.port
5709 if port == ':80':
5709 if port == ':80':
5710 port = ''
5710 port = ''
5711
5711
5712 bindaddr = self.httpd.addr
5712 bindaddr = self.httpd.addr
5713 if bindaddr == '0.0.0.0':
5713 if bindaddr == '0.0.0.0':
5714 bindaddr = '*'
5714 bindaddr = '*'
5715 elif ':' in bindaddr: # IPv6
5715 elif ':' in bindaddr: # IPv6
5716 bindaddr = '[%s]' % bindaddr
5716 bindaddr = '[%s]' % bindaddr
5717
5717
5718 fqaddr = self.httpd.fqaddr
5718 fqaddr = self.httpd.fqaddr
5719 if ':' in fqaddr:
5719 if ':' in fqaddr:
5720 fqaddr = '[%s]' % fqaddr
5720 fqaddr = '[%s]' % fqaddr
5721 if self.opts['port']:
5721 if self.opts['port']:
5722 write = self.ui.status
5722 write = self.ui.status
5723 else:
5723 else:
5724 write = self.ui.write
5724 write = self.ui.write
5725 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5725 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5726 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5726 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5727 self.ui.flush() # avoid buffering of status message
5727 self.ui.flush() # avoid buffering of status message
5728
5728
5729 def run(self):
5729 def run(self):
5730 self.httpd.serve_forever()
5730 self.httpd.serve_forever()
5731
5731
5732
5732
5733 @command('^status|st',
5733 @command('^status|st',
5734 [('A', 'all', None, _('show status of all files')),
5734 [('A', 'all', None, _('show status of all files')),
5735 ('m', 'modified', None, _('show only modified files')),
5735 ('m', 'modified', None, _('show only modified files')),
5736 ('a', 'added', None, _('show only added files')),
5736 ('a', 'added', None, _('show only added files')),
5737 ('r', 'removed', None, _('show only removed files')),
5737 ('r', 'removed', None, _('show only removed files')),
5738 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5738 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5739 ('c', 'clean', None, _('show only files without changes')),
5739 ('c', 'clean', None, _('show only files without changes')),
5740 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5740 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5741 ('i', 'ignored', None, _('show only ignored files')),
5741 ('i', 'ignored', None, _('show only ignored files')),
5742 ('n', 'no-status', None, _('hide status prefix')),
5742 ('n', 'no-status', None, _('hide status prefix')),
5743 ('C', 'copies', None, _('show source of copied files')),
5743 ('C', 'copies', None, _('show source of copied files')),
5744 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5744 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5745 ('', 'rev', [], _('show difference from revision'), _('REV')),
5745 ('', 'rev', [], _('show difference from revision'), _('REV')),
5746 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5746 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5747 ] + walkopts + subrepoopts + formatteropts,
5747 ] + walkopts + subrepoopts + formatteropts,
5748 _('[OPTION]... [FILE]...'),
5748 _('[OPTION]... [FILE]...'),
5749 inferrepo=True)
5749 inferrepo=True)
5750 def status(ui, repo, *pats, **opts):
5750 def status(ui, repo, *pats, **opts):
5751 """show changed files in the working directory
5751 """show changed files in the working directory
5752
5752
5753 Show status of files in the repository. If names are given, only
5753 Show status of files in the repository. If names are given, only
5754 files that match are shown. Files that are clean or ignored or
5754 files that match are shown. Files that are clean or ignored or
5755 the source of a copy/move operation, are not listed unless
5755 the source of a copy/move operation, are not listed unless
5756 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5756 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5757 Unless options described with "show only ..." are given, the
5757 Unless options described with "show only ..." are given, the
5758 options -mardu are used.
5758 options -mardu are used.
5759
5759
5760 Option -q/--quiet hides untracked (unknown and ignored) files
5760 Option -q/--quiet hides untracked (unknown and ignored) files
5761 unless explicitly requested with -u/--unknown or -i/--ignored.
5761 unless explicitly requested with -u/--unknown or -i/--ignored.
5762
5762
5763 .. note::
5763 .. note::
5764
5764
5765 status may appear to disagree with diff if permissions have
5765 status may appear to disagree with diff if permissions have
5766 changed or a merge has occurred. The standard diff format does
5766 changed or a merge has occurred. The standard diff format does
5767 not report permission changes and diff only reports changes
5767 not report permission changes and diff only reports changes
5768 relative to one merge parent.
5768 relative to one merge parent.
5769
5769
5770 If one revision is given, it is used as the base revision.
5770 If one revision is given, it is used as the base revision.
5771 If two revisions are given, the differences between them are
5771 If two revisions are given, the differences between them are
5772 shown. The --change option can also be used as a shortcut to list
5772 shown. The --change option can also be used as a shortcut to list
5773 the changed files of a revision from its first parent.
5773 the changed files of a revision from its first parent.
5774
5774
5775 The codes used to show the status of files are::
5775 The codes used to show the status of files are::
5776
5776
5777 M = modified
5777 M = modified
5778 A = added
5778 A = added
5779 R = removed
5779 R = removed
5780 C = clean
5780 C = clean
5781 ! = missing (deleted by non-hg command, but still tracked)
5781 ! = missing (deleted by non-hg command, but still tracked)
5782 ? = not tracked
5782 ? = not tracked
5783 I = ignored
5783 I = ignored
5784 = origin of the previous file (with --copies)
5784 = origin of the previous file (with --copies)
5785
5785
5786 .. container:: verbose
5786 .. container:: verbose
5787
5787
5788 Examples:
5788 Examples:
5789
5789
5790 - show changes in the working directory relative to a
5790 - show changes in the working directory relative to a
5791 changeset::
5791 changeset::
5792
5792
5793 hg status --rev 9353
5793 hg status --rev 9353
5794
5794
5795 - show changes in the working directory relative to the
5795 - show changes in the working directory relative to the
5796 current directory (see :hg:`help patterns` for more information)::
5796 current directory (see :hg:`help patterns` for more information)::
5797
5797
5798 hg status re:
5798 hg status re:
5799
5799
5800 - show all changes including copies in an existing changeset::
5800 - show all changes including copies in an existing changeset::
5801
5801
5802 hg status --copies --change 9353
5802 hg status --copies --change 9353
5803
5803
5804 - get a NUL separated list of added files, suitable for xargs::
5804 - get a NUL separated list of added files, suitable for xargs::
5805
5805
5806 hg status -an0
5806 hg status -an0
5807
5807
5808 Returns 0 on success.
5808 Returns 0 on success.
5809 """
5809 """
5810
5810
5811 revs = opts.get('rev')
5811 revs = opts.get('rev')
5812 change = opts.get('change')
5812 change = opts.get('change')
5813
5813
5814 if revs and change:
5814 if revs and change:
5815 msg = _('cannot specify --rev and --change at the same time')
5815 msg = _('cannot specify --rev and --change at the same time')
5816 raise util.Abort(msg)
5816 raise util.Abort(msg)
5817 elif change:
5817 elif change:
5818 node2 = scmutil.revsingle(repo, change, None).node()
5818 node2 = scmutil.revsingle(repo, change, None).node()
5819 node1 = repo[node2].p1().node()
5819 node1 = repo[node2].p1().node()
5820 else:
5820 else:
5821 node1, node2 = scmutil.revpair(repo, revs)
5821 node1, node2 = scmutil.revpair(repo, revs)
5822
5822
5823 if pats:
5823 if pats:
5824 cwd = repo.getcwd()
5824 cwd = repo.getcwd()
5825 else:
5825 else:
5826 cwd = ''
5826 cwd = ''
5827
5827
5828 if opts.get('print0'):
5828 if opts.get('print0'):
5829 end = '\0'
5829 end = '\0'
5830 else:
5830 else:
5831 end = '\n'
5831 end = '\n'
5832 copy = {}
5832 copy = {}
5833 states = 'modified added removed deleted unknown ignored clean'.split()
5833 states = 'modified added removed deleted unknown ignored clean'.split()
5834 show = [k for k in states if opts.get(k)]
5834 show = [k for k in states if opts.get(k)]
5835 if opts.get('all'):
5835 if opts.get('all'):
5836 show += ui.quiet and (states[:4] + ['clean']) or states
5836 show += ui.quiet and (states[:4] + ['clean']) or states
5837 if not show:
5837 if not show:
5838 if ui.quiet:
5838 if ui.quiet:
5839 show = states[:4]
5839 show = states[:4]
5840 else:
5840 else:
5841 show = states[:5]
5841 show = states[:5]
5842
5842
5843 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5843 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5844 'ignored' in show, 'clean' in show, 'unknown' in show,
5844 'ignored' in show, 'clean' in show, 'unknown' in show,
5845 opts.get('subrepos'))
5845 opts.get('subrepos'))
5846 changestates = zip(states, 'MAR!?IC', stat)
5846 changestates = zip(states, 'MAR!?IC', stat)
5847
5847
5848 if (opts.get('all') or opts.get('copies')
5848 if (opts.get('all') or opts.get('copies')
5849 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5849 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5850 copy = copies.pathcopies(repo[node1], repo[node2])
5850 copy = copies.pathcopies(repo[node1], repo[node2])
5851
5851
5852 fm = ui.formatter('status', opts)
5852 fm = ui.formatter('status', opts)
5853 fmt = '%s' + end
5853 fmt = '%s' + end
5854 showchar = not opts.get('no_status')
5854 showchar = not opts.get('no_status')
5855
5855
5856 for state, char, files in changestates:
5856 for state, char, files in changestates:
5857 if state in show:
5857 if state in show:
5858 label = 'status.' + state
5858 label = 'status.' + state
5859 for f in files:
5859 for f in files:
5860 fm.startitem()
5860 fm.startitem()
5861 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5861 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5862 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5862 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5863 if f in copy:
5863 if f in copy:
5864 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5864 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5865 label='status.copied')
5865 label='status.copied')
5866 fm.end()
5866 fm.end()
5867
5867
5868 @command('^summary|sum',
5868 @command('^summary|sum',
5869 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5869 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5870 def summary(ui, repo, **opts):
5870 def summary(ui, repo, **opts):
5871 """summarize working directory state
5871 """summarize working directory state
5872
5872
5873 This generates a brief summary of the working directory state,
5873 This generates a brief summary of the working directory state,
5874 including parents, branch, commit status, and available updates.
5874 including parents, branch, commit status, and available updates.
5875
5875
5876 With the --remote option, this will check the default paths for
5876 With the --remote option, this will check the default paths for
5877 incoming and outgoing changes. This can be time-consuming.
5877 incoming and outgoing changes. This can be time-consuming.
5878
5878
5879 Returns 0 on success.
5879 Returns 0 on success.
5880 """
5880 """
5881
5881
5882 ctx = repo[None]
5882 ctx = repo[None]
5883 parents = ctx.parents()
5883 parents = ctx.parents()
5884 pnode = parents[0].node()
5884 pnode = parents[0].node()
5885 marks = []
5885 marks = []
5886
5886
5887 for p in parents:
5887 for p in parents:
5888 # label with log.changeset (instead of log.parent) since this
5888 # label with log.changeset (instead of log.parent) since this
5889 # shows a working directory parent *changeset*:
5889 # shows a working directory parent *changeset*:
5890 # i18n: column positioning for "hg summary"
5890 # i18n: column positioning for "hg summary"
5891 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5891 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5892 label='log.changeset changeset.%s' % p.phasestr())
5892 label='log.changeset changeset.%s' % p.phasestr())
5893 ui.write(' '.join(p.tags()), label='log.tag')
5893 ui.write(' '.join(p.tags()), label='log.tag')
5894 if p.bookmarks():
5894 if p.bookmarks():
5895 marks.extend(p.bookmarks())
5895 marks.extend(p.bookmarks())
5896 if p.rev() == -1:
5896 if p.rev() == -1:
5897 if not len(repo):
5897 if not len(repo):
5898 ui.write(_(' (empty repository)'))
5898 ui.write(_(' (empty repository)'))
5899 else:
5899 else:
5900 ui.write(_(' (no revision checked out)'))
5900 ui.write(_(' (no revision checked out)'))
5901 ui.write('\n')
5901 ui.write('\n')
5902 if p.description():
5902 if p.description():
5903 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5903 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5904 label='log.summary')
5904 label='log.summary')
5905
5905
5906 branch = ctx.branch()
5906 branch = ctx.branch()
5907 bheads = repo.branchheads(branch)
5907 bheads = repo.branchheads(branch)
5908 # i18n: column positioning for "hg summary"
5908 # i18n: column positioning for "hg summary"
5909 m = _('branch: %s\n') % branch
5909 m = _('branch: %s\n') % branch
5910 if branch != 'default':
5910 if branch != 'default':
5911 ui.write(m, label='log.branch')
5911 ui.write(m, label='log.branch')
5912 else:
5912 else:
5913 ui.status(m, label='log.branch')
5913 ui.status(m, label='log.branch')
5914
5914
5915 if marks:
5915 if marks:
5916 current = repo._bookmarkcurrent
5916 current = repo._bookmarkcurrent
5917 # i18n: column positioning for "hg summary"
5917 # i18n: column positioning for "hg summary"
5918 ui.write(_('bookmarks:'), label='log.bookmark')
5918 ui.write(_('bookmarks:'), label='log.bookmark')
5919 if current is not None:
5919 if current is not None:
5920 if current in marks:
5920 if current in marks:
5921 ui.write(' *' + current, label='bookmarks.current')
5921 ui.write(' *' + current, label='bookmarks.current')
5922 marks.remove(current)
5922 marks.remove(current)
5923 else:
5923 else:
5924 ui.write(' [%s]' % current, label='bookmarks.current')
5924 ui.write(' [%s]' % current, label='bookmarks.current')
5925 for m in marks:
5925 for m in marks:
5926 ui.write(' ' + m, label='log.bookmark')
5926 ui.write(' ' + m, label='log.bookmark')
5927 ui.write('\n', label='log.bookmark')
5927 ui.write('\n', label='log.bookmark')
5928
5928
5929 status = repo.status(unknown=True)
5929 status = repo.status(unknown=True)
5930
5930
5931 c = repo.dirstate.copies()
5931 c = repo.dirstate.copies()
5932 copied, renamed = [], []
5932 copied, renamed = [], []
5933 for d, s in c.iteritems():
5933 for d, s in c.iteritems():
5934 if s in status.removed:
5934 if s in status.removed:
5935 status.removed.remove(s)
5935 status.removed.remove(s)
5936 renamed.append(d)
5936 renamed.append(d)
5937 else:
5937 else:
5938 copied.append(d)
5938 copied.append(d)
5939 if d in status.added:
5939 if d in status.added:
5940 status.added.remove(d)
5940 status.added.remove(d)
5941
5941
5942 ms = mergemod.mergestate(repo)
5942 ms = mergemod.mergestate(repo)
5943 unresolved = [f for f in ms if ms[f] == 'u']
5943 unresolved = [f for f in ms if ms[f] == 'u']
5944
5944
5945 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5945 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5946
5946
5947 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5947 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5948 (ui.label(_('%d added'), 'status.added'), status.added),
5948 (ui.label(_('%d added'), 'status.added'), status.added),
5949 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5949 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5950 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5950 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5951 (ui.label(_('%d copied'), 'status.copied'), copied),
5951 (ui.label(_('%d copied'), 'status.copied'), copied),
5952 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5952 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5953 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5953 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5954 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5954 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5955 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5955 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5956 t = []
5956 t = []
5957 for l, s in labels:
5957 for l, s in labels:
5958 if s:
5958 if s:
5959 t.append(l % len(s))
5959 t.append(l % len(s))
5960
5960
5961 t = ', '.join(t)
5961 t = ', '.join(t)
5962 cleanworkdir = False
5962 cleanworkdir = False
5963
5963
5964 if repo.vfs.exists('updatestate'):
5964 if repo.vfs.exists('updatestate'):
5965 t += _(' (interrupted update)')
5965 t += _(' (interrupted update)')
5966 elif len(parents) > 1:
5966 elif len(parents) > 1:
5967 t += _(' (merge)')
5967 t += _(' (merge)')
5968 elif branch != parents[0].branch():
5968 elif branch != parents[0].branch():
5969 t += _(' (new branch)')
5969 t += _(' (new branch)')
5970 elif (parents[0].closesbranch() and
5970 elif (parents[0].closesbranch() and
5971 pnode in repo.branchheads(branch, closed=True)):
5971 pnode in repo.branchheads(branch, closed=True)):
5972 t += _(' (head closed)')
5972 t += _(' (head closed)')
5973 elif not (status.modified or status.added or status.removed or renamed or
5973 elif not (status.modified or status.added or status.removed or renamed or
5974 copied or subs):
5974 copied or subs):
5975 t += _(' (clean)')
5975 t += _(' (clean)')
5976 cleanworkdir = True
5976 cleanworkdir = True
5977 elif pnode not in bheads:
5977 elif pnode not in bheads:
5978 t += _(' (new branch head)')
5978 t += _(' (new branch head)')
5979
5979
5980 if cleanworkdir:
5980 if cleanworkdir:
5981 # i18n: column positioning for "hg summary"
5981 # i18n: column positioning for "hg summary"
5982 ui.status(_('commit: %s\n') % t.strip())
5982 ui.status(_('commit: %s\n') % t.strip())
5983 else:
5983 else:
5984 # i18n: column positioning for "hg summary"
5984 # i18n: column positioning for "hg summary"
5985 ui.write(_('commit: %s\n') % t.strip())
5985 ui.write(_('commit: %s\n') % t.strip())
5986
5986
5987 # all ancestors of branch heads - all ancestors of parent = new csets
5987 # all ancestors of branch heads - all ancestors of parent = new csets
5988 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5988 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5989 bheads))
5989 bheads))
5990
5990
5991 if new == 0:
5991 if new == 0:
5992 # i18n: column positioning for "hg summary"
5992 # i18n: column positioning for "hg summary"
5993 ui.status(_('update: (current)\n'))
5993 ui.status(_('update: (current)\n'))
5994 elif pnode not in bheads:
5994 elif pnode not in bheads:
5995 # i18n: column positioning for "hg summary"
5995 # i18n: column positioning for "hg summary"
5996 ui.write(_('update: %d new changesets (update)\n') % new)
5996 ui.write(_('update: %d new changesets (update)\n') % new)
5997 else:
5997 else:
5998 # i18n: column positioning for "hg summary"
5998 # i18n: column positioning for "hg summary"
5999 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5999 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6000 (new, len(bheads)))
6000 (new, len(bheads)))
6001
6001
6002 cmdutil.summaryhooks(ui, repo)
6002 cmdutil.summaryhooks(ui, repo)
6003
6003
6004 if opts.get('remote'):
6004 if opts.get('remote'):
6005 needsincoming, needsoutgoing = True, True
6005 needsincoming, needsoutgoing = True, True
6006 else:
6006 else:
6007 needsincoming, needsoutgoing = False, False
6007 needsincoming, needsoutgoing = False, False
6008 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6008 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6009 if i:
6009 if i:
6010 needsincoming = True
6010 needsincoming = True
6011 if o:
6011 if o:
6012 needsoutgoing = True
6012 needsoutgoing = True
6013 if not needsincoming and not needsoutgoing:
6013 if not needsincoming and not needsoutgoing:
6014 return
6014 return
6015
6015
6016 def getincoming():
6016 def getincoming():
6017 source, branches = hg.parseurl(ui.expandpath('default'))
6017 source, branches = hg.parseurl(ui.expandpath('default'))
6018 sbranch = branches[0]
6018 sbranch = branches[0]
6019 try:
6019 try:
6020 other = hg.peer(repo, {}, source)
6020 other = hg.peer(repo, {}, source)
6021 except error.RepoError:
6021 except error.RepoError:
6022 if opts.get('remote'):
6022 if opts.get('remote'):
6023 raise
6023 raise
6024 return source, sbranch, None, None, None
6024 return source, sbranch, None, None, None
6025 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6025 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6026 if revs:
6026 if revs:
6027 revs = [other.lookup(rev) for rev in revs]
6027 revs = [other.lookup(rev) for rev in revs]
6028 ui.debug('comparing with %s\n' % util.hidepassword(source))
6028 ui.debug('comparing with %s\n' % util.hidepassword(source))
6029 repo.ui.pushbuffer()
6029 repo.ui.pushbuffer()
6030 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6030 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6031 repo.ui.popbuffer()
6031 repo.ui.popbuffer()
6032 return source, sbranch, other, commoninc, commoninc[1]
6032 return source, sbranch, other, commoninc, commoninc[1]
6033
6033
6034 if needsincoming:
6034 if needsincoming:
6035 source, sbranch, sother, commoninc, incoming = getincoming()
6035 source, sbranch, sother, commoninc, incoming = getincoming()
6036 else:
6036 else:
6037 source = sbranch = sother = commoninc = incoming = None
6037 source = sbranch = sother = commoninc = incoming = None
6038
6038
6039 def getoutgoing():
6039 def getoutgoing():
6040 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6040 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6041 dbranch = branches[0]
6041 dbranch = branches[0]
6042 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6042 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6043 if source != dest:
6043 if source != dest:
6044 try:
6044 try:
6045 dother = hg.peer(repo, {}, dest)
6045 dother = hg.peer(repo, {}, dest)
6046 except error.RepoError:
6046 except error.RepoError:
6047 if opts.get('remote'):
6047 if opts.get('remote'):
6048 raise
6048 raise
6049 return dest, dbranch, None, None
6049 return dest, dbranch, None, None
6050 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6050 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6051 elif sother is None:
6051 elif sother is None:
6052 # there is no explicit destination peer, but source one is invalid
6052 # there is no explicit destination peer, but source one is invalid
6053 return dest, dbranch, None, None
6053 return dest, dbranch, None, None
6054 else:
6054 else:
6055 dother = sother
6055 dother = sother
6056 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6056 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6057 common = None
6057 common = None
6058 else:
6058 else:
6059 common = commoninc
6059 common = commoninc
6060 if revs:
6060 if revs:
6061 revs = [repo.lookup(rev) for rev in revs]
6061 revs = [repo.lookup(rev) for rev in revs]
6062 repo.ui.pushbuffer()
6062 repo.ui.pushbuffer()
6063 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6063 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6064 commoninc=common)
6064 commoninc=common)
6065 repo.ui.popbuffer()
6065 repo.ui.popbuffer()
6066 return dest, dbranch, dother, outgoing
6066 return dest, dbranch, dother, outgoing
6067
6067
6068 if needsoutgoing:
6068 if needsoutgoing:
6069 dest, dbranch, dother, outgoing = getoutgoing()
6069 dest, dbranch, dother, outgoing = getoutgoing()
6070 else:
6070 else:
6071 dest = dbranch = dother = outgoing = None
6071 dest = dbranch = dother = outgoing = None
6072
6072
6073 if opts.get('remote'):
6073 if opts.get('remote'):
6074 t = []
6074 t = []
6075 if incoming:
6075 if incoming:
6076 t.append(_('1 or more incoming'))
6076 t.append(_('1 or more incoming'))
6077 o = outgoing.missing
6077 o = outgoing.missing
6078 if o:
6078 if o:
6079 t.append(_('%d outgoing') % len(o))
6079 t.append(_('%d outgoing') % len(o))
6080 other = dother or sother
6080 other = dother or sother
6081 if 'bookmarks' in other.listkeys('namespaces'):
6081 if 'bookmarks' in other.listkeys('namespaces'):
6082 counts = bookmarks.summary(repo, other)
6082 counts = bookmarks.summary(repo, other)
6083 if counts[0] > 0:
6083 if counts[0] > 0:
6084 t.append(_('%d incoming bookmarks') % counts[0])
6084 t.append(_('%d incoming bookmarks') % counts[0])
6085 if counts[1] > 0:
6085 if counts[1] > 0:
6086 t.append(_('%d outgoing bookmarks') % counts[1])
6086 t.append(_('%d outgoing bookmarks') % counts[1])
6087
6087
6088 if t:
6088 if t:
6089 # i18n: column positioning for "hg summary"
6089 # i18n: column positioning for "hg summary"
6090 ui.write(_('remote: %s\n') % (', '.join(t)))
6090 ui.write(_('remote: %s\n') % (', '.join(t)))
6091 else:
6091 else:
6092 # i18n: column positioning for "hg summary"
6092 # i18n: column positioning for "hg summary"
6093 ui.status(_('remote: (synced)\n'))
6093 ui.status(_('remote: (synced)\n'))
6094
6094
6095 cmdutil.summaryremotehooks(ui, repo, opts,
6095 cmdutil.summaryremotehooks(ui, repo, opts,
6096 ((source, sbranch, sother, commoninc),
6096 ((source, sbranch, sother, commoninc),
6097 (dest, dbranch, dother, outgoing)))
6097 (dest, dbranch, dother, outgoing)))
6098
6098
6099 @command('tag',
6099 @command('tag',
6100 [('f', 'force', None, _('force tag')),
6100 [('f', 'force', None, _('force tag')),
6101 ('l', 'local', None, _('make the tag local')),
6101 ('l', 'local', None, _('make the tag local')),
6102 ('r', 'rev', '', _('revision to tag'), _('REV')),
6102 ('r', 'rev', '', _('revision to tag'), _('REV')),
6103 ('', 'remove', None, _('remove a tag')),
6103 ('', 'remove', None, _('remove a tag')),
6104 # -l/--local is already there, commitopts cannot be used
6104 # -l/--local is already there, commitopts cannot be used
6105 ('e', 'edit', None, _('invoke editor on commit messages')),
6105 ('e', 'edit', None, _('invoke editor on commit messages')),
6106 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6106 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6107 ] + commitopts2,
6107 ] + commitopts2,
6108 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6108 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6109 def tag(ui, repo, name1, *names, **opts):
6109 def tag(ui, repo, name1, *names, **opts):
6110 """add one or more tags for the current or given revision
6110 """add one or more tags for the current or given revision
6111
6111
6112 Name a particular revision using <name>.
6112 Name a particular revision using <name>.
6113
6113
6114 Tags are used to name particular revisions of the repository and are
6114 Tags are used to name particular revisions of the repository and are
6115 very useful to compare different revisions, to go back to significant
6115 very useful to compare different revisions, to go back to significant
6116 earlier versions or to mark branch points as releases, etc. Changing
6116 earlier versions or to mark branch points as releases, etc. Changing
6117 an existing tag is normally disallowed; use -f/--force to override.
6117 an existing tag is normally disallowed; use -f/--force to override.
6118
6118
6119 If no revision is given, the parent of the working directory is
6119 If no revision is given, the parent of the working directory is
6120 used.
6120 used.
6121
6121
6122 To facilitate version control, distribution, and merging of tags,
6122 To facilitate version control, distribution, and merging of tags,
6123 they are stored as a file named ".hgtags" which is managed similarly
6123 they are stored as a file named ".hgtags" which is managed similarly
6124 to other project files and can be hand-edited if necessary. This
6124 to other project files and can be hand-edited if necessary. This
6125 also means that tagging creates a new commit. The file
6125 also means that tagging creates a new commit. The file
6126 ".hg/localtags" is used for local tags (not shared among
6126 ".hg/localtags" is used for local tags (not shared among
6127 repositories).
6127 repositories).
6128
6128
6129 Tag commits are usually made at the head of a branch. If the parent
6129 Tag commits are usually made at the head of a branch. If the parent
6130 of the working directory is not a branch head, :hg:`tag` aborts; use
6130 of the working directory is not a branch head, :hg:`tag` aborts; use
6131 -f/--force to force the tag commit to be based on a non-head
6131 -f/--force to force the tag commit to be based on a non-head
6132 changeset.
6132 changeset.
6133
6133
6134 See :hg:`help dates` for a list of formats valid for -d/--date.
6134 See :hg:`help dates` for a list of formats valid for -d/--date.
6135
6135
6136 Since tag names have priority over branch names during revision
6136 Since tag names have priority over branch names during revision
6137 lookup, using an existing branch name as a tag name is discouraged.
6137 lookup, using an existing branch name as a tag name is discouraged.
6138
6138
6139 Returns 0 on success.
6139 Returns 0 on success.
6140 """
6140 """
6141 wlock = lock = None
6141 wlock = lock = None
6142 try:
6142 try:
6143 wlock = repo.wlock()
6143 wlock = repo.wlock()
6144 lock = repo.lock()
6144 lock = repo.lock()
6145 rev_ = "."
6145 rev_ = "."
6146 names = [t.strip() for t in (name1,) + names]
6146 names = [t.strip() for t in (name1,) + names]
6147 if len(names) != len(set(names)):
6147 if len(names) != len(set(names)):
6148 raise util.Abort(_('tag names must be unique'))
6148 raise util.Abort(_('tag names must be unique'))
6149 for n in names:
6149 for n in names:
6150 scmutil.checknewlabel(repo, n, 'tag')
6150 scmutil.checknewlabel(repo, n, 'tag')
6151 if not n:
6151 if not n:
6152 raise util.Abort(_('tag names cannot consist entirely of '
6152 raise util.Abort(_('tag names cannot consist entirely of '
6153 'whitespace'))
6153 'whitespace'))
6154 if opts.get('rev') and opts.get('remove'):
6154 if opts.get('rev') and opts.get('remove'):
6155 raise util.Abort(_("--rev and --remove are incompatible"))
6155 raise util.Abort(_("--rev and --remove are incompatible"))
6156 if opts.get('rev'):
6156 if opts.get('rev'):
6157 rev_ = opts['rev']
6157 rev_ = opts['rev']
6158 message = opts.get('message')
6158 message = opts.get('message')
6159 if opts.get('remove'):
6159 if opts.get('remove'):
6160 if opts.get('local'):
6160 if opts.get('local'):
6161 expectedtype = 'local'
6161 expectedtype = 'local'
6162 else:
6162 else:
6163 expectedtype = 'global'
6163 expectedtype = 'global'
6164
6164
6165 for n in names:
6165 for n in names:
6166 if not repo.tagtype(n):
6166 if not repo.tagtype(n):
6167 raise util.Abort(_("tag '%s' does not exist") % n)
6167 raise util.Abort(_("tag '%s' does not exist") % n)
6168 if repo.tagtype(n) != expectedtype:
6168 if repo.tagtype(n) != expectedtype:
6169 if expectedtype == 'global':
6169 if expectedtype == 'global':
6170 raise util.Abort(_("tag '%s' is not a global tag") % n)
6170 raise util.Abort(_("tag '%s' is not a global tag") % n)
6171 else:
6171 else:
6172 raise util.Abort(_("tag '%s' is not a local tag") % n)
6172 raise util.Abort(_("tag '%s' is not a local tag") % n)
6173 rev_ = nullid
6173 rev_ = nullid
6174 if not message:
6174 if not message:
6175 # we don't translate commit messages
6175 # we don't translate commit messages
6176 message = 'Removed tag %s' % ', '.join(names)
6176 message = 'Removed tag %s' % ', '.join(names)
6177 elif not opts.get('force'):
6177 elif not opts.get('force'):
6178 for n in names:
6178 for n in names:
6179 if n in repo.tags():
6179 if n in repo.tags():
6180 raise util.Abort(_("tag '%s' already exists "
6180 raise util.Abort(_("tag '%s' already exists "
6181 "(use -f to force)") % n)
6181 "(use -f to force)") % n)
6182 if not opts.get('local'):
6182 if not opts.get('local'):
6183 p1, p2 = repo.dirstate.parents()
6183 p1, p2 = repo.dirstate.parents()
6184 if p2 != nullid:
6184 if p2 != nullid:
6185 raise util.Abort(_('uncommitted merge'))
6185 raise util.Abort(_('uncommitted merge'))
6186 bheads = repo.branchheads()
6186 bheads = repo.branchheads()
6187 if not opts.get('force') and bheads and p1 not in bheads:
6187 if not opts.get('force') and bheads and p1 not in bheads:
6188 raise util.Abort(_('not at a branch head (use -f to force)'))
6188 raise util.Abort(_('not at a branch head (use -f to force)'))
6189 r = scmutil.revsingle(repo, rev_).node()
6189 r = scmutil.revsingle(repo, rev_).node()
6190
6190
6191 if not message:
6191 if not message:
6192 # we don't translate commit messages
6192 # we don't translate commit messages
6193 message = ('Added tag %s for changeset %s' %
6193 message = ('Added tag %s for changeset %s' %
6194 (', '.join(names), short(r)))
6194 (', '.join(names), short(r)))
6195
6195
6196 date = opts.get('date')
6196 date = opts.get('date')
6197 if date:
6197 if date:
6198 date = util.parsedate(date)
6198 date = util.parsedate(date)
6199
6199
6200 if opts.get('remove'):
6200 if opts.get('remove'):
6201 editform = 'tag.remove'
6201 editform = 'tag.remove'
6202 else:
6202 else:
6203 editform = 'tag.add'
6203 editform = 'tag.add'
6204 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6204 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6205
6205
6206 # don't allow tagging the null rev
6206 # don't allow tagging the null rev
6207 if (not opts.get('remove') and
6207 if (not opts.get('remove') and
6208 scmutil.revsingle(repo, rev_).rev() == nullrev):
6208 scmutil.revsingle(repo, rev_).rev() == nullrev):
6209 raise util.Abort(_("cannot tag null revision"))
6209 raise util.Abort(_("cannot tag null revision"))
6210
6210
6211 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6211 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6212 editor=editor)
6212 editor=editor)
6213 finally:
6213 finally:
6214 release(lock, wlock)
6214 release(lock, wlock)
6215
6215
6216 @command('tags', formatteropts, '')
6216 @command('tags', formatteropts, '')
6217 def tags(ui, repo, **opts):
6217 def tags(ui, repo, **opts):
6218 """list repository tags
6218 """list repository tags
6219
6219
6220 This lists both regular and local tags. When the -v/--verbose
6220 This lists both regular and local tags. When the -v/--verbose
6221 switch is used, a third column "local" is printed for local tags.
6221 switch is used, a third column "local" is printed for local tags.
6222
6222
6223 Returns 0 on success.
6223 Returns 0 on success.
6224 """
6224 """
6225
6225
6226 fm = ui.formatter('tags', opts)
6226 fm = ui.formatter('tags', opts)
6227 hexfunc = fm.hexfunc
6227 hexfunc = fm.hexfunc
6228 tagtype = ""
6228 tagtype = ""
6229
6229
6230 for t, n in reversed(repo.tagslist()):
6230 for t, n in reversed(repo.tagslist()):
6231 hn = hexfunc(n)
6231 hn = hexfunc(n)
6232 label = 'tags.normal'
6232 label = 'tags.normal'
6233 tagtype = ''
6233 tagtype = ''
6234 if repo.tagtype(t) == 'local':
6234 if repo.tagtype(t) == 'local':
6235 label = 'tags.local'
6235 label = 'tags.local'
6236 tagtype = 'local'
6236 tagtype = 'local'
6237
6237
6238 fm.startitem()
6238 fm.startitem()
6239 fm.write('tag', '%s', t, label=label)
6239 fm.write('tag', '%s', t, label=label)
6240 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6240 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6241 fm.condwrite(not ui.quiet, 'rev node', fmt,
6241 fm.condwrite(not ui.quiet, 'rev node', fmt,
6242 repo.changelog.rev(n), hn, label=label)
6242 repo.changelog.rev(n), hn, label=label)
6243 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6243 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6244 tagtype, label=label)
6244 tagtype, label=label)
6245 fm.plain('\n')
6245 fm.plain('\n')
6246 fm.end()
6246 fm.end()
6247
6247
6248 @command('tip',
6248 @command('tip',
6249 [('p', 'patch', None, _('show patch')),
6249 [('p', 'patch', None, _('show patch')),
6250 ('g', 'git', None, _('use git extended diff format')),
6250 ('g', 'git', None, _('use git extended diff format')),
6251 ] + templateopts,
6251 ] + templateopts,
6252 _('[-p] [-g]'))
6252 _('[-p] [-g]'))
6253 def tip(ui, repo, **opts):
6253 def tip(ui, repo, **opts):
6254 """show the tip revision (DEPRECATED)
6254 """show the tip revision (DEPRECATED)
6255
6255
6256 The tip revision (usually just called the tip) is the changeset
6256 The tip revision (usually just called the tip) is the changeset
6257 most recently added to the repository (and therefore the most
6257 most recently added to the repository (and therefore the most
6258 recently changed head).
6258 recently changed head).
6259
6259
6260 If you have just made a commit, that commit will be the tip. If
6260 If you have just made a commit, that commit will be the tip. If
6261 you have just pulled changes from another repository, the tip of
6261 you have just pulled changes from another repository, the tip of
6262 that repository becomes the current tip. The "tip" tag is special
6262 that repository becomes the current tip. The "tip" tag is special
6263 and cannot be renamed or assigned to a different changeset.
6263 and cannot be renamed or assigned to a different changeset.
6264
6264
6265 This command is deprecated, please use :hg:`heads` instead.
6265 This command is deprecated, please use :hg:`heads` instead.
6266
6266
6267 Returns 0 on success.
6267 Returns 0 on success.
6268 """
6268 """
6269 displayer = cmdutil.show_changeset(ui, repo, opts)
6269 displayer = cmdutil.show_changeset(ui, repo, opts)
6270 displayer.show(repo['tip'])
6270 displayer.show(repo['tip'])
6271 displayer.close()
6271 displayer.close()
6272
6272
6273 @command('unbundle',
6273 @command('unbundle',
6274 [('u', 'update', None,
6274 [('u', 'update', None,
6275 _('update to new branch head if changesets were unbundled'))],
6275 _('update to new branch head if changesets were unbundled'))],
6276 _('[-u] FILE...'))
6276 _('[-u] FILE...'))
6277 def unbundle(ui, repo, fname1, *fnames, **opts):
6277 def unbundle(ui, repo, fname1, *fnames, **opts):
6278 """apply one or more changegroup files
6278 """apply one or more changegroup files
6279
6279
6280 Apply one or more compressed changegroup files generated by the
6280 Apply one or more compressed changegroup files generated by the
6281 bundle command.
6281 bundle command.
6282
6282
6283 Returns 0 on success, 1 if an update has unresolved files.
6283 Returns 0 on success, 1 if an update has unresolved files.
6284 """
6284 """
6285 fnames = (fname1,) + fnames
6285 fnames = (fname1,) + fnames
6286
6286
6287 lock = repo.lock()
6287 lock = repo.lock()
6288 try:
6288 try:
6289 for fname in fnames:
6289 for fname in fnames:
6290 f = hg.openpath(ui, fname)
6290 f = hg.openpath(ui, fname)
6291 gen = exchange.readbundle(ui, f, fname)
6291 gen = exchange.readbundle(ui, f, fname)
6292 if isinstance(gen, bundle2.unbundle20):
6292 if isinstance(gen, bundle2.unbundle20):
6293 tr = repo.transaction('unbundle')
6293 tr = repo.transaction('unbundle')
6294 try:
6294 try:
6295 op = bundle2.processbundle(repo, gen, lambda: tr)
6295 op = bundle2.processbundle(repo, gen, lambda: tr)
6296 tr.close()
6296 tr.close()
6297 finally:
6297 finally:
6298 if tr:
6298 if tr:
6299 tr.release()
6299 tr.release()
6300 changes = [r.get('result', 0)
6300 changes = [r.get('result', 0)
6301 for r in op.records['changegroup']]
6301 for r in op.records['changegroup']]
6302 modheads = changegroup.combineresults(changes)
6302 modheads = changegroup.combineresults(changes)
6303 else:
6303 else:
6304 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6304 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6305 'bundle:' + fname)
6305 'bundle:' + fname)
6306 finally:
6306 finally:
6307 lock.release()
6307 lock.release()
6308
6308
6309 return postincoming(ui, repo, modheads, opts.get('update'), None)
6309 return postincoming(ui, repo, modheads, opts.get('update'), None)
6310
6310
6311 @command('^update|up|checkout|co',
6311 @command('^update|up|checkout|co',
6312 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6312 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6313 ('c', 'check', None,
6313 ('c', 'check', None,
6314 _('update across branches if no uncommitted changes')),
6314 _('update across branches if no uncommitted changes')),
6315 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6315 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6316 ('r', 'rev', '', _('revision'), _('REV'))
6316 ('r', 'rev', '', _('revision'), _('REV'))
6317 ] + mergetoolopts,
6317 ] + mergetoolopts,
6318 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6318 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6319 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6319 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6320 tool=None):
6320 tool=None):
6321 """update working directory (or switch revisions)
6321 """update working directory (or switch revisions)
6322
6322
6323 Update the repository's working directory to the specified
6323 Update the repository's working directory to the specified
6324 changeset. If no changeset is specified, update to the tip of the
6324 changeset. If no changeset is specified, update to the tip of the
6325 current named branch and move the current bookmark (see :hg:`help
6325 current named branch and move the current bookmark (see :hg:`help
6326 bookmarks`).
6326 bookmarks`).
6327
6327
6328 Update sets the working directory's parent revision to the specified
6328 Update sets the working directory's parent revision to the specified
6329 changeset (see :hg:`help parents`).
6329 changeset (see :hg:`help parents`).
6330
6330
6331 If the changeset is not a descendant or ancestor of the working
6331 If the changeset is not a descendant or ancestor of the working
6332 directory's parent, the update is aborted. With the -c/--check
6332 directory's parent, the update is aborted. With the -c/--check
6333 option, the working directory is checked for uncommitted changes; if
6333 option, the working directory is checked for uncommitted changes; if
6334 none are found, the working directory is updated to the specified
6334 none are found, the working directory is updated to the specified
6335 changeset.
6335 changeset.
6336
6336
6337 .. container:: verbose
6337 .. container:: verbose
6338
6338
6339 The following rules apply when the working directory contains
6339 The following rules apply when the working directory contains
6340 uncommitted changes:
6340 uncommitted changes:
6341
6341
6342 1. If neither -c/--check nor -C/--clean is specified, and if
6342 1. If neither -c/--check nor -C/--clean is specified, and if
6343 the requested changeset is an ancestor or descendant of
6343 the requested changeset is an ancestor or descendant of
6344 the working directory's parent, the uncommitted changes
6344 the working directory's parent, the uncommitted changes
6345 are merged into the requested changeset and the merged
6345 are merged into the requested changeset and the merged
6346 result is left uncommitted. If the requested changeset is
6346 result is left uncommitted. If the requested changeset is
6347 not an ancestor or descendant (that is, it is on another
6347 not an ancestor or descendant (that is, it is on another
6348 branch), the update is aborted and the uncommitted changes
6348 branch), the update is aborted and the uncommitted changes
6349 are preserved.
6349 are preserved.
6350
6350
6351 2. With the -c/--check option, the update is aborted and the
6351 2. With the -c/--check option, the update is aborted and the
6352 uncommitted changes are preserved.
6352 uncommitted changes are preserved.
6353
6353
6354 3. With the -C/--clean option, uncommitted changes are discarded and
6354 3. With the -C/--clean option, uncommitted changes are discarded and
6355 the working directory is updated to the requested changeset.
6355 the working directory is updated to the requested changeset.
6356
6356
6357 To cancel an uncommitted merge (and lose your changes), use
6357 To cancel an uncommitted merge (and lose your changes), use
6358 :hg:`update --clean .`.
6358 :hg:`update --clean .`.
6359
6359
6360 Use null as the changeset to remove the working directory (like
6360 Use null as the changeset to remove the working directory (like
6361 :hg:`clone -U`).
6361 :hg:`clone -U`).
6362
6362
6363 If you want to revert just one file to an older revision, use
6363 If you want to revert just one file to an older revision, use
6364 :hg:`revert [-r REV] NAME`.
6364 :hg:`revert [-r REV] NAME`.
6365
6365
6366 See :hg:`help dates` for a list of formats valid for -d/--date.
6366 See :hg:`help dates` for a list of formats valid for -d/--date.
6367
6367
6368 Returns 0 on success, 1 if there are unresolved files.
6368 Returns 0 on success, 1 if there are unresolved files.
6369 """
6369 """
6370 if rev and node:
6370 if rev and node:
6371 raise util.Abort(_("please specify just one revision"))
6371 raise util.Abort(_("please specify just one revision"))
6372
6372
6373 if rev is None or rev == '':
6373 if rev is None or rev == '':
6374 rev = node
6374 rev = node
6375
6375
6376 cmdutil.clearunfinished(repo)
6376 cmdutil.clearunfinished(repo)
6377
6377
6378 # with no argument, we also move the current bookmark, if any
6378 # with no argument, we also move the current bookmark, if any
6379 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6379 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6380
6380
6381 # if we defined a bookmark, we have to remember the original bookmark name
6381 # if we defined a bookmark, we have to remember the original bookmark name
6382 brev = rev
6382 brev = rev
6383 rev = scmutil.revsingle(repo, rev, rev).rev()
6383 rev = scmutil.revsingle(repo, rev, rev).rev()
6384
6384
6385 if check and clean:
6385 if check and clean:
6386 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6386 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6387
6387
6388 if date:
6388 if date:
6389 if rev is not None:
6389 if rev is not None:
6390 raise util.Abort(_("you can't specify a revision and a date"))
6390 raise util.Abort(_("you can't specify a revision and a date"))
6391 rev = cmdutil.finddate(ui, repo, date)
6391 rev = cmdutil.finddate(ui, repo, date)
6392
6392
6393 if check:
6393 if check:
6394 cmdutil.bailifchanged(repo, merge=False)
6394 cmdutil.bailifchanged(repo, merge=False)
6395 if rev is None:
6395 if rev is None:
6396 rev = repo[repo[None].branch()].rev()
6396 rev = repo[repo[None].branch()].rev()
6397
6397
6398 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6398 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6399
6399
6400 if clean:
6400 if clean:
6401 ret = hg.clean(repo, rev)
6401 ret = hg.clean(repo, rev)
6402 else:
6402 else:
6403 ret = hg.update(repo, rev)
6403 ret = hg.update(repo, rev)
6404
6404
6405 if not ret and movemarkfrom:
6405 if not ret and movemarkfrom:
6406 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6406 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6407 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6407 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6408 elif brev in repo._bookmarks:
6408 elif brev in repo._bookmarks:
6409 bookmarks.setcurrent(repo, brev)
6409 bookmarks.setcurrent(repo, brev)
6410 ui.status(_("(activating bookmark %s)\n") % brev)
6410 ui.status(_("(activating bookmark %s)\n") % brev)
6411 elif brev:
6411 elif brev:
6412 if repo._bookmarkcurrent:
6412 if repo._bookmarkcurrent:
6413 ui.status(_("(leaving bookmark %s)\n") %
6413 ui.status(_("(leaving bookmark %s)\n") %
6414 repo._bookmarkcurrent)
6414 repo._bookmarkcurrent)
6415 bookmarks.unsetcurrent(repo)
6415 bookmarks.unsetcurrent(repo)
6416
6416
6417 return ret
6417 return ret
6418
6418
6419 @command('verify', [])
6419 @command('verify', [])
6420 def verify(ui, repo):
6420 def verify(ui, repo):
6421 """verify the integrity of the repository
6421 """verify the integrity of the repository
6422
6422
6423 Verify the integrity of the current repository.
6423 Verify the integrity of the current repository.
6424
6424
6425 This will perform an extensive check of the repository's
6425 This will perform an extensive check of the repository's
6426 integrity, validating the hashes and checksums of each entry in
6426 integrity, validating the hashes and checksums of each entry in
6427 the changelog, manifest, and tracked files, as well as the
6427 the changelog, manifest, and tracked files, as well as the
6428 integrity of their crosslinks and indices.
6428 integrity of their crosslinks and indices.
6429
6429
6430 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6430 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6431 for more information about recovery from corruption of the
6431 for more information about recovery from corruption of the
6432 repository.
6432 repository.
6433
6433
6434 Returns 0 on success, 1 if errors are encountered.
6434 Returns 0 on success, 1 if errors are encountered.
6435 """
6435 """
6436 return hg.verify(repo)
6436 return hg.verify(repo)
6437
6437
6438 @command('version', [], norepo=True)
6438 @command('version', [], norepo=True)
6439 def version_(ui):
6439 def version_(ui):
6440 """output version and copyright information"""
6440 """output version and copyright information"""
6441 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6441 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6442 % util.version())
6442 % util.version())
6443 ui.status(_(
6443 ui.status(_(
6444 "(see http://mercurial.selenic.com for more information)\n"
6444 "(see http://mercurial.selenic.com for more information)\n"
6445 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6445 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6446 "This is free software; see the source for copying conditions. "
6446 "This is free software; see the source for copying conditions. "
6447 "There is NO\nwarranty; "
6447 "There is NO\nwarranty; "
6448 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6448 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6449 ))
6449 ))
6450
6450
6451 ui.note(_("\nEnabled extensions:\n\n"))
6451 ui.note(_("\nEnabled extensions:\n\n"))
6452 if ui.verbose:
6452 if ui.verbose:
6453 # format names and versions into columns
6453 # format names and versions into columns
6454 names = []
6454 names = []
6455 vers = []
6455 vers = []
6456 for name, module in extensions.extensions():
6456 for name, module in extensions.extensions():
6457 names.append(name)
6457 names.append(name)
6458 vers.append(extensions.moduleversion(module))
6458 vers.append(extensions.moduleversion(module))
6459 if names:
6459 if names:
6460 maxnamelen = max(len(n) for n in names)
6460 maxnamelen = max(len(n) for n in names)
6461 for i, name in enumerate(names):
6461 for i, name in enumerate(names):
6462 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6462 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,257 +1,272 b''
1 Revert interactive tests
1 Revert interactive tests
2 1 add and commit file f
2 1 add and commit file f
3 2 add commit file folder1/g
3 2 add commit file folder1/g
4 3 add and commit file folder2/h
4 3 add and commit file folder2/h
5 4 add and commit file folder1/i
5 4 add and commit file folder1/i
6 5 commit change to file f
6 5 commit change to file f
7 6 commit changes to files folder1/g folder2/h
7 6 commit changes to files folder1/g folder2/h
8 7 commit changes to files folder1/g folder2/h
8 7 commit changes to files folder1/g folder2/h
9 8 revert interactive to commit id 2 (line 3 above), check that folder1/i is removed and
9 8 revert interactive to commit id 2 (line 3 above), check that folder1/i is removed and
10 9 make workdir match 7
10 9 make workdir match 7
11 10 run the same test than 8 from within folder1 and check same expectations
11 10 run the same test than 8 from within folder1 and check same expectations
12
12
13 $ cat <<EOF >> $HGRCPATH
13 $ cat <<EOF >> $HGRCPATH
14 > [ui]
14 > [ui]
15 > interactive = true
15 > interactive = true
16 > [extensions]
16 > [extensions]
17 > record =
17 > record =
18 > EOF
18 > EOF
19
19
20
20
21 $ mkdir -p a/folder1 a/folder2
21 $ mkdir -p a/folder1 a/folder2
22 $ cd a
22 $ cd a
23 $ hg init
23 $ hg init
24 >>> open('f', 'wb').write("1\n2\n3\n4\n5\n")
24 >>> open('f', 'wb').write("1\n2\n3\n4\n5\n")
25 $ hg add f ; hg commit -m "adding f"
25 $ hg add f ; hg commit -m "adding f"
26 $ cat f > folder1/g ; hg add folder1/g ; hg commit -m "adding folder1/g"
26 $ cat f > folder1/g ; hg add folder1/g ; hg commit -m "adding folder1/g"
27 $ cat f > folder2/h ; hg add folder2/h ; hg commit -m "adding folder2/h"
27 $ cat f > folder2/h ; hg add folder2/h ; hg commit -m "adding folder2/h"
28 $ cat f > folder1/i ; hg add folder1/i ; hg commit -m "adding folder1/i"
28 $ cat f > folder1/i ; hg add folder1/i ; hg commit -m "adding folder1/i"
29 >>> open('f', 'wb').write("a\n1\n2\n3\n4\n5\nb\n")
29 >>> open('f', 'wb').write("a\n1\n2\n3\n4\n5\nb\n")
30 $ hg commit -m "modifying f"
30 $ hg commit -m "modifying f"
31 >>> open('folder1/g', 'wb').write("c\n1\n2\n3\n4\n5\nd\n")
31 >>> open('folder1/g', 'wb').write("c\n1\n2\n3\n4\n5\nd\n")
32 $ hg commit -m "modifying folder1/g"
32 $ hg commit -m "modifying folder1/g"
33 >>> open('folder2/h', 'wb').write("e\n1\n2\n3\n4\n5\nf\n")
33 >>> open('folder2/h', 'wb').write("e\n1\n2\n3\n4\n5\nf\n")
34 $ hg commit -m "modifying folder2/h"
34 $ hg commit -m "modifying folder2/h"
35 $ hg tip
35 $ hg tip
36 changeset: 6:59dd6e4ab63a
36 changeset: 6:59dd6e4ab63a
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: modifying folder2/h
40 summary: modifying folder2/h
41
41
42 $ hg revert -i -r 2 --all -- << EOF
42 $ hg revert -i -r 2 --all -- << EOF
43 > y
43 > y
44 > y
44 > y
45 > y
45 > y
46 > y
46 > y
47 > y
47 > y
48 > n
48 > n
49 > n
49 > n
50 > EOF
50 > EOF
51 reverting f
51 reverting f
52 reverting folder1/g (glob)
52 reverting folder1/g (glob)
53 removing folder1/i (glob)
53 removing folder1/i (glob)
54 reverting folder2/h (glob)
54 reverting folder2/h (glob)
55 diff -r 89ac3d72e4a4 f
55 diff -r 89ac3d72e4a4 f
56 2 hunks, 2 lines changed
56 2 hunks, 2 lines changed
57 examine changes to 'f'? [Ynesfdaq?] y
57 examine changes to 'f'? [Ynesfdaq?] y
58
58
59 @@ -1,6 +1,5 @@
59 @@ -1,6 +1,5 @@
60 -a
60 -a
61 1
61 1
62 2
62 2
63 3
63 3
64 4
64 4
65 5
65 5
66 record change 1/6 to 'f'? [Ynesfdaq?] y
66 record change 1/6 to 'f'? [Ynesfdaq?] y
67
67
68 @@ -2,6 +1,5 @@
68 @@ -2,6 +1,5 @@
69 1
69 1
70 2
70 2
71 3
71 3
72 4
72 4
73 5
73 5
74 -b
74 -b
75 record change 2/6 to 'f'? [Ynesfdaq?] y
75 record change 2/6 to 'f'? [Ynesfdaq?] y
76
76
77 diff -r 89ac3d72e4a4 folder1/g
77 diff -r 89ac3d72e4a4 folder1/g
78 2 hunks, 2 lines changed
78 2 hunks, 2 lines changed
79 examine changes to 'folder1/g'? [Ynesfdaq?] y
79 examine changes to 'folder1/g'? [Ynesfdaq?] y
80
80
81 @@ -1,6 +1,5 @@
81 @@ -1,6 +1,5 @@
82 -c
82 -c
83 1
83 1
84 2
84 2
85 3
85 3
86 4
86 4
87 5
87 5
88 record change 3/6 to 'folder1/g'? [Ynesfdaq?] y
88 record change 3/6 to 'folder1/g'? [Ynesfdaq?] y
89
89
90 @@ -2,6 +1,5 @@
90 @@ -2,6 +1,5 @@
91 1
91 1
92 2
92 2
93 3
93 3
94 4
94 4
95 5
95 5
96 -d
96 -d
97 record change 4/6 to 'folder1/g'? [Ynesfdaq?] n
97 record change 4/6 to 'folder1/g'? [Ynesfdaq?] n
98
98
99 diff -r 89ac3d72e4a4 folder2/h
99 diff -r 89ac3d72e4a4 folder2/h
100 2 hunks, 2 lines changed
100 2 hunks, 2 lines changed
101 examine changes to 'folder2/h'? [Ynesfdaq?] n
101 examine changes to 'folder2/h'? [Ynesfdaq?] n
102
102
103 $ cat f
103 $ cat f
104 1
104 1
105 2
105 2
106 3
106 3
107 4
107 4
108 5
108 5
109 $ cat folder1/g
109 $ cat folder1/g
110 1
110 1
111 2
111 2
112 3
112 3
113 4
113 4
114 5
114 5
115 d
115 d
116 $ cat folder2/h
116 $ cat folder2/h
117 e
117 e
118 1
118 1
119 2
119 2
120 3
120 3
121 4
121 4
122 5
122 5
123 f
123 f
124
125 Test that --interactive lift the need for --all
126
127 $ echo q | hg revert -i -r 2
128 reverting folder1/g (glob)
129 reverting folder2/h (glob)
130 diff -r 89ac3d72e4a4 folder1/g
131 1 hunks, 1 lines changed
132 examine changes to 'folder1/g'? [Ynesfdaq?] q
133
134 abort: user quit
135 [255]
136 $ rm folder1/g.orig
137
138
124 $ hg update -C 6
139 $ hg update -C 6
125 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 $ hg revert -i -r 2 --all -- << EOF
141 $ hg revert -i -r 2 --all -- << EOF
127 > y
142 > y
128 > y
143 > y
129 > y
144 > y
130 > y
145 > y
131 > y
146 > y
132 > n
147 > n
133 > n
148 > n
134 > EOF
149 > EOF
135 reverting f
150 reverting f
136 reverting folder1/g (glob)
151 reverting folder1/g (glob)
137 removing folder1/i (glob)
152 removing folder1/i (glob)
138 reverting folder2/h (glob)
153 reverting folder2/h (glob)
139 diff -r 89ac3d72e4a4 f
154 diff -r 89ac3d72e4a4 f
140 2 hunks, 2 lines changed
155 2 hunks, 2 lines changed
141 examine changes to 'f'? [Ynesfdaq?] y
156 examine changes to 'f'? [Ynesfdaq?] y
142
157
143 @@ -1,6 +1,5 @@
158 @@ -1,6 +1,5 @@
144 -a
159 -a
145 1
160 1
146 2
161 2
147 3
162 3
148 4
163 4
149 5
164 5
150 record change 1/6 to 'f'? [Ynesfdaq?] y
165 record change 1/6 to 'f'? [Ynesfdaq?] y
151
166
152 @@ -2,6 +1,5 @@
167 @@ -2,6 +1,5 @@
153 1
168 1
154 2
169 2
155 3
170 3
156 4
171 4
157 5
172 5
158 -b
173 -b
159 record change 2/6 to 'f'? [Ynesfdaq?] y
174 record change 2/6 to 'f'? [Ynesfdaq?] y
160
175
161 diff -r 89ac3d72e4a4 folder1/g
176 diff -r 89ac3d72e4a4 folder1/g
162 2 hunks, 2 lines changed
177 2 hunks, 2 lines changed
163 examine changes to 'folder1/g'? [Ynesfdaq?] y
178 examine changes to 'folder1/g'? [Ynesfdaq?] y
164
179
165 @@ -1,6 +1,5 @@
180 @@ -1,6 +1,5 @@
166 -c
181 -c
167 1
182 1
168 2
183 2
169 3
184 3
170 4
185 4
171 5
186 5
172 record change 3/6 to 'folder1/g'? [Ynesfdaq?] y
187 record change 3/6 to 'folder1/g'? [Ynesfdaq?] y
173
188
174 @@ -2,6 +1,5 @@
189 @@ -2,6 +1,5 @@
175 1
190 1
176 2
191 2
177 3
192 3
178 4
193 4
179 5
194 5
180 -d
195 -d
181 record change 4/6 to 'folder1/g'? [Ynesfdaq?] n
196 record change 4/6 to 'folder1/g'? [Ynesfdaq?] n
182
197
183 diff -r 89ac3d72e4a4 folder2/h
198 diff -r 89ac3d72e4a4 folder2/h
184 2 hunks, 2 lines changed
199 2 hunks, 2 lines changed
185 examine changes to 'folder2/h'? [Ynesfdaq?] n
200 examine changes to 'folder2/h'? [Ynesfdaq?] n
186
201
187 $ cat f
202 $ cat f
188 1
203 1
189 2
204 2
190 3
205 3
191 4
206 4
192 5
207 5
193 $ cat folder1/g
208 $ cat folder1/g
194 1
209 1
195 2
210 2
196 3
211 3
197 4
212 4
198 5
213 5
199 d
214 d
200 $ cat folder2/h
215 $ cat folder2/h
201 e
216 e
202 1
217 1
203 2
218 2
204 3
219 3
205 4
220 4
206 5
221 5
207 f
222 f
208 $ hg st
223 $ hg st
209 M f
224 M f
210 M folder1/g
225 M folder1/g
211 R folder1/i
226 R folder1/i
212 $ hg revert --interactive f << EOF
227 $ hg revert --interactive f << EOF
213 > y
228 > y
214 > y
229 > y
215 > n
230 > n
216 > n
231 > n
217 > EOF
232 > EOF
218 diff -r 59dd6e4ab63a f
233 diff -r 59dd6e4ab63a f
219 2 hunks, 2 lines changed
234 2 hunks, 2 lines changed
220 examine changes to 'f'? [Ynesfdaq?] y
235 examine changes to 'f'? [Ynesfdaq?] y
221
236
222 @@ -1,5 +1,6 @@
237 @@ -1,5 +1,6 @@
223 +a
238 +a
224 1
239 1
225 2
240 2
226 3
241 3
227 4
242 4
228 5
243 5
229 record change 1/2 to 'f'? [Ynesfdaq?] y
244 record change 1/2 to 'f'? [Ynesfdaq?] y
230
245
231 @@ -1,5 +2,6 @@
246 @@ -1,5 +2,6 @@
232 1
247 1
233 2
248 2
234 3
249 3
235 4
250 4
236 5
251 5
237 +b
252 +b
238 record change 2/2 to 'f'? [Ynesfdaq?] n
253 record change 2/2 to 'f'? [Ynesfdaq?] n
239
254
240 $ hg st
255 $ hg st
241 M f
256 M f
242 M folder1/g
257 M folder1/g
243 R folder1/i
258 R folder1/i
244 ? f.orig
259 ? f.orig
245 $ cat f
260 $ cat f
246 a
261 a
247 1
262 1
248 2
263 2
249 3
264 3
250 4
265 4
251 5
266 5
252 $ cat f.orig
267 $ cat f.orig
253 1
268 1
254 2
269 2
255 3
270 3
256 4
271 4
257 5
272 5
General Comments 0
You need to be logged in to leave comments. Login now