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