##// END OF EJS Templates
commands: add ui.statuscopies config knob...
Mathias De Maré -
r24663:7d01371e default
parent child Browse files
Show More
@@ -1,6461 +1,6462 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import hex, bin, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _
11 11 import os, re, difflib, time, tempfile, errno, shlex
12 12 import sys, socket
13 13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 14 import patch, help, encoding, templatekw, discovery
15 15 import archival, changegroup, cmdutil, hbisect
16 16 import sshserver, hgweb, commandserver
17 17 import extensions
18 18 from hgweb import server as hgweb_server
19 19 import merge as mergemod
20 20 import minirst, revset, fileset
21 21 import dagparser, context, simplemerge, graphmod, copies
22 22 import random
23 23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 24 import phases, obsolete, exchange, bundle2
25 25 import ui as uimod
26 26
27 27 table = {}
28 28
29 29 command = cmdutil.command(table)
30 30
31 31 # Space delimited list of commands that don't require local repositories.
32 32 # This should be populated by passing norepo=True into the @command decorator.
33 33 norepo = ''
34 34 # Space delimited list of commands that optionally require local repositories.
35 35 # This should be populated by passing optionalrepo=True into the @command
36 36 # decorator.
37 37 optionalrepo = ''
38 38 # Space delimited list of commands that will examine arguments looking for
39 39 # a repository. This should be populated by passing inferrepo=True into the
40 40 # @command decorator.
41 41 inferrepo = ''
42 42
43 43 # common command options
44 44
45 45 globalopts = [
46 46 ('R', 'repository', '',
47 47 _('repository root directory or name of overlay bundle file'),
48 48 _('REPO')),
49 49 ('', 'cwd', '',
50 50 _('change working directory'), _('DIR')),
51 51 ('y', 'noninteractive', None,
52 52 _('do not prompt, automatically pick the first choice for all prompts')),
53 53 ('q', 'quiet', None, _('suppress output')),
54 54 ('v', 'verbose', None, _('enable additional output')),
55 55 ('', 'config', [],
56 56 _('set/override config option (use \'section.name=value\')'),
57 57 _('CONFIG')),
58 58 ('', 'debug', None, _('enable debugging output')),
59 59 ('', 'debugger', None, _('start debugger')),
60 60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
61 61 _('ENCODE')),
62 62 ('', 'encodingmode', encoding.encodingmode,
63 63 _('set the charset encoding mode'), _('MODE')),
64 64 ('', 'traceback', None, _('always print a traceback on exception')),
65 65 ('', 'time', None, _('time how long the command takes')),
66 66 ('', 'profile', None, _('print command execution profile')),
67 67 ('', 'version', None, _('output version information and exit')),
68 68 ('h', 'help', None, _('display help and exit')),
69 69 ('', 'hidden', False, _('consider hidden changesets')),
70 70 ]
71 71
72 72 dryrunopts = [('n', 'dry-run', None,
73 73 _('do not perform actions, just print output'))]
74 74
75 75 remoteopts = [
76 76 ('e', 'ssh', '',
77 77 _('specify ssh command to use'), _('CMD')),
78 78 ('', 'remotecmd', '',
79 79 _('specify hg command to run on the remote side'), _('CMD')),
80 80 ('', 'insecure', None,
81 81 _('do not verify server certificate (ignoring web.cacerts config)')),
82 82 ]
83 83
84 84 walkopts = [
85 85 ('I', 'include', [],
86 86 _('include names matching the given patterns'), _('PATTERN')),
87 87 ('X', 'exclude', [],
88 88 _('exclude names matching the given patterns'), _('PATTERN')),
89 89 ]
90 90
91 91 commitopts = [
92 92 ('m', 'message', '',
93 93 _('use text as commit message'), _('TEXT')),
94 94 ('l', 'logfile', '',
95 95 _('read commit message from file'), _('FILE')),
96 96 ]
97 97
98 98 commitopts2 = [
99 99 ('d', 'date', '',
100 100 _('record the specified date as commit date'), _('DATE')),
101 101 ('u', 'user', '',
102 102 _('record the specified user as committer'), _('USER')),
103 103 ]
104 104
105 105 # hidden for now
106 106 formatteropts = [
107 107 ('T', 'template', '',
108 108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
109 109 ]
110 110
111 111 templateopts = [
112 112 ('', 'style', '',
113 113 _('display using template map file (DEPRECATED)'), _('STYLE')),
114 114 ('T', 'template', '',
115 115 _('display with template'), _('TEMPLATE')),
116 116 ]
117 117
118 118 logopts = [
119 119 ('p', 'patch', None, _('show patch')),
120 120 ('g', 'git', None, _('use git extended diff format')),
121 121 ('l', 'limit', '',
122 122 _('limit number of changes displayed'), _('NUM')),
123 123 ('M', 'no-merges', None, _('do not show merges')),
124 124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 125 ('G', 'graph', None, _("show the revision DAG")),
126 126 ] + templateopts
127 127
128 128 diffopts = [
129 129 ('a', 'text', None, _('treat all files as text')),
130 130 ('g', 'git', None, _('use git extended diff format')),
131 131 ('', 'nodates', None, _('omit dates from diff headers'))
132 132 ]
133 133
134 134 diffwsopts = [
135 135 ('w', 'ignore-all-space', None,
136 136 _('ignore white space when comparing lines')),
137 137 ('b', 'ignore-space-change', None,
138 138 _('ignore changes in the amount of white space')),
139 139 ('B', 'ignore-blank-lines', None,
140 140 _('ignore changes whose lines are all blank')),
141 141 ]
142 142
143 143 diffopts2 = [
144 144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
145 145 ('p', 'show-function', None, _('show which function each change is in')),
146 146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
147 147 ] + diffwsopts + [
148 148 ('U', 'unified', '',
149 149 _('number of lines of context to show'), _('NUM')),
150 150 ('', 'stat', None, _('output diffstat-style summary of changes')),
151 151 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
152 152 ]
153 153
154 154 mergetoolopts = [
155 155 ('t', 'tool', '', _('specify merge tool')),
156 156 ]
157 157
158 158 similarityopts = [
159 159 ('s', 'similarity', '',
160 160 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
161 161 ]
162 162
163 163 subrepoopts = [
164 164 ('S', 'subrepos', None,
165 165 _('recurse into subrepositories'))
166 166 ]
167 167
168 168 # Commands start here, listed alphabetically
169 169
170 170 @command('^add',
171 171 walkopts + subrepoopts + dryrunopts,
172 172 _('[OPTION]... [FILE]...'),
173 173 inferrepo=True)
174 174 def add(ui, repo, *pats, **opts):
175 175 """add the specified files on the next commit
176 176
177 177 Schedule files to be version controlled and added to the
178 178 repository.
179 179
180 180 The files will be added to the repository at the next commit. To
181 181 undo an add before that, see :hg:`forget`.
182 182
183 183 If no names are given, add all files to the repository.
184 184
185 185 .. container:: verbose
186 186
187 187 An example showing how new (unknown) files are added
188 188 automatically by :hg:`add`::
189 189
190 190 $ ls
191 191 foo.c
192 192 $ hg status
193 193 ? foo.c
194 194 $ hg add
195 195 adding foo.c
196 196 $ hg status
197 197 A foo.c
198 198
199 199 Returns 0 if all files are successfully added.
200 200 """
201 201
202 202 m = scmutil.match(repo[None], pats, opts)
203 203 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
204 204 return rejected and 1 or 0
205 205
206 206 @command('addremove',
207 207 similarityopts + subrepoopts + walkopts + dryrunopts,
208 208 _('[OPTION]... [FILE]...'),
209 209 inferrepo=True)
210 210 def addremove(ui, repo, *pats, **opts):
211 211 """add all new files, delete all missing files
212 212
213 213 Add all new files and remove all missing files from the
214 214 repository.
215 215
216 216 New files are ignored if they match any of the patterns in
217 217 ``.hgignore``. As with add, these changes take effect at the next
218 218 commit.
219 219
220 220 Use the -s/--similarity option to detect renamed files. This
221 221 option takes a percentage between 0 (disabled) and 100 (files must
222 222 be identical) as its parameter. With a parameter greater than 0,
223 223 this compares every removed file with every added file and records
224 224 those similar enough as renames. Detecting renamed files this way
225 225 can be expensive. After using this option, :hg:`status -C` can be
226 226 used to check which files were identified as moved or renamed. If
227 227 not specified, -s/--similarity defaults to 100 and only renames of
228 228 identical files are detected.
229 229
230 230 Returns 0 if all files are successfully added.
231 231 """
232 232 try:
233 233 sim = float(opts.get('similarity') or 100)
234 234 except ValueError:
235 235 raise util.Abort(_('similarity must be a number'))
236 236 if sim < 0 or sim > 100:
237 237 raise util.Abort(_('similarity must be between 0 and 100'))
238 238 matcher = scmutil.match(repo[None], pats, opts)
239 239 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
240 240
241 241 @command('^annotate|blame',
242 242 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
243 243 ('', 'follow', None,
244 244 _('follow copies/renames and list the filename (DEPRECATED)')),
245 245 ('', 'no-follow', None, _("don't follow copies and renames")),
246 246 ('a', 'text', None, _('treat all files as text')),
247 247 ('u', 'user', None, _('list the author (long with -v)')),
248 248 ('f', 'file', None, _('list the filename')),
249 249 ('d', 'date', None, _('list the date (short with -q)')),
250 250 ('n', 'number', None, _('list the revision number (default)')),
251 251 ('c', 'changeset', None, _('list the changeset')),
252 252 ('l', 'line-number', None, _('show line number at the first appearance'))
253 253 ] + diffwsopts + walkopts + formatteropts,
254 254 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
255 255 inferrepo=True)
256 256 def annotate(ui, repo, *pats, **opts):
257 257 """show changeset information by line for each file
258 258
259 259 List changes in files, showing the revision id responsible for
260 260 each line
261 261
262 262 This command is useful for discovering when a change was made and
263 263 by whom.
264 264
265 265 Without the -a/--text option, annotate will avoid processing files
266 266 it detects as binary. With -a, annotate will annotate the file
267 267 anyway, although the results will probably be neither useful
268 268 nor desirable.
269 269
270 270 By default, annotate files in the parent of the working directory.
271 271 Use -r "wdir()" to annotate the working directory files.
272 272
273 273 Returns 0 on success.
274 274 """
275 275 if not pats:
276 276 raise util.Abort(_('at least one filename or pattern is required'))
277 277
278 278 if opts.get('follow'):
279 279 # --follow is deprecated and now just an alias for -f/--file
280 280 # to mimic the behavior of Mercurial before version 1.5
281 281 opts['file'] = True
282 282
283 283 ctx = scmutil.revsingle(repo, opts.get('rev'))
284 284
285 285 fm = ui.formatter('annotate', opts)
286 286 if ui.quiet:
287 287 datefunc = util.shortdate
288 288 else:
289 289 datefunc = util.datestr
290 290 if ctx.rev() is None:
291 291 def hexfn(node):
292 292 if node is None:
293 293 return None
294 294 else:
295 295 return fm.hexfunc(node)
296 296 if opts.get('changeset'):
297 297 # omit "+" suffix which is appended to node hex
298 298 def formatrev(rev):
299 299 if rev is None:
300 300 return '%d' % ctx.p1().rev()
301 301 else:
302 302 return '%d' % rev
303 303 else:
304 304 def formatrev(rev):
305 305 if rev is None:
306 306 return '%d+' % ctx.p1().rev()
307 307 else:
308 308 return '%d ' % rev
309 309 def formathex(hex):
310 310 if hex is None:
311 311 return '%s+' % fm.hexfunc(ctx.p1().node())
312 312 else:
313 313 return '%s ' % hex
314 314 else:
315 315 hexfn = fm.hexfunc
316 316 formatrev = formathex = str
317 317
318 318 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
319 319 ('number', ' ', lambda x: x[0].rev(), formatrev),
320 320 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
321 321 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
322 322 ('file', ' ', lambda x: x[0].path(), str),
323 323 ('line_number', ':', lambda x: x[1], str),
324 324 ]
325 325 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
326 326
327 327 if (not opts.get('user') and not opts.get('changeset')
328 328 and not opts.get('date') and not opts.get('file')):
329 329 opts['number'] = True
330 330
331 331 linenumber = opts.get('line_number') is not None
332 332 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
333 333 raise util.Abort(_('at least one of -n/-c is required for -l'))
334 334
335 335 if fm:
336 336 def makefunc(get, fmt):
337 337 return get
338 338 else:
339 339 def makefunc(get, fmt):
340 340 return lambda x: fmt(get(x))
341 341 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
342 342 if opts.get(op)]
343 343 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
344 344 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
345 345 if opts.get(op))
346 346
347 347 def bad(x, y):
348 348 raise util.Abort("%s: %s" % (x, y))
349 349
350 350 m = scmutil.match(ctx, pats, opts)
351 351 m.bad = bad
352 352 follow = not opts.get('no_follow')
353 353 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
354 354 whitespace=True)
355 355 for abs in ctx.walk(m):
356 356 fctx = ctx[abs]
357 357 if not opts.get('text') and util.binary(fctx.data()):
358 358 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
359 359 continue
360 360
361 361 lines = fctx.annotate(follow=follow, linenumber=linenumber,
362 362 diffopts=diffopts)
363 363 formats = []
364 364 pieces = []
365 365
366 366 for f, sep in funcmap:
367 367 l = [f(n) for n, dummy in lines]
368 368 if l:
369 369 if fm:
370 370 formats.append(['%s' for x in l])
371 371 else:
372 372 sizes = [encoding.colwidth(x) for x in l]
373 373 ml = max(sizes)
374 374 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
375 375 pieces.append(l)
376 376
377 377 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
378 378 fm.startitem()
379 379 fm.write(fields, "".join(f), *p)
380 380 fm.write('line', ": %s", l[1])
381 381
382 382 if lines and not lines[-1][1].endswith('\n'):
383 383 fm.plain('\n')
384 384
385 385 fm.end()
386 386
387 387 @command('archive',
388 388 [('', 'no-decode', None, _('do not pass files through decoders')),
389 389 ('p', 'prefix', '', _('directory prefix for files in archive'),
390 390 _('PREFIX')),
391 391 ('r', 'rev', '', _('revision to distribute'), _('REV')),
392 392 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
393 393 ] + subrepoopts + walkopts,
394 394 _('[OPTION]... DEST'))
395 395 def archive(ui, repo, dest, **opts):
396 396 '''create an unversioned archive of a repository revision
397 397
398 398 By default, the revision used is the parent of the working
399 399 directory; use -r/--rev to specify a different revision.
400 400
401 401 The archive type is automatically detected based on file
402 402 extension (or override using -t/--type).
403 403
404 404 .. container:: verbose
405 405
406 406 Examples:
407 407
408 408 - create a zip file containing the 1.0 release::
409 409
410 410 hg archive -r 1.0 project-1.0.zip
411 411
412 412 - create a tarball excluding .hg files::
413 413
414 414 hg archive project.tar.gz -X ".hg*"
415 415
416 416 Valid types are:
417 417
418 418 :``files``: a directory full of files (default)
419 419 :``tar``: tar archive, uncompressed
420 420 :``tbz2``: tar archive, compressed using bzip2
421 421 :``tgz``: tar archive, compressed using gzip
422 422 :``uzip``: zip archive, uncompressed
423 423 :``zip``: zip archive, compressed using deflate
424 424
425 425 The exact name of the destination archive or directory is given
426 426 using a format string; see :hg:`help export` for details.
427 427
428 428 Each member added to an archive file has a directory prefix
429 429 prepended. Use -p/--prefix to specify a format string for the
430 430 prefix. The default is the basename of the archive, with suffixes
431 431 removed.
432 432
433 433 Returns 0 on success.
434 434 '''
435 435
436 436 ctx = scmutil.revsingle(repo, opts.get('rev'))
437 437 if not ctx:
438 438 raise util.Abort(_('no working directory: please specify a revision'))
439 439 node = ctx.node()
440 440 dest = cmdutil.makefilename(repo, dest, node)
441 441 if os.path.realpath(dest) == repo.root:
442 442 raise util.Abort(_('repository root cannot be destination'))
443 443
444 444 kind = opts.get('type') or archival.guesskind(dest) or 'files'
445 445 prefix = opts.get('prefix')
446 446
447 447 if dest == '-':
448 448 if kind == 'files':
449 449 raise util.Abort(_('cannot archive plain files to stdout'))
450 450 dest = cmdutil.makefileobj(repo, dest)
451 451 if not prefix:
452 452 prefix = os.path.basename(repo.root) + '-%h'
453 453
454 454 prefix = cmdutil.makefilename(repo, prefix, node)
455 455 matchfn = scmutil.match(ctx, [], opts)
456 456 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
457 457 matchfn, prefix, subrepos=opts.get('subrepos'))
458 458
459 459 @command('backout',
460 460 [('', 'merge', None, _('merge with old dirstate parent after backout')),
461 461 ('', 'commit', None, _('commit if no conflicts were encountered')),
462 462 ('', 'parent', '',
463 463 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
464 464 ('r', 'rev', '', _('revision to backout'), _('REV')),
465 465 ('e', 'edit', False, _('invoke editor on commit messages')),
466 466 ] + mergetoolopts + walkopts + commitopts + commitopts2,
467 467 _('[OPTION]... [-r] REV'))
468 468 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
469 469 '''reverse effect of earlier changeset
470 470
471 471 Prepare a new changeset with the effect of REV undone in the
472 472 current working directory.
473 473
474 474 If REV is the parent of the working directory, then this new changeset
475 475 is committed automatically. Otherwise, hg needs to merge the
476 476 changes and the merged result is left uncommitted.
477 477
478 478 .. note::
479 479
480 480 backout cannot be used to fix either an unwanted or
481 481 incorrect merge.
482 482
483 483 .. container:: verbose
484 484
485 485 By default, the pending changeset will have one parent,
486 486 maintaining a linear history. With --merge, the pending
487 487 changeset will instead have two parents: the old parent of the
488 488 working directory and a new child of REV that simply undoes REV.
489 489
490 490 Before version 1.7, the behavior without --merge was equivalent
491 491 to specifying --merge followed by :hg:`update --clean .` to
492 492 cancel the merge and leave the child of REV as a head to be
493 493 merged separately.
494 494
495 495 See :hg:`help dates` for a list of formats valid for -d/--date.
496 496
497 497 Returns 0 on success, 1 if nothing to backout or there are unresolved
498 498 files.
499 499 '''
500 500 if rev and node:
501 501 raise util.Abort(_("please specify just one revision"))
502 502
503 503 if not rev:
504 504 rev = node
505 505
506 506 if not rev:
507 507 raise util.Abort(_("please specify a revision to backout"))
508 508
509 509 date = opts.get('date')
510 510 if date:
511 511 opts['date'] = util.parsedate(date)
512 512
513 513 cmdutil.checkunfinished(repo)
514 514 cmdutil.bailifchanged(repo)
515 515 node = scmutil.revsingle(repo, rev).node()
516 516
517 517 op1, op2 = repo.dirstate.parents()
518 518 if not repo.changelog.isancestor(node, op1):
519 519 raise util.Abort(_('cannot backout change that is not an ancestor'))
520 520
521 521 p1, p2 = repo.changelog.parents(node)
522 522 if p1 == nullid:
523 523 raise util.Abort(_('cannot backout a change with no parents'))
524 524 if p2 != nullid:
525 525 if not opts.get('parent'):
526 526 raise util.Abort(_('cannot backout a merge changeset'))
527 527 p = repo.lookup(opts['parent'])
528 528 if p not in (p1, p2):
529 529 raise util.Abort(_('%s is not a parent of %s') %
530 530 (short(p), short(node)))
531 531 parent = p
532 532 else:
533 533 if opts.get('parent'):
534 534 raise util.Abort(_('cannot use --parent on non-merge changeset'))
535 535 parent = p1
536 536
537 537 # the backout should appear on the same branch
538 538 wlock = repo.wlock()
539 539 try:
540 540 branch = repo.dirstate.branch()
541 541 bheads = repo.branchheads(branch)
542 542 rctx = scmutil.revsingle(repo, hex(parent))
543 543 if not opts.get('merge') and op1 != node:
544 544 try:
545 545 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
546 546 'backout')
547 547 repo.dirstate.beginparentchange()
548 548 stats = mergemod.update(repo, parent, True, True, False,
549 549 node, False)
550 550 repo.setparents(op1, op2)
551 551 repo.dirstate.endparentchange()
552 552 hg._showstats(repo, stats)
553 553 if stats[3]:
554 554 repo.ui.status(_("use 'hg resolve' to retry unresolved "
555 555 "file merges\n"))
556 556 return 1
557 557 elif not commit:
558 558 msg = _("changeset %s backed out, "
559 559 "don't forget to commit.\n")
560 560 ui.status(msg % short(node))
561 561 return 0
562 562 finally:
563 563 ui.setconfig('ui', 'forcemerge', '', '')
564 564 else:
565 565 hg.clean(repo, node, show_stats=False)
566 566 repo.dirstate.setbranch(branch)
567 567 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
568 568
569 569
570 570 def commitfunc(ui, repo, message, match, opts):
571 571 editform = 'backout'
572 572 e = cmdutil.getcommiteditor(editform=editform, **opts)
573 573 if not message:
574 574 # we don't translate commit messages
575 575 message = "Backed out changeset %s" % short(node)
576 576 e = cmdutil.getcommiteditor(edit=True, editform=editform)
577 577 return repo.commit(message, opts.get('user'), opts.get('date'),
578 578 match, editor=e)
579 579 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
580 580 if not newnode:
581 581 ui.status(_("nothing changed\n"))
582 582 return 1
583 583 cmdutil.commitstatus(repo, newnode, branch, bheads)
584 584
585 585 def nice(node):
586 586 return '%d:%s' % (repo.changelog.rev(node), short(node))
587 587 ui.status(_('changeset %s backs out changeset %s\n') %
588 588 (nice(repo.changelog.tip()), nice(node)))
589 589 if opts.get('merge') and op1 != node:
590 590 hg.clean(repo, op1, show_stats=False)
591 591 ui.status(_('merging with changeset %s\n')
592 592 % nice(repo.changelog.tip()))
593 593 try:
594 594 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
595 595 'backout')
596 596 return hg.merge(repo, hex(repo.changelog.tip()))
597 597 finally:
598 598 ui.setconfig('ui', 'forcemerge', '', '')
599 599 finally:
600 600 wlock.release()
601 601 return 0
602 602
603 603 @command('bisect',
604 604 [('r', 'reset', False, _('reset bisect state')),
605 605 ('g', 'good', False, _('mark changeset good')),
606 606 ('b', 'bad', False, _('mark changeset bad')),
607 607 ('s', 'skip', False, _('skip testing changeset')),
608 608 ('e', 'extend', False, _('extend the bisect range')),
609 609 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
610 610 ('U', 'noupdate', False, _('do not update to target'))],
611 611 _("[-gbsr] [-U] [-c CMD] [REV]"))
612 612 def bisect(ui, repo, rev=None, extra=None, command=None,
613 613 reset=None, good=None, bad=None, skip=None, extend=None,
614 614 noupdate=None):
615 615 """subdivision search of changesets
616 616
617 617 This command helps to find changesets which introduce problems. To
618 618 use, mark the earliest changeset you know exhibits the problem as
619 619 bad, then mark the latest changeset which is free from the problem
620 620 as good. Bisect will update your working directory to a revision
621 621 for testing (unless the -U/--noupdate option is specified). Once
622 622 you have performed tests, mark the working directory as good or
623 623 bad, and bisect will either update to another candidate changeset
624 624 or announce that it has found the bad revision.
625 625
626 626 As a shortcut, you can also use the revision argument to mark a
627 627 revision as good or bad without checking it out first.
628 628
629 629 If you supply a command, it will be used for automatic bisection.
630 630 The environment variable HG_NODE will contain the ID of the
631 631 changeset being tested. The exit status of the command will be
632 632 used to mark revisions as good or bad: status 0 means good, 125
633 633 means to skip the revision, 127 (command not found) will abort the
634 634 bisection, and any other non-zero exit status means the revision
635 635 is bad.
636 636
637 637 .. container:: verbose
638 638
639 639 Some examples:
640 640
641 641 - start a bisection with known bad revision 34, and good revision 12::
642 642
643 643 hg bisect --bad 34
644 644 hg bisect --good 12
645 645
646 646 - advance the current bisection by marking current revision as good or
647 647 bad::
648 648
649 649 hg bisect --good
650 650 hg bisect --bad
651 651
652 652 - mark the current revision, or a known revision, to be skipped (e.g. if
653 653 that revision is not usable because of another issue)::
654 654
655 655 hg bisect --skip
656 656 hg bisect --skip 23
657 657
658 658 - skip all revisions that do not touch directories ``foo`` or ``bar``::
659 659
660 660 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
661 661
662 662 - forget the current bisection::
663 663
664 664 hg bisect --reset
665 665
666 666 - use 'make && make tests' to automatically find the first broken
667 667 revision::
668 668
669 669 hg bisect --reset
670 670 hg bisect --bad 34
671 671 hg bisect --good 12
672 672 hg bisect --command "make && make tests"
673 673
674 674 - see all changesets whose states are already known in the current
675 675 bisection::
676 676
677 677 hg log -r "bisect(pruned)"
678 678
679 679 - see the changeset currently being bisected (especially useful
680 680 if running with -U/--noupdate)::
681 681
682 682 hg log -r "bisect(current)"
683 683
684 684 - see all changesets that took part in the current bisection::
685 685
686 686 hg log -r "bisect(range)"
687 687
688 688 - you can even get a nice graph::
689 689
690 690 hg log --graph -r "bisect(range)"
691 691
692 692 See :hg:`help revsets` for more about the `bisect()` keyword.
693 693
694 694 Returns 0 on success.
695 695 """
696 696 def extendbisectrange(nodes, good):
697 697 # bisect is incomplete when it ends on a merge node and
698 698 # one of the parent was not checked.
699 699 parents = repo[nodes[0]].parents()
700 700 if len(parents) > 1:
701 701 if good:
702 702 side = state['bad']
703 703 else:
704 704 side = state['good']
705 705 num = len(set(i.node() for i in parents) & set(side))
706 706 if num == 1:
707 707 return parents[0].ancestor(parents[1])
708 708 return None
709 709
710 710 def print_result(nodes, good):
711 711 displayer = cmdutil.show_changeset(ui, repo, {})
712 712 if len(nodes) == 1:
713 713 # narrowed it down to a single revision
714 714 if good:
715 715 ui.write(_("The first good revision is:\n"))
716 716 else:
717 717 ui.write(_("The first bad revision is:\n"))
718 718 displayer.show(repo[nodes[0]])
719 719 extendnode = extendbisectrange(nodes, good)
720 720 if extendnode is not None:
721 721 ui.write(_('Not all ancestors of this changeset have been'
722 722 ' checked.\nUse bisect --extend to continue the '
723 723 'bisection from\nthe common ancestor, %s.\n')
724 724 % extendnode)
725 725 else:
726 726 # multiple possible revisions
727 727 if good:
728 728 ui.write(_("Due to skipped revisions, the first "
729 729 "good revision could be any of:\n"))
730 730 else:
731 731 ui.write(_("Due to skipped revisions, the first "
732 732 "bad revision could be any of:\n"))
733 733 for n in nodes:
734 734 displayer.show(repo[n])
735 735 displayer.close()
736 736
737 737 def check_state(state, interactive=True):
738 738 if not state['good'] or not state['bad']:
739 739 if (good or bad or skip or reset) and interactive:
740 740 return
741 741 if not state['good']:
742 742 raise util.Abort(_('cannot bisect (no known good revisions)'))
743 743 else:
744 744 raise util.Abort(_('cannot bisect (no known bad revisions)'))
745 745 return True
746 746
747 747 # backward compatibility
748 748 if rev in "good bad reset init".split():
749 749 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
750 750 cmd, rev, extra = rev, extra, None
751 751 if cmd == "good":
752 752 good = True
753 753 elif cmd == "bad":
754 754 bad = True
755 755 else:
756 756 reset = True
757 757 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
758 758 raise util.Abort(_('incompatible arguments'))
759 759
760 760 cmdutil.checkunfinished(repo)
761 761
762 762 if reset:
763 763 p = repo.join("bisect.state")
764 764 if os.path.exists(p):
765 765 os.unlink(p)
766 766 return
767 767
768 768 state = hbisect.load_state(repo)
769 769
770 770 if command:
771 771 changesets = 1
772 772 if noupdate:
773 773 try:
774 774 node = state['current'][0]
775 775 except LookupError:
776 776 raise util.Abort(_('current bisect revision is unknown - '
777 777 'start a new bisect to fix'))
778 778 else:
779 779 node, p2 = repo.dirstate.parents()
780 780 if p2 != nullid:
781 781 raise util.Abort(_('current bisect revision is a merge'))
782 782 try:
783 783 while changesets:
784 784 # update state
785 785 state['current'] = [node]
786 786 hbisect.save_state(repo, state)
787 787 status = ui.system(command, environ={'HG_NODE': hex(node)})
788 788 if status == 125:
789 789 transition = "skip"
790 790 elif status == 0:
791 791 transition = "good"
792 792 # status < 0 means process was killed
793 793 elif status == 127:
794 794 raise util.Abort(_("failed to execute %s") % command)
795 795 elif status < 0:
796 796 raise util.Abort(_("%s killed") % command)
797 797 else:
798 798 transition = "bad"
799 799 ctx = scmutil.revsingle(repo, rev, node)
800 800 rev = None # clear for future iterations
801 801 state[transition].append(ctx.node())
802 802 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
803 803 check_state(state, interactive=False)
804 804 # bisect
805 805 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
806 806 # update to next check
807 807 node = nodes[0]
808 808 if not noupdate:
809 809 cmdutil.bailifchanged(repo)
810 810 hg.clean(repo, node, show_stats=False)
811 811 finally:
812 812 state['current'] = [node]
813 813 hbisect.save_state(repo, state)
814 814 print_result(nodes, bgood)
815 815 return
816 816
817 817 # update state
818 818
819 819 if rev:
820 820 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
821 821 else:
822 822 nodes = [repo.lookup('.')]
823 823
824 824 if good or bad or skip:
825 825 if good:
826 826 state['good'] += nodes
827 827 elif bad:
828 828 state['bad'] += nodes
829 829 elif skip:
830 830 state['skip'] += nodes
831 831 hbisect.save_state(repo, state)
832 832
833 833 if not check_state(state):
834 834 return
835 835
836 836 # actually bisect
837 837 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
838 838 if extend:
839 839 if not changesets:
840 840 extendnode = extendbisectrange(nodes, good)
841 841 if extendnode is not None:
842 842 ui.write(_("Extending search to changeset %d:%s\n")
843 843 % (extendnode.rev(), extendnode))
844 844 state['current'] = [extendnode.node()]
845 845 hbisect.save_state(repo, state)
846 846 if noupdate:
847 847 return
848 848 cmdutil.bailifchanged(repo)
849 849 return hg.clean(repo, extendnode.node())
850 850 raise util.Abort(_("nothing to extend"))
851 851
852 852 if changesets == 0:
853 853 print_result(nodes, good)
854 854 else:
855 855 assert len(nodes) == 1 # only a single node can be tested next
856 856 node = nodes[0]
857 857 # compute the approximate number of remaining tests
858 858 tests, size = 0, 2
859 859 while size <= changesets:
860 860 tests, size = tests + 1, size * 2
861 861 rev = repo.changelog.rev(node)
862 862 ui.write(_("Testing changeset %d:%s "
863 863 "(%d changesets remaining, ~%d tests)\n")
864 864 % (rev, short(node), changesets, tests))
865 865 state['current'] = [node]
866 866 hbisect.save_state(repo, state)
867 867 if not noupdate:
868 868 cmdutil.bailifchanged(repo)
869 869 return hg.clean(repo, node)
870 870
871 871 @command('bookmarks|bookmark',
872 872 [('f', 'force', False, _('force')),
873 873 ('r', 'rev', '', _('revision'), _('REV')),
874 874 ('d', 'delete', False, _('delete a given bookmark')),
875 875 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
876 876 ('i', 'inactive', False, _('mark a bookmark inactive')),
877 877 ] + formatteropts,
878 878 _('hg bookmarks [OPTIONS]... [NAME]...'))
879 879 def bookmark(ui, repo, *names, **opts):
880 880 '''create a new bookmark or list existing bookmarks
881 881
882 882 Bookmarks are labels on changesets to help track lines of development.
883 883 Bookmarks are unversioned and can be moved, renamed and deleted.
884 884 Deleting or moving a bookmark has no effect on the associated changesets.
885 885
886 886 Creating or updating to a bookmark causes it to be marked as 'active'.
887 887 The active bookmark is indicated with a '*'.
888 888 When a commit is made, the active bookmark will advance to the new commit.
889 889 A plain :hg:`update` will also advance an active bookmark, if possible.
890 890 Updating away from a bookmark will cause it to be deactivated.
891 891
892 892 Bookmarks can be pushed and pulled between repositories (see
893 893 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
894 894 diverged, a new 'divergent bookmark' of the form 'name@path' will
895 895 be created. Using :hg:`merge` will resolve the divergence.
896 896
897 897 A bookmark named '@' has the special property that :hg:`clone` will
898 898 check it out by default if it exists.
899 899
900 900 .. container:: verbose
901 901
902 902 Examples:
903 903
904 904 - create an active bookmark for a new line of development::
905 905
906 906 hg book new-feature
907 907
908 908 - create an inactive bookmark as a place marker::
909 909
910 910 hg book -i reviewed
911 911
912 912 - create an inactive bookmark on another changeset::
913 913
914 914 hg book -r .^ tested
915 915
916 916 - move the '@' bookmark from another branch::
917 917
918 918 hg book -f @
919 919 '''
920 920 force = opts.get('force')
921 921 rev = opts.get('rev')
922 922 delete = opts.get('delete')
923 923 rename = opts.get('rename')
924 924 inactive = opts.get('inactive')
925 925
926 926 def checkformat(mark):
927 927 mark = mark.strip()
928 928 if not mark:
929 929 raise util.Abort(_("bookmark names cannot consist entirely of "
930 930 "whitespace"))
931 931 scmutil.checknewlabel(repo, mark, 'bookmark')
932 932 return mark
933 933
934 934 def checkconflict(repo, mark, cur, force=False, target=None):
935 935 if mark in marks and not force:
936 936 if target:
937 937 if marks[mark] == target and target == cur:
938 938 # re-activating a bookmark
939 939 return
940 940 anc = repo.changelog.ancestors([repo[target].rev()])
941 941 bmctx = repo[marks[mark]]
942 942 divs = [repo[b].node() for b in marks
943 943 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
944 944
945 945 # allow resolving a single divergent bookmark even if moving
946 946 # the bookmark across branches when a revision is specified
947 947 # that contains a divergent bookmark
948 948 if bmctx.rev() not in anc and target in divs:
949 949 bookmarks.deletedivergent(repo, [target], mark)
950 950 return
951 951
952 952 deletefrom = [b for b in divs
953 953 if repo[b].rev() in anc or b == target]
954 954 bookmarks.deletedivergent(repo, deletefrom, mark)
955 955 if bookmarks.validdest(repo, bmctx, repo[target]):
956 956 ui.status(_("moving bookmark '%s' forward from %s\n") %
957 957 (mark, short(bmctx.node())))
958 958 return
959 959 raise util.Abort(_("bookmark '%s' already exists "
960 960 "(use -f to force)") % mark)
961 961 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
962 962 and not force):
963 963 raise util.Abort(
964 964 _("a bookmark cannot have the name of an existing branch"))
965 965
966 966 if delete and rename:
967 967 raise util.Abort(_("--delete and --rename are incompatible"))
968 968 if delete and rev:
969 969 raise util.Abort(_("--rev is incompatible with --delete"))
970 970 if rename and rev:
971 971 raise util.Abort(_("--rev is incompatible with --rename"))
972 972 if not names and (delete or rev):
973 973 raise util.Abort(_("bookmark name required"))
974 974
975 975 if delete or rename or names or inactive:
976 976 wlock = repo.wlock()
977 977 try:
978 978 cur = repo.changectx('.').node()
979 979 marks = repo._bookmarks
980 980 if delete:
981 981 for mark in names:
982 982 if mark not in marks:
983 983 raise util.Abort(_("bookmark '%s' does not exist") %
984 984 mark)
985 985 if mark == repo._bookmarkcurrent:
986 986 bookmarks.unsetcurrent(repo)
987 987 del marks[mark]
988 988 marks.write()
989 989
990 990 elif rename:
991 991 if not names:
992 992 raise util.Abort(_("new bookmark name required"))
993 993 elif len(names) > 1:
994 994 raise util.Abort(_("only one new bookmark name allowed"))
995 995 mark = checkformat(names[0])
996 996 if rename not in marks:
997 997 raise util.Abort(_("bookmark '%s' does not exist") % rename)
998 998 checkconflict(repo, mark, cur, force)
999 999 marks[mark] = marks[rename]
1000 1000 if repo._bookmarkcurrent == rename and not inactive:
1001 1001 bookmarks.setcurrent(repo, mark)
1002 1002 del marks[rename]
1003 1003 marks.write()
1004 1004
1005 1005 elif names:
1006 1006 newact = None
1007 1007 for mark in names:
1008 1008 mark = checkformat(mark)
1009 1009 if newact is None:
1010 1010 newact = mark
1011 1011 if inactive and mark == repo._bookmarkcurrent:
1012 1012 bookmarks.unsetcurrent(repo)
1013 1013 return
1014 1014 tgt = cur
1015 1015 if rev:
1016 1016 tgt = scmutil.revsingle(repo, rev).node()
1017 1017 checkconflict(repo, mark, cur, force, tgt)
1018 1018 marks[mark] = tgt
1019 1019 if not inactive and cur == marks[newact] and not rev:
1020 1020 bookmarks.setcurrent(repo, newact)
1021 1021 elif cur != tgt and newact == repo._bookmarkcurrent:
1022 1022 bookmarks.unsetcurrent(repo)
1023 1023 marks.write()
1024 1024
1025 1025 elif inactive:
1026 1026 if len(marks) == 0:
1027 1027 ui.status(_("no bookmarks set\n"))
1028 1028 elif not repo._bookmarkcurrent:
1029 1029 ui.status(_("no active bookmark\n"))
1030 1030 else:
1031 1031 bookmarks.unsetcurrent(repo)
1032 1032 finally:
1033 1033 wlock.release()
1034 1034 else: # show bookmarks
1035 1035 fm = ui.formatter('bookmarks', opts)
1036 1036 hexfn = fm.hexfunc
1037 1037 marks = repo._bookmarks
1038 1038 if len(marks) == 0 and not fm:
1039 1039 ui.status(_("no bookmarks set\n"))
1040 1040 for bmark, n in sorted(marks.iteritems()):
1041 1041 current = repo._bookmarkcurrent
1042 1042 if bmark == current:
1043 1043 prefix, label = '*', 'bookmarks.current'
1044 1044 else:
1045 1045 prefix, label = ' ', ''
1046 1046
1047 1047 fm.startitem()
1048 1048 if not ui.quiet:
1049 1049 fm.plain(' %s ' % prefix, label=label)
1050 1050 fm.write('bookmark', '%s', bmark, label=label)
1051 1051 pad = " " * (25 - encoding.colwidth(bmark))
1052 1052 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1053 1053 repo.changelog.rev(n), hexfn(n), label=label)
1054 1054 fm.data(active=(bmark == current))
1055 1055 fm.plain('\n')
1056 1056 fm.end()
1057 1057
1058 1058 @command('branch',
1059 1059 [('f', 'force', None,
1060 1060 _('set branch name even if it shadows an existing branch')),
1061 1061 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1062 1062 _('[-fC] [NAME]'))
1063 1063 def branch(ui, repo, label=None, **opts):
1064 1064 """set or show the current branch name
1065 1065
1066 1066 .. note::
1067 1067
1068 1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1069 1069 light-weight bookmark instead. See :hg:`help glossary` for more
1070 1070 information about named branches and bookmarks.
1071 1071
1072 1072 With no argument, show the current branch name. With one argument,
1073 1073 set the working directory branch name (the branch will not exist
1074 1074 in the repository until the next commit). Standard practice
1075 1075 recommends that primary development take place on the 'default'
1076 1076 branch.
1077 1077
1078 1078 Unless -f/--force is specified, branch will not let you set a
1079 1079 branch name that already exists.
1080 1080
1081 1081 Use -C/--clean to reset the working directory branch to that of
1082 1082 the parent of the working directory, negating a previous branch
1083 1083 change.
1084 1084
1085 1085 Use the command :hg:`update` to switch to an existing branch. Use
1086 1086 :hg:`commit --close-branch` to mark this branch as closed.
1087 1087
1088 1088 Returns 0 on success.
1089 1089 """
1090 1090 if label:
1091 1091 label = label.strip()
1092 1092
1093 1093 if not opts.get('clean') and not label:
1094 1094 ui.write("%s\n" % repo.dirstate.branch())
1095 1095 return
1096 1096
1097 1097 wlock = repo.wlock()
1098 1098 try:
1099 1099 if opts.get('clean'):
1100 1100 label = repo[None].p1().branch()
1101 1101 repo.dirstate.setbranch(label)
1102 1102 ui.status(_('reset working directory to branch %s\n') % label)
1103 1103 elif label:
1104 1104 if not opts.get('force') and label in repo.branchmap():
1105 1105 if label not in [p.branch() for p in repo.parents()]:
1106 1106 raise util.Abort(_('a branch of the same name already'
1107 1107 ' exists'),
1108 1108 # i18n: "it" refers to an existing branch
1109 1109 hint=_("use 'hg update' to switch to it"))
1110 1110 scmutil.checknewlabel(repo, label, 'branch')
1111 1111 repo.dirstate.setbranch(label)
1112 1112 ui.status(_('marked working directory as branch %s\n') % label)
1113 1113 ui.status(_('(branches are permanent and global, '
1114 1114 'did you want a bookmark?)\n'))
1115 1115 finally:
1116 1116 wlock.release()
1117 1117
1118 1118 @command('branches',
1119 1119 [('a', 'active', False,
1120 1120 _('show only branches that have unmerged heads (DEPRECATED)')),
1121 1121 ('c', 'closed', False, _('show normal and closed branches')),
1122 1122 ] + formatteropts,
1123 1123 _('[-ac]'))
1124 1124 def branches(ui, repo, active=False, closed=False, **opts):
1125 1125 """list repository named branches
1126 1126
1127 1127 List the repository's named branches, indicating which ones are
1128 1128 inactive. If -c/--closed is specified, also list branches which have
1129 1129 been marked closed (see :hg:`commit --close-branch`).
1130 1130
1131 1131 Use the command :hg:`update` to switch to an existing branch.
1132 1132
1133 1133 Returns 0.
1134 1134 """
1135 1135
1136 1136 fm = ui.formatter('branches', opts)
1137 1137 hexfunc = fm.hexfunc
1138 1138
1139 1139 allheads = set(repo.heads())
1140 1140 branches = []
1141 1141 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1142 1142 isactive = not isclosed and bool(set(heads) & allheads)
1143 1143 branches.append((tag, repo[tip], isactive, not isclosed))
1144 1144 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1145 1145 reverse=True)
1146 1146
1147 1147 for tag, ctx, isactive, isopen in branches:
1148 1148 if active and not isactive:
1149 1149 continue
1150 1150 if isactive:
1151 1151 label = 'branches.active'
1152 1152 notice = ''
1153 1153 elif not isopen:
1154 1154 if not closed:
1155 1155 continue
1156 1156 label = 'branches.closed'
1157 1157 notice = _(' (closed)')
1158 1158 else:
1159 1159 label = 'branches.inactive'
1160 1160 notice = _(' (inactive)')
1161 1161 current = (tag == repo.dirstate.branch())
1162 1162 if current:
1163 1163 label = 'branches.current'
1164 1164
1165 1165 fm.startitem()
1166 1166 fm.write('branch', '%s', tag, label=label)
1167 1167 rev = ctx.rev()
1168 1168 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1169 1169 fmt = ' ' * padsize + ' %d:%s'
1170 1170 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1171 1171 label='log.changeset changeset.%s' % ctx.phasestr())
1172 1172 fm.data(active=isactive, closed=not isopen, current=current)
1173 1173 if not ui.quiet:
1174 1174 fm.plain(notice)
1175 1175 fm.plain('\n')
1176 1176 fm.end()
1177 1177
1178 1178 @command('bundle',
1179 1179 [('f', 'force', None, _('run even when the destination is unrelated')),
1180 1180 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1181 1181 _('REV')),
1182 1182 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1183 1183 _('BRANCH')),
1184 1184 ('', 'base', [],
1185 1185 _('a base changeset assumed to be available at the destination'),
1186 1186 _('REV')),
1187 1187 ('a', 'all', None, _('bundle all changesets in the repository')),
1188 1188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1189 1189 ] + remoteopts,
1190 1190 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1191 1191 def bundle(ui, repo, fname, dest=None, **opts):
1192 1192 """create a changegroup file
1193 1193
1194 1194 Generate a compressed changegroup file collecting changesets not
1195 1195 known to be in another repository.
1196 1196
1197 1197 If you omit the destination repository, then hg assumes the
1198 1198 destination will have all the nodes you specify with --base
1199 1199 parameters. To create a bundle containing all changesets, use
1200 1200 -a/--all (or --base null).
1201 1201
1202 1202 You can change compression method with the -t/--type option.
1203 1203 The available compression methods are: none, bzip2, and
1204 1204 gzip (by default, bundles are compressed using bzip2).
1205 1205
1206 1206 The bundle file can then be transferred using conventional means
1207 1207 and applied to another repository with the unbundle or pull
1208 1208 command. This is useful when direct push and pull are not
1209 1209 available or when exporting an entire repository is undesirable.
1210 1210
1211 1211 Applying bundles preserves all changeset contents including
1212 1212 permissions, copy/rename information, and revision history.
1213 1213
1214 1214 Returns 0 on success, 1 if no changes found.
1215 1215 """
1216 1216 revs = None
1217 1217 if 'rev' in opts:
1218 1218 revs = scmutil.revrange(repo, opts['rev'])
1219 1219
1220 1220 bundletype = opts.get('type', 'bzip2').lower()
1221 1221 btypes = {'none': 'HG10UN',
1222 1222 'bzip2': 'HG10BZ',
1223 1223 'gzip': 'HG10GZ',
1224 1224 'bundle2': 'HG2Y'}
1225 1225 bundletype = btypes.get(bundletype)
1226 1226 if bundletype not in changegroup.bundletypes:
1227 1227 raise util.Abort(_('unknown bundle type specified with --type'))
1228 1228
1229 1229 if opts.get('all'):
1230 1230 base = ['null']
1231 1231 else:
1232 1232 base = scmutil.revrange(repo, opts.get('base'))
1233 1233 # TODO: get desired bundlecaps from command line.
1234 1234 bundlecaps = None
1235 1235 if base:
1236 1236 if dest:
1237 1237 raise util.Abort(_("--base is incompatible with specifying "
1238 1238 "a destination"))
1239 1239 common = [repo.lookup(rev) for rev in base]
1240 1240 heads = revs and map(repo.lookup, revs) or revs
1241 1241 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1242 1242 common=common, bundlecaps=bundlecaps)
1243 1243 outgoing = None
1244 1244 else:
1245 1245 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1246 1246 dest, branches = hg.parseurl(dest, opts.get('branch'))
1247 1247 other = hg.peer(repo, opts, dest)
1248 1248 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1249 1249 heads = revs and map(repo.lookup, revs) or revs
1250 1250 outgoing = discovery.findcommonoutgoing(repo, other,
1251 1251 onlyheads=heads,
1252 1252 force=opts.get('force'),
1253 1253 portable=True)
1254 1254 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1255 1255 bundlecaps)
1256 1256 if not cg:
1257 1257 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1258 1258 return 1
1259 1259
1260 1260 changegroup.writebundle(ui, cg, fname, bundletype)
1261 1261
1262 1262 @command('cat',
1263 1263 [('o', 'output', '',
1264 1264 _('print output to file with formatted name'), _('FORMAT')),
1265 1265 ('r', 'rev', '', _('print the given revision'), _('REV')),
1266 1266 ('', 'decode', None, _('apply any matching decode filter')),
1267 1267 ] + walkopts,
1268 1268 _('[OPTION]... FILE...'),
1269 1269 inferrepo=True)
1270 1270 def cat(ui, repo, file1, *pats, **opts):
1271 1271 """output the current or given revision of files
1272 1272
1273 1273 Print the specified files as they were at the given revision. If
1274 1274 no revision is given, the parent of the working directory is used.
1275 1275
1276 1276 Output may be to a file, in which case the name of the file is
1277 1277 given using a format string. The formatting rules as follows:
1278 1278
1279 1279 :``%%``: literal "%" character
1280 1280 :``%s``: basename of file being printed
1281 1281 :``%d``: dirname of file being printed, or '.' if in repository root
1282 1282 :``%p``: root-relative path name of file being printed
1283 1283 :``%H``: changeset hash (40 hexadecimal digits)
1284 1284 :``%R``: changeset revision number
1285 1285 :``%h``: short-form changeset hash (12 hexadecimal digits)
1286 1286 :``%r``: zero-padded changeset revision number
1287 1287 :``%b``: basename of the exporting repository
1288 1288
1289 1289 Returns 0 on success.
1290 1290 """
1291 1291 ctx = scmutil.revsingle(repo, opts.get('rev'))
1292 1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1293 1293
1294 1294 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1295 1295
1296 1296 @command('^clone',
1297 1297 [('U', 'noupdate', None, _('the clone will include an empty working '
1298 1298 'directory (only a repository)')),
1299 1299 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1300 1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1301 1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1302 1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1303 1303 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1304 1304 ] + remoteopts,
1305 1305 _('[OPTION]... SOURCE [DEST]'),
1306 1306 norepo=True)
1307 1307 def clone(ui, source, dest=None, **opts):
1308 1308 """make a copy of an existing repository
1309 1309
1310 1310 Create a copy of an existing repository in a new directory.
1311 1311
1312 1312 If no destination directory name is specified, it defaults to the
1313 1313 basename of the source.
1314 1314
1315 1315 The location of the source is added to the new repository's
1316 1316 ``.hg/hgrc`` file, as the default to be used for future pulls.
1317 1317
1318 1318 Only local paths and ``ssh://`` URLs are supported as
1319 1319 destinations. For ``ssh://`` destinations, no working directory or
1320 1320 ``.hg/hgrc`` will be created on the remote side.
1321 1321
1322 1322 To pull only a subset of changesets, specify one or more revisions
1323 1323 identifiers with -r/--rev or branches with -b/--branch. The
1324 1324 resulting clone will contain only the specified changesets and
1325 1325 their ancestors. These options (or 'clone src#rev dest') imply
1326 1326 --pull, even for local source repositories. Note that specifying a
1327 1327 tag will include the tagged changeset but not the changeset
1328 1328 containing the tag.
1329 1329
1330 1330 If the source repository has a bookmark called '@' set, that
1331 1331 revision will be checked out in the new repository by default.
1332 1332
1333 1333 To check out a particular version, use -u/--update, or
1334 1334 -U/--noupdate to create a clone with no working directory.
1335 1335
1336 1336 .. container:: verbose
1337 1337
1338 1338 For efficiency, hardlinks are used for cloning whenever the
1339 1339 source and destination are on the same filesystem (note this
1340 1340 applies only to the repository data, not to the working
1341 1341 directory). Some filesystems, such as AFS, implement hardlinking
1342 1342 incorrectly, but do not report errors. In these cases, use the
1343 1343 --pull option to avoid hardlinking.
1344 1344
1345 1345 In some cases, you can clone repositories and the working
1346 1346 directory using full hardlinks with ::
1347 1347
1348 1348 $ cp -al REPO REPOCLONE
1349 1349
1350 1350 This is the fastest way to clone, but it is not always safe. The
1351 1351 operation is not atomic (making sure REPO is not modified during
1352 1352 the operation is up to you) and you have to make sure your
1353 1353 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1354 1354 so). Also, this is not compatible with certain extensions that
1355 1355 place their metadata under the .hg directory, such as mq.
1356 1356
1357 1357 Mercurial will update the working directory to the first applicable
1358 1358 revision from this list:
1359 1359
1360 1360 a) null if -U or the source repository has no changesets
1361 1361 b) if -u . and the source repository is local, the first parent of
1362 1362 the source repository's working directory
1363 1363 c) the changeset specified with -u (if a branch name, this means the
1364 1364 latest head of that branch)
1365 1365 d) the changeset specified with -r
1366 1366 e) the tipmost head specified with -b
1367 1367 f) the tipmost head specified with the url#branch source syntax
1368 1368 g) the revision marked with the '@' bookmark, if present
1369 1369 h) the tipmost head of the default branch
1370 1370 i) tip
1371 1371
1372 1372 Examples:
1373 1373
1374 1374 - clone a remote repository to a new directory named hg/::
1375 1375
1376 1376 hg clone http://selenic.com/hg
1377 1377
1378 1378 - create a lightweight local clone::
1379 1379
1380 1380 hg clone project/ project-feature/
1381 1381
1382 1382 - clone from an absolute path on an ssh server (note double-slash)::
1383 1383
1384 1384 hg clone ssh://user@server//home/projects/alpha/
1385 1385
1386 1386 - do a high-speed clone over a LAN while checking out a
1387 1387 specified version::
1388 1388
1389 1389 hg clone --uncompressed http://server/repo -u 1.5
1390 1390
1391 1391 - create a repository without changesets after a particular revision::
1392 1392
1393 1393 hg clone -r 04e544 experimental/ good/
1394 1394
1395 1395 - clone (and track) a particular named branch::
1396 1396
1397 1397 hg clone http://selenic.com/hg#stable
1398 1398
1399 1399 See :hg:`help urls` for details on specifying URLs.
1400 1400
1401 1401 Returns 0 on success.
1402 1402 """
1403 1403 if opts.get('noupdate') and opts.get('updaterev'):
1404 1404 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1405 1405
1406 1406 r = hg.clone(ui, opts, source, dest,
1407 1407 pull=opts.get('pull'),
1408 1408 stream=opts.get('uncompressed'),
1409 1409 rev=opts.get('rev'),
1410 1410 update=opts.get('updaterev') or not opts.get('noupdate'),
1411 1411 branch=opts.get('branch'))
1412 1412
1413 1413 return r is None
1414 1414
1415 1415 @command('^commit|ci',
1416 1416 [('A', 'addremove', None,
1417 1417 _('mark new/missing files as added/removed before committing')),
1418 1418 ('', 'close-branch', None,
1419 1419 _('mark a branch as closed, hiding it from the branch list')),
1420 1420 ('', 'amend', None, _('amend the parent of the working directory')),
1421 1421 ('s', 'secret', None, _('use the secret phase for committing')),
1422 1422 ('e', 'edit', None, _('invoke editor on commit messages')),
1423 1423 ('i', 'interactive', None, _('use interactive mode')),
1424 1424 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1425 1425 _('[OPTION]... [FILE]...'),
1426 1426 inferrepo=True)
1427 1427 def commit(ui, repo, *pats, **opts):
1428 1428 """commit the specified files or all outstanding changes
1429 1429
1430 1430 Commit changes to the given files into the repository. Unlike a
1431 1431 centralized SCM, this operation is a local operation. See
1432 1432 :hg:`push` for a way to actively distribute your changes.
1433 1433
1434 1434 If a list of files is omitted, all changes reported by :hg:`status`
1435 1435 will be committed.
1436 1436
1437 1437 If you are committing the result of a merge, do not provide any
1438 1438 filenames or -I/-X filters.
1439 1439
1440 1440 If no commit message is specified, Mercurial starts your
1441 1441 configured editor where you can enter a message. In case your
1442 1442 commit fails, you will find a backup of your message in
1443 1443 ``.hg/last-message.txt``.
1444 1444
1445 1445 The --amend flag can be used to amend the parent of the
1446 1446 working directory with a new commit that contains the changes
1447 1447 in the parent in addition to those currently reported by :hg:`status`,
1448 1448 if there are any. The old commit is stored in a backup bundle in
1449 1449 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1450 1450 on how to restore it).
1451 1451
1452 1452 Message, user and date are taken from the amended commit unless
1453 1453 specified. When a message isn't specified on the command line,
1454 1454 the editor will open with the message of the amended commit.
1455 1455
1456 1456 It is not possible to amend public changesets (see :hg:`help phases`)
1457 1457 or changesets that have children.
1458 1458
1459 1459 See :hg:`help dates` for a list of formats valid for -d/--date.
1460 1460
1461 1461 Returns 0 on success, 1 if nothing changed.
1462 1462 """
1463 1463 if opts.get('interactive'):
1464 1464 opts.pop('interactive')
1465 1465 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1466 1466 cmdutil.recordfilter, *pats, **opts)
1467 1467 return
1468 1468
1469 1469 if opts.get('subrepos'):
1470 1470 if opts.get('amend'):
1471 1471 raise util.Abort(_('cannot amend with --subrepos'))
1472 1472 # Let --subrepos on the command line override config setting.
1473 1473 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1474 1474
1475 1475 cmdutil.checkunfinished(repo, commit=True)
1476 1476
1477 1477 branch = repo[None].branch()
1478 1478 bheads = repo.branchheads(branch)
1479 1479
1480 1480 extra = {}
1481 1481 if opts.get('close_branch'):
1482 1482 extra['close'] = 1
1483 1483
1484 1484 if not bheads:
1485 1485 raise util.Abort(_('can only close branch heads'))
1486 1486 elif opts.get('amend'):
1487 1487 if repo.parents()[0].p1().branch() != branch and \
1488 1488 repo.parents()[0].p2().branch() != branch:
1489 1489 raise util.Abort(_('can only close branch heads'))
1490 1490
1491 1491 if opts.get('amend'):
1492 1492 if ui.configbool('ui', 'commitsubrepos'):
1493 1493 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1494 1494
1495 1495 old = repo['.']
1496 1496 if not old.mutable():
1497 1497 raise util.Abort(_('cannot amend public changesets'))
1498 1498 if len(repo[None].parents()) > 1:
1499 1499 raise util.Abort(_('cannot amend while merging'))
1500 1500 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1501 1501 if not allowunstable and old.children():
1502 1502 raise util.Abort(_('cannot amend changeset with children'))
1503 1503
1504 1504 # commitfunc is used only for temporary amend commit by cmdutil.amend
1505 1505 def commitfunc(ui, repo, message, match, opts):
1506 1506 return repo.commit(message,
1507 1507 opts.get('user') or old.user(),
1508 1508 opts.get('date') or old.date(),
1509 1509 match,
1510 1510 extra=extra)
1511 1511
1512 1512 current = repo._bookmarkcurrent
1513 1513 marks = old.bookmarks()
1514 1514 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1515 1515 if node == old.node():
1516 1516 ui.status(_("nothing changed\n"))
1517 1517 return 1
1518 1518 elif marks:
1519 1519 ui.debug('moving bookmarks %r from %s to %s\n' %
1520 1520 (marks, old.hex(), hex(node)))
1521 1521 newmarks = repo._bookmarks
1522 1522 for bm in marks:
1523 1523 newmarks[bm] = node
1524 1524 if bm == current:
1525 1525 bookmarks.setcurrent(repo, bm)
1526 1526 newmarks.write()
1527 1527 else:
1528 1528 def commitfunc(ui, repo, message, match, opts):
1529 1529 backup = ui.backupconfig('phases', 'new-commit')
1530 1530 baseui = repo.baseui
1531 1531 basebackup = baseui.backupconfig('phases', 'new-commit')
1532 1532 try:
1533 1533 if opts.get('secret'):
1534 1534 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1535 1535 # Propagate to subrepos
1536 1536 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1537 1537
1538 1538 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1539 1539 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1540 1540 return repo.commit(message, opts.get('user'), opts.get('date'),
1541 1541 match,
1542 1542 editor=editor,
1543 1543 extra=extra)
1544 1544 finally:
1545 1545 ui.restoreconfig(backup)
1546 1546 repo.baseui.restoreconfig(basebackup)
1547 1547
1548 1548
1549 1549 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1550 1550
1551 1551 if not node:
1552 1552 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1553 1553 if stat[3]:
1554 1554 ui.status(_("nothing changed (%d missing files, see "
1555 1555 "'hg status')\n") % len(stat[3]))
1556 1556 else:
1557 1557 ui.status(_("nothing changed\n"))
1558 1558 return 1
1559 1559
1560 1560 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1561 1561
1562 1562 @command('config|showconfig|debugconfig',
1563 1563 [('u', 'untrusted', None, _('show untrusted configuration options')),
1564 1564 ('e', 'edit', None, _('edit user config')),
1565 1565 ('l', 'local', None, _('edit repository config')),
1566 1566 ('g', 'global', None, _('edit global config'))],
1567 1567 _('[-u] [NAME]...'),
1568 1568 optionalrepo=True)
1569 1569 def config(ui, repo, *values, **opts):
1570 1570 """show combined config settings from all hgrc files
1571 1571
1572 1572 With no arguments, print names and values of all config items.
1573 1573
1574 1574 With one argument of the form section.name, print just the value
1575 1575 of that config item.
1576 1576
1577 1577 With multiple arguments, print names and values of all config
1578 1578 items with matching section names.
1579 1579
1580 1580 With --edit, start an editor on the user-level config file. With
1581 1581 --global, edit the system-wide config file. With --local, edit the
1582 1582 repository-level config file.
1583 1583
1584 1584 With --debug, the source (filename and line number) is printed
1585 1585 for each config item.
1586 1586
1587 1587 See :hg:`help config` for more information about config files.
1588 1588
1589 1589 Returns 0 on success, 1 if NAME does not exist.
1590 1590
1591 1591 """
1592 1592
1593 1593 if opts.get('edit') or opts.get('local') or opts.get('global'):
1594 1594 if opts.get('local') and opts.get('global'):
1595 1595 raise util.Abort(_("can't use --local and --global together"))
1596 1596
1597 1597 if opts.get('local'):
1598 1598 if not repo:
1599 1599 raise util.Abort(_("can't use --local outside a repository"))
1600 1600 paths = [repo.join('hgrc')]
1601 1601 elif opts.get('global'):
1602 1602 paths = scmutil.systemrcpath()
1603 1603 else:
1604 1604 paths = scmutil.userrcpath()
1605 1605
1606 1606 for f in paths:
1607 1607 if os.path.exists(f):
1608 1608 break
1609 1609 else:
1610 1610 if opts.get('global'):
1611 1611 samplehgrc = uimod.samplehgrcs['global']
1612 1612 elif opts.get('local'):
1613 1613 samplehgrc = uimod.samplehgrcs['local']
1614 1614 else:
1615 1615 samplehgrc = uimod.samplehgrcs['user']
1616 1616
1617 1617 f = paths[0]
1618 1618 fp = open(f, "w")
1619 1619 fp.write(samplehgrc)
1620 1620 fp.close()
1621 1621
1622 1622 editor = ui.geteditor()
1623 1623 ui.system("%s \"%s\"" % (editor, f),
1624 1624 onerr=util.Abort, errprefix=_("edit failed"))
1625 1625 return
1626 1626
1627 1627 for f in scmutil.rcpath():
1628 1628 ui.debug('read config from: %s\n' % f)
1629 1629 untrusted = bool(opts.get('untrusted'))
1630 1630 if values:
1631 1631 sections = [v for v in values if '.' not in v]
1632 1632 items = [v for v in values if '.' in v]
1633 1633 if len(items) > 1 or items and sections:
1634 1634 raise util.Abort(_('only one config item permitted'))
1635 1635 matched = False
1636 1636 for section, name, value in ui.walkconfig(untrusted=untrusted):
1637 1637 value = str(value).replace('\n', '\\n')
1638 1638 sectname = section + '.' + name
1639 1639 if values:
1640 1640 for v in values:
1641 1641 if v == section:
1642 1642 ui.debug('%s: ' %
1643 1643 ui.configsource(section, name, untrusted))
1644 1644 ui.write('%s=%s\n' % (sectname, value))
1645 1645 matched = True
1646 1646 elif v == sectname:
1647 1647 ui.debug('%s: ' %
1648 1648 ui.configsource(section, name, untrusted))
1649 1649 ui.write(value, '\n')
1650 1650 matched = True
1651 1651 else:
1652 1652 ui.debug('%s: ' %
1653 1653 ui.configsource(section, name, untrusted))
1654 1654 ui.write('%s=%s\n' % (sectname, value))
1655 1655 matched = True
1656 1656 if matched:
1657 1657 return 0
1658 1658 return 1
1659 1659
1660 1660 @command('copy|cp',
1661 1661 [('A', 'after', None, _('record a copy that has already occurred')),
1662 1662 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1663 1663 ] + walkopts + dryrunopts,
1664 1664 _('[OPTION]... [SOURCE]... DEST'))
1665 1665 def copy(ui, repo, *pats, **opts):
1666 1666 """mark files as copied for the next commit
1667 1667
1668 1668 Mark dest as having copies of source files. If dest is a
1669 1669 directory, copies are put in that directory. If dest is a file,
1670 1670 the source must be a single file.
1671 1671
1672 1672 By default, this command copies the contents of files as they
1673 1673 exist in the working directory. If invoked with -A/--after, the
1674 1674 operation is recorded, but no copying is performed.
1675 1675
1676 1676 This command takes effect with the next commit. To undo a copy
1677 1677 before that, see :hg:`revert`.
1678 1678
1679 1679 Returns 0 on success, 1 if errors are encountered.
1680 1680 """
1681 1681 wlock = repo.wlock(False)
1682 1682 try:
1683 1683 return cmdutil.copy(ui, repo, pats, opts)
1684 1684 finally:
1685 1685 wlock.release()
1686 1686
1687 1687 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1688 1688 def debugancestor(ui, repo, *args):
1689 1689 """find the ancestor revision of two revisions in a given index"""
1690 1690 if len(args) == 3:
1691 1691 index, rev1, rev2 = args
1692 1692 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1693 1693 lookup = r.lookup
1694 1694 elif len(args) == 2:
1695 1695 if not repo:
1696 1696 raise util.Abort(_("there is no Mercurial repository here "
1697 1697 "(.hg not found)"))
1698 1698 rev1, rev2 = args
1699 1699 r = repo.changelog
1700 1700 lookup = repo.lookup
1701 1701 else:
1702 1702 raise util.Abort(_('either two or three arguments required'))
1703 1703 a = r.ancestor(lookup(rev1), lookup(rev2))
1704 1704 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1705 1705
1706 1706 @command('debugbuilddag',
1707 1707 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1708 1708 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1709 1709 ('n', 'new-file', None, _('add new file at each rev'))],
1710 1710 _('[OPTION]... [TEXT]'))
1711 1711 def debugbuilddag(ui, repo, text=None,
1712 1712 mergeable_file=False,
1713 1713 overwritten_file=False,
1714 1714 new_file=False):
1715 1715 """builds a repo with a given DAG from scratch in the current empty repo
1716 1716
1717 1717 The description of the DAG is read from stdin if not given on the
1718 1718 command line.
1719 1719
1720 1720 Elements:
1721 1721
1722 1722 - "+n" is a linear run of n nodes based on the current default parent
1723 1723 - "." is a single node based on the current default parent
1724 1724 - "$" resets the default parent to null (implied at the start);
1725 1725 otherwise the default parent is always the last node created
1726 1726 - "<p" sets the default parent to the backref p
1727 1727 - "*p" is a fork at parent p, which is a backref
1728 1728 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1729 1729 - "/p2" is a merge of the preceding node and p2
1730 1730 - ":tag" defines a local tag for the preceding node
1731 1731 - "@branch" sets the named branch for subsequent nodes
1732 1732 - "#...\\n" is a comment up to the end of the line
1733 1733
1734 1734 Whitespace between the above elements is ignored.
1735 1735
1736 1736 A backref is either
1737 1737
1738 1738 - a number n, which references the node curr-n, where curr is the current
1739 1739 node, or
1740 1740 - the name of a local tag you placed earlier using ":tag", or
1741 1741 - empty to denote the default parent.
1742 1742
1743 1743 All string valued-elements are either strictly alphanumeric, or must
1744 1744 be enclosed in double quotes ("..."), with "\\" as escape character.
1745 1745 """
1746 1746
1747 1747 if text is None:
1748 1748 ui.status(_("reading DAG from stdin\n"))
1749 1749 text = ui.fin.read()
1750 1750
1751 1751 cl = repo.changelog
1752 1752 if len(cl) > 0:
1753 1753 raise util.Abort(_('repository is not empty'))
1754 1754
1755 1755 # determine number of revs in DAG
1756 1756 total = 0
1757 1757 for type, data in dagparser.parsedag(text):
1758 1758 if type == 'n':
1759 1759 total += 1
1760 1760
1761 1761 if mergeable_file:
1762 1762 linesperrev = 2
1763 1763 # make a file with k lines per rev
1764 1764 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1765 1765 initialmergedlines.append("")
1766 1766
1767 1767 tags = []
1768 1768
1769 1769 lock = tr = None
1770 1770 try:
1771 1771 lock = repo.lock()
1772 1772 tr = repo.transaction("builddag")
1773 1773
1774 1774 at = -1
1775 1775 atbranch = 'default'
1776 1776 nodeids = []
1777 1777 id = 0
1778 1778 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1779 1779 for type, data in dagparser.parsedag(text):
1780 1780 if type == 'n':
1781 1781 ui.note(('node %s\n' % str(data)))
1782 1782 id, ps = data
1783 1783
1784 1784 files = []
1785 1785 fctxs = {}
1786 1786
1787 1787 p2 = None
1788 1788 if mergeable_file:
1789 1789 fn = "mf"
1790 1790 p1 = repo[ps[0]]
1791 1791 if len(ps) > 1:
1792 1792 p2 = repo[ps[1]]
1793 1793 pa = p1.ancestor(p2)
1794 1794 base, local, other = [x[fn].data() for x in (pa, p1,
1795 1795 p2)]
1796 1796 m3 = simplemerge.Merge3Text(base, local, other)
1797 1797 ml = [l.strip() for l in m3.merge_lines()]
1798 1798 ml.append("")
1799 1799 elif at > 0:
1800 1800 ml = p1[fn].data().split("\n")
1801 1801 else:
1802 1802 ml = initialmergedlines
1803 1803 ml[id * linesperrev] += " r%i" % id
1804 1804 mergedtext = "\n".join(ml)
1805 1805 files.append(fn)
1806 1806 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1807 1807
1808 1808 if overwritten_file:
1809 1809 fn = "of"
1810 1810 files.append(fn)
1811 1811 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1812 1812
1813 1813 if new_file:
1814 1814 fn = "nf%i" % id
1815 1815 files.append(fn)
1816 1816 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1817 1817 if len(ps) > 1:
1818 1818 if not p2:
1819 1819 p2 = repo[ps[1]]
1820 1820 for fn in p2:
1821 1821 if fn.startswith("nf"):
1822 1822 files.append(fn)
1823 1823 fctxs[fn] = p2[fn]
1824 1824
1825 1825 def fctxfn(repo, cx, path):
1826 1826 return fctxs.get(path)
1827 1827
1828 1828 if len(ps) == 0 or ps[0] < 0:
1829 1829 pars = [None, None]
1830 1830 elif len(ps) == 1:
1831 1831 pars = [nodeids[ps[0]], None]
1832 1832 else:
1833 1833 pars = [nodeids[p] for p in ps]
1834 1834 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1835 1835 date=(id, 0),
1836 1836 user="debugbuilddag",
1837 1837 extra={'branch': atbranch})
1838 1838 nodeid = repo.commitctx(cx)
1839 1839 nodeids.append(nodeid)
1840 1840 at = id
1841 1841 elif type == 'l':
1842 1842 id, name = data
1843 1843 ui.note(('tag %s\n' % name))
1844 1844 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1845 1845 elif type == 'a':
1846 1846 ui.note(('branch %s\n' % data))
1847 1847 atbranch = data
1848 1848 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1849 1849 tr.close()
1850 1850
1851 1851 if tags:
1852 1852 repo.vfs.write("localtags", "".join(tags))
1853 1853 finally:
1854 1854 ui.progress(_('building'), None)
1855 1855 release(tr, lock)
1856 1856
1857 1857 @command('debugbundle',
1858 1858 [('a', 'all', None, _('show all details'))],
1859 1859 _('FILE'),
1860 1860 norepo=True)
1861 1861 def debugbundle(ui, bundlepath, all=None, **opts):
1862 1862 """lists the contents of a bundle"""
1863 1863 f = hg.openpath(ui, bundlepath)
1864 1864 try:
1865 1865 gen = exchange.readbundle(ui, f, bundlepath)
1866 1866 if isinstance(gen, bundle2.unbundle20):
1867 1867 return _debugbundle2(ui, gen, all=all, **opts)
1868 1868 if all:
1869 1869 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1870 1870
1871 1871 def showchunks(named):
1872 1872 ui.write("\n%s\n" % named)
1873 1873 chain = None
1874 1874 while True:
1875 1875 chunkdata = gen.deltachunk(chain)
1876 1876 if not chunkdata:
1877 1877 break
1878 1878 node = chunkdata['node']
1879 1879 p1 = chunkdata['p1']
1880 1880 p2 = chunkdata['p2']
1881 1881 cs = chunkdata['cs']
1882 1882 deltabase = chunkdata['deltabase']
1883 1883 delta = chunkdata['delta']
1884 1884 ui.write("%s %s %s %s %s %s\n" %
1885 1885 (hex(node), hex(p1), hex(p2),
1886 1886 hex(cs), hex(deltabase), len(delta)))
1887 1887 chain = node
1888 1888
1889 1889 chunkdata = gen.changelogheader()
1890 1890 showchunks("changelog")
1891 1891 chunkdata = gen.manifestheader()
1892 1892 showchunks("manifest")
1893 1893 while True:
1894 1894 chunkdata = gen.filelogheader()
1895 1895 if not chunkdata:
1896 1896 break
1897 1897 fname = chunkdata['filename']
1898 1898 showchunks(fname)
1899 1899 else:
1900 1900 if isinstance(gen, bundle2.unbundle20):
1901 1901 raise util.Abort(_('use debugbundle2 for this file'))
1902 1902 chunkdata = gen.changelogheader()
1903 1903 chain = None
1904 1904 while True:
1905 1905 chunkdata = gen.deltachunk(chain)
1906 1906 if not chunkdata:
1907 1907 break
1908 1908 node = chunkdata['node']
1909 1909 ui.write("%s\n" % hex(node))
1910 1910 chain = node
1911 1911 finally:
1912 1912 f.close()
1913 1913
1914 1914 def _debugbundle2(ui, gen, **opts):
1915 1915 """lists the contents of a bundle2"""
1916 1916 if not isinstance(gen, bundle2.unbundle20):
1917 1917 raise util.Abort(_('not a bundle2 file'))
1918 1918 ui.write(('Stream params: %s\n' % repr(gen.params)))
1919 1919 for part in gen.iterparts():
1920 1920 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1921 1921 if part.type == 'b2x:changegroup':
1922 1922 version = part.params.get('version', '01')
1923 1923 cg = changegroup.packermap[version][1](part, 'UN')
1924 1924 chunkdata = cg.changelogheader()
1925 1925 chain = None
1926 1926 while True:
1927 1927 chunkdata = cg.deltachunk(chain)
1928 1928 if not chunkdata:
1929 1929 break
1930 1930 node = chunkdata['node']
1931 1931 ui.write(" %s\n" % hex(node))
1932 1932 chain = node
1933 1933
1934 1934 @command('debugcheckstate', [], '')
1935 1935 def debugcheckstate(ui, repo):
1936 1936 """validate the correctness of the current dirstate"""
1937 1937 parent1, parent2 = repo.dirstate.parents()
1938 1938 m1 = repo[parent1].manifest()
1939 1939 m2 = repo[parent2].manifest()
1940 1940 errors = 0
1941 1941 for f in repo.dirstate:
1942 1942 state = repo.dirstate[f]
1943 1943 if state in "nr" and f not in m1:
1944 1944 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1945 1945 errors += 1
1946 1946 if state in "a" and f in m1:
1947 1947 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1948 1948 errors += 1
1949 1949 if state in "m" and f not in m1 and f not in m2:
1950 1950 ui.warn(_("%s in state %s, but not in either manifest\n") %
1951 1951 (f, state))
1952 1952 errors += 1
1953 1953 for f in m1:
1954 1954 state = repo.dirstate[f]
1955 1955 if state not in "nrm":
1956 1956 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1957 1957 errors += 1
1958 1958 if errors:
1959 1959 error = _(".hg/dirstate inconsistent with current parent's manifest")
1960 1960 raise util.Abort(error)
1961 1961
1962 1962 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1963 1963 def debugcommands(ui, cmd='', *args):
1964 1964 """list all available commands and options"""
1965 1965 for cmd, vals in sorted(table.iteritems()):
1966 1966 cmd = cmd.split('|')[0].strip('^')
1967 1967 opts = ', '.join([i[1] for i in vals[1]])
1968 1968 ui.write('%s: %s\n' % (cmd, opts))
1969 1969
1970 1970 @command('debugcomplete',
1971 1971 [('o', 'options', None, _('show the command options'))],
1972 1972 _('[-o] CMD'),
1973 1973 norepo=True)
1974 1974 def debugcomplete(ui, cmd='', **opts):
1975 1975 """returns the completion list associated with the given command"""
1976 1976
1977 1977 if opts.get('options'):
1978 1978 options = []
1979 1979 otables = [globalopts]
1980 1980 if cmd:
1981 1981 aliases, entry = cmdutil.findcmd(cmd, table, False)
1982 1982 otables.append(entry[1])
1983 1983 for t in otables:
1984 1984 for o in t:
1985 1985 if "(DEPRECATED)" in o[3]:
1986 1986 continue
1987 1987 if o[0]:
1988 1988 options.append('-%s' % o[0])
1989 1989 options.append('--%s' % o[1])
1990 1990 ui.write("%s\n" % "\n".join(options))
1991 1991 return
1992 1992
1993 1993 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1994 1994 if ui.verbose:
1995 1995 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1996 1996 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1997 1997
1998 1998 @command('debugdag',
1999 1999 [('t', 'tags', None, _('use tags as labels')),
2000 2000 ('b', 'branches', None, _('annotate with branch names')),
2001 2001 ('', 'dots', None, _('use dots for runs')),
2002 2002 ('s', 'spaces', None, _('separate elements by spaces'))],
2003 2003 _('[OPTION]... [FILE [REV]...]'),
2004 2004 optionalrepo=True)
2005 2005 def debugdag(ui, repo, file_=None, *revs, **opts):
2006 2006 """format the changelog or an index DAG as a concise textual description
2007 2007
2008 2008 If you pass a revlog index, the revlog's DAG is emitted. If you list
2009 2009 revision numbers, they get labeled in the output as rN.
2010 2010
2011 2011 Otherwise, the changelog DAG of the current repo is emitted.
2012 2012 """
2013 2013 spaces = opts.get('spaces')
2014 2014 dots = opts.get('dots')
2015 2015 if file_:
2016 2016 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2017 2017 revs = set((int(r) for r in revs))
2018 2018 def events():
2019 2019 for r in rlog:
2020 2020 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2021 2021 if p != -1))
2022 2022 if r in revs:
2023 2023 yield 'l', (r, "r%i" % r)
2024 2024 elif repo:
2025 2025 cl = repo.changelog
2026 2026 tags = opts.get('tags')
2027 2027 branches = opts.get('branches')
2028 2028 if tags:
2029 2029 labels = {}
2030 2030 for l, n in repo.tags().items():
2031 2031 labels.setdefault(cl.rev(n), []).append(l)
2032 2032 def events():
2033 2033 b = "default"
2034 2034 for r in cl:
2035 2035 if branches:
2036 2036 newb = cl.read(cl.node(r))[5]['branch']
2037 2037 if newb != b:
2038 2038 yield 'a', newb
2039 2039 b = newb
2040 2040 yield 'n', (r, list(p for p in cl.parentrevs(r)
2041 2041 if p != -1))
2042 2042 if tags:
2043 2043 ls = labels.get(r)
2044 2044 if ls:
2045 2045 for l in ls:
2046 2046 yield 'l', (r, l)
2047 2047 else:
2048 2048 raise util.Abort(_('need repo for changelog dag'))
2049 2049
2050 2050 for line in dagparser.dagtextlines(events(),
2051 2051 addspaces=spaces,
2052 2052 wraplabels=True,
2053 2053 wrapannotations=True,
2054 2054 wrapnonlinear=dots,
2055 2055 usedots=dots,
2056 2056 maxlinewidth=70):
2057 2057 ui.write(line)
2058 2058 ui.write("\n")
2059 2059
2060 2060 @command('debugdata',
2061 2061 [('c', 'changelog', False, _('open changelog')),
2062 2062 ('m', 'manifest', False, _('open manifest'))],
2063 2063 _('-c|-m|FILE REV'))
2064 2064 def debugdata(ui, repo, file_, rev=None, **opts):
2065 2065 """dump the contents of a data file revision"""
2066 2066 if opts.get('changelog') or opts.get('manifest'):
2067 2067 file_, rev = None, file_
2068 2068 elif rev is None:
2069 2069 raise error.CommandError('debugdata', _('invalid arguments'))
2070 2070 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2071 2071 try:
2072 2072 ui.write(r.revision(r.lookup(rev)))
2073 2073 except KeyError:
2074 2074 raise util.Abort(_('invalid revision identifier %s') % rev)
2075 2075
2076 2076 @command('debugdate',
2077 2077 [('e', 'extended', None, _('try extended date formats'))],
2078 2078 _('[-e] DATE [RANGE]'),
2079 2079 norepo=True, optionalrepo=True)
2080 2080 def debugdate(ui, date, range=None, **opts):
2081 2081 """parse and display a date"""
2082 2082 if opts["extended"]:
2083 2083 d = util.parsedate(date, util.extendeddateformats)
2084 2084 else:
2085 2085 d = util.parsedate(date)
2086 2086 ui.write(("internal: %s %s\n") % d)
2087 2087 ui.write(("standard: %s\n") % util.datestr(d))
2088 2088 if range:
2089 2089 m = util.matchdate(range)
2090 2090 ui.write(("match: %s\n") % m(d[0]))
2091 2091
2092 2092 @command('debugdiscovery',
2093 2093 [('', 'old', None, _('use old-style discovery')),
2094 2094 ('', 'nonheads', None,
2095 2095 _('use old-style discovery with non-heads included')),
2096 2096 ] + remoteopts,
2097 2097 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2098 2098 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2099 2099 """runs the changeset discovery protocol in isolation"""
2100 2100 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2101 2101 opts.get('branch'))
2102 2102 remote = hg.peer(repo, opts, remoteurl)
2103 2103 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2104 2104
2105 2105 # make sure tests are repeatable
2106 2106 random.seed(12323)
2107 2107
2108 2108 def doit(localheads, remoteheads, remote=remote):
2109 2109 if opts.get('old'):
2110 2110 if localheads:
2111 2111 raise util.Abort('cannot use localheads with old style '
2112 2112 'discovery')
2113 2113 if not util.safehasattr(remote, 'branches'):
2114 2114 # enable in-client legacy support
2115 2115 remote = localrepo.locallegacypeer(remote.local())
2116 2116 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2117 2117 force=True)
2118 2118 common = set(common)
2119 2119 if not opts.get('nonheads'):
2120 2120 ui.write(("unpruned common: %s\n") %
2121 2121 " ".join(sorted(short(n) for n in common)))
2122 2122 dag = dagutil.revlogdag(repo.changelog)
2123 2123 all = dag.ancestorset(dag.internalizeall(common))
2124 2124 common = dag.externalizeall(dag.headsetofconnecteds(all))
2125 2125 else:
2126 2126 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2127 2127 common = set(common)
2128 2128 rheads = set(hds)
2129 2129 lheads = set(repo.heads())
2130 2130 ui.write(("common heads: %s\n") %
2131 2131 " ".join(sorted(short(n) for n in common)))
2132 2132 if lheads <= common:
2133 2133 ui.write(("local is subset\n"))
2134 2134 elif rheads <= common:
2135 2135 ui.write(("remote is subset\n"))
2136 2136
2137 2137 serverlogs = opts.get('serverlog')
2138 2138 if serverlogs:
2139 2139 for filename in serverlogs:
2140 2140 logfile = open(filename, 'r')
2141 2141 try:
2142 2142 line = logfile.readline()
2143 2143 while line:
2144 2144 parts = line.strip().split(';')
2145 2145 op = parts[1]
2146 2146 if op == 'cg':
2147 2147 pass
2148 2148 elif op == 'cgss':
2149 2149 doit(parts[2].split(' '), parts[3].split(' '))
2150 2150 elif op == 'unb':
2151 2151 doit(parts[3].split(' '), parts[2].split(' '))
2152 2152 line = logfile.readline()
2153 2153 finally:
2154 2154 logfile.close()
2155 2155
2156 2156 else:
2157 2157 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2158 2158 opts.get('remote_head'))
2159 2159 localrevs = opts.get('local_head')
2160 2160 doit(localrevs, remoterevs)
2161 2161
2162 2162 @command('debugfileset',
2163 2163 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2164 2164 _('[-r REV] FILESPEC'))
2165 2165 def debugfileset(ui, repo, expr, **opts):
2166 2166 '''parse and apply a fileset specification'''
2167 2167 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2168 2168 if ui.verbose:
2169 2169 tree = fileset.parse(expr)[0]
2170 2170 ui.note(tree, "\n")
2171 2171
2172 2172 for f in ctx.getfileset(expr):
2173 2173 ui.write("%s\n" % f)
2174 2174
2175 2175 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2176 2176 def debugfsinfo(ui, path="."):
2177 2177 """show information detected about current filesystem"""
2178 2178 util.writefile('.debugfsinfo', '')
2179 2179 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2180 2180 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2181 2181 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2182 2182 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2183 2183 and 'yes' or 'no'))
2184 2184 os.unlink('.debugfsinfo')
2185 2185
2186 2186 @command('debuggetbundle',
2187 2187 [('H', 'head', [], _('id of head node'), _('ID')),
2188 2188 ('C', 'common', [], _('id of common node'), _('ID')),
2189 2189 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2190 2190 _('REPO FILE [-H|-C ID]...'),
2191 2191 norepo=True)
2192 2192 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2193 2193 """retrieves a bundle from a repo
2194 2194
2195 2195 Every ID must be a full-length hex node id string. Saves the bundle to the
2196 2196 given file.
2197 2197 """
2198 2198 repo = hg.peer(ui, opts, repopath)
2199 2199 if not repo.capable('getbundle'):
2200 2200 raise util.Abort("getbundle() not supported by target repository")
2201 2201 args = {}
2202 2202 if common:
2203 2203 args['common'] = [bin(s) for s in common]
2204 2204 if head:
2205 2205 args['heads'] = [bin(s) for s in head]
2206 2206 # TODO: get desired bundlecaps from command line.
2207 2207 args['bundlecaps'] = None
2208 2208 bundle = repo.getbundle('debug', **args)
2209 2209
2210 2210 bundletype = opts.get('type', 'bzip2').lower()
2211 2211 btypes = {'none': 'HG10UN',
2212 2212 'bzip2': 'HG10BZ',
2213 2213 'gzip': 'HG10GZ',
2214 2214 'bundle2': 'HG2Y'}
2215 2215 bundletype = btypes.get(bundletype)
2216 2216 if bundletype not in changegroup.bundletypes:
2217 2217 raise util.Abort(_('unknown bundle type specified with --type'))
2218 2218 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2219 2219
2220 2220 @command('debugignore', [], '')
2221 2221 def debugignore(ui, repo, *values, **opts):
2222 2222 """display the combined ignore pattern"""
2223 2223 ignore = repo.dirstate._ignore
2224 2224 includepat = getattr(ignore, 'includepat', None)
2225 2225 if includepat is not None:
2226 2226 ui.write("%s\n" % includepat)
2227 2227 else:
2228 2228 raise util.Abort(_("no ignore patterns found"))
2229 2229
2230 2230 @command('debugindex',
2231 2231 [('c', 'changelog', False, _('open changelog')),
2232 2232 ('m', 'manifest', False, _('open manifest')),
2233 2233 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2234 2234 _('[-f FORMAT] -c|-m|FILE'),
2235 2235 optionalrepo=True)
2236 2236 def debugindex(ui, repo, file_=None, **opts):
2237 2237 """dump the contents of an index file"""
2238 2238 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2239 2239 format = opts.get('format', 0)
2240 2240 if format not in (0, 1):
2241 2241 raise util.Abort(_("unknown format %d") % format)
2242 2242
2243 2243 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2244 2244 if generaldelta:
2245 2245 basehdr = ' delta'
2246 2246 else:
2247 2247 basehdr = ' base'
2248 2248
2249 2249 if ui.debugflag:
2250 2250 shortfn = hex
2251 2251 else:
2252 2252 shortfn = short
2253 2253
2254 2254 # There might not be anything in r, so have a sane default
2255 2255 idlen = 12
2256 2256 for i in r:
2257 2257 idlen = len(shortfn(r.node(i)))
2258 2258 break
2259 2259
2260 2260 if format == 0:
2261 2261 ui.write(" rev offset length " + basehdr + " linkrev"
2262 2262 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2263 2263 elif format == 1:
2264 2264 ui.write(" rev flag offset length"
2265 2265 " size " + basehdr + " link p1 p2"
2266 2266 " %s\n" % "nodeid".rjust(idlen))
2267 2267
2268 2268 for i in r:
2269 2269 node = r.node(i)
2270 2270 if generaldelta:
2271 2271 base = r.deltaparent(i)
2272 2272 else:
2273 2273 base = r.chainbase(i)
2274 2274 if format == 0:
2275 2275 try:
2276 2276 pp = r.parents(node)
2277 2277 except Exception:
2278 2278 pp = [nullid, nullid]
2279 2279 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2280 2280 i, r.start(i), r.length(i), base, r.linkrev(i),
2281 2281 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2282 2282 elif format == 1:
2283 2283 pr = r.parentrevs(i)
2284 2284 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2285 2285 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2286 2286 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2287 2287
2288 2288 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2289 2289 def debugindexdot(ui, repo, file_):
2290 2290 """dump an index DAG as a graphviz dot file"""
2291 2291 r = None
2292 2292 if repo:
2293 2293 filelog = repo.file(file_)
2294 2294 if len(filelog):
2295 2295 r = filelog
2296 2296 if not r:
2297 2297 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2298 2298 ui.write(("digraph G {\n"))
2299 2299 for i in r:
2300 2300 node = r.node(i)
2301 2301 pp = r.parents(node)
2302 2302 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2303 2303 if pp[1] != nullid:
2304 2304 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2305 2305 ui.write("}\n")
2306 2306
2307 2307 @command('debuginstall', [], '', norepo=True)
2308 2308 def debuginstall(ui):
2309 2309 '''test Mercurial installation
2310 2310
2311 2311 Returns 0 on success.
2312 2312 '''
2313 2313
2314 2314 def writetemp(contents):
2315 2315 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2316 2316 f = os.fdopen(fd, "wb")
2317 2317 f.write(contents)
2318 2318 f.close()
2319 2319 return name
2320 2320
2321 2321 problems = 0
2322 2322
2323 2323 # encoding
2324 2324 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2325 2325 try:
2326 2326 encoding.fromlocal("test")
2327 2327 except util.Abort, inst:
2328 2328 ui.write(" %s\n" % inst)
2329 2329 ui.write(_(" (check that your locale is properly set)\n"))
2330 2330 problems += 1
2331 2331
2332 2332 # Python
2333 2333 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2334 2334 ui.status(_("checking Python version (%s)\n")
2335 2335 % ("%s.%s.%s" % sys.version_info[:3]))
2336 2336 ui.status(_("checking Python lib (%s)...\n")
2337 2337 % os.path.dirname(os.__file__))
2338 2338
2339 2339 # compiled modules
2340 2340 ui.status(_("checking installed modules (%s)...\n")
2341 2341 % os.path.dirname(__file__))
2342 2342 try:
2343 2343 import bdiff, mpatch, base85, osutil
2344 2344 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2345 2345 except Exception, inst:
2346 2346 ui.write(" %s\n" % inst)
2347 2347 ui.write(_(" One or more extensions could not be found"))
2348 2348 ui.write(_(" (check that you compiled the extensions)\n"))
2349 2349 problems += 1
2350 2350
2351 2351 # templates
2352 2352 import templater
2353 2353 p = templater.templatepaths()
2354 2354 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2355 2355 if p:
2356 2356 m = templater.templatepath("map-cmdline.default")
2357 2357 if m:
2358 2358 # template found, check if it is working
2359 2359 try:
2360 2360 templater.templater(m)
2361 2361 except Exception, inst:
2362 2362 ui.write(" %s\n" % inst)
2363 2363 p = None
2364 2364 else:
2365 2365 ui.write(_(" template 'default' not found\n"))
2366 2366 p = None
2367 2367 else:
2368 2368 ui.write(_(" no template directories found\n"))
2369 2369 if not p:
2370 2370 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2371 2371 problems += 1
2372 2372
2373 2373 # editor
2374 2374 ui.status(_("checking commit editor...\n"))
2375 2375 editor = ui.geteditor()
2376 2376 cmdpath = util.findexe(shlex.split(editor)[0])
2377 2377 if not cmdpath:
2378 2378 if editor == 'vi':
2379 2379 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2380 2380 ui.write(_(" (specify a commit editor in your configuration"
2381 2381 " file)\n"))
2382 2382 else:
2383 2383 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2384 2384 ui.write(_(" (specify a commit editor in your configuration"
2385 2385 " file)\n"))
2386 2386 problems += 1
2387 2387
2388 2388 # check username
2389 2389 ui.status(_("checking username...\n"))
2390 2390 try:
2391 2391 ui.username()
2392 2392 except util.Abort, e:
2393 2393 ui.write(" %s\n" % e)
2394 2394 ui.write(_(" (specify a username in your configuration file)\n"))
2395 2395 problems += 1
2396 2396
2397 2397 if not problems:
2398 2398 ui.status(_("no problems detected\n"))
2399 2399 else:
2400 2400 ui.write(_("%s problems detected,"
2401 2401 " please check your install!\n") % problems)
2402 2402
2403 2403 return problems
2404 2404
2405 2405 @command('debugknown', [], _('REPO ID...'), norepo=True)
2406 2406 def debugknown(ui, repopath, *ids, **opts):
2407 2407 """test whether node ids are known to a repo
2408 2408
2409 2409 Every ID must be a full-length hex node id string. Returns a list of 0s
2410 2410 and 1s indicating unknown/known.
2411 2411 """
2412 2412 repo = hg.peer(ui, opts, repopath)
2413 2413 if not repo.capable('known'):
2414 2414 raise util.Abort("known() not supported by target repository")
2415 2415 flags = repo.known([bin(s) for s in ids])
2416 2416 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2417 2417
2418 2418 @command('debuglabelcomplete', [], _('LABEL...'))
2419 2419 def debuglabelcomplete(ui, repo, *args):
2420 2420 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2421 2421 debugnamecomplete(ui, repo, *args)
2422 2422
2423 2423 @command('debugnamecomplete', [], _('NAME...'))
2424 2424 def debugnamecomplete(ui, repo, *args):
2425 2425 '''complete "names" - tags, open branch names, bookmark names'''
2426 2426
2427 2427 names = set()
2428 2428 # since we previously only listed open branches, we will handle that
2429 2429 # specially (after this for loop)
2430 2430 for name, ns in repo.names.iteritems():
2431 2431 if name != 'branches':
2432 2432 names.update(ns.listnames(repo))
2433 2433 names.update(tag for (tag, heads, tip, closed)
2434 2434 in repo.branchmap().iterbranches() if not closed)
2435 2435 completions = set()
2436 2436 if not args:
2437 2437 args = ['']
2438 2438 for a in args:
2439 2439 completions.update(n for n in names if n.startswith(a))
2440 2440 ui.write('\n'.join(sorted(completions)))
2441 2441 ui.write('\n')
2442 2442
2443 2443 @command('debuglocks',
2444 2444 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2445 2445 ('W', 'force-wlock', None,
2446 2446 _('free the working state lock (DANGEROUS)'))],
2447 2447 _('[OPTION]...'))
2448 2448 def debuglocks(ui, repo, **opts):
2449 2449 """show or modify state of locks
2450 2450
2451 2451 By default, this command will show which locks are held. This
2452 2452 includes the user and process holding the lock, the amount of time
2453 2453 the lock has been held, and the machine name where the process is
2454 2454 running if it's not local.
2455 2455
2456 2456 Locks protect the integrity of Mercurial's data, so should be
2457 2457 treated with care. System crashes or other interruptions may cause
2458 2458 locks to not be properly released, though Mercurial will usually
2459 2459 detect and remove such stale locks automatically.
2460 2460
2461 2461 However, detecting stale locks may not always be possible (for
2462 2462 instance, on a shared filesystem). Removing locks may also be
2463 2463 blocked by filesystem permissions.
2464 2464
2465 2465 Returns 0 if no locks are held.
2466 2466
2467 2467 """
2468 2468
2469 2469 if opts.get('force_lock'):
2470 2470 repo.svfs.unlink('lock')
2471 2471 if opts.get('force_wlock'):
2472 2472 repo.vfs.unlink('wlock')
2473 2473 if opts.get('force_lock') or opts.get('force_lock'):
2474 2474 return 0
2475 2475
2476 2476 now = time.time()
2477 2477 held = 0
2478 2478
2479 2479 def report(vfs, name, method):
2480 2480 # this causes stale locks to get reaped for more accurate reporting
2481 2481 try:
2482 2482 l = method(False)
2483 2483 except error.LockHeld:
2484 2484 l = None
2485 2485
2486 2486 if l:
2487 2487 l.release()
2488 2488 else:
2489 2489 try:
2490 2490 stat = repo.svfs.lstat(name)
2491 2491 age = now - stat.st_mtime
2492 2492 user = util.username(stat.st_uid)
2493 2493 locker = vfs.readlock(name)
2494 2494 if ":" in locker:
2495 2495 host, pid = locker.split(':')
2496 2496 if host == socket.gethostname():
2497 2497 locker = 'user %s, process %s' % (user, pid)
2498 2498 else:
2499 2499 locker = 'user %s, process %s, host %s' \
2500 2500 % (user, pid, host)
2501 2501 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2502 2502 return 1
2503 2503 except OSError, e:
2504 2504 if e.errno != errno.ENOENT:
2505 2505 raise
2506 2506
2507 2507 ui.write("%-6s free\n" % (name + ":"))
2508 2508 return 0
2509 2509
2510 2510 held += report(repo.svfs, "lock", repo.lock)
2511 2511 held += report(repo.vfs, "wlock", repo.wlock)
2512 2512
2513 2513 return held
2514 2514
2515 2515 @command('debugobsolete',
2516 2516 [('', 'flags', 0, _('markers flag')),
2517 2517 ('', 'record-parents', False,
2518 2518 _('record parent information for the precursor')),
2519 2519 ('r', 'rev', [], _('display markers relevant to REV')),
2520 2520 ] + commitopts2,
2521 2521 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2522 2522 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2523 2523 """create arbitrary obsolete marker
2524 2524
2525 2525 With no arguments, displays the list of obsolescence markers."""
2526 2526
2527 2527 def parsenodeid(s):
2528 2528 try:
2529 2529 # We do not use revsingle/revrange functions here to accept
2530 2530 # arbitrary node identifiers, possibly not present in the
2531 2531 # local repository.
2532 2532 n = bin(s)
2533 2533 if len(n) != len(nullid):
2534 2534 raise TypeError()
2535 2535 return n
2536 2536 except TypeError:
2537 2537 raise util.Abort('changeset references must be full hexadecimal '
2538 2538 'node identifiers')
2539 2539
2540 2540 if precursor is not None:
2541 2541 if opts['rev']:
2542 2542 raise util.Abort('cannot select revision when creating marker')
2543 2543 metadata = {}
2544 2544 metadata['user'] = opts['user'] or ui.username()
2545 2545 succs = tuple(parsenodeid(succ) for succ in successors)
2546 2546 l = repo.lock()
2547 2547 try:
2548 2548 tr = repo.transaction('debugobsolete')
2549 2549 try:
2550 2550 try:
2551 2551 date = opts.get('date')
2552 2552 if date:
2553 2553 date = util.parsedate(date)
2554 2554 else:
2555 2555 date = None
2556 2556 prec = parsenodeid(precursor)
2557 2557 parents = None
2558 2558 if opts['record_parents']:
2559 2559 if prec not in repo.unfiltered():
2560 2560 raise util.Abort('cannot used --record-parents on '
2561 2561 'unknown changesets')
2562 2562 parents = repo.unfiltered()[prec].parents()
2563 2563 parents = tuple(p.node() for p in parents)
2564 2564 repo.obsstore.create(tr, prec, succs, opts['flags'],
2565 2565 parents=parents, date=date,
2566 2566 metadata=metadata)
2567 2567 tr.close()
2568 2568 except ValueError, exc:
2569 2569 raise util.Abort(_('bad obsmarker input: %s') % exc)
2570 2570 finally:
2571 2571 tr.release()
2572 2572 finally:
2573 2573 l.release()
2574 2574 else:
2575 2575 if opts['rev']:
2576 2576 revs = scmutil.revrange(repo, opts['rev'])
2577 2577 nodes = [repo[r].node() for r in revs]
2578 2578 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2579 2579 markers.sort(key=lambda x: x._data)
2580 2580 else:
2581 2581 markers = obsolete.getmarkers(repo)
2582 2582
2583 2583 for m in markers:
2584 2584 cmdutil.showmarker(ui, m)
2585 2585
2586 2586 @command('debugpathcomplete',
2587 2587 [('f', 'full', None, _('complete an entire path')),
2588 2588 ('n', 'normal', None, _('show only normal files')),
2589 2589 ('a', 'added', None, _('show only added files')),
2590 2590 ('r', 'removed', None, _('show only removed files'))],
2591 2591 _('FILESPEC...'))
2592 2592 def debugpathcomplete(ui, repo, *specs, **opts):
2593 2593 '''complete part or all of a tracked path
2594 2594
2595 2595 This command supports shells that offer path name completion. It
2596 2596 currently completes only files already known to the dirstate.
2597 2597
2598 2598 Completion extends only to the next path segment unless
2599 2599 --full is specified, in which case entire paths are used.'''
2600 2600
2601 2601 def complete(path, acceptable):
2602 2602 dirstate = repo.dirstate
2603 2603 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2604 2604 rootdir = repo.root + os.sep
2605 2605 if spec != repo.root and not spec.startswith(rootdir):
2606 2606 return [], []
2607 2607 if os.path.isdir(spec):
2608 2608 spec += '/'
2609 2609 spec = spec[len(rootdir):]
2610 2610 fixpaths = os.sep != '/'
2611 2611 if fixpaths:
2612 2612 spec = spec.replace(os.sep, '/')
2613 2613 speclen = len(spec)
2614 2614 fullpaths = opts['full']
2615 2615 files, dirs = set(), set()
2616 2616 adddir, addfile = dirs.add, files.add
2617 2617 for f, st in dirstate.iteritems():
2618 2618 if f.startswith(spec) and st[0] in acceptable:
2619 2619 if fixpaths:
2620 2620 f = f.replace('/', os.sep)
2621 2621 if fullpaths:
2622 2622 addfile(f)
2623 2623 continue
2624 2624 s = f.find(os.sep, speclen)
2625 2625 if s >= 0:
2626 2626 adddir(f[:s])
2627 2627 else:
2628 2628 addfile(f)
2629 2629 return files, dirs
2630 2630
2631 2631 acceptable = ''
2632 2632 if opts['normal']:
2633 2633 acceptable += 'nm'
2634 2634 if opts['added']:
2635 2635 acceptable += 'a'
2636 2636 if opts['removed']:
2637 2637 acceptable += 'r'
2638 2638 cwd = repo.getcwd()
2639 2639 if not specs:
2640 2640 specs = ['.']
2641 2641
2642 2642 files, dirs = set(), set()
2643 2643 for spec in specs:
2644 2644 f, d = complete(spec, acceptable or 'nmar')
2645 2645 files.update(f)
2646 2646 dirs.update(d)
2647 2647 files.update(dirs)
2648 2648 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2649 2649 ui.write('\n')
2650 2650
2651 2651 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2652 2652 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2653 2653 '''access the pushkey key/value protocol
2654 2654
2655 2655 With two args, list the keys in the given namespace.
2656 2656
2657 2657 With five args, set a key to new if it currently is set to old.
2658 2658 Reports success or failure.
2659 2659 '''
2660 2660
2661 2661 target = hg.peer(ui, {}, repopath)
2662 2662 if keyinfo:
2663 2663 key, old, new = keyinfo
2664 2664 r = target.pushkey(namespace, key, old, new)
2665 2665 ui.status(str(r) + '\n')
2666 2666 return not r
2667 2667 else:
2668 2668 for k, v in sorted(target.listkeys(namespace).iteritems()):
2669 2669 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2670 2670 v.encode('string-escape')))
2671 2671
2672 2672 @command('debugpvec', [], _('A B'))
2673 2673 def debugpvec(ui, repo, a, b=None):
2674 2674 ca = scmutil.revsingle(repo, a)
2675 2675 cb = scmutil.revsingle(repo, b)
2676 2676 pa = pvec.ctxpvec(ca)
2677 2677 pb = pvec.ctxpvec(cb)
2678 2678 if pa == pb:
2679 2679 rel = "="
2680 2680 elif pa > pb:
2681 2681 rel = ">"
2682 2682 elif pa < pb:
2683 2683 rel = "<"
2684 2684 elif pa | pb:
2685 2685 rel = "|"
2686 2686 ui.write(_("a: %s\n") % pa)
2687 2687 ui.write(_("b: %s\n") % pb)
2688 2688 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2689 2689 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2690 2690 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2691 2691 pa.distance(pb), rel))
2692 2692
2693 2693 @command('debugrebuilddirstate|debugrebuildstate',
2694 2694 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2695 2695 _('[-r REV]'))
2696 2696 def debugrebuilddirstate(ui, repo, rev):
2697 2697 """rebuild the dirstate as it would look like for the given revision
2698 2698
2699 2699 If no revision is specified the first current parent will be used.
2700 2700
2701 2701 The dirstate will be set to the files of the given revision.
2702 2702 The actual working directory content or existing dirstate
2703 2703 information such as adds or removes is not considered.
2704 2704
2705 2705 One use of this command is to make the next :hg:`status` invocation
2706 2706 check the actual file content.
2707 2707 """
2708 2708 ctx = scmutil.revsingle(repo, rev)
2709 2709 wlock = repo.wlock()
2710 2710 try:
2711 2711 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2712 2712 finally:
2713 2713 wlock.release()
2714 2714
2715 2715 @command('debugrename',
2716 2716 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2717 2717 _('[-r REV] FILE'))
2718 2718 def debugrename(ui, repo, file1, *pats, **opts):
2719 2719 """dump rename information"""
2720 2720
2721 2721 ctx = scmutil.revsingle(repo, opts.get('rev'))
2722 2722 m = scmutil.match(ctx, (file1,) + pats, opts)
2723 2723 for abs in ctx.walk(m):
2724 2724 fctx = ctx[abs]
2725 2725 o = fctx.filelog().renamed(fctx.filenode())
2726 2726 rel = m.rel(abs)
2727 2727 if o:
2728 2728 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2729 2729 else:
2730 2730 ui.write(_("%s not renamed\n") % rel)
2731 2731
2732 2732 @command('debugrevlog',
2733 2733 [('c', 'changelog', False, _('open changelog')),
2734 2734 ('m', 'manifest', False, _('open manifest')),
2735 2735 ('d', 'dump', False, _('dump index data'))],
2736 2736 _('-c|-m|FILE'),
2737 2737 optionalrepo=True)
2738 2738 def debugrevlog(ui, repo, file_=None, **opts):
2739 2739 """show data and statistics about a revlog"""
2740 2740 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2741 2741
2742 2742 if opts.get("dump"):
2743 2743 numrevs = len(r)
2744 2744 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2745 2745 " rawsize totalsize compression heads chainlen\n")
2746 2746 ts = 0
2747 2747 heads = set()
2748 2748
2749 2749 for rev in xrange(numrevs):
2750 2750 dbase = r.deltaparent(rev)
2751 2751 if dbase == -1:
2752 2752 dbase = rev
2753 2753 cbase = r.chainbase(rev)
2754 2754 clen = r.chainlen(rev)
2755 2755 p1, p2 = r.parentrevs(rev)
2756 2756 rs = r.rawsize(rev)
2757 2757 ts = ts + rs
2758 2758 heads -= set(r.parentrevs(rev))
2759 2759 heads.add(rev)
2760 2760 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2761 2761 "%11d %5d %8d\n" %
2762 2762 (rev, p1, p2, r.start(rev), r.end(rev),
2763 2763 r.start(dbase), r.start(cbase),
2764 2764 r.start(p1), r.start(p2),
2765 2765 rs, ts, ts / r.end(rev), len(heads), clen))
2766 2766 return 0
2767 2767
2768 2768 v = r.version
2769 2769 format = v & 0xFFFF
2770 2770 flags = []
2771 2771 gdelta = False
2772 2772 if v & revlog.REVLOGNGINLINEDATA:
2773 2773 flags.append('inline')
2774 2774 if v & revlog.REVLOGGENERALDELTA:
2775 2775 gdelta = True
2776 2776 flags.append('generaldelta')
2777 2777 if not flags:
2778 2778 flags = ['(none)']
2779 2779
2780 2780 nummerges = 0
2781 2781 numfull = 0
2782 2782 numprev = 0
2783 2783 nump1 = 0
2784 2784 nump2 = 0
2785 2785 numother = 0
2786 2786 nump1prev = 0
2787 2787 nump2prev = 0
2788 2788 chainlengths = []
2789 2789
2790 2790 datasize = [None, 0, 0L]
2791 2791 fullsize = [None, 0, 0L]
2792 2792 deltasize = [None, 0, 0L]
2793 2793
2794 2794 def addsize(size, l):
2795 2795 if l[0] is None or size < l[0]:
2796 2796 l[0] = size
2797 2797 if size > l[1]:
2798 2798 l[1] = size
2799 2799 l[2] += size
2800 2800
2801 2801 numrevs = len(r)
2802 2802 for rev in xrange(numrevs):
2803 2803 p1, p2 = r.parentrevs(rev)
2804 2804 delta = r.deltaparent(rev)
2805 2805 if format > 0:
2806 2806 addsize(r.rawsize(rev), datasize)
2807 2807 if p2 != nullrev:
2808 2808 nummerges += 1
2809 2809 size = r.length(rev)
2810 2810 if delta == nullrev:
2811 2811 chainlengths.append(0)
2812 2812 numfull += 1
2813 2813 addsize(size, fullsize)
2814 2814 else:
2815 2815 chainlengths.append(chainlengths[delta] + 1)
2816 2816 addsize(size, deltasize)
2817 2817 if delta == rev - 1:
2818 2818 numprev += 1
2819 2819 if delta == p1:
2820 2820 nump1prev += 1
2821 2821 elif delta == p2:
2822 2822 nump2prev += 1
2823 2823 elif delta == p1:
2824 2824 nump1 += 1
2825 2825 elif delta == p2:
2826 2826 nump2 += 1
2827 2827 elif delta != nullrev:
2828 2828 numother += 1
2829 2829
2830 2830 # Adjust size min value for empty cases
2831 2831 for size in (datasize, fullsize, deltasize):
2832 2832 if size[0] is None:
2833 2833 size[0] = 0
2834 2834
2835 2835 numdeltas = numrevs - numfull
2836 2836 numoprev = numprev - nump1prev - nump2prev
2837 2837 totalrawsize = datasize[2]
2838 2838 datasize[2] /= numrevs
2839 2839 fulltotal = fullsize[2]
2840 2840 fullsize[2] /= numfull
2841 2841 deltatotal = deltasize[2]
2842 2842 if numrevs - numfull > 0:
2843 2843 deltasize[2] /= numrevs - numfull
2844 2844 totalsize = fulltotal + deltatotal
2845 2845 avgchainlen = sum(chainlengths) / numrevs
2846 2846 maxchainlen = max(chainlengths)
2847 2847 compratio = totalrawsize / totalsize
2848 2848
2849 2849 basedfmtstr = '%%%dd\n'
2850 2850 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2851 2851
2852 2852 def dfmtstr(max):
2853 2853 return basedfmtstr % len(str(max))
2854 2854 def pcfmtstr(max, padding=0):
2855 2855 return basepcfmtstr % (len(str(max)), ' ' * padding)
2856 2856
2857 2857 def pcfmt(value, total):
2858 2858 return (value, 100 * float(value) / total)
2859 2859
2860 2860 ui.write(('format : %d\n') % format)
2861 2861 ui.write(('flags : %s\n') % ', '.join(flags))
2862 2862
2863 2863 ui.write('\n')
2864 2864 fmt = pcfmtstr(totalsize)
2865 2865 fmt2 = dfmtstr(totalsize)
2866 2866 ui.write(('revisions : ') + fmt2 % numrevs)
2867 2867 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2868 2868 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2869 2869 ui.write(('revisions : ') + fmt2 % numrevs)
2870 2870 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2871 2871 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2872 2872 ui.write(('revision size : ') + fmt2 % totalsize)
2873 2873 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2874 2874 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2875 2875
2876 2876 ui.write('\n')
2877 2877 fmt = dfmtstr(max(avgchainlen, compratio))
2878 2878 ui.write(('avg chain length : ') + fmt % avgchainlen)
2879 2879 ui.write(('max chain length : ') + fmt % maxchainlen)
2880 2880 ui.write(('compression ratio : ') + fmt % compratio)
2881 2881
2882 2882 if format > 0:
2883 2883 ui.write('\n')
2884 2884 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2885 2885 % tuple(datasize))
2886 2886 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2887 2887 % tuple(fullsize))
2888 2888 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2889 2889 % tuple(deltasize))
2890 2890
2891 2891 if numdeltas > 0:
2892 2892 ui.write('\n')
2893 2893 fmt = pcfmtstr(numdeltas)
2894 2894 fmt2 = pcfmtstr(numdeltas, 4)
2895 2895 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2896 2896 if numprev > 0:
2897 2897 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2898 2898 numprev))
2899 2899 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2900 2900 numprev))
2901 2901 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2902 2902 numprev))
2903 2903 if gdelta:
2904 2904 ui.write(('deltas against p1 : ')
2905 2905 + fmt % pcfmt(nump1, numdeltas))
2906 2906 ui.write(('deltas against p2 : ')
2907 2907 + fmt % pcfmt(nump2, numdeltas))
2908 2908 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2909 2909 numdeltas))
2910 2910
2911 2911 @command('debugrevspec',
2912 2912 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2913 2913 ('REVSPEC'))
2914 2914 def debugrevspec(ui, repo, expr, **opts):
2915 2915 """parse and apply a revision specification
2916 2916
2917 2917 Use --verbose to print the parsed tree before and after aliases
2918 2918 expansion.
2919 2919 """
2920 2920 if ui.verbose:
2921 2921 tree = revset.parse(expr)[0]
2922 2922 ui.note(revset.prettyformat(tree), "\n")
2923 2923 newtree = revset.findaliases(ui, tree)
2924 2924 if newtree != tree:
2925 2925 ui.note(revset.prettyformat(newtree), "\n")
2926 2926 tree = newtree
2927 2927 newtree = revset.foldconcat(tree)
2928 2928 if newtree != tree:
2929 2929 ui.note(revset.prettyformat(newtree), "\n")
2930 2930 if opts["optimize"]:
2931 2931 weight, optimizedtree = revset.optimize(newtree, True)
2932 2932 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2933 2933 func = revset.match(ui, expr)
2934 2934 revs = func(repo)
2935 2935 if ui.verbose:
2936 2936 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2937 2937 for c in revs:
2938 2938 ui.write("%s\n" % c)
2939 2939
2940 2940 @command('debugsetparents', [], _('REV1 [REV2]'))
2941 2941 def debugsetparents(ui, repo, rev1, rev2=None):
2942 2942 """manually set the parents of the current working directory
2943 2943
2944 2944 This is useful for writing repository conversion tools, but should
2945 2945 be used with care. For example, neither the working directory nor the
2946 2946 dirstate is updated, so file status may be incorrect after running this
2947 2947 command.
2948 2948
2949 2949 Returns 0 on success.
2950 2950 """
2951 2951
2952 2952 r1 = scmutil.revsingle(repo, rev1).node()
2953 2953 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2954 2954
2955 2955 wlock = repo.wlock()
2956 2956 try:
2957 2957 repo.dirstate.beginparentchange()
2958 2958 repo.setparents(r1, r2)
2959 2959 repo.dirstate.endparentchange()
2960 2960 finally:
2961 2961 wlock.release()
2962 2962
2963 2963 @command('debugdirstate|debugstate',
2964 2964 [('', 'nodates', None, _('do not display the saved mtime')),
2965 2965 ('', 'datesort', None, _('sort by saved mtime'))],
2966 2966 _('[OPTION]...'))
2967 2967 def debugstate(ui, repo, nodates=None, datesort=None):
2968 2968 """show the contents of the current dirstate"""
2969 2969 timestr = ""
2970 2970 if datesort:
2971 2971 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2972 2972 else:
2973 2973 keyfunc = None # sort by filename
2974 2974 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2975 2975 if ent[3] == -1:
2976 2976 timestr = 'unset '
2977 2977 elif nodates:
2978 2978 timestr = 'set '
2979 2979 else:
2980 2980 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2981 2981 time.localtime(ent[3]))
2982 2982 if ent[1] & 020000:
2983 2983 mode = 'lnk'
2984 2984 else:
2985 2985 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2986 2986 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2987 2987 for f in repo.dirstate.copies():
2988 2988 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2989 2989
2990 2990 @command('debugsub',
2991 2991 [('r', 'rev', '',
2992 2992 _('revision to check'), _('REV'))],
2993 2993 _('[-r REV] [REV]'))
2994 2994 def debugsub(ui, repo, rev=None):
2995 2995 ctx = scmutil.revsingle(repo, rev, None)
2996 2996 for k, v in sorted(ctx.substate.items()):
2997 2997 ui.write(('path %s\n') % k)
2998 2998 ui.write((' source %s\n') % v[0])
2999 2999 ui.write((' revision %s\n') % v[1])
3000 3000
3001 3001 @command('debugsuccessorssets',
3002 3002 [],
3003 3003 _('[REV]'))
3004 3004 def debugsuccessorssets(ui, repo, *revs):
3005 3005 """show set of successors for revision
3006 3006
3007 3007 A successors set of changeset A is a consistent group of revisions that
3008 3008 succeed A. It contains non-obsolete changesets only.
3009 3009
3010 3010 In most cases a changeset A has a single successors set containing a single
3011 3011 successor (changeset A replaced by A').
3012 3012
3013 3013 A changeset that is made obsolete with no successors are called "pruned".
3014 3014 Such changesets have no successors sets at all.
3015 3015
3016 3016 A changeset that has been "split" will have a successors set containing
3017 3017 more than one successor.
3018 3018
3019 3019 A changeset that has been rewritten in multiple different ways is called
3020 3020 "divergent". Such changesets have multiple successor sets (each of which
3021 3021 may also be split, i.e. have multiple successors).
3022 3022
3023 3023 Results are displayed as follows::
3024 3024
3025 3025 <rev1>
3026 3026 <successors-1A>
3027 3027 <rev2>
3028 3028 <successors-2A>
3029 3029 <successors-2B1> <successors-2B2> <successors-2B3>
3030 3030
3031 3031 Here rev2 has two possible (i.e. divergent) successors sets. The first
3032 3032 holds one element, whereas the second holds three (i.e. the changeset has
3033 3033 been split).
3034 3034 """
3035 3035 # passed to successorssets caching computation from one call to another
3036 3036 cache = {}
3037 3037 ctx2str = str
3038 3038 node2str = short
3039 3039 if ui.debug():
3040 3040 def ctx2str(ctx):
3041 3041 return ctx.hex()
3042 3042 node2str = hex
3043 3043 for rev in scmutil.revrange(repo, revs):
3044 3044 ctx = repo[rev]
3045 3045 ui.write('%s\n'% ctx2str(ctx))
3046 3046 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3047 3047 if succsset:
3048 3048 ui.write(' ')
3049 3049 ui.write(node2str(succsset[0]))
3050 3050 for node in succsset[1:]:
3051 3051 ui.write(' ')
3052 3052 ui.write(node2str(node))
3053 3053 ui.write('\n')
3054 3054
3055 3055 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3056 3056 def debugwalk(ui, repo, *pats, **opts):
3057 3057 """show how files match on given patterns"""
3058 3058 m = scmutil.match(repo[None], pats, opts)
3059 3059 items = list(repo.walk(m))
3060 3060 if not items:
3061 3061 return
3062 3062 f = lambda fn: fn
3063 3063 if ui.configbool('ui', 'slash') and os.sep != '/':
3064 3064 f = lambda fn: util.normpath(fn)
3065 3065 fmt = 'f %%-%ds %%-%ds %%s' % (
3066 3066 max([len(abs) for abs in items]),
3067 3067 max([len(m.rel(abs)) for abs in items]))
3068 3068 for abs in items:
3069 3069 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3070 3070 ui.write("%s\n" % line.rstrip())
3071 3071
3072 3072 @command('debugwireargs',
3073 3073 [('', 'three', '', 'three'),
3074 3074 ('', 'four', '', 'four'),
3075 3075 ('', 'five', '', 'five'),
3076 3076 ] + remoteopts,
3077 3077 _('REPO [OPTIONS]... [ONE [TWO]]'),
3078 3078 norepo=True)
3079 3079 def debugwireargs(ui, repopath, *vals, **opts):
3080 3080 repo = hg.peer(ui, opts, repopath)
3081 3081 for opt in remoteopts:
3082 3082 del opts[opt[1]]
3083 3083 args = {}
3084 3084 for k, v in opts.iteritems():
3085 3085 if v:
3086 3086 args[k] = v
3087 3087 # run twice to check that we don't mess up the stream for the next command
3088 3088 res1 = repo.debugwireargs(*vals, **args)
3089 3089 res2 = repo.debugwireargs(*vals, **args)
3090 3090 ui.write("%s\n" % res1)
3091 3091 if res1 != res2:
3092 3092 ui.warn("%s\n" % res2)
3093 3093
3094 3094 @command('^diff',
3095 3095 [('r', 'rev', [], _('revision'), _('REV')),
3096 3096 ('c', 'change', '', _('change made by revision'), _('REV'))
3097 3097 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3098 3098 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3099 3099 inferrepo=True)
3100 3100 def diff(ui, repo, *pats, **opts):
3101 3101 """diff repository (or selected files)
3102 3102
3103 3103 Show differences between revisions for the specified files.
3104 3104
3105 3105 Differences between files are shown using the unified diff format.
3106 3106
3107 3107 .. note::
3108 3108
3109 3109 diff may generate unexpected results for merges, as it will
3110 3110 default to comparing against the working directory's first
3111 3111 parent changeset if no revisions are specified.
3112 3112
3113 3113 When two revision arguments are given, then changes are shown
3114 3114 between those revisions. If only one revision is specified then
3115 3115 that revision is compared to the working directory, and, when no
3116 3116 revisions are specified, the working directory files are compared
3117 3117 to its parent.
3118 3118
3119 3119 Alternatively you can specify -c/--change with a revision to see
3120 3120 the changes in that changeset relative to its first parent.
3121 3121
3122 3122 Without the -a/--text option, diff will avoid generating diffs of
3123 3123 files it detects as binary. With -a, diff will generate a diff
3124 3124 anyway, probably with undesirable results.
3125 3125
3126 3126 Use the -g/--git option to generate diffs in the git extended diff
3127 3127 format. For more information, read :hg:`help diffs`.
3128 3128
3129 3129 .. container:: verbose
3130 3130
3131 3131 Examples:
3132 3132
3133 3133 - compare a file in the current working directory to its parent::
3134 3134
3135 3135 hg diff foo.c
3136 3136
3137 3137 - compare two historical versions of a directory, with rename info::
3138 3138
3139 3139 hg diff --git -r 1.0:1.2 lib/
3140 3140
3141 3141 - get change stats relative to the last change on some date::
3142 3142
3143 3143 hg diff --stat -r "date('may 2')"
3144 3144
3145 3145 - diff all newly-added files that contain a keyword::
3146 3146
3147 3147 hg diff "set:added() and grep(GNU)"
3148 3148
3149 3149 - compare a revision and its parents::
3150 3150
3151 3151 hg diff -c 9353 # compare against first parent
3152 3152 hg diff -r 9353^:9353 # same using revset syntax
3153 3153 hg diff -r 9353^2:9353 # compare against the second parent
3154 3154
3155 3155 Returns 0 on success.
3156 3156 """
3157 3157
3158 3158 revs = opts.get('rev')
3159 3159 change = opts.get('change')
3160 3160 stat = opts.get('stat')
3161 3161 reverse = opts.get('reverse')
3162 3162
3163 3163 if revs and change:
3164 3164 msg = _('cannot specify --rev and --change at the same time')
3165 3165 raise util.Abort(msg)
3166 3166 elif change:
3167 3167 node2 = scmutil.revsingle(repo, change, None).node()
3168 3168 node1 = repo[node2].p1().node()
3169 3169 else:
3170 3170 node1, node2 = scmutil.revpair(repo, revs)
3171 3171
3172 3172 if reverse:
3173 3173 node1, node2 = node2, node1
3174 3174
3175 3175 diffopts = patch.diffallopts(ui, opts)
3176 3176 m = scmutil.match(repo[node2], pats, opts)
3177 3177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3178 3178 listsubrepos=opts.get('subrepos'),
3179 3179 root=opts.get('root'))
3180 3180
3181 3181 @command('^export',
3182 3182 [('o', 'output', '',
3183 3183 _('print output to file with formatted name'), _('FORMAT')),
3184 3184 ('', 'switch-parent', None, _('diff against the second parent')),
3185 3185 ('r', 'rev', [], _('revisions to export'), _('REV')),
3186 3186 ] + diffopts,
3187 3187 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3188 3188 def export(ui, repo, *changesets, **opts):
3189 3189 """dump the header and diffs for one or more changesets
3190 3190
3191 3191 Print the changeset header and diffs for one or more revisions.
3192 3192 If no revision is given, the parent of the working directory is used.
3193 3193
3194 3194 The information shown in the changeset header is: author, date,
3195 3195 branch name (if non-default), changeset hash, parent(s) and commit
3196 3196 comment.
3197 3197
3198 3198 .. note::
3199 3199
3200 3200 export may generate unexpected diff output for merge
3201 3201 changesets, as it will compare the merge changeset against its
3202 3202 first parent only.
3203 3203
3204 3204 Output may be to a file, in which case the name of the file is
3205 3205 given using a format string. The formatting rules are as follows:
3206 3206
3207 3207 :``%%``: literal "%" character
3208 3208 :``%H``: changeset hash (40 hexadecimal digits)
3209 3209 :``%N``: number of patches being generated
3210 3210 :``%R``: changeset revision number
3211 3211 :``%b``: basename of the exporting repository
3212 3212 :``%h``: short-form changeset hash (12 hexadecimal digits)
3213 3213 :``%m``: first line of the commit message (only alphanumeric characters)
3214 3214 :``%n``: zero-padded sequence number, starting at 1
3215 3215 :``%r``: zero-padded changeset revision number
3216 3216
3217 3217 Without the -a/--text option, export will avoid generating diffs
3218 3218 of files it detects as binary. With -a, export will generate a
3219 3219 diff anyway, probably with undesirable results.
3220 3220
3221 3221 Use the -g/--git option to generate diffs in the git extended diff
3222 3222 format. See :hg:`help diffs` for more information.
3223 3223
3224 3224 With the --switch-parent option, the diff will be against the
3225 3225 second parent. It can be useful to review a merge.
3226 3226
3227 3227 .. container:: verbose
3228 3228
3229 3229 Examples:
3230 3230
3231 3231 - use export and import to transplant a bugfix to the current
3232 3232 branch::
3233 3233
3234 3234 hg export -r 9353 | hg import -
3235 3235
3236 3236 - export all the changesets between two revisions to a file with
3237 3237 rename information::
3238 3238
3239 3239 hg export --git -r 123:150 > changes.txt
3240 3240
3241 3241 - split outgoing changes into a series of patches with
3242 3242 descriptive names::
3243 3243
3244 3244 hg export -r "outgoing()" -o "%n-%m.patch"
3245 3245
3246 3246 Returns 0 on success.
3247 3247 """
3248 3248 changesets += tuple(opts.get('rev', []))
3249 3249 if not changesets:
3250 3250 changesets = ['.']
3251 3251 revs = scmutil.revrange(repo, changesets)
3252 3252 if not revs:
3253 3253 raise util.Abort(_("export requires at least one changeset"))
3254 3254 if len(revs) > 1:
3255 3255 ui.note(_('exporting patches:\n'))
3256 3256 else:
3257 3257 ui.note(_('exporting patch:\n'))
3258 3258 cmdutil.export(repo, revs, template=opts.get('output'),
3259 3259 switch_parent=opts.get('switch_parent'),
3260 3260 opts=patch.diffallopts(ui, opts))
3261 3261
3262 3262 @command('files',
3263 3263 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3264 3264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3265 3265 ] + walkopts + formatteropts + subrepoopts,
3266 3266 _('[OPTION]... [PATTERN]...'))
3267 3267 def files(ui, repo, *pats, **opts):
3268 3268 """list tracked files
3269 3269
3270 3270 Print files under Mercurial control in the working directory or
3271 3271 specified revision whose names match the given patterns (excluding
3272 3272 removed files).
3273 3273
3274 3274 If no patterns are given to match, this command prints the names
3275 3275 of all files under Mercurial control in the working directory.
3276 3276
3277 3277 .. container:: verbose
3278 3278
3279 3279 Examples:
3280 3280
3281 3281 - list all files under the current directory::
3282 3282
3283 3283 hg files .
3284 3284
3285 3285 - shows sizes and flags for current revision::
3286 3286
3287 3287 hg files -vr .
3288 3288
3289 3289 - list all files named README::
3290 3290
3291 3291 hg files -I "**/README"
3292 3292
3293 3293 - list all binary files::
3294 3294
3295 3295 hg files "set:binary()"
3296 3296
3297 3297 - find files containing a regular expression::
3298 3298
3299 3299 hg files "set:grep('bob')"
3300 3300
3301 3301 - search tracked file contents with xargs and grep::
3302 3302
3303 3303 hg files -0 | xargs -0 grep foo
3304 3304
3305 3305 See :hg:`help patterns` and :hg:`help filesets` for more information
3306 3306 on specifying file patterns.
3307 3307
3308 3308 Returns 0 if a match is found, 1 otherwise.
3309 3309
3310 3310 """
3311 3311 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3312 3312
3313 3313 end = '\n'
3314 3314 if opts.get('print0'):
3315 3315 end = '\0'
3316 3316 fm = ui.formatter('files', opts)
3317 3317 fmt = '%s' + end
3318 3318
3319 3319 m = scmutil.match(ctx, pats, opts)
3320 3320 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3321 3321
3322 3322 fm.end()
3323 3323
3324 3324 return ret
3325 3325
3326 3326 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3327 3327 def forget(ui, repo, *pats, **opts):
3328 3328 """forget the specified files on the next commit
3329 3329
3330 3330 Mark the specified files so they will no longer be tracked
3331 3331 after the next commit.
3332 3332
3333 3333 This only removes files from the current branch, not from the
3334 3334 entire project history, and it does not delete them from the
3335 3335 working directory.
3336 3336
3337 3337 To undo a forget before the next commit, see :hg:`add`.
3338 3338
3339 3339 .. container:: verbose
3340 3340
3341 3341 Examples:
3342 3342
3343 3343 - forget newly-added binary files::
3344 3344
3345 3345 hg forget "set:added() and binary()"
3346 3346
3347 3347 - forget files that would be excluded by .hgignore::
3348 3348
3349 3349 hg forget "set:hgignore()"
3350 3350
3351 3351 Returns 0 on success.
3352 3352 """
3353 3353
3354 3354 if not pats:
3355 3355 raise util.Abort(_('no files specified'))
3356 3356
3357 3357 m = scmutil.match(repo[None], pats, opts)
3358 3358 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3359 3359 return rejected and 1 or 0
3360 3360
3361 3361 @command(
3362 3362 'graft',
3363 3363 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3364 3364 ('c', 'continue', False, _('resume interrupted graft')),
3365 3365 ('e', 'edit', False, _('invoke editor on commit messages')),
3366 3366 ('', 'log', None, _('append graft info to log message')),
3367 3367 ('f', 'force', False, _('force graft')),
3368 3368 ('D', 'currentdate', False,
3369 3369 _('record the current date as commit date')),
3370 3370 ('U', 'currentuser', False,
3371 3371 _('record the current user as committer'), _('DATE'))]
3372 3372 + commitopts2 + mergetoolopts + dryrunopts,
3373 3373 _('[OPTION]... [-r] REV...'))
3374 3374 def graft(ui, repo, *revs, **opts):
3375 3375 '''copy changes from other branches onto the current branch
3376 3376
3377 3377 This command uses Mercurial's merge logic to copy individual
3378 3378 changes from other branches without merging branches in the
3379 3379 history graph. This is sometimes known as 'backporting' or
3380 3380 'cherry-picking'. By default, graft will copy user, date, and
3381 3381 description from the source changesets.
3382 3382
3383 3383 Changesets that are ancestors of the current revision, that have
3384 3384 already been grafted, or that are merges will be skipped.
3385 3385
3386 3386 If --log is specified, log messages will have a comment appended
3387 3387 of the form::
3388 3388
3389 3389 (grafted from CHANGESETHASH)
3390 3390
3391 3391 If --force is specified, revisions will be grafted even if they
3392 3392 are already ancestors of or have been grafted to the destination.
3393 3393 This is useful when the revisions have since been backed out.
3394 3394
3395 3395 If a graft merge results in conflicts, the graft process is
3396 3396 interrupted so that the current merge can be manually resolved.
3397 3397 Once all conflicts are addressed, the graft process can be
3398 3398 continued with the -c/--continue option.
3399 3399
3400 3400 .. note::
3401 3401
3402 3402 The -c/--continue option does not reapply earlier options, except
3403 3403 for --force.
3404 3404
3405 3405 .. container:: verbose
3406 3406
3407 3407 Examples:
3408 3408
3409 3409 - copy a single change to the stable branch and edit its description::
3410 3410
3411 3411 hg update stable
3412 3412 hg graft --edit 9393
3413 3413
3414 3414 - graft a range of changesets with one exception, updating dates::
3415 3415
3416 3416 hg graft -D "2085::2093 and not 2091"
3417 3417
3418 3418 - continue a graft after resolving conflicts::
3419 3419
3420 3420 hg graft -c
3421 3421
3422 3422 - show the source of a grafted changeset::
3423 3423
3424 3424 hg log --debug -r .
3425 3425
3426 3426 See :hg:`help revisions` and :hg:`help revsets` for more about
3427 3427 specifying revisions.
3428 3428
3429 3429 Returns 0 on successful completion.
3430 3430 '''
3431 3431
3432 3432 revs = list(revs)
3433 3433 revs.extend(opts['rev'])
3434 3434
3435 3435 if not opts.get('user') and opts.get('currentuser'):
3436 3436 opts['user'] = ui.username()
3437 3437 if not opts.get('date') and opts.get('currentdate'):
3438 3438 opts['date'] = "%d %d" % util.makedate()
3439 3439
3440 3440 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3441 3441
3442 3442 cont = False
3443 3443 if opts['continue']:
3444 3444 cont = True
3445 3445 if revs:
3446 3446 raise util.Abort(_("can't specify --continue and revisions"))
3447 3447 # read in unfinished revisions
3448 3448 try:
3449 3449 nodes = repo.vfs.read('graftstate').splitlines()
3450 3450 revs = [repo[node].rev() for node in nodes]
3451 3451 except IOError, inst:
3452 3452 if inst.errno != errno.ENOENT:
3453 3453 raise
3454 3454 raise util.Abort(_("no graft state found, can't continue"))
3455 3455 else:
3456 3456 cmdutil.checkunfinished(repo)
3457 3457 cmdutil.bailifchanged(repo)
3458 3458 if not revs:
3459 3459 raise util.Abort(_('no revisions specified'))
3460 3460 revs = scmutil.revrange(repo, revs)
3461 3461
3462 3462 skipped = set()
3463 3463 # check for merges
3464 3464 for rev in repo.revs('%ld and merge()', revs):
3465 3465 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3466 3466 skipped.add(rev)
3467 3467 revs = [r for r in revs if r not in skipped]
3468 3468 if not revs:
3469 3469 return -1
3470 3470
3471 3471 # Don't check in the --continue case, in effect retaining --force across
3472 3472 # --continues. That's because without --force, any revisions we decided to
3473 3473 # skip would have been filtered out here, so they wouldn't have made their
3474 3474 # way to the graftstate. With --force, any revisions we would have otherwise
3475 3475 # skipped would not have been filtered out, and if they hadn't been applied
3476 3476 # already, they'd have been in the graftstate.
3477 3477 if not (cont or opts.get('force')):
3478 3478 # check for ancestors of dest branch
3479 3479 crev = repo['.'].rev()
3480 3480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3481 3481 # Cannot use x.remove(y) on smart set, this has to be a list.
3482 3482 # XXX make this lazy in the future
3483 3483 revs = list(revs)
3484 3484 # don't mutate while iterating, create a copy
3485 3485 for rev in list(revs):
3486 3486 if rev in ancestors:
3487 3487 ui.warn(_('skipping ancestor revision %d:%s\n') %
3488 3488 (rev, repo[rev]))
3489 3489 # XXX remove on list is slow
3490 3490 revs.remove(rev)
3491 3491 if not revs:
3492 3492 return -1
3493 3493
3494 3494 # analyze revs for earlier grafts
3495 3495 ids = {}
3496 3496 for ctx in repo.set("%ld", revs):
3497 3497 ids[ctx.hex()] = ctx.rev()
3498 3498 n = ctx.extra().get('source')
3499 3499 if n:
3500 3500 ids[n] = ctx.rev()
3501 3501
3502 3502 # check ancestors for earlier grafts
3503 3503 ui.debug('scanning for duplicate grafts\n')
3504 3504
3505 3505 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3506 3506 ctx = repo[rev]
3507 3507 n = ctx.extra().get('source')
3508 3508 if n in ids:
3509 3509 try:
3510 3510 r = repo[n].rev()
3511 3511 except error.RepoLookupError:
3512 3512 r = None
3513 3513 if r in revs:
3514 3514 ui.warn(_('skipping revision %d:%s '
3515 3515 '(already grafted to %d:%s)\n')
3516 3516 % (r, repo[r], rev, ctx))
3517 3517 revs.remove(r)
3518 3518 elif ids[n] in revs:
3519 3519 if r is None:
3520 3520 ui.warn(_('skipping already grafted revision %d:%s '
3521 3521 '(%d:%s also has unknown origin %s)\n')
3522 3522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3523 3523 else:
3524 3524 ui.warn(_('skipping already grafted revision %d:%s '
3525 3525 '(%d:%s also has origin %d:%s)\n')
3526 3526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3527 3527 revs.remove(ids[n])
3528 3528 elif ctx.hex() in ids:
3529 3529 r = ids[ctx.hex()]
3530 3530 ui.warn(_('skipping already grafted revision %d:%s '
3531 3531 '(was grafted from %d:%s)\n') %
3532 3532 (r, repo[r], rev, ctx))
3533 3533 revs.remove(r)
3534 3534 if not revs:
3535 3535 return -1
3536 3536
3537 3537 wlock = repo.wlock()
3538 3538 try:
3539 3539 for pos, ctx in enumerate(repo.set("%ld", revs)):
3540 3540 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3541 3541 ctx.description().split('\n', 1)[0])
3542 3542 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3543 3543 if names:
3544 3544 desc += ' (%s)' % ' '.join(names)
3545 3545 ui.status(_('grafting %s\n') % desc)
3546 3546 if opts.get('dry_run'):
3547 3547 continue
3548 3548
3549 3549 source = ctx.extra().get('source')
3550 3550 extra = {}
3551 3551 if source:
3552 3552 extra['source'] = source
3553 3553 extra['intermediate-source'] = ctx.hex()
3554 3554 else:
3555 3555 extra['source'] = ctx.hex()
3556 3556 user = ctx.user()
3557 3557 if opts.get('user'):
3558 3558 user = opts['user']
3559 3559 date = ctx.date()
3560 3560 if opts.get('date'):
3561 3561 date = opts['date']
3562 3562 message = ctx.description()
3563 3563 if opts.get('log'):
3564 3564 message += '\n(grafted from %s)' % ctx.hex()
3565 3565
3566 3566 # we don't merge the first commit when continuing
3567 3567 if not cont:
3568 3568 # perform the graft merge with p1(rev) as 'ancestor'
3569 3569 try:
3570 3570 # ui.forcemerge is an internal variable, do not document
3571 3571 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3572 3572 'graft')
3573 3573 stats = mergemod.graft(repo, ctx, ctx.p1(),
3574 3574 ['local', 'graft'])
3575 3575 finally:
3576 3576 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3577 3577 # report any conflicts
3578 3578 if stats and stats[3] > 0:
3579 3579 # write out state for --continue
3580 3580 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3581 3581 repo.vfs.write('graftstate', ''.join(nodelines))
3582 3582 raise util.Abort(
3583 3583 _("unresolved conflicts, can't continue"),
3584 3584 hint=_('use hg resolve and hg graft --continue'))
3585 3585 else:
3586 3586 cont = False
3587 3587
3588 3588 # commit
3589 3589 node = repo.commit(text=message, user=user,
3590 3590 date=date, extra=extra, editor=editor)
3591 3591 if node is None:
3592 3592 ui.warn(
3593 3593 _('note: graft of %d:%s created no changes to commit\n') %
3594 3594 (ctx.rev(), ctx))
3595 3595 finally:
3596 3596 wlock.release()
3597 3597
3598 3598 # remove state when we complete successfully
3599 3599 if not opts.get('dry_run'):
3600 3600 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3601 3601
3602 3602 return 0
3603 3603
3604 3604 @command('grep',
3605 3605 [('0', 'print0', None, _('end fields with NUL')),
3606 3606 ('', 'all', None, _('print all revisions that match')),
3607 3607 ('a', 'text', None, _('treat all files as text')),
3608 3608 ('f', 'follow', None,
3609 3609 _('follow changeset history,'
3610 3610 ' or file history across copies and renames')),
3611 3611 ('i', 'ignore-case', None, _('ignore case when matching')),
3612 3612 ('l', 'files-with-matches', None,
3613 3613 _('print only filenames and revisions that match')),
3614 3614 ('n', 'line-number', None, _('print matching line numbers')),
3615 3615 ('r', 'rev', [],
3616 3616 _('only search files changed within revision range'), _('REV')),
3617 3617 ('u', 'user', None, _('list the author (long with -v)')),
3618 3618 ('d', 'date', None, _('list the date (short with -q)')),
3619 3619 ] + walkopts,
3620 3620 _('[OPTION]... PATTERN [FILE]...'),
3621 3621 inferrepo=True)
3622 3622 def grep(ui, repo, pattern, *pats, **opts):
3623 3623 """search for a pattern in specified files and revisions
3624 3624
3625 3625 Search revisions of files for a regular expression.
3626 3626
3627 3627 This command behaves differently than Unix grep. It only accepts
3628 3628 Python/Perl regexps. It searches repository history, not the
3629 3629 working directory. It always prints the revision number in which a
3630 3630 match appears.
3631 3631
3632 3632 By default, grep only prints output for the first revision of a
3633 3633 file in which it finds a match. To get it to print every revision
3634 3634 that contains a change in match status ("-" for a match that
3635 3635 becomes a non-match, or "+" for a non-match that becomes a match),
3636 3636 use the --all flag.
3637 3637
3638 3638 Returns 0 if a match is found, 1 otherwise.
3639 3639 """
3640 3640 reflags = re.M
3641 3641 if opts.get('ignore_case'):
3642 3642 reflags |= re.I
3643 3643 try:
3644 3644 regexp = util.re.compile(pattern, reflags)
3645 3645 except re.error, inst:
3646 3646 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3647 3647 return 1
3648 3648 sep, eol = ':', '\n'
3649 3649 if opts.get('print0'):
3650 3650 sep = eol = '\0'
3651 3651
3652 3652 getfile = util.lrucachefunc(repo.file)
3653 3653
3654 3654 def matchlines(body):
3655 3655 begin = 0
3656 3656 linenum = 0
3657 3657 while begin < len(body):
3658 3658 match = regexp.search(body, begin)
3659 3659 if not match:
3660 3660 break
3661 3661 mstart, mend = match.span()
3662 3662 linenum += body.count('\n', begin, mstart) + 1
3663 3663 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3664 3664 begin = body.find('\n', mend) + 1 or len(body) + 1
3665 3665 lend = begin - 1
3666 3666 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3667 3667
3668 3668 class linestate(object):
3669 3669 def __init__(self, line, linenum, colstart, colend):
3670 3670 self.line = line
3671 3671 self.linenum = linenum
3672 3672 self.colstart = colstart
3673 3673 self.colend = colend
3674 3674
3675 3675 def __hash__(self):
3676 3676 return hash((self.linenum, self.line))
3677 3677
3678 3678 def __eq__(self, other):
3679 3679 return self.line == other.line
3680 3680
3681 3681 def __iter__(self):
3682 3682 yield (self.line[:self.colstart], '')
3683 3683 yield (self.line[self.colstart:self.colend], 'grep.match')
3684 3684 rest = self.line[self.colend:]
3685 3685 while rest != '':
3686 3686 match = regexp.search(rest)
3687 3687 if not match:
3688 3688 yield (rest, '')
3689 3689 break
3690 3690 mstart, mend = match.span()
3691 3691 yield (rest[:mstart], '')
3692 3692 yield (rest[mstart:mend], 'grep.match')
3693 3693 rest = rest[mend:]
3694 3694
3695 3695 matches = {}
3696 3696 copies = {}
3697 3697 def grepbody(fn, rev, body):
3698 3698 matches[rev].setdefault(fn, [])
3699 3699 m = matches[rev][fn]
3700 3700 for lnum, cstart, cend, line in matchlines(body):
3701 3701 s = linestate(line, lnum, cstart, cend)
3702 3702 m.append(s)
3703 3703
3704 3704 def difflinestates(a, b):
3705 3705 sm = difflib.SequenceMatcher(None, a, b)
3706 3706 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3707 3707 if tag == 'insert':
3708 3708 for i in xrange(blo, bhi):
3709 3709 yield ('+', b[i])
3710 3710 elif tag == 'delete':
3711 3711 for i in xrange(alo, ahi):
3712 3712 yield ('-', a[i])
3713 3713 elif tag == 'replace':
3714 3714 for i in xrange(alo, ahi):
3715 3715 yield ('-', a[i])
3716 3716 for i in xrange(blo, bhi):
3717 3717 yield ('+', b[i])
3718 3718
3719 3719 def display(fn, ctx, pstates, states):
3720 3720 rev = ctx.rev()
3721 3721 if ui.quiet:
3722 3722 datefunc = util.shortdate
3723 3723 else:
3724 3724 datefunc = util.datestr
3725 3725 found = False
3726 3726 @util.cachefunc
3727 3727 def binary():
3728 3728 flog = getfile(fn)
3729 3729 return util.binary(flog.read(ctx.filenode(fn)))
3730 3730
3731 3731 if opts.get('all'):
3732 3732 iter = difflinestates(pstates, states)
3733 3733 else:
3734 3734 iter = [('', l) for l in states]
3735 3735 for change, l in iter:
3736 3736 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3737 3737
3738 3738 if opts.get('line_number'):
3739 3739 cols.append((str(l.linenum), 'grep.linenumber'))
3740 3740 if opts.get('all'):
3741 3741 cols.append((change, 'grep.change'))
3742 3742 if opts.get('user'):
3743 3743 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3744 3744 if opts.get('date'):
3745 3745 cols.append((datefunc(ctx.date()), 'grep.date'))
3746 3746 for col, label in cols[:-1]:
3747 3747 ui.write(col, label=label)
3748 3748 ui.write(sep, label='grep.sep')
3749 3749 ui.write(cols[-1][0], label=cols[-1][1])
3750 3750 if not opts.get('files_with_matches'):
3751 3751 ui.write(sep, label='grep.sep')
3752 3752 if not opts.get('text') and binary():
3753 3753 ui.write(" Binary file matches")
3754 3754 else:
3755 3755 for s, label in l:
3756 3756 ui.write(s, label=label)
3757 3757 ui.write(eol)
3758 3758 found = True
3759 3759 if opts.get('files_with_matches'):
3760 3760 break
3761 3761 return found
3762 3762
3763 3763 skip = {}
3764 3764 revfiles = {}
3765 3765 matchfn = scmutil.match(repo[None], pats, opts)
3766 3766 found = False
3767 3767 follow = opts.get('follow')
3768 3768
3769 3769 def prep(ctx, fns):
3770 3770 rev = ctx.rev()
3771 3771 pctx = ctx.p1()
3772 3772 parent = pctx.rev()
3773 3773 matches.setdefault(rev, {})
3774 3774 matches.setdefault(parent, {})
3775 3775 files = revfiles.setdefault(rev, [])
3776 3776 for fn in fns:
3777 3777 flog = getfile(fn)
3778 3778 try:
3779 3779 fnode = ctx.filenode(fn)
3780 3780 except error.LookupError:
3781 3781 continue
3782 3782
3783 3783 copied = flog.renamed(fnode)
3784 3784 copy = follow and copied and copied[0]
3785 3785 if copy:
3786 3786 copies.setdefault(rev, {})[fn] = copy
3787 3787 if fn in skip:
3788 3788 if copy:
3789 3789 skip[copy] = True
3790 3790 continue
3791 3791 files.append(fn)
3792 3792
3793 3793 if fn not in matches[rev]:
3794 3794 grepbody(fn, rev, flog.read(fnode))
3795 3795
3796 3796 pfn = copy or fn
3797 3797 if pfn not in matches[parent]:
3798 3798 try:
3799 3799 fnode = pctx.filenode(pfn)
3800 3800 grepbody(pfn, parent, flog.read(fnode))
3801 3801 except error.LookupError:
3802 3802 pass
3803 3803
3804 3804 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3805 3805 rev = ctx.rev()
3806 3806 parent = ctx.p1().rev()
3807 3807 for fn in sorted(revfiles.get(rev, [])):
3808 3808 states = matches[rev][fn]
3809 3809 copy = copies.get(rev, {}).get(fn)
3810 3810 if fn in skip:
3811 3811 if copy:
3812 3812 skip[copy] = True
3813 3813 continue
3814 3814 pstates = matches.get(parent, {}).get(copy or fn, [])
3815 3815 if pstates or states:
3816 3816 r = display(fn, ctx, pstates, states)
3817 3817 found = found or r
3818 3818 if r and not opts.get('all'):
3819 3819 skip[fn] = True
3820 3820 if copy:
3821 3821 skip[copy] = True
3822 3822 del matches[rev]
3823 3823 del revfiles[rev]
3824 3824
3825 3825 return not found
3826 3826
3827 3827 @command('heads',
3828 3828 [('r', 'rev', '',
3829 3829 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3830 3830 ('t', 'topo', False, _('show topological heads only')),
3831 3831 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3832 3832 ('c', 'closed', False, _('show normal and closed branch heads')),
3833 3833 ] + templateopts,
3834 3834 _('[-ct] [-r STARTREV] [REV]...'))
3835 3835 def heads(ui, repo, *branchrevs, **opts):
3836 3836 """show branch heads
3837 3837
3838 3838 With no arguments, show all open branch heads in the repository.
3839 3839 Branch heads are changesets that have no descendants on the
3840 3840 same branch. They are where development generally takes place and
3841 3841 are the usual targets for update and merge operations.
3842 3842
3843 3843 If one or more REVs are given, only open branch heads on the
3844 3844 branches associated with the specified changesets are shown. This
3845 3845 means that you can use :hg:`heads .` to see the heads on the
3846 3846 currently checked-out branch.
3847 3847
3848 3848 If -c/--closed is specified, also show branch heads marked closed
3849 3849 (see :hg:`commit --close-branch`).
3850 3850
3851 3851 If STARTREV is specified, only those heads that are descendants of
3852 3852 STARTREV will be displayed.
3853 3853
3854 3854 If -t/--topo is specified, named branch mechanics will be ignored and only
3855 3855 topological heads (changesets with no children) will be shown.
3856 3856
3857 3857 Returns 0 if matching heads are found, 1 if not.
3858 3858 """
3859 3859
3860 3860 start = None
3861 3861 if 'rev' in opts:
3862 3862 start = scmutil.revsingle(repo, opts['rev'], None).node()
3863 3863
3864 3864 if opts.get('topo'):
3865 3865 heads = [repo[h] for h in repo.heads(start)]
3866 3866 else:
3867 3867 heads = []
3868 3868 for branch in repo.branchmap():
3869 3869 heads += repo.branchheads(branch, start, opts.get('closed'))
3870 3870 heads = [repo[h] for h in heads]
3871 3871
3872 3872 if branchrevs:
3873 3873 branches = set(repo[br].branch() for br in branchrevs)
3874 3874 heads = [h for h in heads if h.branch() in branches]
3875 3875
3876 3876 if opts.get('active') and branchrevs:
3877 3877 dagheads = repo.heads(start)
3878 3878 heads = [h for h in heads if h.node() in dagheads]
3879 3879
3880 3880 if branchrevs:
3881 3881 haveheads = set(h.branch() for h in heads)
3882 3882 if branches - haveheads:
3883 3883 headless = ', '.join(b for b in branches - haveheads)
3884 3884 msg = _('no open branch heads found on branches %s')
3885 3885 if opts.get('rev'):
3886 3886 msg += _(' (started at %s)') % opts['rev']
3887 3887 ui.warn((msg + '\n') % headless)
3888 3888
3889 3889 if not heads:
3890 3890 return 1
3891 3891
3892 3892 heads = sorted(heads, key=lambda x: -x.rev())
3893 3893 displayer = cmdutil.show_changeset(ui, repo, opts)
3894 3894 for ctx in heads:
3895 3895 displayer.show(ctx)
3896 3896 displayer.close()
3897 3897
3898 3898 @command('help',
3899 3899 [('e', 'extension', None, _('show only help for extensions')),
3900 3900 ('c', 'command', None, _('show only help for commands')),
3901 3901 ('k', 'keyword', '', _('show topics matching keyword')),
3902 3902 ],
3903 3903 _('[-ec] [TOPIC]'),
3904 3904 norepo=True)
3905 3905 def help_(ui, name=None, **opts):
3906 3906 """show help for a given topic or a help overview
3907 3907
3908 3908 With no arguments, print a list of commands with short help messages.
3909 3909
3910 3910 Given a topic, extension, or command name, print help for that
3911 3911 topic.
3912 3912
3913 3913 Returns 0 if successful.
3914 3914 """
3915 3915
3916 3916 textwidth = min(ui.termwidth(), 80) - 2
3917 3917
3918 3918 keep = []
3919 3919 if ui.verbose:
3920 3920 keep.append('verbose')
3921 3921 if sys.platform.startswith('win'):
3922 3922 keep.append('windows')
3923 3923 elif sys.platform == 'OpenVMS':
3924 3924 keep.append('vms')
3925 3925 elif sys.platform == 'plan9':
3926 3926 keep.append('plan9')
3927 3927 else:
3928 3928 keep.append('unix')
3929 3929 keep.append(sys.platform.lower())
3930 3930
3931 3931 section = None
3932 3932 if name and '.' in name:
3933 3933 name, section = name.split('.', 1)
3934 3934
3935 3935 text = help.help_(ui, name, **opts)
3936 3936
3937 3937 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3938 3938 section=section)
3939 3939 if section and not formatted:
3940 3940 raise util.Abort(_("help section not found"))
3941 3941
3942 3942 if 'verbose' in pruned:
3943 3943 keep.append('omitted')
3944 3944 else:
3945 3945 keep.append('notomitted')
3946 3946 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3947 3947 section=section)
3948 3948 ui.write(formatted)
3949 3949
3950 3950
3951 3951 @command('identify|id',
3952 3952 [('r', 'rev', '',
3953 3953 _('identify the specified revision'), _('REV')),
3954 3954 ('n', 'num', None, _('show local revision number')),
3955 3955 ('i', 'id', None, _('show global revision id')),
3956 3956 ('b', 'branch', None, _('show branch')),
3957 3957 ('t', 'tags', None, _('show tags')),
3958 3958 ('B', 'bookmarks', None, _('show bookmarks')),
3959 3959 ] + remoteopts,
3960 3960 _('[-nibtB] [-r REV] [SOURCE]'),
3961 3961 optionalrepo=True)
3962 3962 def identify(ui, repo, source=None, rev=None,
3963 3963 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3964 3964 """identify the working directory or specified revision
3965 3965
3966 3966 Print a summary identifying the repository state at REV using one or
3967 3967 two parent hash identifiers, followed by a "+" if the working
3968 3968 directory has uncommitted changes, the branch name (if not default),
3969 3969 a list of tags, and a list of bookmarks.
3970 3970
3971 3971 When REV is not given, print a summary of the current state of the
3972 3972 repository.
3973 3973
3974 3974 Specifying a path to a repository root or Mercurial bundle will
3975 3975 cause lookup to operate on that repository/bundle.
3976 3976
3977 3977 .. container:: verbose
3978 3978
3979 3979 Examples:
3980 3980
3981 3981 - generate a build identifier for the working directory::
3982 3982
3983 3983 hg id --id > build-id.dat
3984 3984
3985 3985 - find the revision corresponding to a tag::
3986 3986
3987 3987 hg id -n -r 1.3
3988 3988
3989 3989 - check the most recent revision of a remote repository::
3990 3990
3991 3991 hg id -r tip http://selenic.com/hg/
3992 3992
3993 3993 Returns 0 if successful.
3994 3994 """
3995 3995
3996 3996 if not repo and not source:
3997 3997 raise util.Abort(_("there is no Mercurial repository here "
3998 3998 "(.hg not found)"))
3999 3999
4000 4000 if ui.debugflag:
4001 4001 hexfunc = hex
4002 4002 else:
4003 4003 hexfunc = short
4004 4004 default = not (num or id or branch or tags or bookmarks)
4005 4005 output = []
4006 4006 revs = []
4007 4007
4008 4008 if source:
4009 4009 source, branches = hg.parseurl(ui.expandpath(source))
4010 4010 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4011 4011 repo = peer.local()
4012 4012 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4013 4013
4014 4014 if not repo:
4015 4015 if num or branch or tags:
4016 4016 raise util.Abort(
4017 4017 _("can't query remote revision number, branch, or tags"))
4018 4018 if not rev and revs:
4019 4019 rev = revs[0]
4020 4020 if not rev:
4021 4021 rev = "tip"
4022 4022
4023 4023 remoterev = peer.lookup(rev)
4024 4024 if default or id:
4025 4025 output = [hexfunc(remoterev)]
4026 4026
4027 4027 def getbms():
4028 4028 bms = []
4029 4029
4030 4030 if 'bookmarks' in peer.listkeys('namespaces'):
4031 4031 hexremoterev = hex(remoterev)
4032 4032 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4033 4033 if bmr == hexremoterev]
4034 4034
4035 4035 return sorted(bms)
4036 4036
4037 4037 if bookmarks:
4038 4038 output.extend(getbms())
4039 4039 elif default and not ui.quiet:
4040 4040 # multiple bookmarks for a single parent separated by '/'
4041 4041 bm = '/'.join(getbms())
4042 4042 if bm:
4043 4043 output.append(bm)
4044 4044 else:
4045 4045 if not rev:
4046 4046 ctx = repo[None]
4047 4047 parents = ctx.parents()
4048 4048 changed = ""
4049 4049 if default or id or num:
4050 4050 if (util.any(repo.status())
4051 4051 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4052 4052 changed = '+'
4053 4053 if default or id:
4054 4054 output = ["%s%s" %
4055 4055 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4056 4056 if num:
4057 4057 output.append("%s%s" %
4058 4058 ('+'.join([str(p.rev()) for p in parents]), changed))
4059 4059 else:
4060 4060 ctx = scmutil.revsingle(repo, rev)
4061 4061 if default or id:
4062 4062 output = [hexfunc(ctx.node())]
4063 4063 if num:
4064 4064 output.append(str(ctx.rev()))
4065 4065
4066 4066 if default and not ui.quiet:
4067 4067 b = ctx.branch()
4068 4068 if b != 'default':
4069 4069 output.append("(%s)" % b)
4070 4070
4071 4071 # multiple tags for a single parent separated by '/'
4072 4072 t = '/'.join(ctx.tags())
4073 4073 if t:
4074 4074 output.append(t)
4075 4075
4076 4076 # multiple bookmarks for a single parent separated by '/'
4077 4077 bm = '/'.join(ctx.bookmarks())
4078 4078 if bm:
4079 4079 output.append(bm)
4080 4080 else:
4081 4081 if branch:
4082 4082 output.append(ctx.branch())
4083 4083
4084 4084 if tags:
4085 4085 output.extend(ctx.tags())
4086 4086
4087 4087 if bookmarks:
4088 4088 output.extend(ctx.bookmarks())
4089 4089
4090 4090 ui.write("%s\n" % ' '.join(output))
4091 4091
4092 4092 @command('import|patch',
4093 4093 [('p', 'strip', 1,
4094 4094 _('directory strip option for patch. This has the same '
4095 4095 'meaning as the corresponding patch option'), _('NUM')),
4096 4096 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4097 4097 ('e', 'edit', False, _('invoke editor on commit messages')),
4098 4098 ('f', 'force', None,
4099 4099 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4100 4100 ('', 'no-commit', None,
4101 4101 _("don't commit, just update the working directory")),
4102 4102 ('', 'bypass', None,
4103 4103 _("apply patch without touching the working directory")),
4104 4104 ('', 'partial', None,
4105 4105 _('commit even if some hunks fail')),
4106 4106 ('', 'exact', None,
4107 4107 _('apply patch to the nodes from which it was generated')),
4108 4108 ('', 'prefix', '',
4109 4109 _('apply patch to subdirectory'), _('DIR')),
4110 4110 ('', 'import-branch', None,
4111 4111 _('use any branch information in patch (implied by --exact)'))] +
4112 4112 commitopts + commitopts2 + similarityopts,
4113 4113 _('[OPTION]... PATCH...'))
4114 4114 def import_(ui, repo, patch1=None, *patches, **opts):
4115 4115 """import an ordered set of patches
4116 4116
4117 4117 Import a list of patches and commit them individually (unless
4118 4118 --no-commit is specified).
4119 4119
4120 4120 Because import first applies changes to the working directory,
4121 4121 import will abort if there are outstanding changes.
4122 4122
4123 4123 You can import a patch straight from a mail message. Even patches
4124 4124 as attachments work (to use the body part, it must have type
4125 4125 text/plain or text/x-patch). From and Subject headers of email
4126 4126 message are used as default committer and commit message. All
4127 4127 text/plain body parts before first diff are added to commit
4128 4128 message.
4129 4129
4130 4130 If the imported patch was generated by :hg:`export`, user and
4131 4131 description from patch override values from message headers and
4132 4132 body. Values given on command line with -m/--message and -u/--user
4133 4133 override these.
4134 4134
4135 4135 If --exact is specified, import will set the working directory to
4136 4136 the parent of each patch before applying it, and will abort if the
4137 4137 resulting changeset has a different ID than the one recorded in
4138 4138 the patch. This may happen due to character set problems or other
4139 4139 deficiencies in the text patch format.
4140 4140
4141 4141 Use --bypass to apply and commit patches directly to the
4142 4142 repository, not touching the working directory. Without --exact,
4143 4143 patches will be applied on top of the working directory parent
4144 4144 revision.
4145 4145
4146 4146 With -s/--similarity, hg will attempt to discover renames and
4147 4147 copies in the patch in the same way as :hg:`addremove`.
4148 4148
4149 4149 Use --partial to ensure a changeset will be created from the patch
4150 4150 even if some hunks fail to apply. Hunks that fail to apply will be
4151 4151 written to a <target-file>.rej file. Conflicts can then be resolved
4152 4152 by hand before :hg:`commit --amend` is run to update the created
4153 4153 changeset. This flag exists to let people import patches that
4154 4154 partially apply without losing the associated metadata (author,
4155 4155 date, description, ...). Note that when none of the hunk applies
4156 4156 cleanly, :hg:`import --partial` will create an empty changeset,
4157 4157 importing only the patch metadata.
4158 4158
4159 4159 To read a patch from standard input, use "-" as the patch name. If
4160 4160 a URL is specified, the patch will be downloaded from it.
4161 4161 See :hg:`help dates` for a list of formats valid for -d/--date.
4162 4162
4163 4163 .. container:: verbose
4164 4164
4165 4165 Examples:
4166 4166
4167 4167 - import a traditional patch from a website and detect renames::
4168 4168
4169 4169 hg import -s 80 http://example.com/bugfix.patch
4170 4170
4171 4171 - import a changeset from an hgweb server::
4172 4172
4173 4173 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4174 4174
4175 4175 - import all the patches in an Unix-style mbox::
4176 4176
4177 4177 hg import incoming-patches.mbox
4178 4178
4179 4179 - attempt to exactly restore an exported changeset (not always
4180 4180 possible)::
4181 4181
4182 4182 hg import --exact proposed-fix.patch
4183 4183
4184 4184 Returns 0 on success, 1 on partial success (see --partial).
4185 4185 """
4186 4186
4187 4187 if not patch1:
4188 4188 raise util.Abort(_('need at least one patch to import'))
4189 4189
4190 4190 patches = (patch1,) + patches
4191 4191
4192 4192 date = opts.get('date')
4193 4193 if date:
4194 4194 opts['date'] = util.parsedate(date)
4195 4195
4196 4196 update = not opts.get('bypass')
4197 4197 if not update and opts.get('no_commit'):
4198 4198 raise util.Abort(_('cannot use --no-commit with --bypass'))
4199 4199 try:
4200 4200 sim = float(opts.get('similarity') or 0)
4201 4201 except ValueError:
4202 4202 raise util.Abort(_('similarity must be a number'))
4203 4203 if sim < 0 or sim > 100:
4204 4204 raise util.Abort(_('similarity must be between 0 and 100'))
4205 4205 if sim and not update:
4206 4206 raise util.Abort(_('cannot use --similarity with --bypass'))
4207 4207 if opts.get('exact') and opts.get('edit'):
4208 4208 raise util.Abort(_('cannot use --exact with --edit'))
4209 4209 if opts.get('exact') and opts.get('prefix'):
4210 4210 raise util.Abort(_('cannot use --exact with --prefix'))
4211 4211
4212 4212 if update:
4213 4213 cmdutil.checkunfinished(repo)
4214 4214 if (opts.get('exact') or not opts.get('force')) and update:
4215 4215 cmdutil.bailifchanged(repo)
4216 4216
4217 4217 base = opts["base"]
4218 4218 wlock = lock = tr = None
4219 4219 msgs = []
4220 4220 ret = 0
4221 4221
4222 4222
4223 4223 try:
4224 4224 try:
4225 4225 wlock = repo.wlock()
4226 4226 repo.dirstate.beginparentchange()
4227 4227 if not opts.get('no_commit'):
4228 4228 lock = repo.lock()
4229 4229 tr = repo.transaction('import')
4230 4230 parents = repo.parents()
4231 4231 for patchurl in patches:
4232 4232 if patchurl == '-':
4233 4233 ui.status(_('applying patch from stdin\n'))
4234 4234 patchfile = ui.fin
4235 4235 patchurl = 'stdin' # for error message
4236 4236 else:
4237 4237 patchurl = os.path.join(base, patchurl)
4238 4238 ui.status(_('applying %s\n') % patchurl)
4239 4239 patchfile = hg.openpath(ui, patchurl)
4240 4240
4241 4241 haspatch = False
4242 4242 for hunk in patch.split(patchfile):
4243 4243 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4244 4244 parents, opts,
4245 4245 msgs, hg.clean)
4246 4246 if msg:
4247 4247 haspatch = True
4248 4248 ui.note(msg + '\n')
4249 4249 if update or opts.get('exact'):
4250 4250 parents = repo.parents()
4251 4251 else:
4252 4252 parents = [repo[node]]
4253 4253 if rej:
4254 4254 ui.write_err(_("patch applied partially\n"))
4255 4255 ui.write_err(_("(fix the .rej files and run "
4256 4256 "`hg commit --amend`)\n"))
4257 4257 ret = 1
4258 4258 break
4259 4259
4260 4260 if not haspatch:
4261 4261 raise util.Abort(_('%s: no diffs found') % patchurl)
4262 4262
4263 4263 if tr:
4264 4264 tr.close()
4265 4265 if msgs:
4266 4266 repo.savecommitmessage('\n* * *\n'.join(msgs))
4267 4267 repo.dirstate.endparentchange()
4268 4268 return ret
4269 4269 except: # re-raises
4270 4270 # wlock.release() indirectly calls dirstate.write(): since
4271 4271 # we're crashing, we do not want to change the working dir
4272 4272 # parent after all, so make sure it writes nothing
4273 4273 repo.dirstate.invalidate()
4274 4274 raise
4275 4275 finally:
4276 4276 if tr:
4277 4277 tr.release()
4278 4278 release(lock, wlock)
4279 4279
4280 4280 @command('incoming|in',
4281 4281 [('f', 'force', None,
4282 4282 _('run even if remote repository is unrelated')),
4283 4283 ('n', 'newest-first', None, _('show newest record first')),
4284 4284 ('', 'bundle', '',
4285 4285 _('file to store the bundles into'), _('FILE')),
4286 4286 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4287 4287 ('B', 'bookmarks', False, _("compare bookmarks")),
4288 4288 ('b', 'branch', [],
4289 4289 _('a specific branch you would like to pull'), _('BRANCH')),
4290 4290 ] + logopts + remoteopts + subrepoopts,
4291 4291 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4292 4292 def incoming(ui, repo, source="default", **opts):
4293 4293 """show new changesets found in source
4294 4294
4295 4295 Show new changesets found in the specified path/URL or the default
4296 4296 pull location. These are the changesets that would have been pulled
4297 4297 if a pull at the time you issued this command.
4298 4298
4299 4299 See pull for valid source format details.
4300 4300
4301 4301 .. container:: verbose
4302 4302
4303 4303 With -B/--bookmarks, the result of bookmark comparison between
4304 4304 local and remote repositories is displayed. With -v/--verbose,
4305 4305 status is also displayed for each bookmark like below::
4306 4306
4307 4307 BM1 01234567890a added
4308 4308 BM2 1234567890ab advanced
4309 4309 BM3 234567890abc diverged
4310 4310 BM4 34567890abcd changed
4311 4311
4312 4312 The action taken locally when pulling depends on the
4313 4313 status of each bookmark:
4314 4314
4315 4315 :``added``: pull will create it
4316 4316 :``advanced``: pull will update it
4317 4317 :``diverged``: pull will create a divergent bookmark
4318 4318 :``changed``: result depends on remote changesets
4319 4319
4320 4320 From the point of view of pulling behavior, bookmark
4321 4321 existing only in the remote repository are treated as ``added``,
4322 4322 even if it is in fact locally deleted.
4323 4323
4324 4324 .. container:: verbose
4325 4325
4326 4326 For remote repository, using --bundle avoids downloading the
4327 4327 changesets twice if the incoming is followed by a pull.
4328 4328
4329 4329 Examples:
4330 4330
4331 4331 - show incoming changes with patches and full description::
4332 4332
4333 4333 hg incoming -vp
4334 4334
4335 4335 - show incoming changes excluding merges, store a bundle::
4336 4336
4337 4337 hg in -vpM --bundle incoming.hg
4338 4338 hg pull incoming.hg
4339 4339
4340 4340 - briefly list changes inside a bundle::
4341 4341
4342 4342 hg in changes.hg -T "{desc|firstline}\\n"
4343 4343
4344 4344 Returns 0 if there are incoming changes, 1 otherwise.
4345 4345 """
4346 4346 if opts.get('graph'):
4347 4347 cmdutil.checkunsupportedgraphflags([], opts)
4348 4348 def display(other, chlist, displayer):
4349 4349 revdag = cmdutil.graphrevs(other, chlist, opts)
4350 4350 showparents = [ctx.node() for ctx in repo[None].parents()]
4351 4351 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4352 4352 graphmod.asciiedges)
4353 4353
4354 4354 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4355 4355 return 0
4356 4356
4357 4357 if opts.get('bundle') and opts.get('subrepos'):
4358 4358 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4359 4359
4360 4360 if opts.get('bookmarks'):
4361 4361 source, branches = hg.parseurl(ui.expandpath(source),
4362 4362 opts.get('branch'))
4363 4363 other = hg.peer(repo, opts, source)
4364 4364 if 'bookmarks' not in other.listkeys('namespaces'):
4365 4365 ui.warn(_("remote doesn't support bookmarks\n"))
4366 4366 return 0
4367 4367 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4368 4368 return bookmarks.incoming(ui, repo, other)
4369 4369
4370 4370 repo._subtoppath = ui.expandpath(source)
4371 4371 try:
4372 4372 return hg.incoming(ui, repo, source, opts)
4373 4373 finally:
4374 4374 del repo._subtoppath
4375 4375
4376 4376
4377 4377 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4378 4378 norepo=True)
4379 4379 def init(ui, dest=".", **opts):
4380 4380 """create a new repository in the given directory
4381 4381
4382 4382 Initialize a new repository in the given directory. If the given
4383 4383 directory does not exist, it will be created.
4384 4384
4385 4385 If no directory is given, the current directory is used.
4386 4386
4387 4387 It is possible to specify an ``ssh://`` URL as the destination.
4388 4388 See :hg:`help urls` for more information.
4389 4389
4390 4390 Returns 0 on success.
4391 4391 """
4392 4392 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4393 4393
4394 4394 @command('locate',
4395 4395 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4396 4396 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4397 4397 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4398 4398 ] + walkopts,
4399 4399 _('[OPTION]... [PATTERN]...'))
4400 4400 def locate(ui, repo, *pats, **opts):
4401 4401 """locate files matching specific patterns (DEPRECATED)
4402 4402
4403 4403 Print files under Mercurial control in the working directory whose
4404 4404 names match the given patterns.
4405 4405
4406 4406 By default, this command searches all directories in the working
4407 4407 directory. To search just the current directory and its
4408 4408 subdirectories, use "--include .".
4409 4409
4410 4410 If no patterns are given to match, this command prints the names
4411 4411 of all files under Mercurial control in the working directory.
4412 4412
4413 4413 If you want to feed the output of this command into the "xargs"
4414 4414 command, use the -0 option to both this command and "xargs". This
4415 4415 will avoid the problem of "xargs" treating single filenames that
4416 4416 contain whitespace as multiple filenames.
4417 4417
4418 4418 See :hg:`help files` for a more versatile command.
4419 4419
4420 4420 Returns 0 if a match is found, 1 otherwise.
4421 4421 """
4422 4422 if opts.get('print0'):
4423 4423 end = '\0'
4424 4424 else:
4425 4425 end = '\n'
4426 4426 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4427 4427
4428 4428 ret = 1
4429 4429 ctx = repo[rev]
4430 4430 m = scmutil.match(ctx, pats, opts, default='relglob')
4431 4431 m.bad = lambda x, y: False
4432 4432
4433 4433 for abs in ctx.matches(m):
4434 4434 if opts.get('fullpath'):
4435 4435 ui.write(repo.wjoin(abs), end)
4436 4436 else:
4437 4437 ui.write(((pats and m.rel(abs)) or abs), end)
4438 4438 ret = 0
4439 4439
4440 4440 return ret
4441 4441
4442 4442 @command('^log|history',
4443 4443 [('f', 'follow', None,
4444 4444 _('follow changeset history, or file history across copies and renames')),
4445 4445 ('', 'follow-first', None,
4446 4446 _('only follow the first parent of merge changesets (DEPRECATED)')),
4447 4447 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4448 4448 ('C', 'copies', None, _('show copied files')),
4449 4449 ('k', 'keyword', [],
4450 4450 _('do case-insensitive search for a given text'), _('TEXT')),
4451 4451 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4452 4452 ('', 'removed', None, _('include revisions where files were removed')),
4453 4453 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4454 4454 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4455 4455 ('', 'only-branch', [],
4456 4456 _('show only changesets within the given named branch (DEPRECATED)'),
4457 4457 _('BRANCH')),
4458 4458 ('b', 'branch', [],
4459 4459 _('show changesets within the given named branch'), _('BRANCH')),
4460 4460 ('P', 'prune', [],
4461 4461 _('do not display revision or any of its ancestors'), _('REV')),
4462 4462 ] + logopts + walkopts,
4463 4463 _('[OPTION]... [FILE]'),
4464 4464 inferrepo=True)
4465 4465 def log(ui, repo, *pats, **opts):
4466 4466 """show revision history of entire repository or files
4467 4467
4468 4468 Print the revision history of the specified files or the entire
4469 4469 project.
4470 4470
4471 4471 If no revision range is specified, the default is ``tip:0`` unless
4472 4472 --follow is set, in which case the working directory parent is
4473 4473 used as the starting revision.
4474 4474
4475 4475 File history is shown without following rename or copy history of
4476 4476 files. Use -f/--follow with a filename to follow history across
4477 4477 renames and copies. --follow without a filename will only show
4478 4478 ancestors or descendants of the starting revision.
4479 4479
4480 4480 By default this command prints revision number and changeset id,
4481 4481 tags, non-trivial parents, user, date and time, and a summary for
4482 4482 each commit. When the -v/--verbose switch is used, the list of
4483 4483 changed files and full commit message are shown.
4484 4484
4485 4485 With --graph the revisions are shown as an ASCII art DAG with the most
4486 4486 recent changeset at the top.
4487 4487 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4488 4488 and '+' represents a fork where the changeset from the lines below is a
4489 4489 parent of the 'o' merge on the same line.
4490 4490
4491 4491 .. note::
4492 4492
4493 4493 log -p/--patch may generate unexpected diff output for merge
4494 4494 changesets, as it will only compare the merge changeset against
4495 4495 its first parent. Also, only files different from BOTH parents
4496 4496 will appear in files:.
4497 4497
4498 4498 .. note::
4499 4499
4500 4500 for performance reasons, log FILE may omit duplicate changes
4501 4501 made on branches and will not show removals or mode changes. To
4502 4502 see all such changes, use the --removed switch.
4503 4503
4504 4504 .. container:: verbose
4505 4505
4506 4506 Some examples:
4507 4507
4508 4508 - changesets with full descriptions and file lists::
4509 4509
4510 4510 hg log -v
4511 4511
4512 4512 - changesets ancestral to the working directory::
4513 4513
4514 4514 hg log -f
4515 4515
4516 4516 - last 10 commits on the current branch::
4517 4517
4518 4518 hg log -l 10 -b .
4519 4519
4520 4520 - changesets showing all modifications of a file, including removals::
4521 4521
4522 4522 hg log --removed file.c
4523 4523
4524 4524 - all changesets that touch a directory, with diffs, excluding merges::
4525 4525
4526 4526 hg log -Mp lib/
4527 4527
4528 4528 - all revision numbers that match a keyword::
4529 4529
4530 4530 hg log -k bug --template "{rev}\\n"
4531 4531
4532 4532 - list available log templates::
4533 4533
4534 4534 hg log -T list
4535 4535
4536 4536 - check if a given changeset is included in a tagged release::
4537 4537
4538 4538 hg log -r "a21ccf and ancestor(1.9)"
4539 4539
4540 4540 - find all changesets by some user in a date range::
4541 4541
4542 4542 hg log -k alice -d "may 2008 to jul 2008"
4543 4543
4544 4544 - summary of all changesets after the last tag::
4545 4545
4546 4546 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4547 4547
4548 4548 See :hg:`help dates` for a list of formats valid for -d/--date.
4549 4549
4550 4550 See :hg:`help revisions` and :hg:`help revsets` for more about
4551 4551 specifying revisions.
4552 4552
4553 4553 See :hg:`help templates` for more about pre-packaged styles and
4554 4554 specifying custom templates.
4555 4555
4556 4556 Returns 0 on success.
4557 4557
4558 4558 """
4559 4559 if opts.get('follow') and opts.get('rev'):
4560 4560 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4561 4561 del opts['follow']
4562 4562
4563 4563 if opts.get('graph'):
4564 4564 return cmdutil.graphlog(ui, repo, *pats, **opts)
4565 4565
4566 4566 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4567 4567 limit = cmdutil.loglimit(opts)
4568 4568 count = 0
4569 4569
4570 4570 getrenamed = None
4571 4571 if opts.get('copies'):
4572 4572 endrev = None
4573 4573 if opts.get('rev'):
4574 4574 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4575 4575 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4576 4576
4577 4577 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4578 4578 for rev in revs:
4579 4579 if count == limit:
4580 4580 break
4581 4581 ctx = repo[rev]
4582 4582 copies = None
4583 4583 if getrenamed is not None and rev:
4584 4584 copies = []
4585 4585 for fn in ctx.files():
4586 4586 rename = getrenamed(fn, rev)
4587 4587 if rename:
4588 4588 copies.append((fn, rename[0]))
4589 4589 if filematcher:
4590 4590 revmatchfn = filematcher(ctx.rev())
4591 4591 else:
4592 4592 revmatchfn = None
4593 4593 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4594 4594 if displayer.flush(rev):
4595 4595 count += 1
4596 4596
4597 4597 displayer.close()
4598 4598
4599 4599 @command('manifest',
4600 4600 [('r', 'rev', '', _('revision to display'), _('REV')),
4601 4601 ('', 'all', False, _("list files from all revisions"))]
4602 4602 + formatteropts,
4603 4603 _('[-r REV]'))
4604 4604 def manifest(ui, repo, node=None, rev=None, **opts):
4605 4605 """output the current or given revision of the project manifest
4606 4606
4607 4607 Print a list of version controlled files for the given revision.
4608 4608 If no revision is given, the first parent of the working directory
4609 4609 is used, or the null revision if no revision is checked out.
4610 4610
4611 4611 With -v, print file permissions, symlink and executable bits.
4612 4612 With --debug, print file revision hashes.
4613 4613
4614 4614 If option --all is specified, the list of all files from all revisions
4615 4615 is printed. This includes deleted and renamed files.
4616 4616
4617 4617 Returns 0 on success.
4618 4618 """
4619 4619
4620 4620 fm = ui.formatter('manifest', opts)
4621 4621
4622 4622 if opts.get('all'):
4623 4623 if rev or node:
4624 4624 raise util.Abort(_("can't specify a revision with --all"))
4625 4625
4626 4626 res = []
4627 4627 prefix = "data/"
4628 4628 suffix = ".i"
4629 4629 plen = len(prefix)
4630 4630 slen = len(suffix)
4631 4631 lock = repo.lock()
4632 4632 try:
4633 4633 for fn, b, size in repo.store.datafiles():
4634 4634 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4635 4635 res.append(fn[plen:-slen])
4636 4636 finally:
4637 4637 lock.release()
4638 4638 for f in res:
4639 4639 fm.startitem()
4640 4640 fm.write("path", '%s\n', f)
4641 4641 fm.end()
4642 4642 return
4643 4643
4644 4644 if rev and node:
4645 4645 raise util.Abort(_("please specify just one revision"))
4646 4646
4647 4647 if not node:
4648 4648 node = rev
4649 4649
4650 4650 char = {'l': '@', 'x': '*', '': ''}
4651 4651 mode = {'l': '644', 'x': '755', '': '644'}
4652 4652 ctx = scmutil.revsingle(repo, node)
4653 4653 mf = ctx.manifest()
4654 4654 for f in ctx:
4655 4655 fm.startitem()
4656 4656 fl = ctx[f].flags()
4657 4657 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4658 4658 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4659 4659 fm.write('path', '%s\n', f)
4660 4660 fm.end()
4661 4661
4662 4662 @command('^merge',
4663 4663 [('f', 'force', None,
4664 4664 _('force a merge including outstanding changes (DEPRECATED)')),
4665 4665 ('r', 'rev', '', _('revision to merge'), _('REV')),
4666 4666 ('P', 'preview', None,
4667 4667 _('review revisions to merge (no merge is performed)'))
4668 4668 ] + mergetoolopts,
4669 4669 _('[-P] [-f] [[-r] REV]'))
4670 4670 def merge(ui, repo, node=None, **opts):
4671 4671 """merge another revision into working directory
4672 4672
4673 4673 The current working directory is updated with all changes made in
4674 4674 the requested revision since the last common predecessor revision.
4675 4675
4676 4676 Files that changed between either parent are marked as changed for
4677 4677 the next commit and a commit must be performed before any further
4678 4678 updates to the repository are allowed. The next commit will have
4679 4679 two parents.
4680 4680
4681 4681 ``--tool`` can be used to specify the merge tool used for file
4682 4682 merges. It overrides the HGMERGE environment variable and your
4683 4683 configuration files. See :hg:`help merge-tools` for options.
4684 4684
4685 4685 If no revision is specified, the working directory's parent is a
4686 4686 head revision, and the current branch contains exactly one other
4687 4687 head, the other head is merged with by default. Otherwise, an
4688 4688 explicit revision with which to merge with must be provided.
4689 4689
4690 4690 :hg:`resolve` must be used to resolve unresolved files.
4691 4691
4692 4692 To undo an uncommitted merge, use :hg:`update --clean .` which
4693 4693 will check out a clean copy of the original merge parent, losing
4694 4694 all changes.
4695 4695
4696 4696 Returns 0 on success, 1 if there are unresolved files.
4697 4697 """
4698 4698
4699 4699 if opts.get('rev') and node:
4700 4700 raise util.Abort(_("please specify just one revision"))
4701 4701 if not node:
4702 4702 node = opts.get('rev')
4703 4703
4704 4704 if node:
4705 4705 node = scmutil.revsingle(repo, node).node()
4706 4706
4707 4707 if not node and repo._bookmarkcurrent:
4708 4708 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4709 4709 curhead = repo[repo._bookmarkcurrent].node()
4710 4710 if len(bmheads) == 2:
4711 4711 if curhead == bmheads[0]:
4712 4712 node = bmheads[1]
4713 4713 else:
4714 4714 node = bmheads[0]
4715 4715 elif len(bmheads) > 2:
4716 4716 raise util.Abort(_("multiple matching bookmarks to merge - "
4717 4717 "please merge with an explicit rev or bookmark"),
4718 4718 hint=_("run 'hg heads' to see all heads"))
4719 4719 elif len(bmheads) <= 1:
4720 4720 raise util.Abort(_("no matching bookmark to merge - "
4721 4721 "please merge with an explicit rev or bookmark"),
4722 4722 hint=_("run 'hg heads' to see all heads"))
4723 4723
4724 4724 if not node and not repo._bookmarkcurrent:
4725 4725 branch = repo[None].branch()
4726 4726 bheads = repo.branchheads(branch)
4727 4727 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4728 4728
4729 4729 if len(nbhs) > 2:
4730 4730 raise util.Abort(_("branch '%s' has %d heads - "
4731 4731 "please merge with an explicit rev")
4732 4732 % (branch, len(bheads)),
4733 4733 hint=_("run 'hg heads .' to see heads"))
4734 4734
4735 4735 parent = repo.dirstate.p1()
4736 4736 if len(nbhs) <= 1:
4737 4737 if len(bheads) > 1:
4738 4738 raise util.Abort(_("heads are bookmarked - "
4739 4739 "please merge with an explicit rev"),
4740 4740 hint=_("run 'hg heads' to see all heads"))
4741 4741 if len(repo.heads()) > 1:
4742 4742 raise util.Abort(_("branch '%s' has one head - "
4743 4743 "please merge with an explicit rev")
4744 4744 % branch,
4745 4745 hint=_("run 'hg heads' to see all heads"))
4746 4746 msg, hint = _('nothing to merge'), None
4747 4747 if parent != repo.lookup(branch):
4748 4748 hint = _("use 'hg update' instead")
4749 4749 raise util.Abort(msg, hint=hint)
4750 4750
4751 4751 if parent not in bheads:
4752 4752 raise util.Abort(_('working directory not at a head revision'),
4753 4753 hint=_("use 'hg update' or merge with an "
4754 4754 "explicit revision"))
4755 4755 if parent == nbhs[0]:
4756 4756 node = nbhs[-1]
4757 4757 else:
4758 4758 node = nbhs[0]
4759 4759
4760 4760 if opts.get('preview'):
4761 4761 # find nodes that are ancestors of p2 but not of p1
4762 4762 p1 = repo.lookup('.')
4763 4763 p2 = repo.lookup(node)
4764 4764 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4765 4765
4766 4766 displayer = cmdutil.show_changeset(ui, repo, opts)
4767 4767 for node in nodes:
4768 4768 displayer.show(repo[node])
4769 4769 displayer.close()
4770 4770 return 0
4771 4771
4772 4772 try:
4773 4773 # ui.forcemerge is an internal variable, do not document
4774 4774 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4775 4775 return hg.merge(repo, node, force=opts.get('force'))
4776 4776 finally:
4777 4777 ui.setconfig('ui', 'forcemerge', '', 'merge')
4778 4778
4779 4779 @command('outgoing|out',
4780 4780 [('f', 'force', None, _('run even when the destination is unrelated')),
4781 4781 ('r', 'rev', [],
4782 4782 _('a changeset intended to be included in the destination'), _('REV')),
4783 4783 ('n', 'newest-first', None, _('show newest record first')),
4784 4784 ('B', 'bookmarks', False, _('compare bookmarks')),
4785 4785 ('b', 'branch', [], _('a specific branch you would like to push'),
4786 4786 _('BRANCH')),
4787 4787 ] + logopts + remoteopts + subrepoopts,
4788 4788 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4789 4789 def outgoing(ui, repo, dest=None, **opts):
4790 4790 """show changesets not found in the destination
4791 4791
4792 4792 Show changesets not found in the specified destination repository
4793 4793 or the default push location. These are the changesets that would
4794 4794 be pushed if a push was requested.
4795 4795
4796 4796 See pull for details of valid destination formats.
4797 4797
4798 4798 .. container:: verbose
4799 4799
4800 4800 With -B/--bookmarks, the result of bookmark comparison between
4801 4801 local and remote repositories is displayed. With -v/--verbose,
4802 4802 status is also displayed for each bookmark like below::
4803 4803
4804 4804 BM1 01234567890a added
4805 4805 BM2 deleted
4806 4806 BM3 234567890abc advanced
4807 4807 BM4 34567890abcd diverged
4808 4808 BM5 4567890abcde changed
4809 4809
4810 4810 The action taken when pushing depends on the
4811 4811 status of each bookmark:
4812 4812
4813 4813 :``added``: push with ``-B`` will create it
4814 4814 :``deleted``: push with ``-B`` will delete it
4815 4815 :``advanced``: push will update it
4816 4816 :``diverged``: push with ``-B`` will update it
4817 4817 :``changed``: push with ``-B`` will update it
4818 4818
4819 4819 From the point of view of pushing behavior, bookmarks
4820 4820 existing only in the remote repository are treated as
4821 4821 ``deleted``, even if it is in fact added remotely.
4822 4822
4823 4823 Returns 0 if there are outgoing changes, 1 otherwise.
4824 4824 """
4825 4825 if opts.get('graph'):
4826 4826 cmdutil.checkunsupportedgraphflags([], opts)
4827 4827 o, other = hg._outgoing(ui, repo, dest, opts)
4828 4828 if not o:
4829 4829 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4830 4830 return
4831 4831
4832 4832 revdag = cmdutil.graphrevs(repo, o, opts)
4833 4833 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4834 4834 showparents = [ctx.node() for ctx in repo[None].parents()]
4835 4835 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4836 4836 graphmod.asciiedges)
4837 4837 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4838 4838 return 0
4839 4839
4840 4840 if opts.get('bookmarks'):
4841 4841 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4842 4842 dest, branches = hg.parseurl(dest, opts.get('branch'))
4843 4843 other = hg.peer(repo, opts, dest)
4844 4844 if 'bookmarks' not in other.listkeys('namespaces'):
4845 4845 ui.warn(_("remote doesn't support bookmarks\n"))
4846 4846 return 0
4847 4847 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4848 4848 return bookmarks.outgoing(ui, repo, other)
4849 4849
4850 4850 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4851 4851 try:
4852 4852 return hg.outgoing(ui, repo, dest, opts)
4853 4853 finally:
4854 4854 del repo._subtoppath
4855 4855
4856 4856 @command('parents',
4857 4857 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4858 4858 ] + templateopts,
4859 4859 _('[-r REV] [FILE]'),
4860 4860 inferrepo=True)
4861 4861 def parents(ui, repo, file_=None, **opts):
4862 4862 """show the parents of the working directory or revision (DEPRECATED)
4863 4863
4864 4864 Print the working directory's parent revisions. If a revision is
4865 4865 given via -r/--rev, the parent of that revision will be printed.
4866 4866 If a file argument is given, the revision in which the file was
4867 4867 last changed (before the working directory revision or the
4868 4868 argument to --rev if given) is printed.
4869 4869
4870 4870 See :hg:`summary` and :hg:`help revsets` for related information.
4871 4871
4872 4872 Returns 0 on success.
4873 4873 """
4874 4874
4875 4875 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4876 4876
4877 4877 if file_:
4878 4878 m = scmutil.match(ctx, (file_,), opts)
4879 4879 if m.anypats() or len(m.files()) != 1:
4880 4880 raise util.Abort(_('can only specify an explicit filename'))
4881 4881 file_ = m.files()[0]
4882 4882 filenodes = []
4883 4883 for cp in ctx.parents():
4884 4884 if not cp:
4885 4885 continue
4886 4886 try:
4887 4887 filenodes.append(cp.filenode(file_))
4888 4888 except error.LookupError:
4889 4889 pass
4890 4890 if not filenodes:
4891 4891 raise util.Abort(_("'%s' not found in manifest!") % file_)
4892 4892 p = []
4893 4893 for fn in filenodes:
4894 4894 fctx = repo.filectx(file_, fileid=fn)
4895 4895 p.append(fctx.node())
4896 4896 else:
4897 4897 p = [cp.node() for cp in ctx.parents()]
4898 4898
4899 4899 displayer = cmdutil.show_changeset(ui, repo, opts)
4900 4900 for n in p:
4901 4901 if n != nullid:
4902 4902 displayer.show(repo[n])
4903 4903 displayer.close()
4904 4904
4905 4905 @command('paths', [], _('[NAME]'), optionalrepo=True)
4906 4906 def paths(ui, repo, search=None):
4907 4907 """show aliases for remote repositories
4908 4908
4909 4909 Show definition of symbolic path name NAME. If no name is given,
4910 4910 show definition of all available names.
4911 4911
4912 4912 Option -q/--quiet suppresses all output when searching for NAME
4913 4913 and shows only the path names when listing all definitions.
4914 4914
4915 4915 Path names are defined in the [paths] section of your
4916 4916 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4917 4917 repository, ``.hg/hgrc`` is used, too.
4918 4918
4919 4919 The path names ``default`` and ``default-push`` have a special
4920 4920 meaning. When performing a push or pull operation, they are used
4921 4921 as fallbacks if no location is specified on the command-line.
4922 4922 When ``default-push`` is set, it will be used for push and
4923 4923 ``default`` will be used for pull; otherwise ``default`` is used
4924 4924 as the fallback for both. When cloning a repository, the clone
4925 4925 source is written as ``default`` in ``.hg/hgrc``. Note that
4926 4926 ``default`` and ``default-push`` apply to all inbound (e.g.
4927 4927 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4928 4928 :hg:`bundle`) operations.
4929 4929
4930 4930 See :hg:`help urls` for more information.
4931 4931
4932 4932 Returns 0 on success.
4933 4933 """
4934 4934 if search:
4935 4935 for name, path in sorted(ui.paths.iteritems()):
4936 4936 if name == search:
4937 4937 ui.status("%s\n" % util.hidepassword(path.loc))
4938 4938 return
4939 4939 if not ui.quiet:
4940 4940 ui.warn(_("not found!\n"))
4941 4941 return 1
4942 4942 else:
4943 4943 for name, path in sorted(ui.paths.iteritems()):
4944 4944 if ui.quiet:
4945 4945 ui.write("%s\n" % name)
4946 4946 else:
4947 4947 ui.write("%s = %s\n" % (name,
4948 4948 util.hidepassword(path.loc)))
4949 4949
4950 4950 @command('phase',
4951 4951 [('p', 'public', False, _('set changeset phase to public')),
4952 4952 ('d', 'draft', False, _('set changeset phase to draft')),
4953 4953 ('s', 'secret', False, _('set changeset phase to secret')),
4954 4954 ('f', 'force', False, _('allow to move boundary backward')),
4955 4955 ('r', 'rev', [], _('target revision'), _('REV')),
4956 4956 ],
4957 4957 _('[-p|-d|-s] [-f] [-r] REV...'))
4958 4958 def phase(ui, repo, *revs, **opts):
4959 4959 """set or show the current phase name
4960 4960
4961 4961 With no argument, show the phase name of specified revisions.
4962 4962
4963 4963 With one of -p/--public, -d/--draft or -s/--secret, change the
4964 4964 phase value of the specified revisions.
4965 4965
4966 4966 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4967 4967 lower phase to an higher phase. Phases are ordered as follows::
4968 4968
4969 4969 public < draft < secret
4970 4970
4971 4971 Returns 0 on success, 1 if no phases were changed or some could not
4972 4972 be changed.
4973 4973 """
4974 4974 # search for a unique phase argument
4975 4975 targetphase = None
4976 4976 for idx, name in enumerate(phases.phasenames):
4977 4977 if opts[name]:
4978 4978 if targetphase is not None:
4979 4979 raise util.Abort(_('only one phase can be specified'))
4980 4980 targetphase = idx
4981 4981
4982 4982 # look for specified revision
4983 4983 revs = list(revs)
4984 4984 revs.extend(opts['rev'])
4985 4985 if not revs:
4986 4986 raise util.Abort(_('no revisions specified'))
4987 4987
4988 4988 revs = scmutil.revrange(repo, revs)
4989 4989
4990 4990 lock = None
4991 4991 ret = 0
4992 4992 if targetphase is None:
4993 4993 # display
4994 4994 for r in revs:
4995 4995 ctx = repo[r]
4996 4996 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4997 4997 else:
4998 4998 tr = None
4999 4999 lock = repo.lock()
5000 5000 try:
5001 5001 tr = repo.transaction("phase")
5002 5002 # set phase
5003 5003 if not revs:
5004 5004 raise util.Abort(_('empty revision set'))
5005 5005 nodes = [repo[r].node() for r in revs]
5006 5006 # moving revision from public to draft may hide them
5007 5007 # We have to check result on an unfiltered repository
5008 5008 unfi = repo.unfiltered()
5009 5009 getphase = unfi._phasecache.phase
5010 5010 olddata = [getphase(unfi, r) for r in unfi]
5011 5011 phases.advanceboundary(repo, tr, targetphase, nodes)
5012 5012 if opts['force']:
5013 5013 phases.retractboundary(repo, tr, targetphase, nodes)
5014 5014 tr.close()
5015 5015 finally:
5016 5016 if tr is not None:
5017 5017 tr.release()
5018 5018 lock.release()
5019 5019 getphase = unfi._phasecache.phase
5020 5020 newdata = [getphase(unfi, r) for r in unfi]
5021 5021 changes = sum(newdata[r] != olddata[r] for r in unfi)
5022 5022 cl = unfi.changelog
5023 5023 rejected = [n for n in nodes
5024 5024 if newdata[cl.rev(n)] < targetphase]
5025 5025 if rejected:
5026 5026 ui.warn(_('cannot move %i changesets to a higher '
5027 5027 'phase, use --force\n') % len(rejected))
5028 5028 ret = 1
5029 5029 if changes:
5030 5030 msg = _('phase changed for %i changesets\n') % changes
5031 5031 if ret:
5032 5032 ui.status(msg)
5033 5033 else:
5034 5034 ui.note(msg)
5035 5035 else:
5036 5036 ui.warn(_('no phases changed\n'))
5037 5037 ret = 1
5038 5038 return ret
5039 5039
5040 5040 def postincoming(ui, repo, modheads, optupdate, checkout):
5041 5041 if modheads == 0:
5042 5042 return
5043 5043 if optupdate:
5044 5044 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5045 5045 try:
5046 5046 ret = hg.update(repo, checkout)
5047 5047 except util.Abort, inst:
5048 5048 ui.warn(_("not updating: %s\n") % str(inst))
5049 5049 if inst.hint:
5050 5050 ui.warn(_("(%s)\n") % inst.hint)
5051 5051 return 0
5052 5052 if not ret and not checkout:
5053 5053 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5054 5054 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5055 5055 return ret
5056 5056 if modheads > 1:
5057 5057 currentbranchheads = len(repo.branchheads())
5058 5058 if currentbranchheads == modheads:
5059 5059 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5060 5060 elif currentbranchheads > 1:
5061 5061 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5062 5062 "merge)\n"))
5063 5063 else:
5064 5064 ui.status(_("(run 'hg heads' to see heads)\n"))
5065 5065 else:
5066 5066 ui.status(_("(run 'hg update' to get a working copy)\n"))
5067 5067
5068 5068 @command('^pull',
5069 5069 [('u', 'update', None,
5070 5070 _('update to new branch head if changesets were pulled')),
5071 5071 ('f', 'force', None, _('run even when remote repository is unrelated')),
5072 5072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5073 5073 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5074 5074 ('b', 'branch', [], _('a specific branch you would like to pull'),
5075 5075 _('BRANCH')),
5076 5076 ] + remoteopts,
5077 5077 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5078 5078 def pull(ui, repo, source="default", **opts):
5079 5079 """pull changes from the specified source
5080 5080
5081 5081 Pull changes from a remote repository to a local one.
5082 5082
5083 5083 This finds all changes from the repository at the specified path
5084 5084 or URL and adds them to a local repository (the current one unless
5085 5085 -R is specified). By default, this does not update the copy of the
5086 5086 project in the working directory.
5087 5087
5088 5088 Use :hg:`incoming` if you want to see what would have been added
5089 5089 by a pull at the time you issued this command. If you then decide
5090 5090 to add those changes to the repository, you should use :hg:`pull
5091 5091 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5092 5092
5093 5093 If SOURCE is omitted, the 'default' path will be used.
5094 5094 See :hg:`help urls` for more information.
5095 5095
5096 5096 Returns 0 on success, 1 if an update had unresolved files.
5097 5097 """
5098 5098 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5099 5099 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5100 5100 other = hg.peer(repo, opts, source)
5101 5101 try:
5102 5102 revs, checkout = hg.addbranchrevs(repo, other, branches,
5103 5103 opts.get('rev'))
5104 5104
5105 5105 remotebookmarks = other.listkeys('bookmarks')
5106 5106
5107 5107 if opts.get('bookmark'):
5108 5108 if not revs:
5109 5109 revs = []
5110 5110 for b in opts['bookmark']:
5111 5111 if b not in remotebookmarks:
5112 5112 raise util.Abort(_('remote bookmark %s not found!') % b)
5113 5113 revs.append(remotebookmarks[b])
5114 5114
5115 5115 if revs:
5116 5116 try:
5117 5117 revs = [other.lookup(rev) for rev in revs]
5118 5118 except error.CapabilityError:
5119 5119 err = _("other repository doesn't support revision lookup, "
5120 5120 "so a rev cannot be specified.")
5121 5121 raise util.Abort(err)
5122 5122
5123 5123 modheads = exchange.pull(repo, other, heads=revs,
5124 5124 force=opts.get('force'),
5125 5125 bookmarks=opts.get('bookmark', ())).cgresult
5126 5126 if checkout:
5127 5127 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5128 5128 repo._subtoppath = source
5129 5129 try:
5130 5130 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5131 5131
5132 5132 finally:
5133 5133 del repo._subtoppath
5134 5134
5135 5135 finally:
5136 5136 other.close()
5137 5137 return ret
5138 5138
5139 5139 @command('^push',
5140 5140 [('f', 'force', None, _('force push')),
5141 5141 ('r', 'rev', [],
5142 5142 _('a changeset intended to be included in the destination'),
5143 5143 _('REV')),
5144 5144 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5145 5145 ('b', 'branch', [],
5146 5146 _('a specific branch you would like to push'), _('BRANCH')),
5147 5147 ('', 'new-branch', False, _('allow pushing a new branch')),
5148 5148 ] + remoteopts,
5149 5149 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5150 5150 def push(ui, repo, dest=None, **opts):
5151 5151 """push changes to the specified destination
5152 5152
5153 5153 Push changesets from the local repository to the specified
5154 5154 destination.
5155 5155
5156 5156 This operation is symmetrical to pull: it is identical to a pull
5157 5157 in the destination repository from the current one.
5158 5158
5159 5159 By default, push will not allow creation of new heads at the
5160 5160 destination, since multiple heads would make it unclear which head
5161 5161 to use. In this situation, it is recommended to pull and merge
5162 5162 before pushing.
5163 5163
5164 5164 Use --new-branch if you want to allow push to create a new named
5165 5165 branch that is not present at the destination. This allows you to
5166 5166 only create a new branch without forcing other changes.
5167 5167
5168 5168 .. note::
5169 5169
5170 5170 Extra care should be taken with the -f/--force option,
5171 5171 which will push all new heads on all branches, an action which will
5172 5172 almost always cause confusion for collaborators.
5173 5173
5174 5174 If -r/--rev is used, the specified revision and all its ancestors
5175 5175 will be pushed to the remote repository.
5176 5176
5177 5177 If -B/--bookmark is used, the specified bookmarked revision, its
5178 5178 ancestors, and the bookmark will be pushed to the remote
5179 5179 repository.
5180 5180
5181 5181 Please see :hg:`help urls` for important details about ``ssh://``
5182 5182 URLs. If DESTINATION is omitted, a default path will be used.
5183 5183
5184 5184 Returns 0 if push was successful, 1 if nothing to push.
5185 5185 """
5186 5186
5187 5187 if opts.get('bookmark'):
5188 5188 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5189 5189 for b in opts['bookmark']:
5190 5190 # translate -B options to -r so changesets get pushed
5191 5191 if b in repo._bookmarks:
5192 5192 opts.setdefault('rev', []).append(b)
5193 5193 else:
5194 5194 # if we try to push a deleted bookmark, translate it to null
5195 5195 # this lets simultaneous -r, -b options continue working
5196 5196 opts.setdefault('rev', []).append("null")
5197 5197
5198 5198 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5199 5199 dest, branches = hg.parseurl(dest, opts.get('branch'))
5200 5200 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5201 5201 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5202 5202 try:
5203 5203 other = hg.peer(repo, opts, dest)
5204 5204 except error.RepoError:
5205 5205 if dest == "default-push":
5206 5206 raise util.Abort(_("default repository not configured!"),
5207 5207 hint=_('see the "path" section in "hg help config"'))
5208 5208 else:
5209 5209 raise
5210 5210
5211 5211 if revs:
5212 5212 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5213 5213 if not revs:
5214 5214 raise util.Abort(_("specified revisions evaluate to an empty set"),
5215 5215 hint=_("use different revision arguments"))
5216 5216
5217 5217 repo._subtoppath = dest
5218 5218 try:
5219 5219 # push subrepos depth-first for coherent ordering
5220 5220 c = repo['']
5221 5221 subs = c.substate # only repos that are committed
5222 5222 for s in sorted(subs):
5223 5223 result = c.sub(s).push(opts)
5224 5224 if result == 0:
5225 5225 return not result
5226 5226 finally:
5227 5227 del repo._subtoppath
5228 5228 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5229 5229 newbranch=opts.get('new_branch'),
5230 5230 bookmarks=opts.get('bookmark', ()))
5231 5231
5232 5232 result = not pushop.cgresult
5233 5233
5234 5234 if pushop.bkresult is not None:
5235 5235 if pushop.bkresult == 2:
5236 5236 result = 2
5237 5237 elif not result and pushop.bkresult:
5238 5238 result = 2
5239 5239
5240 5240 return result
5241 5241
5242 5242 @command('recover', [])
5243 5243 def recover(ui, repo):
5244 5244 """roll back an interrupted transaction
5245 5245
5246 5246 Recover from an interrupted commit or pull.
5247 5247
5248 5248 This command tries to fix the repository status after an
5249 5249 interrupted operation. It should only be necessary when Mercurial
5250 5250 suggests it.
5251 5251
5252 5252 Returns 0 if successful, 1 if nothing to recover or verify fails.
5253 5253 """
5254 5254 if repo.recover():
5255 5255 return hg.verify(repo)
5256 5256 return 1
5257 5257
5258 5258 @command('^remove|rm',
5259 5259 [('A', 'after', None, _('record delete for missing files')),
5260 5260 ('f', 'force', None,
5261 5261 _('remove (and delete) file even if added or modified')),
5262 5262 ] + subrepoopts + walkopts,
5263 5263 _('[OPTION]... FILE...'),
5264 5264 inferrepo=True)
5265 5265 def remove(ui, repo, *pats, **opts):
5266 5266 """remove the specified files on the next commit
5267 5267
5268 5268 Schedule the indicated files for removal from the current branch.
5269 5269
5270 5270 This command schedules the files to be removed at the next commit.
5271 5271 To undo a remove before that, see :hg:`revert`. To undo added
5272 5272 files, see :hg:`forget`.
5273 5273
5274 5274 .. container:: verbose
5275 5275
5276 5276 -A/--after can be used to remove only files that have already
5277 5277 been deleted, -f/--force can be used to force deletion, and -Af
5278 5278 can be used to remove files from the next revision without
5279 5279 deleting them from the working directory.
5280 5280
5281 5281 The following table details the behavior of remove for different
5282 5282 file states (columns) and option combinations (rows). The file
5283 5283 states are Added [A], Clean [C], Modified [M] and Missing [!]
5284 5284 (as reported by :hg:`status`). The actions are Warn, Remove
5285 5285 (from branch) and Delete (from disk):
5286 5286
5287 5287 ========= == == == ==
5288 5288 opt/state A C M !
5289 5289 ========= == == == ==
5290 5290 none W RD W R
5291 5291 -f R RD RD R
5292 5292 -A W W W R
5293 5293 -Af R R R R
5294 5294 ========= == == == ==
5295 5295
5296 5296 Note that remove never deletes files in Added [A] state from the
5297 5297 working directory, not even if option --force is specified.
5298 5298
5299 5299 Returns 0 on success, 1 if any warnings encountered.
5300 5300 """
5301 5301
5302 5302 after, force = opts.get('after'), opts.get('force')
5303 5303 if not pats and not after:
5304 5304 raise util.Abort(_('no files specified'))
5305 5305
5306 5306 m = scmutil.match(repo[None], pats, opts)
5307 5307 subrepos = opts.get('subrepos')
5308 5308 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5309 5309
5310 5310 @command('rename|move|mv',
5311 5311 [('A', 'after', None, _('record a rename that has already occurred')),
5312 5312 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5313 5313 ] + walkopts + dryrunopts,
5314 5314 _('[OPTION]... SOURCE... DEST'))
5315 5315 def rename(ui, repo, *pats, **opts):
5316 5316 """rename files; equivalent of copy + remove
5317 5317
5318 5318 Mark dest as copies of sources; mark sources for deletion. If dest
5319 5319 is a directory, copies are put in that directory. If dest is a
5320 5320 file, there can only be one source.
5321 5321
5322 5322 By default, this command copies the contents of files as they
5323 5323 exist in the working directory. If invoked with -A/--after, the
5324 5324 operation is recorded, but no copying is performed.
5325 5325
5326 5326 This command takes effect at the next commit. To undo a rename
5327 5327 before that, see :hg:`revert`.
5328 5328
5329 5329 Returns 0 on success, 1 if errors are encountered.
5330 5330 """
5331 5331 wlock = repo.wlock(False)
5332 5332 try:
5333 5333 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5334 5334 finally:
5335 5335 wlock.release()
5336 5336
5337 5337 @command('resolve',
5338 5338 [('a', 'all', None, _('select all unresolved files')),
5339 5339 ('l', 'list', None, _('list state of files needing merge')),
5340 5340 ('m', 'mark', None, _('mark files as resolved')),
5341 5341 ('u', 'unmark', None, _('mark files as unresolved')),
5342 5342 ('n', 'no-status', None, _('hide status prefix'))]
5343 5343 + mergetoolopts + walkopts + formatteropts,
5344 5344 _('[OPTION]... [FILE]...'),
5345 5345 inferrepo=True)
5346 5346 def resolve(ui, repo, *pats, **opts):
5347 5347 """redo merges or set/view the merge status of files
5348 5348
5349 5349 Merges with unresolved conflicts are often the result of
5350 5350 non-interactive merging using the ``internal:merge`` configuration
5351 5351 setting, or a command-line merge tool like ``diff3``. The resolve
5352 5352 command is used to manage the files involved in a merge, after
5353 5353 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5354 5354 working directory must have two parents). See :hg:`help
5355 5355 merge-tools` for information on configuring merge tools.
5356 5356
5357 5357 The resolve command can be used in the following ways:
5358 5358
5359 5359 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5360 5360 files, discarding any previous merge attempts. Re-merging is not
5361 5361 performed for files already marked as resolved. Use ``--all/-a``
5362 5362 to select all unresolved files. ``--tool`` can be used to specify
5363 5363 the merge tool used for the given files. It overrides the HGMERGE
5364 5364 environment variable and your configuration files. Previous file
5365 5365 contents are saved with a ``.orig`` suffix.
5366 5366
5367 5367 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5368 5368 (e.g. after having manually fixed-up the files). The default is
5369 5369 to mark all unresolved files.
5370 5370
5371 5371 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5372 5372 default is to mark all resolved files.
5373 5373
5374 5374 - :hg:`resolve -l`: list files which had or still have conflicts.
5375 5375 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5376 5376
5377 5377 Note that Mercurial will not let you commit files with unresolved
5378 5378 merge conflicts. You must use :hg:`resolve -m ...` before you can
5379 5379 commit after a conflicting merge.
5380 5380
5381 5381 Returns 0 on success, 1 if any files fail a resolve attempt.
5382 5382 """
5383 5383
5384 5384 all, mark, unmark, show, nostatus = \
5385 5385 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5386 5386
5387 5387 if (show and (mark or unmark)) or (mark and unmark):
5388 5388 raise util.Abort(_("too many options specified"))
5389 5389 if pats and all:
5390 5390 raise util.Abort(_("can't specify --all and patterns"))
5391 5391 if not (all or pats or show or mark or unmark):
5392 5392 raise util.Abort(_('no files or directories specified'),
5393 5393 hint=('use --all to remerge all files'))
5394 5394
5395 5395 if show:
5396 5396 fm = ui.formatter('resolve', opts)
5397 5397 ms = mergemod.mergestate(repo)
5398 5398 m = scmutil.match(repo[None], pats, opts)
5399 5399 for f in ms:
5400 5400 if not m(f):
5401 5401 continue
5402 5402 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5403 5403 fm.startitem()
5404 5404 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5405 5405 fm.write('path', '%s\n', f, label=l)
5406 5406 fm.end()
5407 5407 return 0
5408 5408
5409 5409 wlock = repo.wlock()
5410 5410 try:
5411 5411 ms = mergemod.mergestate(repo)
5412 5412
5413 5413 if not (ms.active() or repo.dirstate.p2() != nullid):
5414 5414 raise util.Abort(
5415 5415 _('resolve command not applicable when not merging'))
5416 5416
5417 5417 m = scmutil.match(repo[None], pats, opts)
5418 5418 ret = 0
5419 5419 didwork = False
5420 5420
5421 5421 for f in ms:
5422 5422 if not m(f):
5423 5423 continue
5424 5424
5425 5425 didwork = True
5426 5426
5427 5427 if mark:
5428 5428 ms.mark(f, "r")
5429 5429 elif unmark:
5430 5430 ms.mark(f, "u")
5431 5431 else:
5432 5432 wctx = repo[None]
5433 5433
5434 5434 # backup pre-resolve (merge uses .orig for its own purposes)
5435 5435 a = repo.wjoin(f)
5436 5436 util.copyfile(a, a + ".resolve")
5437 5437
5438 5438 try:
5439 5439 # resolve file
5440 5440 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5441 5441 'resolve')
5442 5442 if ms.resolve(f, wctx):
5443 5443 ret = 1
5444 5444 finally:
5445 5445 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5446 5446 ms.commit()
5447 5447
5448 5448 # replace filemerge's .orig file with our resolve file
5449 5449 util.rename(a + ".resolve", a + ".orig")
5450 5450
5451 5451 ms.commit()
5452 5452
5453 5453 if not didwork and pats:
5454 5454 ui.warn(_("arguments do not match paths that need resolving\n"))
5455 5455
5456 5456 finally:
5457 5457 wlock.release()
5458 5458
5459 5459 # Nudge users into finishing an unfinished operation
5460 5460 if not list(ms.unresolved()):
5461 5461 ui.status(_('(no more unresolved files)\n'))
5462 5462
5463 5463 return ret
5464 5464
5465 5465 @command('revert',
5466 5466 [('a', 'all', None, _('revert all changes when no arguments given')),
5467 5467 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5468 5468 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5469 5469 ('C', 'no-backup', None, _('do not save backup copies of files')),
5470 5470 ('i', 'interactive', None, _('interactively select the changes')),
5471 5471 ] + walkopts + dryrunopts,
5472 5472 _('[OPTION]... [-r REV] [NAME]...'))
5473 5473 def revert(ui, repo, *pats, **opts):
5474 5474 """restore files to their checkout state
5475 5475
5476 5476 .. note::
5477 5477
5478 5478 To check out earlier revisions, you should use :hg:`update REV`.
5479 5479 To cancel an uncommitted merge (and lose your changes),
5480 5480 use :hg:`update --clean .`.
5481 5481
5482 5482 With no revision specified, revert the specified files or directories
5483 5483 to the contents they had in the parent of the working directory.
5484 5484 This restores the contents of files to an unmodified
5485 5485 state and unschedules adds, removes, copies, and renames. If the
5486 5486 working directory has two parents, you must explicitly specify a
5487 5487 revision.
5488 5488
5489 5489 Using the -r/--rev or -d/--date options, revert the given files or
5490 5490 directories to their states as of a specific revision. Because
5491 5491 revert does not change the working directory parents, this will
5492 5492 cause these files to appear modified. This can be helpful to "back
5493 5493 out" some or all of an earlier change. See :hg:`backout` for a
5494 5494 related method.
5495 5495
5496 5496 Modified files are saved with a .orig suffix before reverting.
5497 5497 To disable these backups, use --no-backup.
5498 5498
5499 5499 See :hg:`help dates` for a list of formats valid for -d/--date.
5500 5500
5501 5501 Returns 0 on success.
5502 5502 """
5503 5503
5504 5504 if opts.get("date"):
5505 5505 if opts.get("rev"):
5506 5506 raise util.Abort(_("you can't specify a revision and a date"))
5507 5507 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5508 5508
5509 5509 parent, p2 = repo.dirstate.parents()
5510 5510 if not opts.get('rev') and p2 != nullid:
5511 5511 # revert after merge is a trap for new users (issue2915)
5512 5512 raise util.Abort(_('uncommitted merge with no revision specified'),
5513 5513 hint=_('use "hg update" or see "hg help revert"'))
5514 5514
5515 5515 ctx = scmutil.revsingle(repo, opts.get('rev'))
5516 5516
5517 5517 if not pats and not opts.get('all'):
5518 5518 msg = _("no files or directories specified")
5519 5519 if p2 != nullid:
5520 5520 hint = _("uncommitted merge, use --all to discard all changes,"
5521 5521 " or 'hg update -C .' to abort the merge")
5522 5522 raise util.Abort(msg, hint=hint)
5523 5523 dirty = util.any(repo.status())
5524 5524 node = ctx.node()
5525 5525 if node != parent:
5526 5526 if dirty:
5527 5527 hint = _("uncommitted changes, use --all to discard all"
5528 5528 " changes, or 'hg update %s' to update") % ctx.rev()
5529 5529 else:
5530 5530 hint = _("use --all to revert all files,"
5531 5531 " or 'hg update %s' to update") % ctx.rev()
5532 5532 elif dirty:
5533 5533 hint = _("uncommitted changes, use --all to discard all changes")
5534 5534 else:
5535 5535 hint = _("use --all to revert all files")
5536 5536 raise util.Abort(msg, hint=hint)
5537 5537
5538 5538 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5539 5539
5540 5540 @command('rollback', dryrunopts +
5541 5541 [('f', 'force', False, _('ignore safety measures'))])
5542 5542 def rollback(ui, repo, **opts):
5543 5543 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5544 5544
5545 5545 Please use :hg:`commit --amend` instead of rollback to correct
5546 5546 mistakes in the last commit.
5547 5547
5548 5548 This command should be used with care. There is only one level of
5549 5549 rollback, and there is no way to undo a rollback. It will also
5550 5550 restore the dirstate at the time of the last transaction, losing
5551 5551 any dirstate changes since that time. This command does not alter
5552 5552 the working directory.
5553 5553
5554 5554 Transactions are used to encapsulate the effects of all commands
5555 5555 that create new changesets or propagate existing changesets into a
5556 5556 repository.
5557 5557
5558 5558 .. container:: verbose
5559 5559
5560 5560 For example, the following commands are transactional, and their
5561 5561 effects can be rolled back:
5562 5562
5563 5563 - commit
5564 5564 - import
5565 5565 - pull
5566 5566 - push (with this repository as the destination)
5567 5567 - unbundle
5568 5568
5569 5569 To avoid permanent data loss, rollback will refuse to rollback a
5570 5570 commit transaction if it isn't checked out. Use --force to
5571 5571 override this protection.
5572 5572
5573 5573 This command is not intended for use on public repositories. Once
5574 5574 changes are visible for pull by other users, rolling a transaction
5575 5575 back locally is ineffective (someone else may already have pulled
5576 5576 the changes). Furthermore, a race is possible with readers of the
5577 5577 repository; for example an in-progress pull from the repository
5578 5578 may fail if a rollback is performed.
5579 5579
5580 5580 Returns 0 on success, 1 if no rollback data is available.
5581 5581 """
5582 5582 return repo.rollback(dryrun=opts.get('dry_run'),
5583 5583 force=opts.get('force'))
5584 5584
5585 5585 @command('root', [])
5586 5586 def root(ui, repo):
5587 5587 """print the root (top) of the current working directory
5588 5588
5589 5589 Print the root directory of the current repository.
5590 5590
5591 5591 Returns 0 on success.
5592 5592 """
5593 5593 ui.write(repo.root + "\n")
5594 5594
5595 5595 @command('^serve',
5596 5596 [('A', 'accesslog', '', _('name of access log file to write to'),
5597 5597 _('FILE')),
5598 5598 ('d', 'daemon', None, _('run server in background')),
5599 5599 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5600 5600 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5601 5601 # use string type, then we can check if something was passed
5602 5602 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5603 5603 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5604 5604 _('ADDR')),
5605 5605 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5606 5606 _('PREFIX')),
5607 5607 ('n', 'name', '',
5608 5608 _('name to show in web pages (default: working directory)'), _('NAME')),
5609 5609 ('', 'web-conf', '',
5610 5610 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5611 5611 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5612 5612 _('FILE')),
5613 5613 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5614 5614 ('', 'stdio', None, _('for remote clients')),
5615 5615 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5616 5616 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5617 5617 ('', 'style', '', _('template style to use'), _('STYLE')),
5618 5618 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5619 5619 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5620 5620 _('[OPTION]...'),
5621 5621 optionalrepo=True)
5622 5622 def serve(ui, repo, **opts):
5623 5623 """start stand-alone webserver
5624 5624
5625 5625 Start a local HTTP repository browser and pull server. You can use
5626 5626 this for ad-hoc sharing and browsing of repositories. It is
5627 5627 recommended to use a real web server to serve a repository for
5628 5628 longer periods of time.
5629 5629
5630 5630 Please note that the server does not implement access control.
5631 5631 This means that, by default, anybody can read from the server and
5632 5632 nobody can write to it by default. Set the ``web.allow_push``
5633 5633 option to ``*`` to allow everybody to push to the server. You
5634 5634 should use a real web server if you need to authenticate users.
5635 5635
5636 5636 By default, the server logs accesses to stdout and errors to
5637 5637 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5638 5638 files.
5639 5639
5640 5640 To have the server choose a free port number to listen on, specify
5641 5641 a port number of 0; in this case, the server will print the port
5642 5642 number it uses.
5643 5643
5644 5644 Returns 0 on success.
5645 5645 """
5646 5646
5647 5647 if opts["stdio"] and opts["cmdserver"]:
5648 5648 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5649 5649
5650 5650 if opts["stdio"]:
5651 5651 if repo is None:
5652 5652 raise error.RepoError(_("there is no Mercurial repository here"
5653 5653 " (.hg not found)"))
5654 5654 s = sshserver.sshserver(ui, repo)
5655 5655 s.serve_forever()
5656 5656
5657 5657 if opts["cmdserver"]:
5658 5658 service = commandserver.createservice(ui, repo, opts)
5659 5659 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5660 5660
5661 5661 # this way we can check if something was given in the command-line
5662 5662 if opts.get('port'):
5663 5663 opts['port'] = util.getport(opts.get('port'))
5664 5664
5665 5665 if repo:
5666 5666 baseui = repo.baseui
5667 5667 else:
5668 5668 baseui = ui
5669 5669 optlist = ("name templates style address port prefix ipv6"
5670 5670 " accesslog errorlog certificate encoding")
5671 5671 for o in optlist.split():
5672 5672 val = opts.get(o, '')
5673 5673 if val in (None, ''): # should check against default options instead
5674 5674 continue
5675 5675 baseui.setconfig("web", o, val, 'serve')
5676 5676 if repo and repo.ui != baseui:
5677 5677 repo.ui.setconfig("web", o, val, 'serve')
5678 5678
5679 5679 o = opts.get('web_conf') or opts.get('webdir_conf')
5680 5680 if not o:
5681 5681 if not repo:
5682 5682 raise error.RepoError(_("there is no Mercurial repository"
5683 5683 " here (.hg not found)"))
5684 5684 o = repo
5685 5685
5686 5686 app = hgweb.hgweb(o, baseui=baseui)
5687 5687 service = httpservice(ui, app, opts)
5688 5688 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5689 5689
5690 5690 class httpservice(object):
5691 5691 def __init__(self, ui, app, opts):
5692 5692 self.ui = ui
5693 5693 self.app = app
5694 5694 self.opts = opts
5695 5695
5696 5696 def init(self):
5697 5697 util.setsignalhandler()
5698 5698 self.httpd = hgweb_server.create_server(self.ui, self.app)
5699 5699
5700 5700 if self.opts['port'] and not self.ui.verbose:
5701 5701 return
5702 5702
5703 5703 if self.httpd.prefix:
5704 5704 prefix = self.httpd.prefix.strip('/') + '/'
5705 5705 else:
5706 5706 prefix = ''
5707 5707
5708 5708 port = ':%d' % self.httpd.port
5709 5709 if port == ':80':
5710 5710 port = ''
5711 5711
5712 5712 bindaddr = self.httpd.addr
5713 5713 if bindaddr == '0.0.0.0':
5714 5714 bindaddr = '*'
5715 5715 elif ':' in bindaddr: # IPv6
5716 5716 bindaddr = '[%s]' % bindaddr
5717 5717
5718 5718 fqaddr = self.httpd.fqaddr
5719 5719 if ':' in fqaddr:
5720 5720 fqaddr = '[%s]' % fqaddr
5721 5721 if self.opts['port']:
5722 5722 write = self.ui.status
5723 5723 else:
5724 5724 write = self.ui.write
5725 5725 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5726 5726 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5727 5727 self.ui.flush() # avoid buffering of status message
5728 5728
5729 5729 def run(self):
5730 5730 self.httpd.serve_forever()
5731 5731
5732 5732
5733 5733 @command('^status|st',
5734 5734 [('A', 'all', None, _('show status of all files')),
5735 5735 ('m', 'modified', None, _('show only modified files')),
5736 5736 ('a', 'added', None, _('show only added files')),
5737 5737 ('r', 'removed', None, _('show only removed files')),
5738 5738 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5739 5739 ('c', 'clean', None, _('show only files without changes')),
5740 5740 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5741 5741 ('i', 'ignored', None, _('show only ignored files')),
5742 5742 ('n', 'no-status', None, _('hide status prefix')),
5743 5743 ('C', 'copies', None, _('show source of copied files')),
5744 5744 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5745 5745 ('', 'rev', [], _('show difference from revision'), _('REV')),
5746 5746 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5747 5747 ] + walkopts + subrepoopts + formatteropts,
5748 5748 _('[OPTION]... [FILE]...'),
5749 5749 inferrepo=True)
5750 5750 def status(ui, repo, *pats, **opts):
5751 5751 """show changed files in the working directory
5752 5752
5753 5753 Show status of files in the repository. If names are given, only
5754 5754 files that match are shown. Files that are clean or ignored or
5755 5755 the source of a copy/move operation, are not listed unless
5756 5756 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5757 5757 Unless options described with "show only ..." are given, the
5758 5758 options -mardu are used.
5759 5759
5760 5760 Option -q/--quiet hides untracked (unknown and ignored) files
5761 5761 unless explicitly requested with -u/--unknown or -i/--ignored.
5762 5762
5763 5763 .. note::
5764 5764
5765 5765 status may appear to disagree with diff if permissions have
5766 5766 changed or a merge has occurred. The standard diff format does
5767 5767 not report permission changes and diff only reports changes
5768 5768 relative to one merge parent.
5769 5769
5770 5770 If one revision is given, it is used as the base revision.
5771 5771 If two revisions are given, the differences between them are
5772 5772 shown. The --change option can also be used as a shortcut to list
5773 5773 the changed files of a revision from its first parent.
5774 5774
5775 5775 The codes used to show the status of files are::
5776 5776
5777 5777 M = modified
5778 5778 A = added
5779 5779 R = removed
5780 5780 C = clean
5781 5781 ! = missing (deleted by non-hg command, but still tracked)
5782 5782 ? = not tracked
5783 5783 I = ignored
5784 5784 = origin of the previous file (with --copies)
5785 5785
5786 5786 .. container:: verbose
5787 5787
5788 5788 Examples:
5789 5789
5790 5790 - show changes in the working directory relative to a
5791 5791 changeset::
5792 5792
5793 5793 hg status --rev 9353
5794 5794
5795 5795 - show changes in the working directory relative to the
5796 5796 current directory (see :hg:`help patterns` for more information)::
5797 5797
5798 5798 hg status re:
5799 5799
5800 5800 - show all changes including copies in an existing changeset::
5801 5801
5802 5802 hg status --copies --change 9353
5803 5803
5804 5804 - get a NUL separated list of added files, suitable for xargs::
5805 5805
5806 5806 hg status -an0
5807 5807
5808 5808 Returns 0 on success.
5809 5809 """
5810 5810
5811 5811 revs = opts.get('rev')
5812 5812 change = opts.get('change')
5813 5813
5814 5814 if revs and change:
5815 5815 msg = _('cannot specify --rev and --change at the same time')
5816 5816 raise util.Abort(msg)
5817 5817 elif change:
5818 5818 node2 = scmutil.revsingle(repo, change, None).node()
5819 5819 node1 = repo[node2].p1().node()
5820 5820 else:
5821 5821 node1, node2 = scmutil.revpair(repo, revs)
5822 5822
5823 5823 if pats:
5824 5824 cwd = repo.getcwd()
5825 5825 else:
5826 5826 cwd = ''
5827 5827
5828 5828 if opts.get('print0'):
5829 5829 end = '\0'
5830 5830 else:
5831 5831 end = '\n'
5832 5832 copy = {}
5833 5833 states = 'modified added removed deleted unknown ignored clean'.split()
5834 5834 show = [k for k in states if opts.get(k)]
5835 5835 if opts.get('all'):
5836 5836 show += ui.quiet and (states[:4] + ['clean']) or states
5837 5837 if not show:
5838 5838 if ui.quiet:
5839 5839 show = states[:4]
5840 5840 else:
5841 5841 show = states[:5]
5842 5842
5843 5843 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5844 5844 'ignored' in show, 'clean' in show, 'unknown' in show,
5845 5845 opts.get('subrepos'))
5846 5846 changestates = zip(states, 'MAR!?IC', stat)
5847 5847
5848 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5848 if (opts.get('all') or opts.get('copies')
5849 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5849 5850 copy = copies.pathcopies(repo[node1], repo[node2])
5850 5851
5851 5852 fm = ui.formatter('status', opts)
5852 5853 fmt = '%s' + end
5853 5854 showchar = not opts.get('no_status')
5854 5855
5855 5856 for state, char, files in changestates:
5856 5857 if state in show:
5857 5858 label = 'status.' + state
5858 5859 for f in files:
5859 5860 fm.startitem()
5860 5861 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5861 5862 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5862 5863 if f in copy:
5863 5864 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5864 5865 label='status.copied')
5865 5866 fm.end()
5866 5867
5867 5868 @command('^summary|sum',
5868 5869 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5869 5870 def summary(ui, repo, **opts):
5870 5871 """summarize working directory state
5871 5872
5872 5873 This generates a brief summary of the working directory state,
5873 5874 including parents, branch, commit status, and available updates.
5874 5875
5875 5876 With the --remote option, this will check the default paths for
5876 5877 incoming and outgoing changes. This can be time-consuming.
5877 5878
5878 5879 Returns 0 on success.
5879 5880 """
5880 5881
5881 5882 ctx = repo[None]
5882 5883 parents = ctx.parents()
5883 5884 pnode = parents[0].node()
5884 5885 marks = []
5885 5886
5886 5887 for p in parents:
5887 5888 # label with log.changeset (instead of log.parent) since this
5888 5889 # shows a working directory parent *changeset*:
5889 5890 # i18n: column positioning for "hg summary"
5890 5891 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5891 5892 label='log.changeset changeset.%s' % p.phasestr())
5892 5893 ui.write(' '.join(p.tags()), label='log.tag')
5893 5894 if p.bookmarks():
5894 5895 marks.extend(p.bookmarks())
5895 5896 if p.rev() == -1:
5896 5897 if not len(repo):
5897 5898 ui.write(_(' (empty repository)'))
5898 5899 else:
5899 5900 ui.write(_(' (no revision checked out)'))
5900 5901 ui.write('\n')
5901 5902 if p.description():
5902 5903 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5903 5904 label='log.summary')
5904 5905
5905 5906 branch = ctx.branch()
5906 5907 bheads = repo.branchheads(branch)
5907 5908 # i18n: column positioning for "hg summary"
5908 5909 m = _('branch: %s\n') % branch
5909 5910 if branch != 'default':
5910 5911 ui.write(m, label='log.branch')
5911 5912 else:
5912 5913 ui.status(m, label='log.branch')
5913 5914
5914 5915 if marks:
5915 5916 current = repo._bookmarkcurrent
5916 5917 # i18n: column positioning for "hg summary"
5917 5918 ui.write(_('bookmarks:'), label='log.bookmark')
5918 5919 if current is not None:
5919 5920 if current in marks:
5920 5921 ui.write(' *' + current, label='bookmarks.current')
5921 5922 marks.remove(current)
5922 5923 else:
5923 5924 ui.write(' [%s]' % current, label='bookmarks.current')
5924 5925 for m in marks:
5925 5926 ui.write(' ' + m, label='log.bookmark')
5926 5927 ui.write('\n', label='log.bookmark')
5927 5928
5928 5929 status = repo.status(unknown=True)
5929 5930
5930 5931 c = repo.dirstate.copies()
5931 5932 copied, renamed = [], []
5932 5933 for d, s in c.iteritems():
5933 5934 if s in status.removed:
5934 5935 status.removed.remove(s)
5935 5936 renamed.append(d)
5936 5937 else:
5937 5938 copied.append(d)
5938 5939 if d in status.added:
5939 5940 status.added.remove(d)
5940 5941
5941 5942 ms = mergemod.mergestate(repo)
5942 5943 unresolved = [f for f in ms if ms[f] == 'u']
5943 5944
5944 5945 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5945 5946
5946 5947 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5947 5948 (ui.label(_('%d added'), 'status.added'), status.added),
5948 5949 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5949 5950 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5950 5951 (ui.label(_('%d copied'), 'status.copied'), copied),
5951 5952 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5952 5953 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5953 5954 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5954 5955 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5955 5956 t = []
5956 5957 for l, s in labels:
5957 5958 if s:
5958 5959 t.append(l % len(s))
5959 5960
5960 5961 t = ', '.join(t)
5961 5962 cleanworkdir = False
5962 5963
5963 5964 if repo.vfs.exists('updatestate'):
5964 5965 t += _(' (interrupted update)')
5965 5966 elif len(parents) > 1:
5966 5967 t += _(' (merge)')
5967 5968 elif branch != parents[0].branch():
5968 5969 t += _(' (new branch)')
5969 5970 elif (parents[0].closesbranch() and
5970 5971 pnode in repo.branchheads(branch, closed=True)):
5971 5972 t += _(' (head closed)')
5972 5973 elif not (status.modified or status.added or status.removed or renamed or
5973 5974 copied or subs):
5974 5975 t += _(' (clean)')
5975 5976 cleanworkdir = True
5976 5977 elif pnode not in bheads:
5977 5978 t += _(' (new branch head)')
5978 5979
5979 5980 if cleanworkdir:
5980 5981 # i18n: column positioning for "hg summary"
5981 5982 ui.status(_('commit: %s\n') % t.strip())
5982 5983 else:
5983 5984 # i18n: column positioning for "hg summary"
5984 5985 ui.write(_('commit: %s\n') % t.strip())
5985 5986
5986 5987 # all ancestors of branch heads - all ancestors of parent = new csets
5987 5988 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5988 5989 bheads))
5989 5990
5990 5991 if new == 0:
5991 5992 # i18n: column positioning for "hg summary"
5992 5993 ui.status(_('update: (current)\n'))
5993 5994 elif pnode not in bheads:
5994 5995 # i18n: column positioning for "hg summary"
5995 5996 ui.write(_('update: %d new changesets (update)\n') % new)
5996 5997 else:
5997 5998 # i18n: column positioning for "hg summary"
5998 5999 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5999 6000 (new, len(bheads)))
6000 6001
6001 6002 cmdutil.summaryhooks(ui, repo)
6002 6003
6003 6004 if opts.get('remote'):
6004 6005 needsincoming, needsoutgoing = True, True
6005 6006 else:
6006 6007 needsincoming, needsoutgoing = False, False
6007 6008 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6008 6009 if i:
6009 6010 needsincoming = True
6010 6011 if o:
6011 6012 needsoutgoing = True
6012 6013 if not needsincoming and not needsoutgoing:
6013 6014 return
6014 6015
6015 6016 def getincoming():
6016 6017 source, branches = hg.parseurl(ui.expandpath('default'))
6017 6018 sbranch = branches[0]
6018 6019 try:
6019 6020 other = hg.peer(repo, {}, source)
6020 6021 except error.RepoError:
6021 6022 if opts.get('remote'):
6022 6023 raise
6023 6024 return source, sbranch, None, None, None
6024 6025 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6025 6026 if revs:
6026 6027 revs = [other.lookup(rev) for rev in revs]
6027 6028 ui.debug('comparing with %s\n' % util.hidepassword(source))
6028 6029 repo.ui.pushbuffer()
6029 6030 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6030 6031 repo.ui.popbuffer()
6031 6032 return source, sbranch, other, commoninc, commoninc[1]
6032 6033
6033 6034 if needsincoming:
6034 6035 source, sbranch, sother, commoninc, incoming = getincoming()
6035 6036 else:
6036 6037 source = sbranch = sother = commoninc = incoming = None
6037 6038
6038 6039 def getoutgoing():
6039 6040 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6040 6041 dbranch = branches[0]
6041 6042 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6042 6043 if source != dest:
6043 6044 try:
6044 6045 dother = hg.peer(repo, {}, dest)
6045 6046 except error.RepoError:
6046 6047 if opts.get('remote'):
6047 6048 raise
6048 6049 return dest, dbranch, None, None
6049 6050 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6050 6051 elif sother is None:
6051 6052 # there is no explicit destination peer, but source one is invalid
6052 6053 return dest, dbranch, None, None
6053 6054 else:
6054 6055 dother = sother
6055 6056 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6056 6057 common = None
6057 6058 else:
6058 6059 common = commoninc
6059 6060 if revs:
6060 6061 revs = [repo.lookup(rev) for rev in revs]
6061 6062 repo.ui.pushbuffer()
6062 6063 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6063 6064 commoninc=common)
6064 6065 repo.ui.popbuffer()
6065 6066 return dest, dbranch, dother, outgoing
6066 6067
6067 6068 if needsoutgoing:
6068 6069 dest, dbranch, dother, outgoing = getoutgoing()
6069 6070 else:
6070 6071 dest = dbranch = dother = outgoing = None
6071 6072
6072 6073 if opts.get('remote'):
6073 6074 t = []
6074 6075 if incoming:
6075 6076 t.append(_('1 or more incoming'))
6076 6077 o = outgoing.missing
6077 6078 if o:
6078 6079 t.append(_('%d outgoing') % len(o))
6079 6080 other = dother or sother
6080 6081 if 'bookmarks' in other.listkeys('namespaces'):
6081 6082 counts = bookmarks.summary(repo, other)
6082 6083 if counts[0] > 0:
6083 6084 t.append(_('%d incoming bookmarks') % counts[0])
6084 6085 if counts[1] > 0:
6085 6086 t.append(_('%d outgoing bookmarks') % counts[1])
6086 6087
6087 6088 if t:
6088 6089 # i18n: column positioning for "hg summary"
6089 6090 ui.write(_('remote: %s\n') % (', '.join(t)))
6090 6091 else:
6091 6092 # i18n: column positioning for "hg summary"
6092 6093 ui.status(_('remote: (synced)\n'))
6093 6094
6094 6095 cmdutil.summaryremotehooks(ui, repo, opts,
6095 6096 ((source, sbranch, sother, commoninc),
6096 6097 (dest, dbranch, dother, outgoing)))
6097 6098
6098 6099 @command('tag',
6099 6100 [('f', 'force', None, _('force tag')),
6100 6101 ('l', 'local', None, _('make the tag local')),
6101 6102 ('r', 'rev', '', _('revision to tag'), _('REV')),
6102 6103 ('', 'remove', None, _('remove a tag')),
6103 6104 # -l/--local is already there, commitopts cannot be used
6104 6105 ('e', 'edit', None, _('invoke editor on commit messages')),
6105 6106 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6106 6107 ] + commitopts2,
6107 6108 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6108 6109 def tag(ui, repo, name1, *names, **opts):
6109 6110 """add one or more tags for the current or given revision
6110 6111
6111 6112 Name a particular revision using <name>.
6112 6113
6113 6114 Tags are used to name particular revisions of the repository and are
6114 6115 very useful to compare different revisions, to go back to significant
6115 6116 earlier versions or to mark branch points as releases, etc. Changing
6116 6117 an existing tag is normally disallowed; use -f/--force to override.
6117 6118
6118 6119 If no revision is given, the parent of the working directory is
6119 6120 used.
6120 6121
6121 6122 To facilitate version control, distribution, and merging of tags,
6122 6123 they are stored as a file named ".hgtags" which is managed similarly
6123 6124 to other project files and can be hand-edited if necessary. This
6124 6125 also means that tagging creates a new commit. The file
6125 6126 ".hg/localtags" is used for local tags (not shared among
6126 6127 repositories).
6127 6128
6128 6129 Tag commits are usually made at the head of a branch. If the parent
6129 6130 of the working directory is not a branch head, :hg:`tag` aborts; use
6130 6131 -f/--force to force the tag commit to be based on a non-head
6131 6132 changeset.
6132 6133
6133 6134 See :hg:`help dates` for a list of formats valid for -d/--date.
6134 6135
6135 6136 Since tag names have priority over branch names during revision
6136 6137 lookup, using an existing branch name as a tag name is discouraged.
6137 6138
6138 6139 Returns 0 on success.
6139 6140 """
6140 6141 wlock = lock = None
6141 6142 try:
6142 6143 wlock = repo.wlock()
6143 6144 lock = repo.lock()
6144 6145 rev_ = "."
6145 6146 names = [t.strip() for t in (name1,) + names]
6146 6147 if len(names) != len(set(names)):
6147 6148 raise util.Abort(_('tag names must be unique'))
6148 6149 for n in names:
6149 6150 scmutil.checknewlabel(repo, n, 'tag')
6150 6151 if not n:
6151 6152 raise util.Abort(_('tag names cannot consist entirely of '
6152 6153 'whitespace'))
6153 6154 if opts.get('rev') and opts.get('remove'):
6154 6155 raise util.Abort(_("--rev and --remove are incompatible"))
6155 6156 if opts.get('rev'):
6156 6157 rev_ = opts['rev']
6157 6158 message = opts.get('message')
6158 6159 if opts.get('remove'):
6159 6160 if opts.get('local'):
6160 6161 expectedtype = 'local'
6161 6162 else:
6162 6163 expectedtype = 'global'
6163 6164
6164 6165 for n in names:
6165 6166 if not repo.tagtype(n):
6166 6167 raise util.Abort(_("tag '%s' does not exist") % n)
6167 6168 if repo.tagtype(n) != expectedtype:
6168 6169 if expectedtype == 'global':
6169 6170 raise util.Abort(_("tag '%s' is not a global tag") % n)
6170 6171 else:
6171 6172 raise util.Abort(_("tag '%s' is not a local tag") % n)
6172 6173 rev_ = nullid
6173 6174 if not message:
6174 6175 # we don't translate commit messages
6175 6176 message = 'Removed tag %s' % ', '.join(names)
6176 6177 elif not opts.get('force'):
6177 6178 for n in names:
6178 6179 if n in repo.tags():
6179 6180 raise util.Abort(_("tag '%s' already exists "
6180 6181 "(use -f to force)") % n)
6181 6182 if not opts.get('local'):
6182 6183 p1, p2 = repo.dirstate.parents()
6183 6184 if p2 != nullid:
6184 6185 raise util.Abort(_('uncommitted merge'))
6185 6186 bheads = repo.branchheads()
6186 6187 if not opts.get('force') and bheads and p1 not in bheads:
6187 6188 raise util.Abort(_('not at a branch head (use -f to force)'))
6188 6189 r = scmutil.revsingle(repo, rev_).node()
6189 6190
6190 6191 if not message:
6191 6192 # we don't translate commit messages
6192 6193 message = ('Added tag %s for changeset %s' %
6193 6194 (', '.join(names), short(r)))
6194 6195
6195 6196 date = opts.get('date')
6196 6197 if date:
6197 6198 date = util.parsedate(date)
6198 6199
6199 6200 if opts.get('remove'):
6200 6201 editform = 'tag.remove'
6201 6202 else:
6202 6203 editform = 'tag.add'
6203 6204 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6204 6205
6205 6206 # don't allow tagging the null rev
6206 6207 if (not opts.get('remove') and
6207 6208 scmutil.revsingle(repo, rev_).rev() == nullrev):
6208 6209 raise util.Abort(_("cannot tag null revision"))
6209 6210
6210 6211 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6211 6212 editor=editor)
6212 6213 finally:
6213 6214 release(lock, wlock)
6214 6215
6215 6216 @command('tags', formatteropts, '')
6216 6217 def tags(ui, repo, **opts):
6217 6218 """list repository tags
6218 6219
6219 6220 This lists both regular and local tags. When the -v/--verbose
6220 6221 switch is used, a third column "local" is printed for local tags.
6221 6222
6222 6223 Returns 0 on success.
6223 6224 """
6224 6225
6225 6226 fm = ui.formatter('tags', opts)
6226 6227 hexfunc = fm.hexfunc
6227 6228 tagtype = ""
6228 6229
6229 6230 for t, n in reversed(repo.tagslist()):
6230 6231 hn = hexfunc(n)
6231 6232 label = 'tags.normal'
6232 6233 tagtype = ''
6233 6234 if repo.tagtype(t) == 'local':
6234 6235 label = 'tags.local'
6235 6236 tagtype = 'local'
6236 6237
6237 6238 fm.startitem()
6238 6239 fm.write('tag', '%s', t, label=label)
6239 6240 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6240 6241 fm.condwrite(not ui.quiet, 'rev node', fmt,
6241 6242 repo.changelog.rev(n), hn, label=label)
6242 6243 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6243 6244 tagtype, label=label)
6244 6245 fm.plain('\n')
6245 6246 fm.end()
6246 6247
6247 6248 @command('tip',
6248 6249 [('p', 'patch', None, _('show patch')),
6249 6250 ('g', 'git', None, _('use git extended diff format')),
6250 6251 ] + templateopts,
6251 6252 _('[-p] [-g]'))
6252 6253 def tip(ui, repo, **opts):
6253 6254 """show the tip revision (DEPRECATED)
6254 6255
6255 6256 The tip revision (usually just called the tip) is the changeset
6256 6257 most recently added to the repository (and therefore the most
6257 6258 recently changed head).
6258 6259
6259 6260 If you have just made a commit, that commit will be the tip. If
6260 6261 you have just pulled changes from another repository, the tip of
6261 6262 that repository becomes the current tip. The "tip" tag is special
6262 6263 and cannot be renamed or assigned to a different changeset.
6263 6264
6264 6265 This command is deprecated, please use :hg:`heads` instead.
6265 6266
6266 6267 Returns 0 on success.
6267 6268 """
6268 6269 displayer = cmdutil.show_changeset(ui, repo, opts)
6269 6270 displayer.show(repo['tip'])
6270 6271 displayer.close()
6271 6272
6272 6273 @command('unbundle',
6273 6274 [('u', 'update', None,
6274 6275 _('update to new branch head if changesets were unbundled'))],
6275 6276 _('[-u] FILE...'))
6276 6277 def unbundle(ui, repo, fname1, *fnames, **opts):
6277 6278 """apply one or more changegroup files
6278 6279
6279 6280 Apply one or more compressed changegroup files generated by the
6280 6281 bundle command.
6281 6282
6282 6283 Returns 0 on success, 1 if an update has unresolved files.
6283 6284 """
6284 6285 fnames = (fname1,) + fnames
6285 6286
6286 6287 lock = repo.lock()
6287 6288 try:
6288 6289 for fname in fnames:
6289 6290 f = hg.openpath(ui, fname)
6290 6291 gen = exchange.readbundle(ui, f, fname)
6291 6292 if isinstance(gen, bundle2.unbundle20):
6292 6293 tr = repo.transaction('unbundle')
6293 6294 try:
6294 6295 op = bundle2.processbundle(repo, gen, lambda: tr)
6295 6296 tr.close()
6296 6297 finally:
6297 6298 if tr:
6298 6299 tr.release()
6299 6300 changes = [r.get('result', 0)
6300 6301 for r in op.records['changegroup']]
6301 6302 modheads = changegroup.combineresults(changes)
6302 6303 else:
6303 6304 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6304 6305 'bundle:' + fname)
6305 6306 finally:
6306 6307 lock.release()
6307 6308
6308 6309 return postincoming(ui, repo, modheads, opts.get('update'), None)
6309 6310
6310 6311 @command('^update|up|checkout|co',
6311 6312 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6312 6313 ('c', 'check', None,
6313 6314 _('update across branches if no uncommitted changes')),
6314 6315 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6315 6316 ('r', 'rev', '', _('revision'), _('REV'))
6316 6317 ] + mergetoolopts,
6317 6318 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6318 6319 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6319 6320 tool=None):
6320 6321 """update working directory (or switch revisions)
6321 6322
6322 6323 Update the repository's working directory to the specified
6323 6324 changeset. If no changeset is specified, update to the tip of the
6324 6325 current named branch and move the current bookmark (see :hg:`help
6325 6326 bookmarks`).
6326 6327
6327 6328 Update sets the working directory's parent revision to the specified
6328 6329 changeset (see :hg:`help parents`).
6329 6330
6330 6331 If the changeset is not a descendant or ancestor of the working
6331 6332 directory's parent, the update is aborted. With the -c/--check
6332 6333 option, the working directory is checked for uncommitted changes; if
6333 6334 none are found, the working directory is updated to the specified
6334 6335 changeset.
6335 6336
6336 6337 .. container:: verbose
6337 6338
6338 6339 The following rules apply when the working directory contains
6339 6340 uncommitted changes:
6340 6341
6341 6342 1. If neither -c/--check nor -C/--clean is specified, and if
6342 6343 the requested changeset is an ancestor or descendant of
6343 6344 the working directory's parent, the uncommitted changes
6344 6345 are merged into the requested changeset and the merged
6345 6346 result is left uncommitted. If the requested changeset is
6346 6347 not an ancestor or descendant (that is, it is on another
6347 6348 branch), the update is aborted and the uncommitted changes
6348 6349 are preserved.
6349 6350
6350 6351 2. With the -c/--check option, the update is aborted and the
6351 6352 uncommitted changes are preserved.
6352 6353
6353 6354 3. With the -C/--clean option, uncommitted changes are discarded and
6354 6355 the working directory is updated to the requested changeset.
6355 6356
6356 6357 To cancel an uncommitted merge (and lose your changes), use
6357 6358 :hg:`update --clean .`.
6358 6359
6359 6360 Use null as the changeset to remove the working directory (like
6360 6361 :hg:`clone -U`).
6361 6362
6362 6363 If you want to revert just one file to an older revision, use
6363 6364 :hg:`revert [-r REV] NAME`.
6364 6365
6365 6366 See :hg:`help dates` for a list of formats valid for -d/--date.
6366 6367
6367 6368 Returns 0 on success, 1 if there are unresolved files.
6368 6369 """
6369 6370 if rev and node:
6370 6371 raise util.Abort(_("please specify just one revision"))
6371 6372
6372 6373 if rev is None or rev == '':
6373 6374 rev = node
6374 6375
6375 6376 cmdutil.clearunfinished(repo)
6376 6377
6377 6378 # with no argument, we also move the current bookmark, if any
6378 6379 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6379 6380
6380 6381 # if we defined a bookmark, we have to remember the original bookmark name
6381 6382 brev = rev
6382 6383 rev = scmutil.revsingle(repo, rev, rev).rev()
6383 6384
6384 6385 if check and clean:
6385 6386 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6386 6387
6387 6388 if date:
6388 6389 if rev is not None:
6389 6390 raise util.Abort(_("you can't specify a revision and a date"))
6390 6391 rev = cmdutil.finddate(ui, repo, date)
6391 6392
6392 6393 if check:
6393 6394 cmdutil.bailifchanged(repo, merge=False)
6394 6395 if rev is None:
6395 6396 rev = repo[repo[None].branch()].rev()
6396 6397
6397 6398 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6398 6399
6399 6400 if clean:
6400 6401 ret = hg.clean(repo, rev)
6401 6402 else:
6402 6403 ret = hg.update(repo, rev)
6403 6404
6404 6405 if not ret and movemarkfrom:
6405 6406 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6406 6407 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6407 6408 elif brev in repo._bookmarks:
6408 6409 bookmarks.setcurrent(repo, brev)
6409 6410 ui.status(_("(activating bookmark %s)\n") % brev)
6410 6411 elif brev:
6411 6412 if repo._bookmarkcurrent:
6412 6413 ui.status(_("(leaving bookmark %s)\n") %
6413 6414 repo._bookmarkcurrent)
6414 6415 bookmarks.unsetcurrent(repo)
6415 6416
6416 6417 return ret
6417 6418
6418 6419 @command('verify', [])
6419 6420 def verify(ui, repo):
6420 6421 """verify the integrity of the repository
6421 6422
6422 6423 Verify the integrity of the current repository.
6423 6424
6424 6425 This will perform an extensive check of the repository's
6425 6426 integrity, validating the hashes and checksums of each entry in
6426 6427 the changelog, manifest, and tracked files, as well as the
6427 6428 integrity of their crosslinks and indices.
6428 6429
6429 6430 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6430 6431 for more information about recovery from corruption of the
6431 6432 repository.
6432 6433
6433 6434 Returns 0 on success, 1 if errors are encountered.
6434 6435 """
6435 6436 return hg.verify(repo)
6436 6437
6437 6438 @command('version', [], norepo=True)
6438 6439 def version_(ui):
6439 6440 """output version and copyright information"""
6440 6441 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6441 6442 % util.version())
6442 6443 ui.status(_(
6443 6444 "(see http://mercurial.selenic.com for more information)\n"
6444 6445 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6445 6446 "This is free software; see the source for copying conditions. "
6446 6447 "There is NO\nwarranty; "
6447 6448 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6448 6449 ))
6449 6450
6450 6451 ui.note(_("\nEnabled extensions:\n\n"))
6451 6452 if ui.verbose:
6452 6453 # format names and versions into columns
6453 6454 names = []
6454 6455 vers = []
6455 6456 for name, module in extensions.extensions():
6456 6457 names.append(name)
6457 6458 vers.append(extensions.moduleversion(module))
6458 6459 if names:
6459 6460 maxnamelen = max(len(n) for n in names)
6460 6461 for i, name in enumerate(names):
6461 6462 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,1746 +1,1749 b''
1 1 The Mercurial system uses a set of configuration files to control
2 2 aspects of its behavior.
3 3
4 4 The configuration files use a simple ini-file format. A configuration
5 5 file consists of sections, led by a ``[section]`` header and followed
6 6 by ``name = value`` entries::
7 7
8 8 [ui]
9 9 username = Firstname Lastname <firstname.lastname@example.net>
10 10 verbose = True
11 11
12 12 The above entries will be referred to as ``ui.username`` and
13 13 ``ui.verbose``, respectively. See the Syntax section below.
14 14
15 15 Files
16 16 =====
17 17
18 18 Mercurial reads configuration data from several files, if they exist.
19 19 These files do not exist by default and you will have to create the
20 20 appropriate configuration files yourself: global configuration like
21 21 the username setting is typically put into
22 22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
23 23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
24 24
25 25 The names of these files depend on the system on which Mercurial is
26 26 installed. ``*.rc`` files from a single directory are read in
27 27 alphabetical order, later ones overriding earlier ones. Where multiple
28 28 paths are given below, settings from earlier paths override later
29 29 ones.
30 30
31 31 .. container:: verbose.unix
32 32
33 33 On Unix, the following files are consulted:
34 34
35 35 - ``<repo>/.hg/hgrc`` (per-repository)
36 36 - ``$HOME/.hgrc`` (per-user)
37 37 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
38 38 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
39 39 - ``/etc/mercurial/hgrc`` (per-system)
40 40 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
41 41 - ``<internal>/default.d/*.rc`` (defaults)
42 42
43 43 .. container:: verbose.windows
44 44
45 45 On Windows, the following files are consulted:
46 46
47 47 - ``<repo>/.hg/hgrc`` (per-repository)
48 48 - ``%USERPROFILE%\.hgrc`` (per-user)
49 49 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
50 50 - ``%HOME%\.hgrc`` (per-user)
51 51 - ``%HOME%\Mercurial.ini`` (per-user)
52 52 - ``<install-dir>\Mercurial.ini`` (per-installation)
53 53 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
54 54 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
55 55 - ``<internal>/default.d/*.rc`` (defaults)
56 56
57 57 .. note::
58 58
59 59 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
60 60 is used when running 32-bit Python on 64-bit Windows.
61 61
62 62 .. container:: verbose.plan9
63 63
64 64 On Plan9, the following files are consulted:
65 65
66 66 - ``<repo>/.hg/hgrc`` (per-repository)
67 67 - ``$home/lib/hgrc`` (per-user)
68 68 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
69 69 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
70 70 - ``/lib/mercurial/hgrc`` (per-system)
71 71 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
72 72 - ``<internal>/default.d/*.rc`` (defaults)
73 73
74 74 Per-repository configuration options only apply in a
75 75 particular repository. This file is not version-controlled, and
76 76 will not get transferred during a "clone" operation. Options in
77 77 this file override options in all other configuration files. On
78 78 Plan 9 and Unix, most of this file will be ignored if it doesn't
79 79 belong to a trusted user or to a trusted group. See the documentation
80 80 for the ``[trusted]`` section below for more details.
81 81
82 82 Per-user configuration file(s) are for the user running Mercurial. On
83 83 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
84 84 files apply to all Mercurial commands executed by this user in any
85 85 directory. Options in these files override per-system and per-installation
86 86 options.
87 87
88 88 Per-installation configuration files are searched for in the
89 89 directory where Mercurial is installed. ``<install-root>`` is the
90 90 parent directory of the **hg** executable (or symlink) being run. For
91 91 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
92 92 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
93 93 to all Mercurial commands executed by any user in any directory.
94 94
95 95 Per-installation configuration files are for the system on
96 96 which Mercurial is running. Options in these files apply to all
97 97 Mercurial commands executed by any user in any directory. Registry
98 98 keys contain PATH-like strings, every part of which must reference
99 99 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
100 100 be read. Mercurial checks each of these locations in the specified
101 101 order until one or more configuration files are detected.
102 102
103 103 Per-system configuration files are for the system on which Mercurial
104 104 is running. Options in these files apply to all Mercurial commands
105 105 executed by any user in any directory. Options in these files
106 106 override per-installation options.
107 107
108 108 Mercurial comes with some default configuration. The default configuration
109 109 files are installed with Mercurial and will be overwritten on upgrades. Default
110 110 configuration files should never be edited by users or administrators but can
111 111 be overridden in other configuration files. So far the directory only contains
112 112 merge tool configuration but packagers can also put other default configuration
113 113 there.
114 114
115 115 Syntax
116 116 ======
117 117
118 118 A configuration file consists of sections, led by a ``[section]`` header
119 119 and followed by ``name = value`` entries (sometimes called
120 120 ``configuration keys``)::
121 121
122 122 [spam]
123 123 eggs=ham
124 124 green=
125 125 eggs
126 126
127 127 Each line contains one entry. If the lines that follow are indented,
128 128 they are treated as continuations of that entry. Leading whitespace is
129 129 removed from values. Empty lines are skipped. Lines beginning with
130 130 ``#`` or ``;`` are ignored and may be used to provide comments.
131 131
132 132 Configuration keys can be set multiple times, in which case Mercurial
133 133 will use the value that was configured last. As an example::
134 134
135 135 [spam]
136 136 eggs=large
137 137 ham=serrano
138 138 eggs=small
139 139
140 140 This would set the configuration key named ``eggs`` to ``small``.
141 141
142 142 It is also possible to define a section multiple times. A section can
143 143 be redefined on the same and/or on different configuration files. For
144 144 example::
145 145
146 146 [foo]
147 147 eggs=large
148 148 ham=serrano
149 149 eggs=small
150 150
151 151 [bar]
152 152 eggs=ham
153 153 green=
154 154 eggs
155 155
156 156 [foo]
157 157 ham=prosciutto
158 158 eggs=medium
159 159 bread=toasted
160 160
161 161 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
162 162 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
163 163 respectively. As you can see there only thing that matters is the last
164 164 value that was set for each of the configuration keys.
165 165
166 166 If a configuration key is set multiple times in different
167 167 configuration files the final value will depend on the order in which
168 168 the different configuration files are read, with settings from earlier
169 169 paths overriding later ones as described on the ``Files`` section
170 170 above.
171 171
172 172 A line of the form ``%include file`` will include ``file`` into the
173 173 current configuration file. The inclusion is recursive, which means
174 174 that included files can include other files. Filenames are relative to
175 175 the configuration file in which the ``%include`` directive is found.
176 176 Environment variables and ``~user`` constructs are expanded in
177 177 ``file``. This lets you do something like::
178 178
179 179 %include ~/.hgrc.d/$HOST.rc
180 180
181 181 to include a different configuration file on each computer you use.
182 182
183 183 A line with ``%unset name`` will remove ``name`` from the current
184 184 section, if it has been set previously.
185 185
186 186 The values are either free-form text strings, lists of text strings,
187 187 or Boolean values. Boolean values can be set to true using any of "1",
188 188 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
189 189 (all case insensitive).
190 190
191 191 List values are separated by whitespace or comma, except when values are
192 192 placed in double quotation marks::
193 193
194 194 allow_read = "John Doe, PhD", brian, betty
195 195
196 196 Quotation marks can be escaped by prefixing them with a backslash. Only
197 197 quotation marks at the beginning of a word is counted as a quotation
198 198 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
199 199
200 200 Sections
201 201 ========
202 202
203 203 This section describes the different sections that may appear in a
204 204 Mercurial configuration file, the purpose of each section, its possible
205 205 keys, and their possible values.
206 206
207 207 ``alias``
208 208 ---------
209 209
210 210 Defines command aliases.
211 211 Aliases allow you to define your own commands in terms of other
212 212 commands (or aliases), optionally including arguments. Positional
213 213 arguments in the form of ``$1``, ``$2``, etc in the alias definition
214 214 are expanded by Mercurial before execution. Positional arguments not
215 215 already used by ``$N`` in the definition are put at the end of the
216 216 command to be executed.
217 217
218 218 Alias definitions consist of lines of the form::
219 219
220 220 <alias> = <command> [<argument>]...
221 221
222 222 For example, this definition::
223 223
224 224 latest = log --limit 5
225 225
226 226 creates a new command ``latest`` that shows only the five most recent
227 227 changesets. You can define subsequent aliases using earlier ones::
228 228
229 229 stable5 = latest -b stable
230 230
231 231 .. note::
232 232
233 233 It is possible to create aliases with the same names as
234 234 existing commands, which will then override the original
235 235 definitions. This is almost always a bad idea!
236 236
237 237 An alias can start with an exclamation point (``!``) to make it a
238 238 shell alias. A shell alias is executed with the shell and will let you
239 239 run arbitrary commands. As an example, ::
240 240
241 241 echo = !echo $@
242 242
243 243 will let you do ``hg echo foo`` to have ``foo`` printed in your
244 244 terminal. A better example might be::
245 245
246 246 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
247 247
248 248 which will make ``hg purge`` delete all unknown files in the
249 249 repository in the same manner as the purge extension.
250 250
251 251 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
252 252 expand to the command arguments. Unmatched arguments are
253 253 removed. ``$0`` expands to the alias name and ``$@`` expands to all
254 254 arguments separated by a space. ``"$@"`` (with quotes) expands to all
255 255 arguments quoted individually and separated by a space. These expansions
256 256 happen before the command is passed to the shell.
257 257
258 258 Shell aliases are executed in an environment where ``$HG`` expands to
259 259 the path of the Mercurial that was used to execute the alias. This is
260 260 useful when you want to call further Mercurial commands in a shell
261 261 alias, as was done above for the purge alias. In addition,
262 262 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
263 263 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
264 264
265 265 .. note::
266 266
267 267 Some global configuration options such as ``-R`` are
268 268 processed before shell aliases and will thus not be passed to
269 269 aliases.
270 270
271 271
272 272 ``annotate``
273 273 ------------
274 274
275 275 Settings used when displaying file annotations. All values are
276 276 Booleans and default to False. See ``diff`` section for related
277 277 options for the diff command.
278 278
279 279 ``ignorews``
280 280 Ignore white space when comparing lines.
281 281
282 282 ``ignorewsamount``
283 283 Ignore changes in the amount of white space.
284 284
285 285 ``ignoreblanklines``
286 286 Ignore changes whose lines are all blank.
287 287
288 288
289 289 ``auth``
290 290 --------
291 291
292 292 Authentication credentials for HTTP authentication. This section
293 293 allows you to store usernames and passwords for use when logging
294 294 *into* HTTP servers. See the ``[web]`` configuration section if
295 295 you want to configure *who* can login to your HTTP server.
296 296
297 297 Each line has the following format::
298 298
299 299 <name>.<argument> = <value>
300 300
301 301 where ``<name>`` is used to group arguments into authentication
302 302 entries. Example::
303 303
304 304 foo.prefix = hg.intevation.org/mercurial
305 305 foo.username = foo
306 306 foo.password = bar
307 307 foo.schemes = http https
308 308
309 309 bar.prefix = secure.example.org
310 310 bar.key = path/to/file.key
311 311 bar.cert = path/to/file.cert
312 312 bar.schemes = https
313 313
314 314 Supported arguments:
315 315
316 316 ``prefix``
317 317 Either ``*`` or a URI prefix with or without the scheme part.
318 318 The authentication entry with the longest matching prefix is used
319 319 (where ``*`` matches everything and counts as a match of length
320 320 1). If the prefix doesn't include a scheme, the match is performed
321 321 against the URI with its scheme stripped as well, and the schemes
322 322 argument, q.v., is then subsequently consulted.
323 323
324 324 ``username``
325 325 Optional. Username to authenticate with. If not given, and the
326 326 remote site requires basic or digest authentication, the user will
327 327 be prompted for it. Environment variables are expanded in the
328 328 username letting you do ``foo.username = $USER``. If the URI
329 329 includes a username, only ``[auth]`` entries with a matching
330 330 username or without a username will be considered.
331 331
332 332 ``password``
333 333 Optional. Password to authenticate with. If not given, and the
334 334 remote site requires basic or digest authentication, the user
335 335 will be prompted for it.
336 336
337 337 ``key``
338 338 Optional. PEM encoded client certificate key file. Environment
339 339 variables are expanded in the filename.
340 340
341 341 ``cert``
342 342 Optional. PEM encoded client certificate chain file. Environment
343 343 variables are expanded in the filename.
344 344
345 345 ``schemes``
346 346 Optional. Space separated list of URI schemes to use this
347 347 authentication entry with. Only used if the prefix doesn't include
348 348 a scheme. Supported schemes are http and https. They will match
349 349 static-http and static-https respectively, as well.
350 350 Default: https.
351 351
352 352 If no suitable authentication entry is found, the user is prompted
353 353 for credentials as usual if required by the remote.
354 354
355 355
356 356 ``committemplate``
357 357 ------------------
358 358
359 359 ``changeset`` configuration in this section is used as the template to
360 360 customize the text shown in the editor when committing.
361 361
362 362 In addition to pre-defined template keywords, commit log specific one
363 363 below can be used for customization:
364 364
365 365 ``extramsg``
366 366 String: Extra message (typically 'Leave message empty to abort
367 367 commit.'). This may be changed by some commands or extensions.
368 368
369 369 For example, the template configuration below shows as same text as
370 370 one shown by default::
371 371
372 372 [committemplate]
373 373 changeset = {desc}\n\n
374 374 HG: Enter commit message. Lines beginning with 'HG:' are removed.
375 375 HG: {extramsg}
376 376 HG: --
377 377 HG: user: {author}\n{ifeq(p2rev, "-1", "",
378 378 "HG: branch merge\n")
379 379 }HG: branch '{branch}'\n{if(currentbookmark,
380 380 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
381 381 "HG: subrepo {subrepo}\n" }{file_adds %
382 382 "HG: added {file}\n" }{file_mods %
383 383 "HG: changed {file}\n" }{file_dels %
384 384 "HG: removed {file}\n" }{if(files, "",
385 385 "HG: no files changed\n")}
386 386
387 387 .. note::
388 388
389 389 For some problematic encodings (see :hg:`help win32mbcs` for
390 390 detail), this customization should be configured carefully, to
391 391 avoid showing broken characters.
392 392
393 393 For example, if multibyte character ending with backslash (0x5c) is
394 394 followed by ASCII character 'n' in the customized template,
395 395 sequence of backslash and 'n' is treated as line-feed unexpectedly
396 396 (and multibyte character is broken, too).
397 397
398 398 Customized template is used for commands below (``--edit`` may be
399 399 required):
400 400
401 401 - :hg:`backout`
402 402 - :hg:`commit`
403 403 - :hg:`fetch` (for merge commit only)
404 404 - :hg:`graft`
405 405 - :hg:`histedit`
406 406 - :hg:`import`
407 407 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
408 408 - :hg:`rebase`
409 409 - :hg:`shelve`
410 410 - :hg:`sign`
411 411 - :hg:`tag`
412 412 - :hg:`transplant`
413 413
414 414 Configuring items below instead of ``changeset`` allows showing
415 415 customized message only for specific actions, or showing different
416 416 messages for each action.
417 417
418 418 - ``changeset.backout`` for :hg:`backout`
419 419 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
420 420 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
421 421 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
422 422 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
423 423 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
424 424 - ``changeset.gpg.sign`` for :hg:`sign`
425 425 - ``changeset.graft`` for :hg:`graft`
426 426 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
427 427 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
428 428 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
429 429 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
430 430 - ``changeset.import.bypass`` for :hg:`import --bypass`
431 431 - ``changeset.import.normal.merge`` for :hg:`import` on merges
432 432 - ``changeset.import.normal.normal`` for :hg:`import` on other
433 433 - ``changeset.mq.qnew`` for :hg:`qnew`
434 434 - ``changeset.mq.qfold`` for :hg:`qfold`
435 435 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
436 436 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
437 437 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
438 438 - ``changeset.rebase.normal`` for :hg:`rebase` on other
439 439 - ``changeset.shelve.shelve`` for :hg:`shelve`
440 440 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
441 441 - ``changeset.tag.remove`` for :hg:`tag --remove`
442 442 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
443 443 - ``changeset.transplant.normal`` for :hg:`transplant` on other
444 444
445 445 These dot-separated lists of names are treated as hierarchical ones.
446 446 For example, ``changeset.tag.remove`` customizes the commit message
447 447 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
448 448 commit message for :hg:`tag` regardless of ``--remove`` option.
449 449
450 450 At the external editor invocation for committing, corresponding
451 451 dot-separated list of names without ``changeset.`` prefix
452 452 (e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable.
453 453
454 454 In this section, items other than ``changeset`` can be referred from
455 455 others. For example, the configuration to list committed files up
456 456 below can be referred as ``{listupfiles}``::
457 457
458 458 [committemplate]
459 459 listupfiles = {file_adds %
460 460 "HG: added {file}\n" }{file_mods %
461 461 "HG: changed {file}\n" }{file_dels %
462 462 "HG: removed {file}\n" }{if(files, "",
463 463 "HG: no files changed\n")}
464 464
465 465 ``decode/encode``
466 466 -----------------
467 467
468 468 Filters for transforming files on checkout/checkin. This would
469 469 typically be used for newline processing or other
470 470 localization/canonicalization of files.
471 471
472 472 Filters consist of a filter pattern followed by a filter command.
473 473 Filter patterns are globs by default, rooted at the repository root.
474 474 For example, to match any file ending in ``.txt`` in the root
475 475 directory only, use the pattern ``*.txt``. To match any file ending
476 476 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
477 477 For each file only the first matching filter applies.
478 478
479 479 The filter command can start with a specifier, either ``pipe:`` or
480 480 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
481 481
482 482 A ``pipe:`` command must accept data on stdin and return the transformed
483 483 data on stdout.
484 484
485 485 Pipe example::
486 486
487 487 [encode]
488 488 # uncompress gzip files on checkin to improve delta compression
489 489 # note: not necessarily a good idea, just an example
490 490 *.gz = pipe: gunzip
491 491
492 492 [decode]
493 493 # recompress gzip files when writing them to the working dir (we
494 494 # can safely omit "pipe:", because it's the default)
495 495 *.gz = gzip
496 496
497 497 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
498 498 with the name of a temporary file that contains the data to be
499 499 filtered by the command. The string ``OUTFILE`` is replaced with the name
500 500 of an empty temporary file, where the filtered data must be written by
501 501 the command.
502 502
503 503 .. note::
504 504
505 505 The tempfile mechanism is recommended for Windows systems,
506 506 where the standard shell I/O redirection operators often have
507 507 strange effects and may corrupt the contents of your files.
508 508
509 509 This filter mechanism is used internally by the ``eol`` extension to
510 510 translate line ending characters between Windows (CRLF) and Unix (LF)
511 511 format. We suggest you use the ``eol`` extension for convenience.
512 512
513 513
514 514 ``defaults``
515 515 ------------
516 516
517 517 (defaults are deprecated. Don't use them. Use aliases instead)
518 518
519 519 Use the ``[defaults]`` section to define command defaults, i.e. the
520 520 default options/arguments to pass to the specified commands.
521 521
522 522 The following example makes :hg:`log` run in verbose mode, and
523 523 :hg:`status` show only the modified files, by default::
524 524
525 525 [defaults]
526 526 log = -v
527 527 status = -m
528 528
529 529 The actual commands, instead of their aliases, must be used when
530 530 defining command defaults. The command defaults will also be applied
531 531 to the aliases of the commands defined.
532 532
533 533
534 534 ``diff``
535 535 --------
536 536
537 537 Settings used when displaying diffs. Everything except for ``unified``
538 538 is a Boolean and defaults to False. See ``annotate`` section for
539 539 related options for the annotate command.
540 540
541 541 ``git``
542 542 Use git extended diff format.
543 543
544 544 ``nobinary``
545 545 Omit git binary patches.
546 546
547 547 ``nodates``
548 548 Don't include dates in diff headers.
549 549
550 550 ``noprefix``
551 551 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
552 552
553 553 ``showfunc``
554 554 Show which function each change is in.
555 555
556 556 ``ignorews``
557 557 Ignore white space when comparing lines.
558 558
559 559 ``ignorewsamount``
560 560 Ignore changes in the amount of white space.
561 561
562 562 ``ignoreblanklines``
563 563 Ignore changes whose lines are all blank.
564 564
565 565 ``unified``
566 566 Number of lines of context to show.
567 567
568 568 ``email``
569 569 ---------
570 570
571 571 Settings for extensions that send email messages.
572 572
573 573 ``from``
574 574 Optional. Email address to use in "From" header and SMTP envelope
575 575 of outgoing messages.
576 576
577 577 ``to``
578 578 Optional. Comma-separated list of recipients' email addresses.
579 579
580 580 ``cc``
581 581 Optional. Comma-separated list of carbon copy recipients'
582 582 email addresses.
583 583
584 584 ``bcc``
585 585 Optional. Comma-separated list of blind carbon copy recipients'
586 586 email addresses.
587 587
588 588 ``method``
589 589 Optional. Method to use to send email messages. If value is ``smtp``
590 590 (default), use SMTP (see the ``[smtp]`` section for configuration).
591 591 Otherwise, use as name of program to run that acts like sendmail
592 592 (takes ``-f`` option for sender, list of recipients on command line,
593 593 message on stdin). Normally, setting this to ``sendmail`` or
594 594 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
595 595
596 596 ``charsets``
597 597 Optional. Comma-separated list of character sets considered
598 598 convenient for recipients. Addresses, headers, and parts not
599 599 containing patches of outgoing messages will be encoded in the
600 600 first character set to which conversion from local encoding
601 601 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
602 602 conversion fails, the text in question is sent as is. Defaults to
603 603 empty (explicit) list.
604 604
605 605 Order of outgoing email character sets:
606 606
607 607 1. ``us-ascii``: always first, regardless of settings
608 608 2. ``email.charsets``: in order given by user
609 609 3. ``ui.fallbackencoding``: if not in email.charsets
610 610 4. ``$HGENCODING``: if not in email.charsets
611 611 5. ``utf-8``: always last, regardless of settings
612 612
613 613 Email example::
614 614
615 615 [email]
616 616 from = Joseph User <joe.user@example.com>
617 617 method = /usr/sbin/sendmail
618 618 # charsets for western Europeans
619 619 # us-ascii, utf-8 omitted, as they are tried first and last
620 620 charsets = iso-8859-1, iso-8859-15, windows-1252
621 621
622 622
623 623 ``extensions``
624 624 --------------
625 625
626 626 Mercurial has an extension mechanism for adding new features. To
627 627 enable an extension, create an entry for it in this section.
628 628
629 629 If you know that the extension is already in Python's search path,
630 630 you can give the name of the module, followed by ``=``, with nothing
631 631 after the ``=``.
632 632
633 633 Otherwise, give a name that you choose, followed by ``=``, followed by
634 634 the path to the ``.py`` file (including the file name extension) that
635 635 defines the extension.
636 636
637 637 To explicitly disable an extension that is enabled in an hgrc of
638 638 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
639 639 or ``foo = !`` when path is not supplied.
640 640
641 641 Example for ``~/.hgrc``::
642 642
643 643 [extensions]
644 644 # (the progress extension will get loaded from Mercurial's path)
645 645 progress =
646 646 # (this extension will get loaded from the file specified)
647 647 myfeature = ~/.hgext/myfeature.py
648 648
649 649
650 650 ``format``
651 651 ----------
652 652
653 653 ``usestore``
654 654 Enable or disable the "store" repository format which improves
655 655 compatibility with systems that fold case or otherwise mangle
656 656 filenames. Enabled by default. Disabling this option will allow
657 657 you to store longer filenames in some situations at the expense of
658 658 compatibility and ensures that the on-disk format of newly created
659 659 repositories will be compatible with Mercurial before version 0.9.4.
660 660
661 661 ``usefncache``
662 662 Enable or disable the "fncache" repository format which enhances
663 663 the "store" repository format (which has to be enabled to use
664 664 fncache) to allow longer filenames and avoids using Windows
665 665 reserved names, e.g. "nul". Enabled by default. Disabling this
666 666 option ensures that the on-disk format of newly created
667 667 repositories will be compatible with Mercurial before version 1.1.
668 668
669 669 ``dotencode``
670 670 Enable or disable the "dotencode" repository format which enhances
671 671 the "fncache" repository format (which has to be enabled to use
672 672 dotencode) to avoid issues with filenames starting with ._ on
673 673 Mac OS X and spaces on Windows. Enabled by default. Disabling this
674 674 option ensures that the on-disk format of newly created
675 675 repositories will be compatible with Mercurial before version 1.7.
676 676
677 677 ``graph``
678 678 ---------
679 679
680 680 Web graph view configuration. This section let you change graph
681 681 elements display properties by branches, for instance to make the
682 682 ``default`` branch stand out.
683 683
684 684 Each line has the following format::
685 685
686 686 <branch>.<argument> = <value>
687 687
688 688 where ``<branch>`` is the name of the branch being
689 689 customized. Example::
690 690
691 691 [graph]
692 692 # 2px width
693 693 default.width = 2
694 694 # red color
695 695 default.color = FF0000
696 696
697 697 Supported arguments:
698 698
699 699 ``width``
700 700 Set branch edges width in pixels.
701 701
702 702 ``color``
703 703 Set branch edges color in hexadecimal RGB notation.
704 704
705 705 ``hooks``
706 706 ---------
707 707
708 708 Commands or Python functions that get automatically executed by
709 709 various actions such as starting or finishing a commit. Multiple
710 710 hooks can be run for the same action by appending a suffix to the
711 711 action. Overriding a site-wide hook can be done by changing its
712 712 value or setting it to an empty string. Hooks can be prioritized
713 713 by adding a prefix of ``priority`` to the hook name on a new line
714 714 and setting the priority. The default priority is 0 if
715 715 not specified.
716 716
717 717 Example ``.hg/hgrc``::
718 718
719 719 [hooks]
720 720 # update working directory after adding changesets
721 721 changegroup.update = hg update
722 722 # do not use the site-wide hook
723 723 incoming =
724 724 incoming.email = /my/email/hook
725 725 incoming.autobuild = /my/build/hook
726 726 # force autobuild hook to run before other incoming hooks
727 727 priority.incoming.autobuild = 1
728 728
729 729 Most hooks are run with environment variables set that give useful
730 730 additional information. For each hook below, the environment
731 731 variables it is passed are listed with names of the form ``$HG_foo``.
732 732
733 733 ``changegroup``
734 734 Run after a changegroup has been added via push, pull or unbundle.
735 735 ID of the first new changeset is in ``$HG_NODE``. URL from which
736 736 changes came is in ``$HG_URL``.
737 737
738 738 ``commit``
739 739 Run after a changeset has been created in the local repository. ID
740 740 of the newly created changeset is in ``$HG_NODE``. Parent changeset
741 741 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
742 742
743 743 ``incoming``
744 744 Run after a changeset has been pulled, pushed, or unbundled into
745 745 the local repository. The ID of the newly arrived changeset is in
746 746 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
747 747
748 748 ``outgoing``
749 749 Run after sending changes from local repository to another. ID of
750 750 first changeset sent is in ``$HG_NODE``. Source of operation is in
751 751 ``$HG_SOURCE``; see "preoutgoing" hook for description.
752 752
753 753 ``post-<command>``
754 754 Run after successful invocations of the associated command. The
755 755 contents of the command line are passed as ``$HG_ARGS`` and the result
756 756 code in ``$HG_RESULT``. Parsed command line arguments are passed as
757 757 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
758 758 the python data internally passed to <command>. ``$HG_OPTS`` is a
759 759 dictionary of options (with unspecified options set to their defaults).
760 760 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
761 761
762 762 ``pre-<command>``
763 763 Run before executing the associated command. The contents of the
764 764 command line are passed as ``$HG_ARGS``. Parsed command line arguments
765 765 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
766 766 representations of the data internally passed to <command>. ``$HG_OPTS``
767 767 is a dictionary of options (with unspecified options set to their
768 768 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
769 769 failure, the command doesn't execute and Mercurial returns the failure
770 770 code.
771 771
772 772 ``prechangegroup``
773 773 Run before a changegroup is added via push, pull or unbundle. Exit
774 774 status 0 allows the changegroup to proceed. Non-zero status will
775 775 cause the push, pull or unbundle to fail. URL from which changes
776 776 will come is in ``$HG_URL``.
777 777
778 778 ``precommit``
779 779 Run before starting a local commit. Exit status 0 allows the
780 780 commit to proceed. Non-zero status will cause the commit to fail.
781 781 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
782 782
783 783 ``prelistkeys``
784 784 Run before listing pushkeys (like bookmarks) in the
785 785 repository. Non-zero status will cause failure. The key namespace is
786 786 in ``$HG_NAMESPACE``.
787 787
788 788 ``preoutgoing``
789 789 Run before collecting changes to send from the local repository to
790 790 another. Non-zero status will cause failure. This lets you prevent
791 791 pull over HTTP or SSH. Also prevents against local pull, push
792 792 (outbound) or bundle commands, but not effective, since you can
793 793 just copy files instead then. Source of operation is in
794 794 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
795 795 SSH or HTTP repository. If "push", "pull" or "bundle", operation
796 796 is happening on behalf of repository on same system.
797 797
798 798 ``prepushkey``
799 799 Run before a pushkey (like a bookmark) is added to the
800 800 repository. Non-zero status will cause the key to be rejected. The
801 801 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
802 802 the old value (if any) is in ``$HG_OLD``, and the new value is in
803 803 ``$HG_NEW``.
804 804
805 805 ``pretag``
806 806 Run before creating a tag. Exit status 0 allows the tag to be
807 807 created. Non-zero status will cause the tag to fail. ID of
808 808 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
809 809 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
810 810
811 811 ``pretxnopen``
812 812 Run before any new repository transaction is open. The reason for the
813 813 transaction will be in ``$HG_TXNNAME``. A non-zero status will
814 814 prevent the transaction from being opened.
815 815
816 816 ``pretxnclose``
817 817 Run right before the transaction is actually finalized. Any
818 818 repository change will be visible to the hook program. This lets you
819 819 validate the transaction content or change it. Exit status 0 allows
820 820 the commit to proceed. Non-zero status will cause the transaction to
821 821 be rolled back. The reason for the transaction opening will be in
822 822 ``$HG_TXNNAME``. The rest of the available data will vary according
823 823 the transaction type. New changesets will add
824 824 ``$HG_NODE`` (id of the first added changeset), ``$HG_URL`` and
825 825 ``$HG_SOURCE`` variables, bookmarks and phases changes will set
826 826 ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``, etc.
827 827
828 828 ``txnclose``
829 829 Run after any repository transaction has been commited. At this
830 830 point, the transaction can no longer be rolled back. The hook will run
831 831 after the lock is released. see ``pretxnclose`` docs for details about
832 832 available variables.
833 833
834 834 ``pretxnchangegroup``
835 835 Run after a changegroup has been added via push, pull or unbundle,
836 836 but before the transaction has been committed. Changegroup is
837 837 visible to hook program. This lets you validate incoming changes
838 838 before accepting them. Passed the ID of the first new changeset in
839 839 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
840 840 status will cause the transaction to be rolled back and the push,
841 841 pull or unbundle will fail. URL that was source of changes is in
842 842 ``$HG_URL``.
843 843
844 844 ``pretxncommit``
845 845 Run after a changeset has been created but the transaction not yet
846 846 committed. Changeset is visible to hook program. This lets you
847 847 validate commit message and changes. Exit status 0 allows the
848 848 commit to proceed. Non-zero status will cause the transaction to
849 849 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
850 850 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
851 851
852 852 ``preupdate``
853 853 Run before updating the working directory. Exit status 0 allows
854 854 the update to proceed. Non-zero status will prevent the update.
855 855 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
856 856 of second new parent is in ``$HG_PARENT2``.
857 857
858 858 ``listkeys``
859 859 Run after listing pushkeys (like bookmarks) in the repository. The
860 860 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
861 861 dictionary containing the keys and values.
862 862
863 863 ``pushkey``
864 864 Run after a pushkey (like a bookmark) is added to the
865 865 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
866 866 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
867 867 value is in ``$HG_NEW``.
868 868
869 869 ``tag``
870 870 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
871 871 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
872 872 repository if ``$HG_LOCAL=0``.
873 873
874 874 ``update``
875 875 Run after updating the working directory. Changeset ID of first
876 876 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
877 877 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
878 878 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
879 879
880 880 .. note::
881 881
882 882 It is generally better to use standard hooks rather than the
883 883 generic pre- and post- command hooks as they are guaranteed to be
884 884 called in the appropriate contexts for influencing transactions.
885 885 Also, hooks like "commit" will be called in all contexts that
886 886 generate a commit (e.g. tag) and not just the commit command.
887 887
888 888 .. note::
889 889
890 890 Environment variables with empty values may not be passed to
891 891 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
892 892 will have an empty value under Unix-like platforms for non-merge
893 893 changesets, while it will not be available at all under Windows.
894 894
895 895 The syntax for Python hooks is as follows::
896 896
897 897 hookname = python:modulename.submodule.callable
898 898 hookname = python:/path/to/python/module.py:callable
899 899
900 900 Python hooks are run within the Mercurial process. Each hook is
901 901 called with at least three keyword arguments: a ui object (keyword
902 902 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
903 903 keyword that tells what kind of hook is used. Arguments listed as
904 904 environment variables above are passed as keyword arguments, with no
905 905 ``HG_`` prefix, and names in lower case.
906 906
907 907 If a Python hook returns a "true" value or raises an exception, this
908 908 is treated as a failure.
909 909
910 910
911 911 ``hostfingerprints``
912 912 --------------------
913 913
914 914 Fingerprints of the certificates of known HTTPS servers.
915 915 A HTTPS connection to a server with a fingerprint configured here will
916 916 only succeed if the servers certificate matches the fingerprint.
917 917 This is very similar to how ssh known hosts works.
918 918 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
919 919 The CA chain and web.cacerts is not used for servers with a fingerprint.
920 920
921 921 For example::
922 922
923 923 [hostfingerprints]
924 924 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
925 925
926 926 This feature is only supported when using Python 2.6 or later.
927 927
928 928
929 929 ``http_proxy``
930 930 --------------
931 931
932 932 Used to access web-based Mercurial repositories through a HTTP
933 933 proxy.
934 934
935 935 ``host``
936 936 Host name and (optional) port of the proxy server, for example
937 937 "myproxy:8000".
938 938
939 939 ``no``
940 940 Optional. Comma-separated list of host names that should bypass
941 941 the proxy.
942 942
943 943 ``passwd``
944 944 Optional. Password to authenticate with at the proxy server.
945 945
946 946 ``user``
947 947 Optional. User name to authenticate with at the proxy server.
948 948
949 949 ``always``
950 950 Optional. Always use the proxy, even for localhost and any entries
951 951 in ``http_proxy.no``. True or False. Default: False.
952 952
953 953 ``merge-patterns``
954 954 ------------------
955 955
956 956 This section specifies merge tools to associate with particular file
957 957 patterns. Tools matched here will take precedence over the default
958 958 merge tool. Patterns are globs by default, rooted at the repository
959 959 root.
960 960
961 961 Example::
962 962
963 963 [merge-patterns]
964 964 **.c = kdiff3
965 965 **.jpg = myimgmerge
966 966
967 967 ``merge-tools``
968 968 ---------------
969 969
970 970 This section configures external merge tools to use for file-level
971 971 merges. This section has likely been preconfigured at install time.
972 972 Use :hg:`config merge-tools` to check the existing configuration.
973 973 Also see :hg:`help merge-tools` for more details.
974 974
975 975 Example ``~/.hgrc``::
976 976
977 977 [merge-tools]
978 978 # Override stock tool location
979 979 kdiff3.executable = ~/bin/kdiff3
980 980 # Specify command line
981 981 kdiff3.args = $base $local $other -o $output
982 982 # Give higher priority
983 983 kdiff3.priority = 1
984 984
985 985 # Changing the priority of preconfigured tool
986 986 vimdiff.priority = 0
987 987
988 988 # Define new tool
989 989 myHtmlTool.args = -m $local $other $base $output
990 990 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
991 991 myHtmlTool.priority = 1
992 992
993 993 Supported arguments:
994 994
995 995 ``priority``
996 996 The priority in which to evaluate this tool.
997 997 Default: 0.
998 998
999 999 ``executable``
1000 1000 Either just the name of the executable or its pathname. On Windows,
1001 1001 the path can use environment variables with ${ProgramFiles} syntax.
1002 1002 Default: the tool name.
1003 1003
1004 1004 ``args``
1005 1005 The arguments to pass to the tool executable. You can refer to the
1006 1006 files being merged as well as the output file through these
1007 1007 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1008 1008 of ``$local`` and ``$other`` can vary depending on which action is being
1009 1009 performed. During and update or merge, ``$local`` represents the original
1010 1010 state of the file, while ``$other`` represents the commit you are updating
1011 1011 to or the commit you are merging with. During a rebase ``$local``
1012 1012 represents the destination of the rebase, and ``$other`` represents the
1013 1013 commit being rebased.
1014 1014 Default: ``$local $base $other``
1015 1015
1016 1016 ``premerge``
1017 1017 Attempt to run internal non-interactive 3-way merge tool before
1018 1018 launching external tool. Options are ``true``, ``false``, ``keep`` or
1019 1019 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1020 1020 premerge fails. The ``keep-merge3`` will do the same but include information
1021 1021 about the base of the merge in the marker (see internal :merge3 in
1022 1022 :hg:`help merge-tools`).
1023 1023 Default: True
1024 1024
1025 1025 ``binary``
1026 1026 This tool can merge binary files. Defaults to False, unless tool
1027 1027 was selected by file pattern match.
1028 1028
1029 1029 ``symlink``
1030 1030 This tool can merge symlinks. Defaults to False, even if tool was
1031 1031 selected by file pattern match.
1032 1032
1033 1033 ``check``
1034 1034 A list of merge success-checking options:
1035 1035
1036 1036 ``changed``
1037 1037 Ask whether merge was successful when the merged file shows no changes.
1038 1038 ``conflicts``
1039 1039 Check whether there are conflicts even though the tool reported success.
1040 1040 ``prompt``
1041 1041 Always prompt for merge success, regardless of success reported by tool.
1042 1042
1043 1043 ``fixeol``
1044 1044 Attempt to fix up EOL changes caused by the merge tool.
1045 1045 Default: False
1046 1046
1047 1047 ``gui``
1048 1048 This tool requires a graphical interface to run. Default: False
1049 1049
1050 1050 ``regkey``
1051 1051 Windows registry key which describes install location of this
1052 1052 tool. Mercurial will search for this key first under
1053 1053 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1054 1054 Default: None
1055 1055
1056 1056 ``regkeyalt``
1057 1057 An alternate Windows registry key to try if the first key is not
1058 1058 found. The alternate key uses the same ``regname`` and ``regappend``
1059 1059 semantics of the primary key. The most common use for this key
1060 1060 is to search for 32bit applications on 64bit operating systems.
1061 1061 Default: None
1062 1062
1063 1063 ``regname``
1064 1064 Name of value to read from specified registry key. Defaults to the
1065 1065 unnamed (default) value.
1066 1066
1067 1067 ``regappend``
1068 1068 String to append to the value read from the registry, typically
1069 1069 the executable name of the tool.
1070 1070 Default: None
1071 1071
1072 1072
1073 1073 ``patch``
1074 1074 ---------
1075 1075
1076 1076 Settings used when applying patches, for instance through the 'import'
1077 1077 command or with Mercurial Queues extension.
1078 1078
1079 1079 ``eol``
1080 1080 When set to 'strict' patch content and patched files end of lines
1081 1081 are preserved. When set to ``lf`` or ``crlf``, both files end of
1082 1082 lines are ignored when patching and the result line endings are
1083 1083 normalized to either LF (Unix) or CRLF (Windows). When set to
1084 1084 ``auto``, end of lines are again ignored while patching but line
1085 1085 endings in patched files are normalized to their original setting
1086 1086 on a per-file basis. If target file does not exist or has no end
1087 1087 of line, patch line endings are preserved.
1088 1088 Default: strict.
1089 1089
1090 1090
1091 1091 ``paths``
1092 1092 ---------
1093 1093
1094 1094 Assigns symbolic names to repositories. The left side is the
1095 1095 symbolic name, and the right gives the directory or URL that is the
1096 1096 location of the repository. Default paths can be declared by setting
1097 1097 the following entries.
1098 1098
1099 1099 ``default``
1100 1100 Directory or URL to use when pulling if no source is specified.
1101 1101 Default is set to repository from which the current repository was
1102 1102 cloned.
1103 1103
1104 1104 ``default-push``
1105 1105 Optional. Directory or URL to use when pushing if no destination
1106 1106 is specified.
1107 1107
1108 1108 Custom paths can be defined by assigning the path to a name that later can be
1109 1109 used from the command line. Example::
1110 1110
1111 1111 [paths]
1112 1112 my_path = http://example.com/path
1113 1113
1114 1114 To push to the path defined in ``my_path`` run the command::
1115 1115
1116 1116 hg push my_path
1117 1117
1118 1118
1119 1119 ``phases``
1120 1120 ----------
1121 1121
1122 1122 Specifies default handling of phases. See :hg:`help phases` for more
1123 1123 information about working with phases.
1124 1124
1125 1125 ``publish``
1126 1126 Controls draft phase behavior when working as a server. When true,
1127 1127 pushed changesets are set to public in both client and server and
1128 1128 pulled or cloned changesets are set to public in the client.
1129 1129 Default: True
1130 1130
1131 1131 ``new-commit``
1132 1132 Phase of newly-created commits.
1133 1133 Default: draft
1134 1134
1135 1135 ``checksubrepos``
1136 1136 Check the phase of the current revision of each subrepository. Allowed
1137 1137 values are "ignore", "follow" and "abort". For settings other than
1138 1138 "ignore", the phase of the current revision of each subrepository is
1139 1139 checked before committing the parent repository. If any of those phases is
1140 1140 greater than the phase of the parent repository (e.g. if a subrepo is in a
1141 1141 "secret" phase while the parent repo is in "draft" phase), the commit is
1142 1142 either aborted (if checksubrepos is set to "abort") or the higher phase is
1143 1143 used for the parent repository commit (if set to "follow").
1144 1144 Default: "follow"
1145 1145
1146 1146
1147 1147 ``profiling``
1148 1148 -------------
1149 1149
1150 1150 Specifies profiling type, format, and file output. Two profilers are
1151 1151 supported: an instrumenting profiler (named ``ls``), and a sampling
1152 1152 profiler (named ``stat``).
1153 1153
1154 1154 In this section description, 'profiling data' stands for the raw data
1155 1155 collected during profiling, while 'profiling report' stands for a
1156 1156 statistical text report generated from the profiling data. The
1157 1157 profiling is done using lsprof.
1158 1158
1159 1159 ``type``
1160 1160 The type of profiler to use.
1161 1161 Default: ls.
1162 1162
1163 1163 ``ls``
1164 1164 Use Python's built-in instrumenting profiler. This profiler
1165 1165 works on all platforms, but each line number it reports is the
1166 1166 first line of a function. This restriction makes it difficult to
1167 1167 identify the expensive parts of a non-trivial function.
1168 1168 ``stat``
1169 1169 Use a third-party statistical profiler, statprof. This profiler
1170 1170 currently runs only on Unix systems, and is most useful for
1171 1171 profiling commands that run for longer than about 0.1 seconds.
1172 1172
1173 1173 ``format``
1174 1174 Profiling format. Specific to the ``ls`` instrumenting profiler.
1175 1175 Default: text.
1176 1176
1177 1177 ``text``
1178 1178 Generate a profiling report. When saving to a file, it should be
1179 1179 noted that only the report is saved, and the profiling data is
1180 1180 not kept.
1181 1181 ``kcachegrind``
1182 1182 Format profiling data for kcachegrind use: when saving to a
1183 1183 file, the generated file can directly be loaded into
1184 1184 kcachegrind.
1185 1185
1186 1186 ``frequency``
1187 1187 Sampling frequency. Specific to the ``stat`` sampling profiler.
1188 1188 Default: 1000.
1189 1189
1190 1190 ``output``
1191 1191 File path where profiling data or report should be saved. If the
1192 1192 file exists, it is replaced. Default: None, data is printed on
1193 1193 stderr
1194 1194
1195 1195 ``sort``
1196 1196 Sort field. Specific to the ``ls`` instrumenting profiler.
1197 1197 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1198 1198 ``inlinetime``.
1199 1199 Default: inlinetime.
1200 1200
1201 1201 ``limit``
1202 1202 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1203 1203 Default: 30.
1204 1204
1205 1205 ``nested``
1206 1206 Show at most this number of lines of drill-down info after each main entry.
1207 1207 This can help explain the difference between Total and Inline.
1208 1208 Specific to the ``ls`` instrumenting profiler.
1209 1209 Default: 5.
1210 1210
1211 1211 ``revsetalias``
1212 1212 ---------------
1213 1213
1214 1214 Alias definitions for revsets. See :hg:`help revsets` for details.
1215 1215
1216 1216 ``server``
1217 1217 ----------
1218 1218
1219 1219 Controls generic server settings.
1220 1220
1221 1221 ``uncompressed``
1222 1222 Whether to allow clients to clone a repository using the
1223 1223 uncompressed streaming protocol. This transfers about 40% more
1224 1224 data than a regular clone, but uses less memory and CPU on both
1225 1225 server and client. Over a LAN (100 Mbps or better) or a very fast
1226 1226 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1227 1227 regular clone. Over most WAN connections (anything slower than
1228 1228 about 6 Mbps), uncompressed streaming is slower, because of the
1229 1229 extra data transfer overhead. This mode will also temporarily hold
1230 1230 the write lock while determining what data to transfer.
1231 1231 Default is True.
1232 1232
1233 1233 ``preferuncompressed``
1234 1234 When set, clients will try to use the uncompressed streaming
1235 1235 protocol. Default is False.
1236 1236
1237 1237 ``validate``
1238 1238 Whether to validate the completeness of pushed changesets by
1239 1239 checking that all new file revisions specified in manifests are
1240 1240 present. Default is False.
1241 1241
1242 1242 ``smtp``
1243 1243 --------
1244 1244
1245 1245 Configuration for extensions that need to send email messages.
1246 1246
1247 1247 ``host``
1248 1248 Host name of mail server, e.g. "mail.example.com".
1249 1249
1250 1250 ``port``
1251 1251 Optional. Port to connect to on mail server. Default: 465 (if
1252 1252 ``tls`` is smtps) or 25 (otherwise).
1253 1253
1254 1254 ``tls``
1255 1255 Optional. Method to enable TLS when connecting to mail server: starttls,
1256 1256 smtps or none. Default: none.
1257 1257
1258 1258 ``verifycert``
1259 1259 Optional. Verification for the certificate of mail server, when
1260 1260 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1261 1261 "strict" or "loose", the certificate is verified as same as the
1262 1262 verification for HTTPS connections (see ``[hostfingerprints]`` and
1263 1263 ``[web] cacerts`` also). For "strict", sending email is also
1264 1264 aborted, if there is no configuration for mail server in
1265 1265 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1266 1266 :hg:`email` overwrites this as "loose". Default: "strict".
1267 1267
1268 1268 ``username``
1269 1269 Optional. User name for authenticating with the SMTP server.
1270 1270 Default: none.
1271 1271
1272 1272 ``password``
1273 1273 Optional. Password for authenticating with the SMTP server. If not
1274 1274 specified, interactive sessions will prompt the user for a
1275 1275 password; non-interactive sessions will fail. Default: none.
1276 1276
1277 1277 ``local_hostname``
1278 1278 Optional. It's the hostname that the sender can use to identify
1279 1279 itself to the MTA.
1280 1280
1281 1281
1282 1282 ``subpaths``
1283 1283 ------------
1284 1284
1285 1285 Subrepository source URLs can go stale if a remote server changes name
1286 1286 or becomes temporarily unavailable. This section lets you define
1287 1287 rewrite rules of the form::
1288 1288
1289 1289 <pattern> = <replacement>
1290 1290
1291 1291 where ``pattern`` is a regular expression matching a subrepository
1292 1292 source URL and ``replacement`` is the replacement string used to
1293 1293 rewrite it. Groups can be matched in ``pattern`` and referenced in
1294 1294 ``replacements``. For instance::
1295 1295
1296 1296 http://server/(.*)-hg/ = http://hg.server/\1/
1297 1297
1298 1298 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1299 1299
1300 1300 Relative subrepository paths are first made absolute, and the
1301 1301 rewrite rules are then applied on the full (absolute) path. The rules
1302 1302 are applied in definition order.
1303 1303
1304 1304 ``trusted``
1305 1305 -----------
1306 1306
1307 1307 Mercurial will not use the settings in the
1308 1308 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1309 1309 user or to a trusted group, as various hgrc features allow arbitrary
1310 1310 commands to be run. This issue is often encountered when configuring
1311 1311 hooks or extensions for shared repositories or servers. However,
1312 1312 the web interface will use some safe settings from the ``[web]``
1313 1313 section.
1314 1314
1315 1315 This section specifies what users and groups are trusted. The
1316 1316 current user is always trusted. To trust everybody, list a user or a
1317 1317 group with name ``*``. These settings must be placed in an
1318 1318 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1319 1319 user or service running Mercurial.
1320 1320
1321 1321 ``users``
1322 1322 Comma-separated list of trusted users.
1323 1323
1324 1324 ``groups``
1325 1325 Comma-separated list of trusted groups.
1326 1326
1327 1327
1328 1328 ``ui``
1329 1329 ------
1330 1330
1331 1331 User interface controls.
1332 1332
1333 1333 ``archivemeta``
1334 1334 Whether to include the .hg_archival.txt file containing meta data
1335 1335 (hashes for the repository base and for tip) in archives created
1336 1336 by the :hg:`archive` command or downloaded via hgweb.
1337 1337 Default is True.
1338 1338
1339 1339 ``askusername``
1340 1340 Whether to prompt for a username when committing. If True, and
1341 1341 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1342 1342 be prompted to enter a username. If no username is entered, the
1343 1343 default ``USER@HOST`` is used instead.
1344 1344 Default is False.
1345 1345
1346 1346 ``commitsubrepos``
1347 1347 Whether to commit modified subrepositories when committing the
1348 1348 parent repository. If False and one subrepository has uncommitted
1349 1349 changes, abort the commit.
1350 1350 Default is False.
1351 1351
1352 1352 ``debug``
1353 1353 Print debugging information. True or False. Default is False.
1354 1354
1355 1355 ``editor``
1356 1356 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1357 1357
1358 1358 ``fallbackencoding``
1359 1359 Encoding to try if it's not possible to decode the changelog using
1360 1360 UTF-8. Default is ISO-8859-1.
1361 1361
1362 1362 ``ignore``
1363 1363 A file to read per-user ignore patterns from. This file should be
1364 1364 in the same format as a repository-wide .hgignore file. Filenames
1365 1365 are relative to the repository root. This option supports hook syntax,
1366 1366 so if you want to specify multiple ignore files, you can do so by
1367 1367 setting something like ``ignore.other = ~/.hgignore2``. For details
1368 1368 of the ignore file format, see the ``hgignore(5)`` man page.
1369 1369
1370 1370 ``interactive``
1371 1371 Allow to prompt the user. True or False. Default is True.
1372 1372
1373 1373 ``logtemplate``
1374 1374 Template string for commands that print changesets.
1375 1375
1376 1376 ``merge``
1377 1377 The conflict resolution program to use during a manual merge.
1378 1378 For more information on merge tools see :hg:`help merge-tools`.
1379 1379 For configuring merge tools see the ``[merge-tools]`` section.
1380 1380
1381 1381 ``mergemarkers``
1382 1382 Sets the merge conflict marker label styling. The ``detailed``
1383 1383 style uses the ``mergemarkertemplate`` setting to style the labels.
1384 1384 The ``basic`` style just uses 'local' and 'other' as the marker label.
1385 1385 One of ``basic`` or ``detailed``.
1386 1386 Default is ``basic``.
1387 1387
1388 1388 ``mergemarkertemplate``
1389 1389 The template used to print the commit description next to each conflict
1390 1390 marker during merge conflicts. See :hg:`help templates` for the template
1391 1391 format.
1392 1392 Defaults to showing the hash, tags, branches, bookmarks, author, and
1393 1393 the first line of the commit description.
1394 1394 If you use non-ASCII characters in names for tags, branches, bookmarks,
1395 1395 authors, and/or commit descriptions, you must pay attention to encodings of
1396 1396 managed files. At template expansion, non-ASCII characters use the encoding
1397 1397 specified by the ``--encoding`` global option, ``HGENCODING`` or other
1398 1398 environment variables that govern your locale. If the encoding of the merge
1399 1399 markers is different from the encoding of the merged files,
1400 1400 serious problems may occur.
1401 1401
1402 1402 ``portablefilenames``
1403 1403 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1404 1404 Default is ``warn``.
1405 1405 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1406 1406 platforms, if a file with a non-portable filename is added (e.g. a file
1407 1407 with a name that can't be created on Windows because it contains reserved
1408 1408 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1409 1409 collision with an existing file).
1410 1410 If set to ``ignore`` (or ``false``), no warning is printed.
1411 1411 If set to ``abort``, the command is aborted.
1412 1412 On Windows, this configuration option is ignored and the command aborted.
1413 1413
1414 1414 ``quiet``
1415 1415 Reduce the amount of output printed. True or False. Default is False.
1416 1416
1417 1417 ``remotecmd``
1418 1418 remote command to use for clone/push/pull operations. Default is ``hg``.
1419 1419
1420 1420 ``reportoldssl``
1421 1421 Warn if an SSL certificate is unable to be used due to using Python
1422 1422 2.5 or earlier. True or False. Default is True.
1423 1423
1424 1424 ``report_untrusted``
1425 1425 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1426 1426 trusted user or group. True or False. Default is True.
1427 1427
1428 1428 ``slash``
1429 1429 Display paths using a slash (``/``) as the path separator. This
1430 1430 only makes a difference on systems where the default path
1431 1431 separator is not the slash character (e.g. Windows uses the
1432 1432 backslash character (``\``)).
1433 1433 Default is False.
1434 1434
1435 ``statuscopies``
1436 Display copies in the status command.
1437
1435 1438 ``ssh``
1436 1439 command to use for SSH connections. Default is ``ssh``.
1437 1440
1438 1441 ``strict``
1439 1442 Require exact command names, instead of allowing unambiguous
1440 1443 abbreviations. True or False. Default is False.
1441 1444
1442 1445 ``style``
1443 1446 Name of style to use for command output.
1444 1447
1445 1448 ``timeout``
1446 1449 The timeout used when a lock is held (in seconds), a negative value
1447 1450 means no timeout. Default is 600.
1448 1451
1449 1452 ``traceback``
1450 1453 Mercurial always prints a traceback when an unknown exception
1451 1454 occurs. Setting this to True will make Mercurial print a traceback
1452 1455 on all exceptions, even those recognized by Mercurial (such as
1453 1456 IOError or MemoryError). Default is False.
1454 1457
1455 1458 ``username``
1456 1459 The committer of a changeset created when running "commit".
1457 1460 Typically a person's name and email address, e.g. ``Fred Widget
1458 1461 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1459 1462 the username in hgrc is empty, it has to be specified manually or
1460 1463 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1461 1464 ``username =`` in the system hgrc). Environment variables in the
1462 1465 username are expanded.
1463 1466
1464 1467 ``verbose``
1465 1468 Increase the amount of output printed. True or False. Default is False.
1466 1469
1467 1470
1468 1471 ``web``
1469 1472 -------
1470 1473
1471 1474 Web interface configuration. The settings in this section apply to
1472 1475 both the builtin webserver (started by :hg:`serve`) and the script you
1473 1476 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1474 1477 and WSGI).
1475 1478
1476 1479 The Mercurial webserver does no authentication (it does not prompt for
1477 1480 usernames and passwords to validate *who* users are), but it does do
1478 1481 authorization (it grants or denies access for *authenticated users*
1479 1482 based on settings in this section). You must either configure your
1480 1483 webserver to do authentication for you, or disable the authorization
1481 1484 checks.
1482 1485
1483 1486 For a quick setup in a trusted environment, e.g., a private LAN, where
1484 1487 you want it to accept pushes from anybody, you can use the following
1485 1488 command line::
1486 1489
1487 1490 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1488 1491
1489 1492 Note that this will allow anybody to push anything to the server and
1490 1493 that this should not be used for public servers.
1491 1494
1492 1495 The full set of options is:
1493 1496
1494 1497 ``accesslog``
1495 1498 Where to output the access log. Default is stdout.
1496 1499
1497 1500 ``address``
1498 1501 Interface address to bind to. Default is all.
1499 1502
1500 1503 ``allow_archive``
1501 1504 List of archive format (bz2, gz, zip) allowed for downloading.
1502 1505 Default is empty.
1503 1506
1504 1507 ``allowbz2``
1505 1508 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1506 1509 revisions.
1507 1510 Default is False.
1508 1511
1509 1512 ``allowgz``
1510 1513 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1511 1514 revisions.
1512 1515 Default is False.
1513 1516
1514 1517 ``allowpull``
1515 1518 Whether to allow pulling from the repository. Default is True.
1516 1519
1517 1520 ``allow_push``
1518 1521 Whether to allow pushing to the repository. If empty or not set,
1519 1522 push is not allowed. If the special value ``*``, any remote user can
1520 1523 push, including unauthenticated users. Otherwise, the remote user
1521 1524 must have been authenticated, and the authenticated user name must
1522 1525 be present in this list. The contents of the allow_push list are
1523 1526 examined after the deny_push list.
1524 1527
1525 1528 ``allow_read``
1526 1529 If the user has not already been denied repository access due to
1527 1530 the contents of deny_read, this list determines whether to grant
1528 1531 repository access to the user. If this list is not empty, and the
1529 1532 user is unauthenticated or not present in the list, then access is
1530 1533 denied for the user. If the list is empty or not set, then access
1531 1534 is permitted to all users by default. Setting allow_read to the
1532 1535 special value ``*`` is equivalent to it not being set (i.e. access
1533 1536 is permitted to all users). The contents of the allow_read list are
1534 1537 examined after the deny_read list.
1535 1538
1536 1539 ``allowzip``
1537 1540 (DEPRECATED) Whether to allow .zip downloading of repository
1538 1541 revisions. Default is False. This feature creates temporary files.
1539 1542
1540 1543 ``archivesubrepos``
1541 1544 Whether to recurse into subrepositories when archiving. Default is
1542 1545 False.
1543 1546
1544 1547 ``baseurl``
1545 1548 Base URL to use when publishing URLs in other locations, so
1546 1549 third-party tools like email notification hooks can construct
1547 1550 URLs. Example: ``http://hgserver/repos/``.
1548 1551
1549 1552 ``cacerts``
1550 1553 Path to file containing a list of PEM encoded certificate
1551 1554 authority certificates. Environment variables and ``~user``
1552 1555 constructs are expanded in the filename. If specified on the
1553 1556 client, then it will verify the identity of remote HTTPS servers
1554 1557 with these certificates.
1555 1558
1556 1559 This feature is only supported when using Python 2.6 or later. If you wish
1557 1560 to use it with earlier versions of Python, install the backported
1558 1561 version of the ssl library that is available from
1559 1562 ``http://pypi.python.org``.
1560 1563
1561 1564 To disable SSL verification temporarily, specify ``--insecure`` from
1562 1565 command line.
1563 1566
1564 1567 You can use OpenSSL's CA certificate file if your platform has
1565 1568 one. On most Linux systems this will be
1566 1569 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1567 1570 generate this file manually. The form must be as follows::
1568 1571
1569 1572 -----BEGIN CERTIFICATE-----
1570 1573 ... (certificate in base64 PEM encoding) ...
1571 1574 -----END CERTIFICATE-----
1572 1575 -----BEGIN CERTIFICATE-----
1573 1576 ... (certificate in base64 PEM encoding) ...
1574 1577 -----END CERTIFICATE-----
1575 1578
1576 1579 ``cache``
1577 1580 Whether to support caching in hgweb. Defaults to True.
1578 1581
1579 1582 ``collapse``
1580 1583 With ``descend`` enabled, repositories in subdirectories are shown at
1581 1584 a single level alongside repositories in the current path. With
1582 1585 ``collapse`` also enabled, repositories residing at a deeper level than
1583 1586 the current path are grouped behind navigable directory entries that
1584 1587 lead to the locations of these repositories. In effect, this setting
1585 1588 collapses each collection of repositories found within a subdirectory
1586 1589 into a single entry for that subdirectory. Default is False.
1587 1590
1588 1591 ``comparisoncontext``
1589 1592 Number of lines of context to show in side-by-side file comparison. If
1590 1593 negative or the value ``full``, whole files are shown. Default is 5.
1591 1594 This setting can be overridden by a ``context`` request parameter to the
1592 1595 ``comparison`` command, taking the same values.
1593 1596
1594 1597 ``contact``
1595 1598 Name or email address of the person in charge of the repository.
1596 1599 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1597 1600
1598 1601 ``deny_push``
1599 1602 Whether to deny pushing to the repository. If empty or not set,
1600 1603 push is not denied. If the special value ``*``, all remote users are
1601 1604 denied push. Otherwise, unauthenticated users are all denied, and
1602 1605 any authenticated user name present in this list is also denied. The
1603 1606 contents of the deny_push list are examined before the allow_push list.
1604 1607
1605 1608 ``deny_read``
1606 1609 Whether to deny reading/viewing of the repository. If this list is
1607 1610 not empty, unauthenticated users are all denied, and any
1608 1611 authenticated user name present in this list is also denied access to
1609 1612 the repository. If set to the special value ``*``, all remote users
1610 1613 are denied access (rarely needed ;). If deny_read is empty or not set,
1611 1614 the determination of repository access depends on the presence and
1612 1615 content of the allow_read list (see description). If both
1613 1616 deny_read and allow_read are empty or not set, then access is
1614 1617 permitted to all users by default. If the repository is being
1615 1618 served via hgwebdir, denied users will not be able to see it in
1616 1619 the list of repositories. The contents of the deny_read list have
1617 1620 priority over (are examined before) the contents of the allow_read
1618 1621 list.
1619 1622
1620 1623 ``descend``
1621 1624 hgwebdir indexes will not descend into subdirectories. Only repositories
1622 1625 directly in the current path will be shown (other repositories are still
1623 1626 available from the index corresponding to their containing path).
1624 1627
1625 1628 ``description``
1626 1629 Textual description of the repository's purpose or contents.
1627 1630 Default is "unknown".
1628 1631
1629 1632 ``encoding``
1630 1633 Character encoding name. Default is the current locale charset.
1631 1634 Example: "UTF-8"
1632 1635
1633 1636 ``errorlog``
1634 1637 Where to output the error log. Default is stderr.
1635 1638
1636 1639 ``guessmime``
1637 1640 Control MIME types for raw download of file content.
1638 1641 Set to True to let hgweb guess the content type from the file
1639 1642 extension. This will serve HTML files as ``text/html`` and might
1640 1643 allow cross-site scripting attacks when serving untrusted
1641 1644 repositories. Default is False.
1642 1645
1643 1646 ``hidden``
1644 1647 Whether to hide the repository in the hgwebdir index.
1645 1648 Default is False.
1646 1649
1647 1650 ``ipv6``
1648 1651 Whether to use IPv6. Default is False.
1649 1652
1650 1653 ``logoimg``
1651 1654 File name of the logo image that some templates display on each page.
1652 1655 The file name is relative to ``staticurl``. That is, the full path to
1653 1656 the logo image is "staticurl/logoimg".
1654 1657 If unset, ``hglogo.png`` will be used.
1655 1658
1656 1659 ``logourl``
1657 1660 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1658 1661 will be used.
1659 1662
1660 1663 ``maxchanges``
1661 1664 Maximum number of changes to list on the changelog. Default is 10.
1662 1665
1663 1666 ``maxfiles``
1664 1667 Maximum number of files to list per changeset. Default is 10.
1665 1668
1666 1669 ``maxshortchanges``
1667 1670 Maximum number of changes to list on the shortlog, graph or filelog
1668 1671 pages. Default is 60.
1669 1672
1670 1673 ``name``
1671 1674 Repository name to use in the web interface. Default is current
1672 1675 working directory.
1673 1676
1674 1677 ``port``
1675 1678 Port to listen on. Default is 8000.
1676 1679
1677 1680 ``prefix``
1678 1681 Prefix path to serve from. Default is '' (server root).
1679 1682
1680 1683 ``push_ssl``
1681 1684 Whether to require that inbound pushes be transported over SSL to
1682 1685 prevent password sniffing. Default is True.
1683 1686
1684 1687 ``staticurl``
1685 1688 Base URL to use for static files. If unset, static files (e.g. the
1686 1689 hgicon.png favicon) will be served by the CGI script itself. Use
1687 1690 this setting to serve them directly with the HTTP server.
1688 1691 Example: ``http://hgserver/static/``.
1689 1692
1690 1693 ``stripes``
1691 1694 How many lines a "zebra stripe" should span in multi-line output.
1692 1695 Default is 1; set to 0 to disable.
1693 1696
1694 1697 ``style``
1695 1698 Which template map style to use. The available options are the names of
1696 1699 subdirectories in the HTML templates path. Default is ``paper``.
1697 1700 Example: ``monoblue``
1698 1701
1699 1702 ``templates``
1700 1703 Where to find the HTML templates. The default path to the HTML templates
1701 1704 can be obtained from ``hg debuginstall``.
1702 1705
1703 1706 ``websub``
1704 1707 ----------
1705 1708
1706 1709 Web substitution filter definition. You can use this section to
1707 1710 define a set of regular expression substitution patterns which
1708 1711 let you automatically modify the hgweb server output.
1709 1712
1710 1713 The default hgweb templates only apply these substitution patterns
1711 1714 on the revision description fields. You can apply them anywhere
1712 1715 you want when you create your own templates by adding calls to the
1713 1716 "websub" filter (usually after calling the "escape" filter).
1714 1717
1715 1718 This can be used, for example, to convert issue references to links
1716 1719 to your issue tracker, or to convert "markdown-like" syntax into
1717 1720 HTML (see the examples below).
1718 1721
1719 1722 Each entry in this section names a substitution filter.
1720 1723 The value of each entry defines the substitution expression itself.
1721 1724 The websub expressions follow the old interhg extension syntax,
1722 1725 which in turn imitates the Unix sed replacement syntax::
1723 1726
1724 1727 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1725 1728
1726 1729 You can use any separator other than "/". The final "i" is optional
1727 1730 and indicates that the search must be case insensitive.
1728 1731
1729 1732 Examples::
1730 1733
1731 1734 [websub]
1732 1735 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1733 1736 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1734 1737 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1735 1738
1736 1739 ``worker``
1737 1740 ----------
1738 1741
1739 1742 Parallel master/worker configuration. We currently perform working
1740 1743 directory updates in parallel on Unix-like systems, which greatly
1741 1744 helps performance.
1742 1745
1743 1746 ``numcpus``
1744 1747 Number of CPUs to use for parallel operations. Default is 4 or the
1745 1748 number of CPUs on the system, whichever is larger. A zero or
1746 1749 negative value is treated as ``use the default``.
@@ -1,974 +1,974 b''
1 1 # ui.py - user interface bits for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from i18n import _
9 9 import errno, getpass, os, socket, sys, tempfile, traceback
10 10 import config, scmutil, util, error, formatter
11 11 from node import hex
12 12
13 13 samplehgrcs = {
14 14 'user':
15 15 """# example user config (see "hg help config" for more info)
16 16 [ui]
17 17 # name and email, e.g.
18 18 # username = Jane Doe <jdoe@example.com>
19 19 username =
20 20
21 21 [extensions]
22 22 # uncomment these lines to enable some popular extensions
23 23 # (see "hg help extensions" for more info)
24 24 #
25 25 # pager =
26 26 # progress =
27 27 # color =""",
28 28
29 29 'cloned':
30 30 """# example repository config (see "hg help config" for more info)
31 31 [paths]
32 32 default = %s
33 33
34 34 # path aliases to other clones of this repo in URLs or filesystem paths
35 35 # (see "hg help config.paths" for more info)
36 36 #
37 37 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
38 38 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
39 39 # my-clone = /home/jdoe/jdoes-clone
40 40
41 41 [ui]
42 42 # name and email (local to this repository, optional), e.g.
43 43 # username = Jane Doe <jdoe@example.com>
44 44 """,
45 45
46 46 'local':
47 47 """# example repository config (see "hg help config" for more info)
48 48 [paths]
49 49 # path aliases to other clones of this repo in URLs or filesystem paths
50 50 # (see "hg help config.paths" for more info)
51 51 #
52 52 # default = http://example.com/hg/example-repo
53 53 # default-push = ssh://jdoe@example.net/hg/jdoes-fork
54 54 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
55 55 # my-clone = /home/jdoe/jdoes-clone
56 56
57 57 [ui]
58 58 # name and email (local to this repository, optional), e.g.
59 59 # username = Jane Doe <jdoe@example.com>
60 60 """,
61 61
62 62 'global':
63 63 """# example system-wide hg config (see "hg help config" for more info)
64 64
65 65 [extensions]
66 66 # uncomment these lines to enable some popular extensions
67 67 # (see "hg help extensions" for more info)
68 68 #
69 69 # blackbox =
70 70 # progress =
71 71 # color =
72 72 # pager =""",
73 73 }
74 74
75 75 class ui(object):
76 76 def __init__(self, src=None):
77 77 # _buffers: used for temporary capture of output
78 78 self._buffers = []
79 79 # _bufferstates: Should the temporary capture includes stderr
80 80 self._bufferstates = []
81 81 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
82 82 self._reportuntrusted = True
83 83 self._ocfg = config.config() # overlay
84 84 self._tcfg = config.config() # trusted
85 85 self._ucfg = config.config() # untrusted
86 86 self._trustusers = set()
87 87 self._trustgroups = set()
88 88 self.callhooks = True
89 89
90 90 if src:
91 91 self.fout = src.fout
92 92 self.ferr = src.ferr
93 93 self.fin = src.fin
94 94
95 95 self._tcfg = src._tcfg.copy()
96 96 self._ucfg = src._ucfg.copy()
97 97 self._ocfg = src._ocfg.copy()
98 98 self._trustusers = src._trustusers.copy()
99 99 self._trustgroups = src._trustgroups.copy()
100 100 self.environ = src.environ
101 101 self.callhooks = src.callhooks
102 102 self.fixconfig()
103 103 else:
104 104 self.fout = sys.stdout
105 105 self.ferr = sys.stderr
106 106 self.fin = sys.stdin
107 107
108 108 # shared read-only environment
109 109 self.environ = os.environ
110 110 # we always trust global config files
111 111 for f in scmutil.rcpath():
112 112 self.readconfig(f, trust=True)
113 113
114 114 def copy(self):
115 115 return self.__class__(self)
116 116
117 117 def formatter(self, topic, opts):
118 118 return formatter.formatter(self, topic, opts)
119 119
120 120 def _trusted(self, fp, f):
121 121 st = util.fstat(fp)
122 122 if util.isowner(st):
123 123 return True
124 124
125 125 tusers, tgroups = self._trustusers, self._trustgroups
126 126 if '*' in tusers or '*' in tgroups:
127 127 return True
128 128
129 129 user = util.username(st.st_uid)
130 130 group = util.groupname(st.st_gid)
131 131 if user in tusers or group in tgroups or user == util.username():
132 132 return True
133 133
134 134 if self._reportuntrusted:
135 135 self.warn(_('not trusting file %s from untrusted '
136 136 'user %s, group %s\n') % (f, user, group))
137 137 return False
138 138
139 139 def readconfig(self, filename, root=None, trust=False,
140 140 sections=None, remap=None):
141 141 try:
142 142 fp = open(filename)
143 143 except IOError:
144 144 if not sections: # ignore unless we were looking for something
145 145 return
146 146 raise
147 147
148 148 cfg = config.config()
149 149 trusted = sections or trust or self._trusted(fp, filename)
150 150
151 151 try:
152 152 cfg.read(filename, fp, sections=sections, remap=remap)
153 153 fp.close()
154 154 except error.ConfigError, inst:
155 155 if trusted:
156 156 raise
157 157 self.warn(_("ignored: %s\n") % str(inst))
158 158
159 159 if self.plain():
160 160 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
161 'logtemplate', 'style',
161 'logtemplate', 'statuscopies', 'style',
162 162 'traceback', 'verbose'):
163 163 if k in cfg['ui']:
164 164 del cfg['ui'][k]
165 165 for k, v in cfg.items('defaults'):
166 166 del cfg['defaults'][k]
167 167 # Don't remove aliases from the configuration if in the exceptionlist
168 168 if self.plain('alias'):
169 169 for k, v in cfg.items('alias'):
170 170 del cfg['alias'][k]
171 171
172 172 if trusted:
173 173 self._tcfg.update(cfg)
174 174 self._tcfg.update(self._ocfg)
175 175 self._ucfg.update(cfg)
176 176 self._ucfg.update(self._ocfg)
177 177
178 178 if root is None:
179 179 root = os.path.expanduser('~')
180 180 self.fixconfig(root=root)
181 181
182 182 def fixconfig(self, root=None, section=None):
183 183 if section in (None, 'paths'):
184 184 # expand vars and ~
185 185 # translate paths relative to root (or home) into absolute paths
186 186 root = root or os.getcwd()
187 187 for c in self._tcfg, self._ucfg, self._ocfg:
188 188 for n, p in c.items('paths'):
189 189 if not p:
190 190 continue
191 191 if '%%' in p:
192 192 self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
193 193 % (n, p, self.configsource('paths', n)))
194 194 p = p.replace('%%', '%')
195 195 p = util.expandpath(p)
196 196 if not util.hasscheme(p) and not os.path.isabs(p):
197 197 p = os.path.normpath(os.path.join(root, p))
198 198 c.set("paths", n, p)
199 199
200 200 if section in (None, 'ui'):
201 201 # update ui options
202 202 self.debugflag = self.configbool('ui', 'debug')
203 203 self.verbose = self.debugflag or self.configbool('ui', 'verbose')
204 204 self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
205 205 if self.verbose and self.quiet:
206 206 self.quiet = self.verbose = False
207 207 self._reportuntrusted = self.debugflag or self.configbool("ui",
208 208 "report_untrusted", True)
209 209 self.tracebackflag = self.configbool('ui', 'traceback', False)
210 210
211 211 if section in (None, 'trusted'):
212 212 # update trust information
213 213 self._trustusers.update(self.configlist('trusted', 'users'))
214 214 self._trustgroups.update(self.configlist('trusted', 'groups'))
215 215
216 216 def backupconfig(self, section, item):
217 217 return (self._ocfg.backup(section, item),
218 218 self._tcfg.backup(section, item),
219 219 self._ucfg.backup(section, item),)
220 220 def restoreconfig(self, data):
221 221 self._ocfg.restore(data[0])
222 222 self._tcfg.restore(data[1])
223 223 self._ucfg.restore(data[2])
224 224
225 225 def setconfig(self, section, name, value, source=''):
226 226 for cfg in (self._ocfg, self._tcfg, self._ucfg):
227 227 cfg.set(section, name, value, source)
228 228 self.fixconfig(section=section)
229 229
230 230 def _data(self, untrusted):
231 231 return untrusted and self._ucfg or self._tcfg
232 232
233 233 def configsource(self, section, name, untrusted=False):
234 234 return self._data(untrusted).source(section, name) or 'none'
235 235
236 236 def config(self, section, name, default=None, untrusted=False):
237 237 if isinstance(name, list):
238 238 alternates = name
239 239 else:
240 240 alternates = [name]
241 241
242 242 for n in alternates:
243 243 value = self._data(untrusted).get(section, n, None)
244 244 if value is not None:
245 245 name = n
246 246 break
247 247 else:
248 248 value = default
249 249
250 250 if self.debugflag and not untrusted and self._reportuntrusted:
251 251 for n in alternates:
252 252 uvalue = self._ucfg.get(section, n)
253 253 if uvalue is not None and uvalue != value:
254 254 self.debug("ignoring untrusted configuration option "
255 255 "%s.%s = %s\n" % (section, n, uvalue))
256 256 return value
257 257
258 258 def configpath(self, section, name, default=None, untrusted=False):
259 259 'get a path config item, expanded relative to repo root or config file'
260 260 v = self.config(section, name, default, untrusted)
261 261 if v is None:
262 262 return None
263 263 if not os.path.isabs(v) or "://" not in v:
264 264 src = self.configsource(section, name, untrusted)
265 265 if ':' in src:
266 266 base = os.path.dirname(src.rsplit(':')[0])
267 267 v = os.path.join(base, os.path.expanduser(v))
268 268 return v
269 269
270 270 def configbool(self, section, name, default=False, untrusted=False):
271 271 """parse a configuration element as a boolean
272 272
273 273 >>> u = ui(); s = 'foo'
274 274 >>> u.setconfig(s, 'true', 'yes')
275 275 >>> u.configbool(s, 'true')
276 276 True
277 277 >>> u.setconfig(s, 'false', 'no')
278 278 >>> u.configbool(s, 'false')
279 279 False
280 280 >>> u.configbool(s, 'unknown')
281 281 False
282 282 >>> u.configbool(s, 'unknown', True)
283 283 True
284 284 >>> u.setconfig(s, 'invalid', 'somevalue')
285 285 >>> u.configbool(s, 'invalid')
286 286 Traceback (most recent call last):
287 287 ...
288 288 ConfigError: foo.invalid is not a boolean ('somevalue')
289 289 """
290 290
291 291 v = self.config(section, name, None, untrusted)
292 292 if v is None:
293 293 return default
294 294 if isinstance(v, bool):
295 295 return v
296 296 b = util.parsebool(v)
297 297 if b is None:
298 298 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
299 299 % (section, name, v))
300 300 return b
301 301
302 302 def configint(self, section, name, default=None, untrusted=False):
303 303 """parse a configuration element as an integer
304 304
305 305 >>> u = ui(); s = 'foo'
306 306 >>> u.setconfig(s, 'int1', '42')
307 307 >>> u.configint(s, 'int1')
308 308 42
309 309 >>> u.setconfig(s, 'int2', '-42')
310 310 >>> u.configint(s, 'int2')
311 311 -42
312 312 >>> u.configint(s, 'unknown', 7)
313 313 7
314 314 >>> u.setconfig(s, 'invalid', 'somevalue')
315 315 >>> u.configint(s, 'invalid')
316 316 Traceback (most recent call last):
317 317 ...
318 318 ConfigError: foo.invalid is not an integer ('somevalue')
319 319 """
320 320
321 321 v = self.config(section, name, None, untrusted)
322 322 if v is None:
323 323 return default
324 324 try:
325 325 return int(v)
326 326 except ValueError:
327 327 raise error.ConfigError(_("%s.%s is not an integer ('%s')")
328 328 % (section, name, v))
329 329
330 330 def configbytes(self, section, name, default=0, untrusted=False):
331 331 """parse a configuration element as a quantity in bytes
332 332
333 333 Units can be specified as b (bytes), k or kb (kilobytes), m or
334 334 mb (megabytes), g or gb (gigabytes).
335 335
336 336 >>> u = ui(); s = 'foo'
337 337 >>> u.setconfig(s, 'val1', '42')
338 338 >>> u.configbytes(s, 'val1')
339 339 42
340 340 >>> u.setconfig(s, 'val2', '42.5 kb')
341 341 >>> u.configbytes(s, 'val2')
342 342 43520
343 343 >>> u.configbytes(s, 'unknown', '7 MB')
344 344 7340032
345 345 >>> u.setconfig(s, 'invalid', 'somevalue')
346 346 >>> u.configbytes(s, 'invalid')
347 347 Traceback (most recent call last):
348 348 ...
349 349 ConfigError: foo.invalid is not a byte quantity ('somevalue')
350 350 """
351 351
352 352 value = self.config(section, name)
353 353 if value is None:
354 354 if not isinstance(default, str):
355 355 return default
356 356 value = default
357 357 try:
358 358 return util.sizetoint(value)
359 359 except error.ParseError:
360 360 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
361 361 % (section, name, value))
362 362
363 363 def configlist(self, section, name, default=None, untrusted=False):
364 364 """parse a configuration element as a list of comma/space separated
365 365 strings
366 366
367 367 >>> u = ui(); s = 'foo'
368 368 >>> u.setconfig(s, 'list1', 'this,is "a small" ,test')
369 369 >>> u.configlist(s, 'list1')
370 370 ['this', 'is', 'a small', 'test']
371 371 """
372 372
373 373 def _parse_plain(parts, s, offset):
374 374 whitespace = False
375 375 while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
376 376 whitespace = True
377 377 offset += 1
378 378 if offset >= len(s):
379 379 return None, parts, offset
380 380 if whitespace:
381 381 parts.append('')
382 382 if s[offset] == '"' and not parts[-1]:
383 383 return _parse_quote, parts, offset + 1
384 384 elif s[offset] == '"' and parts[-1][-1] == '\\':
385 385 parts[-1] = parts[-1][:-1] + s[offset]
386 386 return _parse_plain, parts, offset + 1
387 387 parts[-1] += s[offset]
388 388 return _parse_plain, parts, offset + 1
389 389
390 390 def _parse_quote(parts, s, offset):
391 391 if offset < len(s) and s[offset] == '"': # ""
392 392 parts.append('')
393 393 offset += 1
394 394 while offset < len(s) and (s[offset].isspace() or
395 395 s[offset] == ','):
396 396 offset += 1
397 397 return _parse_plain, parts, offset
398 398
399 399 while offset < len(s) and s[offset] != '"':
400 400 if (s[offset] == '\\' and offset + 1 < len(s)
401 401 and s[offset + 1] == '"'):
402 402 offset += 1
403 403 parts[-1] += '"'
404 404 else:
405 405 parts[-1] += s[offset]
406 406 offset += 1
407 407
408 408 if offset >= len(s):
409 409 real_parts = _configlist(parts[-1])
410 410 if not real_parts:
411 411 parts[-1] = '"'
412 412 else:
413 413 real_parts[0] = '"' + real_parts[0]
414 414 parts = parts[:-1]
415 415 parts.extend(real_parts)
416 416 return None, parts, offset
417 417
418 418 offset += 1
419 419 while offset < len(s) and s[offset] in [' ', ',']:
420 420 offset += 1
421 421
422 422 if offset < len(s):
423 423 if offset + 1 == len(s) and s[offset] == '"':
424 424 parts[-1] += '"'
425 425 offset += 1
426 426 else:
427 427 parts.append('')
428 428 else:
429 429 return None, parts, offset
430 430
431 431 return _parse_plain, parts, offset
432 432
433 433 def _configlist(s):
434 434 s = s.rstrip(' ,')
435 435 if not s:
436 436 return []
437 437 parser, parts, offset = _parse_plain, [''], 0
438 438 while parser:
439 439 parser, parts, offset = parser(parts, s, offset)
440 440 return parts
441 441
442 442 result = self.config(section, name, untrusted=untrusted)
443 443 if result is None:
444 444 result = default or []
445 445 if isinstance(result, basestring):
446 446 result = _configlist(result.lstrip(' ,\n'))
447 447 if result is None:
448 448 result = default or []
449 449 return result
450 450
451 451 def has_section(self, section, untrusted=False):
452 452 '''tell whether section exists in config.'''
453 453 return section in self._data(untrusted)
454 454
455 455 def configitems(self, section, untrusted=False):
456 456 items = self._data(untrusted).items(section)
457 457 if self.debugflag and not untrusted and self._reportuntrusted:
458 458 for k, v in self._ucfg.items(section):
459 459 if self._tcfg.get(section, k) != v:
460 460 self.debug("ignoring untrusted configuration option "
461 461 "%s.%s = %s\n" % (section, k, v))
462 462 return items
463 463
464 464 def walkconfig(self, untrusted=False):
465 465 cfg = self._data(untrusted)
466 466 for section in cfg.sections():
467 467 for name, value in self.configitems(section, untrusted):
468 468 yield section, name, value
469 469
470 470 def plain(self, feature=None):
471 471 '''is plain mode active?
472 472
473 473 Plain mode means that all configuration variables which affect
474 474 the behavior and output of Mercurial should be
475 475 ignored. Additionally, the output should be stable,
476 476 reproducible and suitable for use in scripts or applications.
477 477
478 478 The only way to trigger plain mode is by setting either the
479 479 `HGPLAIN' or `HGPLAINEXCEPT' environment variables.
480 480
481 481 The return value can either be
482 482 - False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
483 483 - True otherwise
484 484 '''
485 485 if 'HGPLAIN' not in os.environ and 'HGPLAINEXCEPT' not in os.environ:
486 486 return False
487 487 exceptions = os.environ.get('HGPLAINEXCEPT', '').strip().split(',')
488 488 if feature and exceptions:
489 489 return feature not in exceptions
490 490 return True
491 491
492 492 def username(self):
493 493 """Return default username to be used in commits.
494 494
495 495 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
496 496 and stop searching if one of these is set.
497 497 If not found and ui.askusername is True, ask the user, else use
498 498 ($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
499 499 """
500 500 user = os.environ.get("HGUSER")
501 501 if user is None:
502 502 user = self.config("ui", ["username", "user"])
503 503 if user is not None:
504 504 user = os.path.expandvars(user)
505 505 if user is None:
506 506 user = os.environ.get("EMAIL")
507 507 if user is None and self.configbool("ui", "askusername"):
508 508 user = self.prompt(_("enter a commit username:"), default=None)
509 509 if user is None and not self.interactive():
510 510 try:
511 511 user = '%s@%s' % (util.getuser(), socket.getfqdn())
512 512 self.warn(_("no username found, using '%s' instead\n") % user)
513 513 except KeyError:
514 514 pass
515 515 if not user:
516 516 raise util.Abort(_('no username supplied'),
517 517 hint=_('use "hg config --edit" '
518 518 'to set your username'))
519 519 if "\n" in user:
520 520 raise util.Abort(_("username %s contains a newline\n") % repr(user))
521 521 return user
522 522
523 523 def shortuser(self, user):
524 524 """Return a short representation of a user name or email address."""
525 525 if not self.verbose:
526 526 user = util.shortuser(user)
527 527 return user
528 528
529 529 def expandpath(self, loc, default=None):
530 530 """Return repository location relative to cwd or from [paths]"""
531 531 if util.hasscheme(loc) or os.path.isdir(os.path.join(loc, '.hg')):
532 532 return loc
533 533
534 534 p = self.paths.getpath(loc, default=default)
535 535 if p:
536 536 return p.loc
537 537 return loc
538 538
539 539 @util.propertycache
540 540 def paths(self):
541 541 return paths(self)
542 542
543 543 def pushbuffer(self, error=False):
544 544 """install a buffer to capture standard output of the ui object
545 545
546 546 If error is True, the error output will be captured too."""
547 547 self._buffers.append([])
548 548 self._bufferstates.append(error)
549 549
550 550 def popbuffer(self, labeled=False):
551 551 '''pop the last buffer and return the buffered output
552 552
553 553 If labeled is True, any labels associated with buffered
554 554 output will be handled. By default, this has no effect
555 555 on the output returned, but extensions and GUI tools may
556 556 handle this argument and returned styled output. If output
557 557 is being buffered so it can be captured and parsed or
558 558 processed, labeled should not be set to True.
559 559 '''
560 560 self._bufferstates.pop()
561 561 return "".join(self._buffers.pop())
562 562
563 563 def write(self, *args, **opts):
564 564 '''write args to output
565 565
566 566 By default, this method simply writes to the buffer or stdout,
567 567 but extensions or GUI tools may override this method,
568 568 write_err(), popbuffer(), and label() to style output from
569 569 various parts of hg.
570 570
571 571 An optional keyword argument, "label", can be passed in.
572 572 This should be a string containing label names separated by
573 573 space. Label names take the form of "topic.type". For example,
574 574 ui.debug() issues a label of "ui.debug".
575 575
576 576 When labeling output for a specific command, a label of
577 577 "cmdname.type" is recommended. For example, status issues
578 578 a label of "status.modified" for modified files.
579 579 '''
580 580 if self._buffers:
581 581 self._buffers[-1].extend([str(a) for a in args])
582 582 else:
583 583 for a in args:
584 584 self.fout.write(str(a))
585 585
586 586 def write_err(self, *args, **opts):
587 587 try:
588 588 if self._bufferstates and self._bufferstates[-1]:
589 589 return self.write(*args, **opts)
590 590 if not getattr(self.fout, 'closed', False):
591 591 self.fout.flush()
592 592 for a in args:
593 593 self.ferr.write(str(a))
594 594 # stderr may be buffered under win32 when redirected to files,
595 595 # including stdout.
596 596 if not getattr(self.ferr, 'closed', False):
597 597 self.ferr.flush()
598 598 except IOError, inst:
599 599 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
600 600 raise
601 601
602 602 def flush(self):
603 603 try: self.fout.flush()
604 604 except (IOError, ValueError): pass
605 605 try: self.ferr.flush()
606 606 except (IOError, ValueError): pass
607 607
608 608 def _isatty(self, fh):
609 609 if self.configbool('ui', 'nontty', False):
610 610 return False
611 611 return util.isatty(fh)
612 612
613 613 def interactive(self):
614 614 '''is interactive input allowed?
615 615
616 616 An interactive session is a session where input can be reasonably read
617 617 from `sys.stdin'. If this function returns false, any attempt to read
618 618 from stdin should fail with an error, unless a sensible default has been
619 619 specified.
620 620
621 621 Interactiveness is triggered by the value of the `ui.interactive'
622 622 configuration variable or - if it is unset - when `sys.stdin' points
623 623 to a terminal device.
624 624
625 625 This function refers to input only; for output, see `ui.formatted()'.
626 626 '''
627 627 i = self.configbool("ui", "interactive", None)
628 628 if i is None:
629 629 # some environments replace stdin without implementing isatty
630 630 # usually those are non-interactive
631 631 return self._isatty(self.fin)
632 632
633 633 return i
634 634
635 635 def termwidth(self):
636 636 '''how wide is the terminal in columns?
637 637 '''
638 638 if 'COLUMNS' in os.environ:
639 639 try:
640 640 return int(os.environ['COLUMNS'])
641 641 except ValueError:
642 642 pass
643 643 return util.termwidth()
644 644
645 645 def formatted(self):
646 646 '''should formatted output be used?
647 647
648 648 It is often desirable to format the output to suite the output medium.
649 649 Examples of this are truncating long lines or colorizing messages.
650 650 However, this is not often not desirable when piping output into other
651 651 utilities, e.g. `grep'.
652 652
653 653 Formatted output is triggered by the value of the `ui.formatted'
654 654 configuration variable or - if it is unset - when `sys.stdout' points
655 655 to a terminal device. Please note that `ui.formatted' should be
656 656 considered an implementation detail; it is not intended for use outside
657 657 Mercurial or its extensions.
658 658
659 659 This function refers to output only; for input, see `ui.interactive()'.
660 660 This function always returns false when in plain mode, see `ui.plain()'.
661 661 '''
662 662 if self.plain():
663 663 return False
664 664
665 665 i = self.configbool("ui", "formatted", None)
666 666 if i is None:
667 667 # some environments replace stdout without implementing isatty
668 668 # usually those are non-interactive
669 669 return self._isatty(self.fout)
670 670
671 671 return i
672 672
673 673 def _readline(self, prompt=''):
674 674 if self._isatty(self.fin):
675 675 try:
676 676 # magically add command line editing support, where
677 677 # available
678 678 import readline
679 679 # force demandimport to really load the module
680 680 readline.read_history_file
681 681 # windows sometimes raises something other than ImportError
682 682 except Exception:
683 683 pass
684 684
685 685 # call write() so output goes through subclassed implementation
686 686 # e.g. color extension on Windows
687 687 self.write(prompt)
688 688
689 689 # instead of trying to emulate raw_input, swap (self.fin,
690 690 # self.fout) with (sys.stdin, sys.stdout)
691 691 oldin = sys.stdin
692 692 oldout = sys.stdout
693 693 sys.stdin = self.fin
694 694 sys.stdout = self.fout
695 695 # prompt ' ' must exist; otherwise readline may delete entire line
696 696 # - http://bugs.python.org/issue12833
697 697 line = raw_input(' ')
698 698 sys.stdin = oldin
699 699 sys.stdout = oldout
700 700
701 701 # When stdin is in binary mode on Windows, it can cause
702 702 # raw_input() to emit an extra trailing carriage return
703 703 if os.linesep == '\r\n' and line and line[-1] == '\r':
704 704 line = line[:-1]
705 705 return line
706 706
707 707 def prompt(self, msg, default="y"):
708 708 """Prompt user with msg, read response.
709 709 If ui is not interactive, the default is returned.
710 710 """
711 711 if not self.interactive():
712 712 self.write(msg, ' ', default, "\n")
713 713 return default
714 714 try:
715 715 r = self._readline(self.label(msg, 'ui.prompt'))
716 716 if not r:
717 717 r = default
718 718 if self.configbool('ui', 'promptecho'):
719 719 self.write(r, "\n")
720 720 return r
721 721 except EOFError:
722 722 raise util.Abort(_('response expected'))
723 723
724 724 @staticmethod
725 725 def extractchoices(prompt):
726 726 """Extract prompt message and list of choices from specified prompt.
727 727
728 728 This returns tuple "(message, choices)", and "choices" is the
729 729 list of tuple "(response character, text without &)".
730 730 """
731 731 parts = prompt.split('$$')
732 732 msg = parts[0].rstrip(' ')
733 733 choices = [p.strip(' ') for p in parts[1:]]
734 734 return (msg,
735 735 [(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
736 736 for s in choices])
737 737
738 738 def promptchoice(self, prompt, default=0):
739 739 """Prompt user with a message, read response, and ensure it matches
740 740 one of the provided choices. The prompt is formatted as follows:
741 741
742 742 "would you like fries with that (Yn)? $$ &Yes $$ &No"
743 743
744 744 The index of the choice is returned. Responses are case
745 745 insensitive. If ui is not interactive, the default is
746 746 returned.
747 747 """
748 748
749 749 msg, choices = self.extractchoices(prompt)
750 750 resps = [r for r, t in choices]
751 751 while True:
752 752 r = self.prompt(msg, resps[default])
753 753 if r.lower() in resps:
754 754 return resps.index(r.lower())
755 755 self.write(_("unrecognized response\n"))
756 756
757 757 def getpass(self, prompt=None, default=None):
758 758 if not self.interactive():
759 759 return default
760 760 try:
761 761 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
762 762 # disable getpass() only if explicitly specified. it's still valid
763 763 # to interact with tty even if fin is not a tty.
764 764 if self.configbool('ui', 'nontty'):
765 765 return self.fin.readline().rstrip('\n')
766 766 else:
767 767 return getpass.getpass('')
768 768 except EOFError:
769 769 raise util.Abort(_('response expected'))
770 770 def status(self, *msg, **opts):
771 771 '''write status message to output (if ui.quiet is False)
772 772
773 773 This adds an output label of "ui.status".
774 774 '''
775 775 if not self.quiet:
776 776 opts['label'] = opts.get('label', '') + ' ui.status'
777 777 self.write(*msg, **opts)
778 778 def warn(self, *msg, **opts):
779 779 '''write warning message to output (stderr)
780 780
781 781 This adds an output label of "ui.warning".
782 782 '''
783 783 opts['label'] = opts.get('label', '') + ' ui.warning'
784 784 self.write_err(*msg, **opts)
785 785 def note(self, *msg, **opts):
786 786 '''write note to output (if ui.verbose is True)
787 787
788 788 This adds an output label of "ui.note".
789 789 '''
790 790 if self.verbose:
791 791 opts['label'] = opts.get('label', '') + ' ui.note'
792 792 self.write(*msg, **opts)
793 793 def debug(self, *msg, **opts):
794 794 '''write debug message to output (if ui.debugflag is True)
795 795
796 796 This adds an output label of "ui.debug".
797 797 '''
798 798 if self.debugflag:
799 799 opts['label'] = opts.get('label', '') + ' ui.debug'
800 800 self.write(*msg, **opts)
801 801 def edit(self, text, user, extra={}, editform=None):
802 802 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
803 803 text=True)
804 804 try:
805 805 f = os.fdopen(fd, "w")
806 806 f.write(text)
807 807 f.close()
808 808
809 809 environ = {'HGUSER': user}
810 810 if 'transplant_source' in extra:
811 811 environ.update({'HGREVISION': hex(extra['transplant_source'])})
812 812 for label in ('source', 'rebase_source'):
813 813 if label in extra:
814 814 environ.update({'HGREVISION': extra[label]})
815 815 break
816 816 if editform:
817 817 environ.update({'HGEDITFORM': editform})
818 818
819 819 editor = self.geteditor()
820 820
821 821 self.system("%s \"%s\"" % (editor, name),
822 822 environ=environ,
823 823 onerr=util.Abort, errprefix=_("edit failed"))
824 824
825 825 f = open(name)
826 826 t = f.read()
827 827 f.close()
828 828 finally:
829 829 os.unlink(name)
830 830
831 831 return t
832 832
833 833 def system(self, cmd, environ={}, cwd=None, onerr=None, errprefix=None):
834 834 '''execute shell command with appropriate output stream. command
835 835 output will be redirected if fout is not stdout.
836 836 '''
837 837 return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
838 838 errprefix=errprefix, out=self.fout)
839 839
840 840 def traceback(self, exc=None, force=False):
841 841 '''print exception traceback if traceback printing enabled or forced.
842 842 only to call in exception handler. returns true if traceback
843 843 printed.'''
844 844 if self.tracebackflag or force:
845 845 if exc is None:
846 846 exc = sys.exc_info()
847 847 cause = getattr(exc[1], 'cause', None)
848 848
849 849 if cause is not None:
850 850 causetb = traceback.format_tb(cause[2])
851 851 exctb = traceback.format_tb(exc[2])
852 852 exconly = traceback.format_exception_only(cause[0], cause[1])
853 853
854 854 # exclude frame where 'exc' was chained and rethrown from exctb
855 855 self.write_err('Traceback (most recent call last):\n',
856 856 ''.join(exctb[:-1]),
857 857 ''.join(causetb),
858 858 ''.join(exconly))
859 859 else:
860 860 traceback.print_exception(exc[0], exc[1], exc[2],
861 861 file=self.ferr)
862 862 return self.tracebackflag or force
863 863
864 864 def geteditor(self):
865 865 '''return editor to use'''
866 866 if sys.platform == 'plan9':
867 867 # vi is the MIPS instruction simulator on Plan 9. We
868 868 # instead default to E to plumb commit messages to
869 869 # avoid confusion.
870 870 editor = 'E'
871 871 else:
872 872 editor = 'vi'
873 873 return (os.environ.get("HGEDITOR") or
874 874 self.config("ui", "editor") or
875 875 os.environ.get("VISUAL") or
876 876 os.environ.get("EDITOR", editor))
877 877
878 878 def progress(self, topic, pos, item="", unit="", total=None):
879 879 '''show a progress message
880 880
881 881 With stock hg, this is simply a debug message that is hidden
882 882 by default, but with extensions or GUI tools it may be
883 883 visible. 'topic' is the current operation, 'item' is a
884 884 non-numeric marker of the current position (i.e. the currently
885 885 in-process file), 'pos' is the current numeric position (i.e.
886 886 revision, bytes, etc.), unit is a corresponding unit label,
887 887 and total is the highest expected pos.
888 888
889 889 Multiple nested topics may be active at a time.
890 890
891 891 All topics should be marked closed by setting pos to None at
892 892 termination.
893 893 '''
894 894
895 895 if pos is None or not self.debugflag:
896 896 return
897 897
898 898 if unit:
899 899 unit = ' ' + unit
900 900 if item:
901 901 item = ' ' + item
902 902
903 903 if total:
904 904 pct = 100.0 * pos / total
905 905 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
906 906 % (topic, item, pos, total, unit, pct))
907 907 else:
908 908 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
909 909
910 910 def log(self, service, *msg, **opts):
911 911 '''hook for logging facility extensions
912 912
913 913 service should be a readily-identifiable subsystem, which will
914 914 allow filtering.
915 915 message should be a newline-terminated string to log.
916 916 '''
917 917 pass
918 918
919 919 def label(self, msg, label):
920 920 '''style msg based on supplied label
921 921
922 922 Like ui.write(), this just returns msg unchanged, but extensions
923 923 and GUI tools can override it to allow styling output without
924 924 writing it.
925 925
926 926 ui.write(s, 'label') is equivalent to
927 927 ui.write(ui.label(s, 'label')).
928 928 '''
929 929 return msg
930 930
931 931 class paths(dict):
932 932 """Represents a collection of paths and their configs.
933 933
934 934 Data is initially derived from ui instances and the config files they have
935 935 loaded.
936 936 """
937 937 def __init__(self, ui):
938 938 dict.__init__(self)
939 939
940 940 for name, loc in ui.configitems('paths'):
941 941 # No location is the same as not existing.
942 942 if not loc:
943 943 continue
944 944 self[name] = path(name, rawloc=loc)
945 945
946 946 def getpath(self, name, default=None):
947 947 """Return a ``path`` for the specified name, falling back to a default.
948 948
949 949 Returns the first of ``name`` or ``default`` that is present, or None
950 950 if neither is present.
951 951 """
952 952 try:
953 953 return self[name]
954 954 except KeyError:
955 955 if default is not None:
956 956 try:
957 957 return self[default]
958 958 except KeyError:
959 959 pass
960 960
961 961 return None
962 962
963 963 class path(object):
964 964 """Represents an individual path and its configuration."""
965 965
966 966 def __init__(self, name, rawloc=None):
967 967 """Construct a path from its config options.
968 968
969 969 ``name`` is the symbolic name of the path.
970 970 ``rawloc`` is the raw location, as defined in the config.
971 971 """
972 972 self.name = name
973 973 # We'll do more intelligent things with rawloc in the future.
974 974 self.loc = rawloc
@@ -1,449 +1,458 b''
1 1 $ hg init repo1
2 2 $ cd repo1
3 3 $ mkdir a b a/1 b/1 b/2
4 4 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
5 5
6 6 hg status in repo root:
7 7
8 8 $ hg status
9 9 ? a/1/in_a_1
10 10 ? a/in_a
11 11 ? b/1/in_b_1
12 12 ? b/2/in_b_2
13 13 ? b/in_b
14 14 ? in_root
15 15
16 16 hg status . in repo root:
17 17
18 18 $ hg status .
19 19 ? a/1/in_a_1
20 20 ? a/in_a
21 21 ? b/1/in_b_1
22 22 ? b/2/in_b_2
23 23 ? b/in_b
24 24 ? in_root
25 25
26 26 $ hg status --cwd a
27 27 ? a/1/in_a_1
28 28 ? a/in_a
29 29 ? b/1/in_b_1
30 30 ? b/2/in_b_2
31 31 ? b/in_b
32 32 ? in_root
33 33 $ hg status --cwd a .
34 34 ? 1/in_a_1
35 35 ? in_a
36 36 $ hg status --cwd a ..
37 37 ? 1/in_a_1
38 38 ? in_a
39 39 ? ../b/1/in_b_1
40 40 ? ../b/2/in_b_2
41 41 ? ../b/in_b
42 42 ? ../in_root
43 43
44 44 $ hg status --cwd b
45 45 ? a/1/in_a_1
46 46 ? a/in_a
47 47 ? b/1/in_b_1
48 48 ? b/2/in_b_2
49 49 ? b/in_b
50 50 ? in_root
51 51 $ hg status --cwd b .
52 52 ? 1/in_b_1
53 53 ? 2/in_b_2
54 54 ? in_b
55 55 $ hg status --cwd b ..
56 56 ? ../a/1/in_a_1
57 57 ? ../a/in_a
58 58 ? 1/in_b_1
59 59 ? 2/in_b_2
60 60 ? in_b
61 61 ? ../in_root
62 62
63 63 $ hg status --cwd a/1
64 64 ? a/1/in_a_1
65 65 ? a/in_a
66 66 ? b/1/in_b_1
67 67 ? b/2/in_b_2
68 68 ? b/in_b
69 69 ? in_root
70 70 $ hg status --cwd a/1 .
71 71 ? in_a_1
72 72 $ hg status --cwd a/1 ..
73 73 ? in_a_1
74 74 ? ../in_a
75 75
76 76 $ hg status --cwd b/1
77 77 ? a/1/in_a_1
78 78 ? a/in_a
79 79 ? b/1/in_b_1
80 80 ? b/2/in_b_2
81 81 ? b/in_b
82 82 ? in_root
83 83 $ hg status --cwd b/1 .
84 84 ? in_b_1
85 85 $ hg status --cwd b/1 ..
86 86 ? in_b_1
87 87 ? ../2/in_b_2
88 88 ? ../in_b
89 89
90 90 $ hg status --cwd b/2
91 91 ? a/1/in_a_1
92 92 ? a/in_a
93 93 ? b/1/in_b_1
94 94 ? b/2/in_b_2
95 95 ? b/in_b
96 96 ? in_root
97 97 $ hg status --cwd b/2 .
98 98 ? in_b_2
99 99 $ hg status --cwd b/2 ..
100 100 ? ../1/in_b_1
101 101 ? in_b_2
102 102 ? ../in_b
103 103
104 104 combining patterns with root and patterns without a root works
105 105
106 106 $ hg st a/in_a re:.*b$
107 107 ? a/in_a
108 108 ? b/in_b
109 109
110 110 $ cd ..
111 111
112 112 $ hg init repo2
113 113 $ cd repo2
114 114 $ touch modified removed deleted ignored
115 115 $ echo "^ignored$" > .hgignore
116 116 $ hg ci -A -m 'initial checkin'
117 117 adding .hgignore
118 118 adding deleted
119 119 adding modified
120 120 adding removed
121 121 $ touch modified added unknown ignored
122 122 $ hg add added
123 123 $ hg remove removed
124 124 $ rm deleted
125 125
126 126 hg status:
127 127
128 128 $ hg status
129 129 A added
130 130 R removed
131 131 ! deleted
132 132 ? unknown
133 133
134 134 hg status modified added removed deleted unknown never-existed ignored:
135 135
136 136 $ hg status modified added removed deleted unknown never-existed ignored
137 137 never-existed: * (glob)
138 138 A added
139 139 R removed
140 140 ! deleted
141 141 ? unknown
142 142
143 143 $ hg copy modified copied
144 144
145 145 hg status -C:
146 146
147 147 $ hg status -C
148 148 A added
149 149 A copied
150 150 modified
151 151 R removed
152 152 ! deleted
153 153 ? unknown
154 154
155 155 hg status -A:
156 156
157 157 $ hg status -A
158 158 A added
159 159 A copied
160 160 modified
161 161 R removed
162 162 ! deleted
163 163 ? unknown
164 164 I ignored
165 165 C .hgignore
166 166 C modified
167 167
168 168 $ hg status -A -Tjson
169 169 [
170 170 {
171 171 "path": "added",
172 172 "status": "A"
173 173 },
174 174 {
175 175 "copy": "modified",
176 176 "path": "copied",
177 177 "status": "A"
178 178 },
179 179 {
180 180 "path": "removed",
181 181 "status": "R"
182 182 },
183 183 {
184 184 "path": "deleted",
185 185 "status": "!"
186 186 },
187 187 {
188 188 "path": "unknown",
189 189 "status": "?"
190 190 },
191 191 {
192 192 "path": "ignored",
193 193 "status": "I"
194 194 },
195 195 {
196 196 "path": ".hgignore",
197 197 "status": "C"
198 198 },
199 199 {
200 200 "path": "modified",
201 201 "status": "C"
202 202 }
203 203 ]
204 204
205 205 $ hg status -A -Tpickle > pickle
206 206 >>> import pickle
207 207 >>> print sorted((x['status'], x['path']) for x in pickle.load(open("pickle")))
208 208 [('!', 'deleted'), ('?', 'pickle'), ('?', 'unknown'), ('A', 'added'), ('A', 'copied'), ('C', '.hgignore'), ('C', 'modified'), ('I', 'ignored'), ('R', 'removed')]
209 209 $ rm pickle
210 210
211 211 $ echo "^ignoreddir$" > .hgignore
212 212 $ mkdir ignoreddir
213 213 $ touch ignoreddir/file
214 214
215 215 hg status ignoreddir/file:
216 216
217 217 $ hg status ignoreddir/file
218 218
219 219 hg status -i ignoreddir/file:
220 220
221 221 $ hg status -i ignoreddir/file
222 222 I ignoreddir/file
223 223 $ cd ..
224 224
225 225 Check 'status -q' and some combinations
226 226
227 227 $ hg init repo3
228 228 $ cd repo3
229 229 $ touch modified removed deleted ignored
230 230 $ echo "^ignored$" > .hgignore
231 231 $ hg commit -A -m 'initial checkin'
232 232 adding .hgignore
233 233 adding deleted
234 234 adding modified
235 235 adding removed
236 236 $ touch added unknown ignored
237 237 $ hg add added
238 238 $ echo "test" >> modified
239 239 $ hg remove removed
240 240 $ rm deleted
241 241 $ hg copy modified copied
242 242
243 243 Specify working directory revision explicitly, that should be the same as
244 244 "hg status"
245 245
246 246 $ hg status --change "wdir()"
247 247 M modified
248 248 A added
249 249 A copied
250 250 R removed
251 251 ! deleted
252 252 ? unknown
253 253
254 254 Run status with 2 different flags.
255 255 Check if result is the same or different.
256 256 If result is not as expected, raise error
257 257
258 258 $ assert() {
259 259 > hg status $1 > ../a
260 260 > hg status $2 > ../b
261 261 > if diff ../a ../b > /dev/null; then
262 262 > out=0
263 263 > else
264 264 > out=1
265 265 > fi
266 266 > if [ $3 -eq 0 ]; then
267 267 > df="same"
268 268 > else
269 269 > df="different"
270 270 > fi
271 271 > if [ $out -ne $3 ]; then
272 272 > echo "Error on $1 and $2, should be $df."
273 273 > fi
274 274 > }
275 275
276 276 Assert flag1 flag2 [0-same | 1-different]
277 277
278 278 $ assert "-q" "-mard" 0
279 279 $ assert "-A" "-marduicC" 0
280 280 $ assert "-qA" "-mardcC" 0
281 281 $ assert "-qAui" "-A" 0
282 282 $ assert "-qAu" "-marducC" 0
283 283 $ assert "-qAi" "-mardicC" 0
284 284 $ assert "-qu" "-u" 0
285 285 $ assert "-q" "-u" 1
286 286 $ assert "-m" "-a" 1
287 287 $ assert "-r" "-d" 1
288 288 $ cd ..
289 289
290 290 $ hg init repo4
291 291 $ cd repo4
292 292 $ touch modified removed deleted
293 293 $ hg ci -q -A -m 'initial checkin'
294 294 $ touch added unknown
295 295 $ hg add added
296 296 $ hg remove removed
297 297 $ rm deleted
298 298 $ echo x > modified
299 299 $ hg copy modified copied
300 300 $ hg ci -m 'test checkin' -d "1000001 0"
301 301 $ rm *
302 302 $ touch unrelated
303 303 $ hg ci -q -A -m 'unrelated checkin' -d "1000002 0"
304 304
305 305 hg status --change 1:
306 306
307 307 $ hg status --change 1
308 308 M modified
309 309 A added
310 310 A copied
311 311 R removed
312 312
313 313 hg status --change 1 unrelated:
314 314
315 315 $ hg status --change 1 unrelated
316 316
317 317 hg status -C --change 1 added modified copied removed deleted:
318 318
319 319 $ hg status -C --change 1 added modified copied removed deleted
320 320 M modified
321 321 A added
322 322 A copied
323 323 modified
324 324 R removed
325 325
326 326 hg status -A --change 1 and revset:
327 327
328 328 $ hg status -A --change '1|1'
329 329 M modified
330 330 A added
331 331 A copied
332 332 modified
333 333 R removed
334 334 C deleted
335 335
336 336 $ cd ..
337 337
338 338 hg status of binary file starting with '\1\n', a separator for metadata:
339 339
340 340 $ hg init repo5
341 341 $ cd repo5
342 342 >>> open("010a", "wb").write("\1\nfoo")
343 343 $ hg ci -q -A -m 'initial checkin'
344 344 $ hg status -A
345 345 C 010a
346 346
347 347 >>> open("010a", "wb").write("\1\nbar")
348 348 $ hg status -A
349 349 M 010a
350 350 $ hg ci -q -m 'modify 010a'
351 351 $ hg status -A --rev 0:1
352 352 M 010a
353 353
354 354 $ touch empty
355 355 $ hg ci -q -A -m 'add another file'
356 356 $ hg status -A --rev 1:2 010a
357 357 C 010a
358 358
359 359 $ cd ..
360 360
361 361 test "hg status" with "directory pattern" which matches against files
362 362 only known on target revision.
363 363
364 364 $ hg init repo6
365 365 $ cd repo6
366 366
367 367 $ echo a > a.txt
368 368 $ hg add a.txt
369 369 $ hg commit -m '#0'
370 370 $ mkdir -p 1/2/3/4/5
371 371 $ echo b > 1/2/3/4/5/b.txt
372 372 $ hg add 1/2/3/4/5/b.txt
373 373 $ hg commit -m '#1'
374 374
375 375 $ hg update -C 0 > /dev/null
376 376 $ hg status -A
377 377 C a.txt
378 378
379 379 the directory matching against specified pattern should be removed,
380 380 because directory existence prevents 'dirstate.walk()' from showing
381 381 warning message about such pattern.
382 382
383 383 $ test ! -d 1
384 384 $ hg status -A --rev 1 1/2/3/4/5/b.txt
385 385 R 1/2/3/4/5/b.txt
386 386 $ hg status -A --rev 1 1/2/3/4/5
387 387 R 1/2/3/4/5/b.txt
388 388 $ hg status -A --rev 1 1/2/3
389 389 R 1/2/3/4/5/b.txt
390 390 $ hg status -A --rev 1 1
391 391 R 1/2/3/4/5/b.txt
392 392
393 393 $ hg status --config ui.formatdebug=True --rev 1 1
394 394 status = [
395 395 {*'path': '1/2/3/4/5/b.txt'*}, (glob)
396 396 ]
397 397
398 398 #if windows
399 399 $ hg --config ui.slash=false status -A --rev 1 1
400 400 R 1\2\3\4\5\b.txt
401 401 #endif
402 402
403 403 $ cd ..
404 404
405 405 Status after move overwriting a file (issue4458)
406 406 =================================================
407 407
408 408
409 409 $ hg init issue4458
410 410 $ cd issue4458
411 411 $ echo a > a
412 412 $ echo b > b
413 413 $ hg commit -Am base
414 414 adding a
415 415 adding b
416 416
417 417
418 418 with --force
419 419
420 420 $ hg mv b --force a
421 421 $ hg st --copies
422 422 M a
423 423 b
424 424 R b
425 425 $ hg revert --all
426 426 reverting a
427 427 undeleting b
428 428 $ rm *.orig
429 429
430 430 without force
431 431
432 432 $ hg rm a
433 433 $ hg st --copies
434 434 R a
435 435 $ hg mv b a
436 436 $ hg st --copies
437 437 M a
438 438 b
439 439 R b
440 440
441 using ui.statuscopies setting
442 $ hg st --config ui.statuscopies=true
443 M a
444 b
445 R b
446 $ hg st --config ui.statuscopies=false
447 M a
448 R b
449
441 450 Other "bug" highlight, the revision status does not report the copy information.
442 451 This is buggy behavior.
443 452
444 453 $ hg commit -m 'blah'
445 454 $ hg st --copies --change .
446 455 M a
447 456 R b
448 457
449 458 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now