##// END OF EJS Templates
cmdutil: use '[committemplate]' section like as map file for style definition...
FUJIWARA Katsunori -
r22013:de5cee8b default
parent child Browse files
Show More
@@ -1,2643 +1,2647 b''
1 1 # cmdutil.py - help for command processing in 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, nullid, nullrev, short
9 9 from i18n import _
10 10 import os, sys, errno, re, tempfile
11 11 import util, scmutil, templater, patch, error, templatekw, revlog, copies
12 12 import match as matchmod
13 13 import context, repair, graphmod, revset, phases, obsolete, pathutil
14 14 import changelog
15 15 import bookmarks
16 16 import lock as lockmod
17 17
18 18 def parsealiases(cmd):
19 19 return cmd.lstrip("^").split("|")
20 20
21 21 def findpossible(cmd, table, strict=False):
22 22 """
23 23 Return cmd -> (aliases, command table entry)
24 24 for each matching command.
25 25 Return debug commands (or their aliases) only if no normal command matches.
26 26 """
27 27 choice = {}
28 28 debugchoice = {}
29 29
30 30 if cmd in table:
31 31 # short-circuit exact matches, "log" alias beats "^log|history"
32 32 keys = [cmd]
33 33 else:
34 34 keys = table.keys()
35 35
36 36 for e in keys:
37 37 aliases = parsealiases(e)
38 38 found = None
39 39 if cmd in aliases:
40 40 found = cmd
41 41 elif not strict:
42 42 for a in aliases:
43 43 if a.startswith(cmd):
44 44 found = a
45 45 break
46 46 if found is not None:
47 47 if aliases[0].startswith("debug") or found.startswith("debug"):
48 48 debugchoice[found] = (aliases, table[e])
49 49 else:
50 50 choice[found] = (aliases, table[e])
51 51
52 52 if not choice and debugchoice:
53 53 choice = debugchoice
54 54
55 55 return choice
56 56
57 57 def findcmd(cmd, table, strict=True):
58 58 """Return (aliases, command table entry) for command string."""
59 59 choice = findpossible(cmd, table, strict)
60 60
61 61 if cmd in choice:
62 62 return choice[cmd]
63 63
64 64 if len(choice) > 1:
65 65 clist = choice.keys()
66 66 clist.sort()
67 67 raise error.AmbiguousCommand(cmd, clist)
68 68
69 69 if choice:
70 70 return choice.values()[0]
71 71
72 72 raise error.UnknownCommand(cmd)
73 73
74 74 def findrepo(p):
75 75 while not os.path.isdir(os.path.join(p, ".hg")):
76 76 oldp, p = p, os.path.dirname(p)
77 77 if p == oldp:
78 78 return None
79 79
80 80 return p
81 81
82 82 def bailifchanged(repo):
83 83 if repo.dirstate.p2() != nullid:
84 84 raise util.Abort(_('outstanding uncommitted merge'))
85 85 modified, added, removed, deleted = repo.status()[:4]
86 86 if modified or added or removed or deleted:
87 87 raise util.Abort(_('uncommitted changes'))
88 88 ctx = repo[None]
89 89 for s in sorted(ctx.substate):
90 90 if ctx.sub(s).dirty():
91 91 raise util.Abort(_("uncommitted changes in subrepo %s") % s)
92 92
93 93 def logmessage(ui, opts):
94 94 """ get the log message according to -m and -l option """
95 95 message = opts.get('message')
96 96 logfile = opts.get('logfile')
97 97
98 98 if message and logfile:
99 99 raise util.Abort(_('options --message and --logfile are mutually '
100 100 'exclusive'))
101 101 if not message and logfile:
102 102 try:
103 103 if logfile == '-':
104 104 message = ui.fin.read()
105 105 else:
106 106 message = '\n'.join(util.readfile(logfile).splitlines())
107 107 except IOError, inst:
108 108 raise util.Abort(_("can't read commit message '%s': %s") %
109 109 (logfile, inst.strerror))
110 110 return message
111 111
112 112 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
113 113 editform='', **opts):
114 114 """get appropriate commit message editor according to '--edit' option
115 115
116 116 'finishdesc' is a function to be called with edited commit message
117 117 (= 'description' of the new changeset) just after editing, but
118 118 before checking empty-ness. It should return actual text to be
119 119 stored into history. This allows to change description before
120 120 storing.
121 121
122 122 'extramsg' is a extra message to be shown in the editor instead of
123 123 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
124 124 is automatically added.
125 125
126 126 'editform' is a dot-separated list of names, to distinguish
127 127 the purpose of commit text editing.
128 128
129 129 'getcommiteditor' returns 'commitforceeditor' regardless of
130 130 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
131 131 they are specific for usage in MQ.
132 132 """
133 133 if edit or finishdesc or extramsg:
134 134 return lambda r, c, s: commitforceeditor(r, c, s,
135 135 finishdesc=finishdesc,
136 136 extramsg=extramsg,
137 137 editform=editform)
138 138 elif editform:
139 139 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
140 140 else:
141 141 return commiteditor
142 142
143 143 def loglimit(opts):
144 144 """get the log limit according to option -l/--limit"""
145 145 limit = opts.get('limit')
146 146 if limit:
147 147 try:
148 148 limit = int(limit)
149 149 except ValueError:
150 150 raise util.Abort(_('limit must be a positive integer'))
151 151 if limit <= 0:
152 152 raise util.Abort(_('limit must be positive'))
153 153 else:
154 154 limit = None
155 155 return limit
156 156
157 157 def makefilename(repo, pat, node, desc=None,
158 158 total=None, seqno=None, revwidth=None, pathname=None):
159 159 node_expander = {
160 160 'H': lambda: hex(node),
161 161 'R': lambda: str(repo.changelog.rev(node)),
162 162 'h': lambda: short(node),
163 163 'm': lambda: re.sub('[^\w]', '_', str(desc))
164 164 }
165 165 expander = {
166 166 '%': lambda: '%',
167 167 'b': lambda: os.path.basename(repo.root),
168 168 }
169 169
170 170 try:
171 171 if node:
172 172 expander.update(node_expander)
173 173 if node:
174 174 expander['r'] = (lambda:
175 175 str(repo.changelog.rev(node)).zfill(revwidth or 0))
176 176 if total is not None:
177 177 expander['N'] = lambda: str(total)
178 178 if seqno is not None:
179 179 expander['n'] = lambda: str(seqno)
180 180 if total is not None and seqno is not None:
181 181 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
182 182 if pathname is not None:
183 183 expander['s'] = lambda: os.path.basename(pathname)
184 184 expander['d'] = lambda: os.path.dirname(pathname) or '.'
185 185 expander['p'] = lambda: pathname
186 186
187 187 newname = []
188 188 patlen = len(pat)
189 189 i = 0
190 190 while i < patlen:
191 191 c = pat[i]
192 192 if c == '%':
193 193 i += 1
194 194 c = pat[i]
195 195 c = expander[c]()
196 196 newname.append(c)
197 197 i += 1
198 198 return ''.join(newname)
199 199 except KeyError, inst:
200 200 raise util.Abort(_("invalid format spec '%%%s' in output filename") %
201 201 inst.args[0])
202 202
203 203 def makefileobj(repo, pat, node=None, desc=None, total=None,
204 204 seqno=None, revwidth=None, mode='wb', modemap=None,
205 205 pathname=None):
206 206
207 207 writable = mode not in ('r', 'rb')
208 208
209 209 if not pat or pat == '-':
210 210 fp = writable and repo.ui.fout or repo.ui.fin
211 211 if util.safehasattr(fp, 'fileno'):
212 212 return os.fdopen(os.dup(fp.fileno()), mode)
213 213 else:
214 214 # if this fp can't be duped properly, return
215 215 # a dummy object that can be closed
216 216 class wrappedfileobj(object):
217 217 noop = lambda x: None
218 218 def __init__(self, f):
219 219 self.f = f
220 220 def __getattr__(self, attr):
221 221 if attr == 'close':
222 222 return self.noop
223 223 else:
224 224 return getattr(self.f, attr)
225 225
226 226 return wrappedfileobj(fp)
227 227 if util.safehasattr(pat, 'write') and writable:
228 228 return pat
229 229 if util.safehasattr(pat, 'read') and 'r' in mode:
230 230 return pat
231 231 fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
232 232 if modemap is not None:
233 233 mode = modemap.get(fn, mode)
234 234 if mode == 'wb':
235 235 modemap[fn] = 'ab'
236 236 return open(fn, mode)
237 237
238 238 def openrevlog(repo, cmd, file_, opts):
239 239 """opens the changelog, manifest, a filelog or a given revlog"""
240 240 cl = opts['changelog']
241 241 mf = opts['manifest']
242 242 msg = None
243 243 if cl and mf:
244 244 msg = _('cannot specify --changelog and --manifest at the same time')
245 245 elif cl or mf:
246 246 if file_:
247 247 msg = _('cannot specify filename with --changelog or --manifest')
248 248 elif not repo:
249 249 msg = _('cannot specify --changelog or --manifest '
250 250 'without a repository')
251 251 if msg:
252 252 raise util.Abort(msg)
253 253
254 254 r = None
255 255 if repo:
256 256 if cl:
257 257 r = repo.unfiltered().changelog
258 258 elif mf:
259 259 r = repo.manifest
260 260 elif file_:
261 261 filelog = repo.file(file_)
262 262 if len(filelog):
263 263 r = filelog
264 264 if not r:
265 265 if not file_:
266 266 raise error.CommandError(cmd, _('invalid arguments'))
267 267 if not os.path.isfile(file_):
268 268 raise util.Abort(_("revlog '%s' not found") % file_)
269 269 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False),
270 270 file_[:-2] + ".i")
271 271 return r
272 272
273 273 def copy(ui, repo, pats, opts, rename=False):
274 274 # called with the repo lock held
275 275 #
276 276 # hgsep => pathname that uses "/" to separate directories
277 277 # ossep => pathname that uses os.sep to separate directories
278 278 cwd = repo.getcwd()
279 279 targets = {}
280 280 after = opts.get("after")
281 281 dryrun = opts.get("dry_run")
282 282 wctx = repo[None]
283 283
284 284 def walkpat(pat):
285 285 srcs = []
286 286 badstates = after and '?' or '?r'
287 287 m = scmutil.match(repo[None], [pat], opts, globbed=True)
288 288 for abs in repo.walk(m):
289 289 state = repo.dirstate[abs]
290 290 rel = m.rel(abs)
291 291 exact = m.exact(abs)
292 292 if state in badstates:
293 293 if exact and state == '?':
294 294 ui.warn(_('%s: not copying - file is not managed\n') % rel)
295 295 if exact and state == 'r':
296 296 ui.warn(_('%s: not copying - file has been marked for'
297 297 ' remove\n') % rel)
298 298 continue
299 299 # abs: hgsep
300 300 # rel: ossep
301 301 srcs.append((abs, rel, exact))
302 302 return srcs
303 303
304 304 # abssrc: hgsep
305 305 # relsrc: ossep
306 306 # otarget: ossep
307 307 def copyfile(abssrc, relsrc, otarget, exact):
308 308 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
309 309 if '/' in abstarget:
310 310 # We cannot normalize abstarget itself, this would prevent
311 311 # case only renames, like a => A.
312 312 abspath, absname = abstarget.rsplit('/', 1)
313 313 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
314 314 reltarget = repo.pathto(abstarget, cwd)
315 315 target = repo.wjoin(abstarget)
316 316 src = repo.wjoin(abssrc)
317 317 state = repo.dirstate[abstarget]
318 318
319 319 scmutil.checkportable(ui, abstarget)
320 320
321 321 # check for collisions
322 322 prevsrc = targets.get(abstarget)
323 323 if prevsrc is not None:
324 324 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
325 325 (reltarget, repo.pathto(abssrc, cwd),
326 326 repo.pathto(prevsrc, cwd)))
327 327 return
328 328
329 329 # check for overwrites
330 330 exists = os.path.lexists(target)
331 331 samefile = False
332 332 if exists and abssrc != abstarget:
333 333 if (repo.dirstate.normalize(abssrc) ==
334 334 repo.dirstate.normalize(abstarget)):
335 335 if not rename:
336 336 ui.warn(_("%s: can't copy - same file\n") % reltarget)
337 337 return
338 338 exists = False
339 339 samefile = True
340 340
341 341 if not after and exists or after and state in 'mn':
342 342 if not opts['force']:
343 343 ui.warn(_('%s: not overwriting - file exists\n') %
344 344 reltarget)
345 345 return
346 346
347 347 if after:
348 348 if not exists:
349 349 if rename:
350 350 ui.warn(_('%s: not recording move - %s does not exist\n') %
351 351 (relsrc, reltarget))
352 352 else:
353 353 ui.warn(_('%s: not recording copy - %s does not exist\n') %
354 354 (relsrc, reltarget))
355 355 return
356 356 elif not dryrun:
357 357 try:
358 358 if exists:
359 359 os.unlink(target)
360 360 targetdir = os.path.dirname(target) or '.'
361 361 if not os.path.isdir(targetdir):
362 362 os.makedirs(targetdir)
363 363 if samefile:
364 364 tmp = target + "~hgrename"
365 365 os.rename(src, tmp)
366 366 os.rename(tmp, target)
367 367 else:
368 368 util.copyfile(src, target)
369 369 srcexists = True
370 370 except IOError, inst:
371 371 if inst.errno == errno.ENOENT:
372 372 ui.warn(_('%s: deleted in working copy\n') % relsrc)
373 373 srcexists = False
374 374 else:
375 375 ui.warn(_('%s: cannot copy - %s\n') %
376 376 (relsrc, inst.strerror))
377 377 return True # report a failure
378 378
379 379 if ui.verbose or not exact:
380 380 if rename:
381 381 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
382 382 else:
383 383 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
384 384
385 385 targets[abstarget] = abssrc
386 386
387 387 # fix up dirstate
388 388 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
389 389 dryrun=dryrun, cwd=cwd)
390 390 if rename and not dryrun:
391 391 if not after and srcexists and not samefile:
392 392 util.unlinkpath(repo.wjoin(abssrc))
393 393 wctx.forget([abssrc])
394 394
395 395 # pat: ossep
396 396 # dest ossep
397 397 # srcs: list of (hgsep, hgsep, ossep, bool)
398 398 # return: function that takes hgsep and returns ossep
399 399 def targetpathfn(pat, dest, srcs):
400 400 if os.path.isdir(pat):
401 401 abspfx = pathutil.canonpath(repo.root, cwd, pat)
402 402 abspfx = util.localpath(abspfx)
403 403 if destdirexists:
404 404 striplen = len(os.path.split(abspfx)[0])
405 405 else:
406 406 striplen = len(abspfx)
407 407 if striplen:
408 408 striplen += len(os.sep)
409 409 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
410 410 elif destdirexists:
411 411 res = lambda p: os.path.join(dest,
412 412 os.path.basename(util.localpath(p)))
413 413 else:
414 414 res = lambda p: dest
415 415 return res
416 416
417 417 # pat: ossep
418 418 # dest ossep
419 419 # srcs: list of (hgsep, hgsep, ossep, bool)
420 420 # return: function that takes hgsep and returns ossep
421 421 def targetpathafterfn(pat, dest, srcs):
422 422 if matchmod.patkind(pat):
423 423 # a mercurial pattern
424 424 res = lambda p: os.path.join(dest,
425 425 os.path.basename(util.localpath(p)))
426 426 else:
427 427 abspfx = pathutil.canonpath(repo.root, cwd, pat)
428 428 if len(abspfx) < len(srcs[0][0]):
429 429 # A directory. Either the target path contains the last
430 430 # component of the source path or it does not.
431 431 def evalpath(striplen):
432 432 score = 0
433 433 for s in srcs:
434 434 t = os.path.join(dest, util.localpath(s[0])[striplen:])
435 435 if os.path.lexists(t):
436 436 score += 1
437 437 return score
438 438
439 439 abspfx = util.localpath(abspfx)
440 440 striplen = len(abspfx)
441 441 if striplen:
442 442 striplen += len(os.sep)
443 443 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
444 444 score = evalpath(striplen)
445 445 striplen1 = len(os.path.split(abspfx)[0])
446 446 if striplen1:
447 447 striplen1 += len(os.sep)
448 448 if evalpath(striplen1) > score:
449 449 striplen = striplen1
450 450 res = lambda p: os.path.join(dest,
451 451 util.localpath(p)[striplen:])
452 452 else:
453 453 # a file
454 454 if destdirexists:
455 455 res = lambda p: os.path.join(dest,
456 456 os.path.basename(util.localpath(p)))
457 457 else:
458 458 res = lambda p: dest
459 459 return res
460 460
461 461
462 462 pats = scmutil.expandpats(pats)
463 463 if not pats:
464 464 raise util.Abort(_('no source or destination specified'))
465 465 if len(pats) == 1:
466 466 raise util.Abort(_('no destination specified'))
467 467 dest = pats.pop()
468 468 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
469 469 if not destdirexists:
470 470 if len(pats) > 1 or matchmod.patkind(pats[0]):
471 471 raise util.Abort(_('with multiple sources, destination must be an '
472 472 'existing directory'))
473 473 if util.endswithsep(dest):
474 474 raise util.Abort(_('destination %s is not a directory') % dest)
475 475
476 476 tfn = targetpathfn
477 477 if after:
478 478 tfn = targetpathafterfn
479 479 copylist = []
480 480 for pat in pats:
481 481 srcs = walkpat(pat)
482 482 if not srcs:
483 483 continue
484 484 copylist.append((tfn(pat, dest, srcs), srcs))
485 485 if not copylist:
486 486 raise util.Abort(_('no files to copy'))
487 487
488 488 errors = 0
489 489 for targetpath, srcs in copylist:
490 490 for abssrc, relsrc, exact in srcs:
491 491 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
492 492 errors += 1
493 493
494 494 if errors:
495 495 ui.warn(_('(consider using --after)\n'))
496 496
497 497 return errors != 0
498 498
499 499 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
500 500 runargs=None, appendpid=False):
501 501 '''Run a command as a service.'''
502 502
503 503 def writepid(pid):
504 504 if opts['pid_file']:
505 505 mode = appendpid and 'a' or 'w'
506 506 fp = open(opts['pid_file'], mode)
507 507 fp.write(str(pid) + '\n')
508 508 fp.close()
509 509
510 510 if opts['daemon'] and not opts['daemon_pipefds']:
511 511 # Signal child process startup with file removal
512 512 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
513 513 os.close(lockfd)
514 514 try:
515 515 if not runargs:
516 516 runargs = util.hgcmd() + sys.argv[1:]
517 517 runargs.append('--daemon-pipefds=%s' % lockpath)
518 518 # Don't pass --cwd to the child process, because we've already
519 519 # changed directory.
520 520 for i in xrange(1, len(runargs)):
521 521 if runargs[i].startswith('--cwd='):
522 522 del runargs[i]
523 523 break
524 524 elif runargs[i].startswith('--cwd'):
525 525 del runargs[i:i + 2]
526 526 break
527 527 def condfn():
528 528 return not os.path.exists(lockpath)
529 529 pid = util.rundetached(runargs, condfn)
530 530 if pid < 0:
531 531 raise util.Abort(_('child process failed to start'))
532 532 writepid(pid)
533 533 finally:
534 534 try:
535 535 os.unlink(lockpath)
536 536 except OSError, e:
537 537 if e.errno != errno.ENOENT:
538 538 raise
539 539 if parentfn:
540 540 return parentfn(pid)
541 541 else:
542 542 return
543 543
544 544 if initfn:
545 545 initfn()
546 546
547 547 if not opts['daemon']:
548 548 writepid(os.getpid())
549 549
550 550 if opts['daemon_pipefds']:
551 551 lockpath = opts['daemon_pipefds']
552 552 try:
553 553 os.setsid()
554 554 except AttributeError:
555 555 pass
556 556 os.unlink(lockpath)
557 557 util.hidewindow()
558 558 sys.stdout.flush()
559 559 sys.stderr.flush()
560 560
561 561 nullfd = os.open(os.devnull, os.O_RDWR)
562 562 logfilefd = nullfd
563 563 if logfile:
564 564 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
565 565 os.dup2(nullfd, 0)
566 566 os.dup2(logfilefd, 1)
567 567 os.dup2(logfilefd, 2)
568 568 if nullfd not in (0, 1, 2):
569 569 os.close(nullfd)
570 570 if logfile and logfilefd not in (0, 1, 2):
571 571 os.close(logfilefd)
572 572
573 573 if runfn:
574 574 return runfn()
575 575
576 576 def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
577 577 """Utility function used by commands.import to import a single patch
578 578
579 579 This function is explicitly defined here to help the evolve extension to
580 580 wrap this part of the import logic.
581 581
582 582 The API is currently a bit ugly because it a simple code translation from
583 583 the import command. Feel free to make it better.
584 584
585 585 :hunk: a patch (as a binary string)
586 586 :parents: nodes that will be parent of the created commit
587 587 :opts: the full dict of option passed to the import command
588 588 :msgs: list to save commit message to.
589 589 (used in case we need to save it when failing)
590 590 :updatefunc: a function that update a repo to a given node
591 591 updatefunc(<repo>, <node>)
592 592 """
593 593 tmpname, message, user, date, branch, nodeid, p1, p2 = \
594 594 patch.extract(ui, hunk)
595 595
596 596 editor = getcommiteditor(editform='import.normal', **opts)
597 597 update = not opts.get('bypass')
598 598 strip = opts["strip"]
599 599 sim = float(opts.get('similarity') or 0)
600 600 if not tmpname:
601 601 return (None, None, False)
602 602 msg = _('applied to working directory')
603 603
604 604 rejects = False
605 605
606 606 try:
607 607 cmdline_message = logmessage(ui, opts)
608 608 if cmdline_message:
609 609 # pickup the cmdline msg
610 610 message = cmdline_message
611 611 elif message:
612 612 # pickup the patch msg
613 613 message = message.strip()
614 614 else:
615 615 # launch the editor
616 616 message = None
617 617 ui.debug('message:\n%s\n' % message)
618 618
619 619 if len(parents) == 1:
620 620 parents.append(repo[nullid])
621 621 if opts.get('exact'):
622 622 if not nodeid or not p1:
623 623 raise util.Abort(_('not a Mercurial patch'))
624 624 p1 = repo[p1]
625 625 p2 = repo[p2 or nullid]
626 626 elif p2:
627 627 try:
628 628 p1 = repo[p1]
629 629 p2 = repo[p2]
630 630 # Without any options, consider p2 only if the
631 631 # patch is being applied on top of the recorded
632 632 # first parent.
633 633 if p1 != parents[0]:
634 634 p1 = parents[0]
635 635 p2 = repo[nullid]
636 636 except error.RepoError:
637 637 p1, p2 = parents
638 638 else:
639 639 p1, p2 = parents
640 640
641 641 n = None
642 642 if update:
643 643 if p1 != parents[0]:
644 644 updatefunc(repo, p1.node())
645 645 if p2 != parents[1]:
646 646 repo.setparents(p1.node(), p2.node())
647 647
648 648 if opts.get('exact') or opts.get('import_branch'):
649 649 repo.dirstate.setbranch(branch or 'default')
650 650
651 651 partial = opts.get('partial', False)
652 652 files = set()
653 653 try:
654 654 patch.patch(ui, repo, tmpname, strip=strip, files=files,
655 655 eolmode=None, similarity=sim / 100.0)
656 656 except patch.PatchError, e:
657 657 if not partial:
658 658 raise util.Abort(str(e))
659 659 if partial:
660 660 rejects = True
661 661
662 662 files = list(files)
663 663 if opts.get('no_commit'):
664 664 if message:
665 665 msgs.append(message)
666 666 else:
667 667 if opts.get('exact') or p2:
668 668 # If you got here, you either use --force and know what
669 669 # you are doing or used --exact or a merge patch while
670 670 # being updated to its first parent.
671 671 m = None
672 672 else:
673 673 m = scmutil.matchfiles(repo, files or [])
674 674 n = repo.commit(message, opts.get('user') or user,
675 675 opts.get('date') or date, match=m,
676 676 editor=editor, force=partial)
677 677 else:
678 678 if opts.get('exact') or opts.get('import_branch'):
679 679 branch = branch or 'default'
680 680 else:
681 681 branch = p1.branch()
682 682 store = patch.filestore()
683 683 try:
684 684 files = set()
685 685 try:
686 686 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
687 687 files, eolmode=None)
688 688 except patch.PatchError, e:
689 689 raise util.Abort(str(e))
690 690 editor = getcommiteditor(editform='import.bypass')
691 691 memctx = context.makememctx(repo, (p1.node(), p2.node()),
692 692 message,
693 693 opts.get('user') or user,
694 694 opts.get('date') or date,
695 695 branch, files, store,
696 696 editor=editor)
697 697 n = memctx.commit()
698 698 finally:
699 699 store.close()
700 700 if opts.get('exact') and hex(n) != nodeid:
701 701 raise util.Abort(_('patch is damaged or loses information'))
702 702 if n:
703 703 # i18n: refers to a short changeset id
704 704 msg = _('created %s') % short(n)
705 705 return (msg, n, rejects)
706 706 finally:
707 707 os.unlink(tmpname)
708 708
709 709 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
710 710 opts=None):
711 711 '''export changesets as hg patches.'''
712 712
713 713 total = len(revs)
714 714 revwidth = max([len(str(rev)) for rev in revs])
715 715 filemode = {}
716 716
717 717 def single(rev, seqno, fp):
718 718 ctx = repo[rev]
719 719 node = ctx.node()
720 720 parents = [p.node() for p in ctx.parents() if p]
721 721 branch = ctx.branch()
722 722 if switch_parent:
723 723 parents.reverse()
724 724 prev = (parents and parents[0]) or nullid
725 725
726 726 shouldclose = False
727 727 if not fp and len(template) > 0:
728 728 desc_lines = ctx.description().rstrip().split('\n')
729 729 desc = desc_lines[0] #Commit always has a first line.
730 730 fp = makefileobj(repo, template, node, desc=desc, total=total,
731 731 seqno=seqno, revwidth=revwidth, mode='wb',
732 732 modemap=filemode)
733 733 if fp != template:
734 734 shouldclose = True
735 735 if fp and fp != sys.stdout and util.safehasattr(fp, 'name'):
736 736 repo.ui.note("%s\n" % fp.name)
737 737
738 738 if not fp:
739 739 write = repo.ui.write
740 740 else:
741 741 def write(s, **kw):
742 742 fp.write(s)
743 743
744 744
745 745 write("# HG changeset patch\n")
746 746 write("# User %s\n" % ctx.user())
747 747 write("# Date %d %d\n" % ctx.date())
748 748 write("# %s\n" % util.datestr(ctx.date()))
749 749 if branch and branch != 'default':
750 750 write("# Branch %s\n" % branch)
751 751 write("# Node ID %s\n" % hex(node))
752 752 write("# Parent %s\n" % hex(prev))
753 753 if len(parents) > 1:
754 754 write("# Parent %s\n" % hex(parents[1]))
755 755 write(ctx.description().rstrip())
756 756 write("\n\n")
757 757
758 758 for chunk, label in patch.diffui(repo, prev, node, opts=opts):
759 759 write(chunk, label=label)
760 760
761 761 if shouldclose:
762 762 fp.close()
763 763
764 764 for seqno, rev in enumerate(revs):
765 765 single(rev, seqno + 1, fp)
766 766
767 767 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
768 768 changes=None, stat=False, fp=None, prefix='',
769 769 listsubrepos=False):
770 770 '''show diff or diffstat.'''
771 771 if fp is None:
772 772 write = ui.write
773 773 else:
774 774 def write(s, **kw):
775 775 fp.write(s)
776 776
777 777 if stat:
778 778 diffopts = diffopts.copy(context=0)
779 779 width = 80
780 780 if not ui.plain():
781 781 width = ui.termwidth()
782 782 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
783 783 prefix=prefix)
784 784 for chunk, label in patch.diffstatui(util.iterlines(chunks),
785 785 width=width,
786 786 git=diffopts.git):
787 787 write(chunk, label=label)
788 788 else:
789 789 for chunk, label in patch.diffui(repo, node1, node2, match,
790 790 changes, diffopts, prefix=prefix):
791 791 write(chunk, label=label)
792 792
793 793 if listsubrepos:
794 794 ctx1 = repo[node1]
795 795 ctx2 = repo[node2]
796 796 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
797 797 tempnode2 = node2
798 798 try:
799 799 if node2 is not None:
800 800 tempnode2 = ctx2.substate[subpath][1]
801 801 except KeyError:
802 802 # A subrepo that existed in node1 was deleted between node1 and
803 803 # node2 (inclusive). Thus, ctx2's substate won't contain that
804 804 # subpath. The best we can do is to ignore it.
805 805 tempnode2 = None
806 806 submatch = matchmod.narrowmatcher(subpath, match)
807 807 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
808 808 stat=stat, fp=fp, prefix=prefix)
809 809
810 810 class changeset_printer(object):
811 811 '''show changeset information when templating not requested.'''
812 812
813 813 def __init__(self, ui, repo, patch, diffopts, buffered):
814 814 self.ui = ui
815 815 self.repo = repo
816 816 self.buffered = buffered
817 817 self.patch = patch
818 818 self.diffopts = diffopts
819 819 self.header = {}
820 820 self.hunk = {}
821 821 self.lastheader = None
822 822 self.footer = None
823 823
824 824 def flush(self, rev):
825 825 if rev in self.header:
826 826 h = self.header[rev]
827 827 if h != self.lastheader:
828 828 self.lastheader = h
829 829 self.ui.write(h)
830 830 del self.header[rev]
831 831 if rev in self.hunk:
832 832 self.ui.write(self.hunk[rev])
833 833 del self.hunk[rev]
834 834 return 1
835 835 return 0
836 836
837 837 def close(self):
838 838 if self.footer:
839 839 self.ui.write(self.footer)
840 840
841 841 def show(self, ctx, copies=None, matchfn=None, **props):
842 842 if self.buffered:
843 843 self.ui.pushbuffer()
844 844 self._show(ctx, copies, matchfn, props)
845 845 self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
846 846 else:
847 847 self._show(ctx, copies, matchfn, props)
848 848
849 849 def _show(self, ctx, copies, matchfn, props):
850 850 '''show a single changeset or file revision'''
851 851 changenode = ctx.node()
852 852 rev = ctx.rev()
853 853
854 854 if self.ui.quiet:
855 855 self.ui.write("%d:%s\n" % (rev, short(changenode)),
856 856 label='log.node')
857 857 return
858 858
859 859 log = self.repo.changelog
860 860 date = util.datestr(ctx.date())
861 861
862 862 hexfunc = self.ui.debugflag and hex or short
863 863
864 864 parents = [(p, hexfunc(log.node(p)))
865 865 for p in self._meaningful_parentrevs(log, rev)]
866 866
867 867 # i18n: column positioning for "hg log"
868 868 self.ui.write(_("changeset: %d:%s\n") % (rev, hexfunc(changenode)),
869 869 label='log.changeset changeset.%s' % ctx.phasestr())
870 870
871 871 branch = ctx.branch()
872 872 # don't show the default branch name
873 873 if branch != 'default':
874 874 # i18n: column positioning for "hg log"
875 875 self.ui.write(_("branch: %s\n") % branch,
876 876 label='log.branch')
877 877 for bookmark in self.repo.nodebookmarks(changenode):
878 878 # i18n: column positioning for "hg log"
879 879 self.ui.write(_("bookmark: %s\n") % bookmark,
880 880 label='log.bookmark')
881 881 for tag in self.repo.nodetags(changenode):
882 882 # i18n: column positioning for "hg log"
883 883 self.ui.write(_("tag: %s\n") % tag,
884 884 label='log.tag')
885 885 if self.ui.debugflag and ctx.phase():
886 886 # i18n: column positioning for "hg log"
887 887 self.ui.write(_("phase: %s\n") % _(ctx.phasestr()),
888 888 label='log.phase')
889 889 for parent in parents:
890 890 # i18n: column positioning for "hg log"
891 891 self.ui.write(_("parent: %d:%s\n") % parent,
892 892 label='log.parent changeset.%s' % ctx.phasestr())
893 893
894 894 if self.ui.debugflag:
895 895 mnode = ctx.manifestnode()
896 896 # i18n: column positioning for "hg log"
897 897 self.ui.write(_("manifest: %d:%s\n") %
898 898 (self.repo.manifest.rev(mnode), hex(mnode)),
899 899 label='ui.debug log.manifest')
900 900 # i18n: column positioning for "hg log"
901 901 self.ui.write(_("user: %s\n") % ctx.user(),
902 902 label='log.user')
903 903 # i18n: column positioning for "hg log"
904 904 self.ui.write(_("date: %s\n") % date,
905 905 label='log.date')
906 906
907 907 if self.ui.debugflag:
908 908 files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
909 909 for key, value in zip([# i18n: column positioning for "hg log"
910 910 _("files:"),
911 911 # i18n: column positioning for "hg log"
912 912 _("files+:"),
913 913 # i18n: column positioning for "hg log"
914 914 _("files-:")], files):
915 915 if value:
916 916 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
917 917 label='ui.debug log.files')
918 918 elif ctx.files() and self.ui.verbose:
919 919 # i18n: column positioning for "hg log"
920 920 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
921 921 label='ui.note log.files')
922 922 if copies and self.ui.verbose:
923 923 copies = ['%s (%s)' % c for c in copies]
924 924 # i18n: column positioning for "hg log"
925 925 self.ui.write(_("copies: %s\n") % ' '.join(copies),
926 926 label='ui.note log.copies')
927 927
928 928 extra = ctx.extra()
929 929 if extra and self.ui.debugflag:
930 930 for key, value in sorted(extra.items()):
931 931 # i18n: column positioning for "hg log"
932 932 self.ui.write(_("extra: %s=%s\n")
933 933 % (key, value.encode('string_escape')),
934 934 label='ui.debug log.extra')
935 935
936 936 description = ctx.description().strip()
937 937 if description:
938 938 if self.ui.verbose:
939 939 self.ui.write(_("description:\n"),
940 940 label='ui.note log.description')
941 941 self.ui.write(description,
942 942 label='ui.note log.description')
943 943 self.ui.write("\n\n")
944 944 else:
945 945 # i18n: column positioning for "hg log"
946 946 self.ui.write(_("summary: %s\n") %
947 947 description.splitlines()[0],
948 948 label='log.summary')
949 949 self.ui.write("\n")
950 950
951 951 self.showpatch(changenode, matchfn)
952 952
953 953 def showpatch(self, node, matchfn):
954 954 if not matchfn:
955 955 matchfn = self.patch
956 956 if matchfn:
957 957 stat = self.diffopts.get('stat')
958 958 diff = self.diffopts.get('patch')
959 959 diffopts = patch.diffopts(self.ui, self.diffopts)
960 960 prev = self.repo.changelog.parents(node)[0]
961 961 if stat:
962 962 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
963 963 match=matchfn, stat=True)
964 964 if diff:
965 965 if stat:
966 966 self.ui.write("\n")
967 967 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
968 968 match=matchfn, stat=False)
969 969 self.ui.write("\n")
970 970
971 971 def _meaningful_parentrevs(self, log, rev):
972 972 """Return list of meaningful (or all if debug) parentrevs for rev.
973 973
974 974 For merges (two non-nullrev revisions) both parents are meaningful.
975 975 Otherwise the first parent revision is considered meaningful if it
976 976 is not the preceding revision.
977 977 """
978 978 parents = log.parentrevs(rev)
979 979 if not self.ui.debugflag and parents[1] == nullrev:
980 980 if parents[0] >= rev - 1:
981 981 parents = []
982 982 else:
983 983 parents = [parents[0]]
984 984 return parents
985 985
986 986
987 987 class changeset_templater(changeset_printer):
988 988 '''format changeset information.'''
989 989
990 990 def __init__(self, ui, repo, patch, diffopts, tmpl, mapfile, buffered):
991 991 changeset_printer.__init__(self, ui, repo, patch, diffopts, buffered)
992 992 formatnode = ui.debugflag and (lambda x: x) or (lambda x: x[:12])
993 993 defaulttempl = {
994 994 'parent': '{rev}:{node|formatnode} ',
995 995 'manifest': '{rev}:{node|formatnode}',
996 996 'file_copy': '{name} ({source})',
997 997 'extra': '{key}={value|stringescape}'
998 998 }
999 999 # filecopy is preserved for compatibility reasons
1000 1000 defaulttempl['filecopy'] = defaulttempl['file_copy']
1001 1001 self.t = templater.templater(mapfile, {'formatnode': formatnode},
1002 1002 cache=defaulttempl)
1003 1003 if tmpl:
1004 1004 self.t.cache['changeset'] = tmpl
1005 1005
1006 1006 self.cache = {}
1007 1007
1008 1008 def _meaningful_parentrevs(self, ctx):
1009 1009 """Return list of meaningful (or all if debug) parentrevs for rev.
1010 1010 """
1011 1011 parents = ctx.parents()
1012 1012 if len(parents) > 1:
1013 1013 return parents
1014 1014 if self.ui.debugflag:
1015 1015 return [parents[0], self.repo['null']]
1016 1016 if parents[0].rev() >= ctx.rev() - 1:
1017 1017 return []
1018 1018 return parents
1019 1019
1020 1020 def _show(self, ctx, copies, matchfn, props):
1021 1021 '''show a single changeset or file revision'''
1022 1022
1023 1023 showlist = templatekw.showlist
1024 1024
1025 1025 # showparents() behaviour depends on ui trace level which
1026 1026 # causes unexpected behaviours at templating level and makes
1027 1027 # it harder to extract it in a standalone function. Its
1028 1028 # behaviour cannot be changed so leave it here for now.
1029 1029 def showparents(**args):
1030 1030 ctx = args['ctx']
1031 1031 parents = [[('rev', p.rev()), ('node', p.hex())]
1032 1032 for p in self._meaningful_parentrevs(ctx)]
1033 1033 return showlist('parent', parents, **args)
1034 1034
1035 1035 props = props.copy()
1036 1036 props.update(templatekw.keywords)
1037 1037 props['parents'] = showparents
1038 1038 props['templ'] = self.t
1039 1039 props['ctx'] = ctx
1040 1040 props['repo'] = self.repo
1041 1041 props['revcache'] = {'copies': copies}
1042 1042 props['cache'] = self.cache
1043 1043
1044 1044 # find correct templates for current mode
1045 1045
1046 1046 tmplmodes = [
1047 1047 (True, None),
1048 1048 (self.ui.verbose, 'verbose'),
1049 1049 (self.ui.quiet, 'quiet'),
1050 1050 (self.ui.debugflag, 'debug'),
1051 1051 ]
1052 1052
1053 1053 types = {'header': '', 'footer':'', 'changeset': 'changeset'}
1054 1054 for mode, postfix in tmplmodes:
1055 1055 for type in types:
1056 1056 cur = postfix and ('%s_%s' % (type, postfix)) or type
1057 1057 if mode and cur in self.t:
1058 1058 types[type] = cur
1059 1059
1060 1060 try:
1061 1061
1062 1062 # write header
1063 1063 if types['header']:
1064 1064 h = templater.stringify(self.t(types['header'], **props))
1065 1065 if self.buffered:
1066 1066 self.header[ctx.rev()] = h
1067 1067 else:
1068 1068 if self.lastheader != h:
1069 1069 self.lastheader = h
1070 1070 self.ui.write(h)
1071 1071
1072 1072 # write changeset metadata, then patch if requested
1073 1073 key = types['changeset']
1074 1074 self.ui.write(templater.stringify(self.t(key, **props)))
1075 1075 self.showpatch(ctx.node(), matchfn)
1076 1076
1077 1077 if types['footer']:
1078 1078 if not self.footer:
1079 1079 self.footer = templater.stringify(self.t(types['footer'],
1080 1080 **props))
1081 1081
1082 1082 except KeyError, inst:
1083 1083 msg = _("%s: no key named '%s'")
1084 1084 raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
1085 1085 except SyntaxError, inst:
1086 1086 raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
1087 1087
1088 1088 def gettemplate(ui, tmpl, style):
1089 1089 """
1090 1090 Find the template matching the given template spec or style.
1091 1091 """
1092 1092
1093 1093 # ui settings
1094 1094 if not tmpl and not style:
1095 1095 tmpl = ui.config('ui', 'logtemplate')
1096 1096 if tmpl:
1097 1097 try:
1098 1098 tmpl = templater.parsestring(tmpl)
1099 1099 except SyntaxError:
1100 1100 tmpl = templater.parsestring(tmpl, quoted=False)
1101 1101 return tmpl, None
1102 1102 else:
1103 1103 style = util.expandpath(ui.config('ui', 'style', ''))
1104 1104
1105 1105 if style:
1106 1106 mapfile = style
1107 1107 if not os.path.split(mapfile)[0]:
1108 1108 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1109 1109 or templater.templatepath(mapfile))
1110 1110 if mapname:
1111 1111 mapfile = mapname
1112 1112 return None, mapfile
1113 1113
1114 1114 if not tmpl:
1115 1115 return None, None
1116 1116
1117 1117 # looks like a literal template?
1118 1118 if '{' in tmpl:
1119 1119 return tmpl, None
1120 1120
1121 1121 # perhaps a stock style?
1122 1122 if not os.path.split(tmpl)[0]:
1123 1123 mapname = (templater.templatepath('map-cmdline.' + tmpl)
1124 1124 or templater.templatepath(tmpl))
1125 1125 if mapname and os.path.isfile(mapname):
1126 1126 return None, mapname
1127 1127
1128 1128 # perhaps it's a reference to [templates]
1129 1129 t = ui.config('templates', tmpl)
1130 1130 if t:
1131 1131 try:
1132 1132 tmpl = templater.parsestring(t)
1133 1133 except SyntaxError:
1134 1134 tmpl = templater.parsestring(t, quoted=False)
1135 1135 return tmpl, None
1136 1136
1137 1137 if tmpl == 'list':
1138 1138 ui.write(_("available styles: %s\n") % templater.stylelist())
1139 1139 raise util.Abort(_("specify a template"))
1140 1140
1141 1141 # perhaps it's a path to a map or a template
1142 1142 if ('/' in tmpl or '\\' in tmpl) and os.path.isfile(tmpl):
1143 1143 # is it a mapfile for a style?
1144 1144 if os.path.basename(tmpl).startswith("map-"):
1145 1145 return None, os.path.realpath(tmpl)
1146 1146 tmpl = open(tmpl).read()
1147 1147 return tmpl, None
1148 1148
1149 1149 # constant string?
1150 1150 return tmpl, None
1151 1151
1152 1152 def show_changeset(ui, repo, opts, buffered=False):
1153 1153 """show one changeset using template or regular display.
1154 1154
1155 1155 Display format will be the first non-empty hit of:
1156 1156 1. option 'template'
1157 1157 2. option 'style'
1158 1158 3. [ui] setting 'logtemplate'
1159 1159 4. [ui] setting 'style'
1160 1160 If all of these values are either the unset or the empty string,
1161 1161 regular display via changeset_printer() is done.
1162 1162 """
1163 1163 # options
1164 1164 patch = None
1165 1165 if opts.get('patch') or opts.get('stat'):
1166 1166 patch = scmutil.matchall(repo)
1167 1167
1168 1168 tmpl, mapfile = gettemplate(ui, opts.get('template'), opts.get('style'))
1169 1169
1170 1170 if not tmpl and not mapfile:
1171 1171 return changeset_printer(ui, repo, patch, opts, buffered)
1172 1172
1173 1173 try:
1174 1174 t = changeset_templater(ui, repo, patch, opts, tmpl, mapfile, buffered)
1175 1175 except SyntaxError, inst:
1176 1176 raise util.Abort(inst.args[0])
1177 1177 return t
1178 1178
1179 1179 def showmarker(ui, marker):
1180 1180 """utility function to display obsolescence marker in a readable way
1181 1181
1182 1182 To be used by debug function."""
1183 1183 ui.write(hex(marker.precnode()))
1184 1184 for repl in marker.succnodes():
1185 1185 ui.write(' ')
1186 1186 ui.write(hex(repl))
1187 1187 ui.write(' %X ' % marker._data[2])
1188 1188 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
1189 1189 sorted(marker.metadata().items()))))
1190 1190 ui.write('\n')
1191 1191
1192 1192 def finddate(ui, repo, date):
1193 1193 """Find the tipmost changeset that matches the given date spec"""
1194 1194
1195 1195 df = util.matchdate(date)
1196 1196 m = scmutil.matchall(repo)
1197 1197 results = {}
1198 1198
1199 1199 def prep(ctx, fns):
1200 1200 d = ctx.date()
1201 1201 if df(d[0]):
1202 1202 results[ctx.rev()] = d
1203 1203
1204 1204 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
1205 1205 rev = ctx.rev()
1206 1206 if rev in results:
1207 1207 ui.status(_("found revision %s from %s\n") %
1208 1208 (rev, util.datestr(results[rev])))
1209 1209 return str(rev)
1210 1210
1211 1211 raise util.Abort(_("revision matching date not found"))
1212 1212
1213 1213 def increasingwindows(windowsize=8, sizelimit=512):
1214 1214 while True:
1215 1215 yield windowsize
1216 1216 if windowsize < sizelimit:
1217 1217 windowsize *= 2
1218 1218
1219 1219 class FileWalkError(Exception):
1220 1220 pass
1221 1221
1222 1222 def walkfilerevs(repo, match, follow, revs, fncache):
1223 1223 '''Walks the file history for the matched files.
1224 1224
1225 1225 Returns the changeset revs that are involved in the file history.
1226 1226
1227 1227 Throws FileWalkError if the file history can't be walked using
1228 1228 filelogs alone.
1229 1229 '''
1230 1230 wanted = set()
1231 1231 copies = []
1232 1232 minrev, maxrev = min(revs), max(revs)
1233 1233 def filerevgen(filelog, last):
1234 1234 """
1235 1235 Only files, no patterns. Check the history of each file.
1236 1236
1237 1237 Examines filelog entries within minrev, maxrev linkrev range
1238 1238 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
1239 1239 tuples in backwards order
1240 1240 """
1241 1241 cl_count = len(repo)
1242 1242 revs = []
1243 1243 for j in xrange(0, last + 1):
1244 1244 linkrev = filelog.linkrev(j)
1245 1245 if linkrev < minrev:
1246 1246 continue
1247 1247 # only yield rev for which we have the changelog, it can
1248 1248 # happen while doing "hg log" during a pull or commit
1249 1249 if linkrev >= cl_count:
1250 1250 break
1251 1251
1252 1252 parentlinkrevs = []
1253 1253 for p in filelog.parentrevs(j):
1254 1254 if p != nullrev:
1255 1255 parentlinkrevs.append(filelog.linkrev(p))
1256 1256 n = filelog.node(j)
1257 1257 revs.append((linkrev, parentlinkrevs,
1258 1258 follow and filelog.renamed(n)))
1259 1259
1260 1260 return reversed(revs)
1261 1261 def iterfiles():
1262 1262 pctx = repo['.']
1263 1263 for filename in match.files():
1264 1264 if follow:
1265 1265 if filename not in pctx:
1266 1266 raise util.Abort(_('cannot follow file not in parent '
1267 1267 'revision: "%s"') % filename)
1268 1268 yield filename, pctx[filename].filenode()
1269 1269 else:
1270 1270 yield filename, None
1271 1271 for filename_node in copies:
1272 1272 yield filename_node
1273 1273
1274 1274 for file_, node in iterfiles():
1275 1275 filelog = repo.file(file_)
1276 1276 if not len(filelog):
1277 1277 if node is None:
1278 1278 # A zero count may be a directory or deleted file, so
1279 1279 # try to find matching entries on the slow path.
1280 1280 if follow:
1281 1281 raise util.Abort(
1282 1282 _('cannot follow nonexistent file: "%s"') % file_)
1283 1283 raise FileWalkError("Cannot walk via filelog")
1284 1284 else:
1285 1285 continue
1286 1286
1287 1287 if node is None:
1288 1288 last = len(filelog) - 1
1289 1289 else:
1290 1290 last = filelog.rev(node)
1291 1291
1292 1292
1293 1293 # keep track of all ancestors of the file
1294 1294 ancestors = set([filelog.linkrev(last)])
1295 1295
1296 1296 # iterate from latest to oldest revision
1297 1297 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
1298 1298 if not follow:
1299 1299 if rev > maxrev:
1300 1300 continue
1301 1301 else:
1302 1302 # Note that last might not be the first interesting
1303 1303 # rev to us:
1304 1304 # if the file has been changed after maxrev, we'll
1305 1305 # have linkrev(last) > maxrev, and we still need
1306 1306 # to explore the file graph
1307 1307 if rev not in ancestors:
1308 1308 continue
1309 1309 # XXX insert 1327 fix here
1310 1310 if flparentlinkrevs:
1311 1311 ancestors.update(flparentlinkrevs)
1312 1312
1313 1313 fncache.setdefault(rev, []).append(file_)
1314 1314 wanted.add(rev)
1315 1315 if copied:
1316 1316 copies.append(copied)
1317 1317
1318 1318 return wanted
1319 1319
1320 1320 def walkchangerevs(repo, match, opts, prepare):
1321 1321 '''Iterate over files and the revs in which they changed.
1322 1322
1323 1323 Callers most commonly need to iterate backwards over the history
1324 1324 in which they are interested. Doing so has awful (quadratic-looking)
1325 1325 performance, so we use iterators in a "windowed" way.
1326 1326
1327 1327 We walk a window of revisions in the desired order. Within the
1328 1328 window, we first walk forwards to gather data, then in the desired
1329 1329 order (usually backwards) to display it.
1330 1330
1331 1331 This function returns an iterator yielding contexts. Before
1332 1332 yielding each context, the iterator will first call the prepare
1333 1333 function on each context in the window in forward order.'''
1334 1334
1335 1335 follow = opts.get('follow') or opts.get('follow_first')
1336 1336
1337 1337 if opts.get('rev'):
1338 1338 revs = scmutil.revrange(repo, opts.get('rev'))
1339 1339 elif follow:
1340 1340 revs = repo.revs('reverse(:.)')
1341 1341 else:
1342 1342 revs = revset.spanset(repo)
1343 1343 revs.reverse()
1344 1344 if not revs:
1345 1345 return []
1346 1346 wanted = set()
1347 1347 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1348 1348 fncache = {}
1349 1349 change = repo.changectx
1350 1350
1351 1351 # First step is to fill wanted, the set of revisions that we want to yield.
1352 1352 # When it does not induce extra cost, we also fill fncache for revisions in
1353 1353 # wanted: a cache of filenames that were changed (ctx.files()) and that
1354 1354 # match the file filtering conditions.
1355 1355
1356 1356 if not slowpath and not match.files():
1357 1357 # No files, no patterns. Display all revs.
1358 1358 wanted = revs
1359 1359
1360 1360 if not slowpath and match.files():
1361 1361 # We only have to read through the filelog to find wanted revisions
1362 1362
1363 1363 try:
1364 1364 wanted = walkfilerevs(repo, match, follow, revs, fncache)
1365 1365 except FileWalkError:
1366 1366 slowpath = True
1367 1367
1368 1368 # We decided to fall back to the slowpath because at least one
1369 1369 # of the paths was not a file. Check to see if at least one of them
1370 1370 # existed in history, otherwise simply return
1371 1371 for path in match.files():
1372 1372 if path == '.' or path in repo.store:
1373 1373 break
1374 1374 else:
1375 1375 return []
1376 1376
1377 1377 if slowpath:
1378 1378 # We have to read the changelog to match filenames against
1379 1379 # changed files
1380 1380
1381 1381 if follow:
1382 1382 raise util.Abort(_('can only follow copies/renames for explicit '
1383 1383 'filenames'))
1384 1384
1385 1385 # The slow path checks files modified in every changeset.
1386 1386 # This is really slow on large repos, so compute the set lazily.
1387 1387 class lazywantedset(object):
1388 1388 def __init__(self):
1389 1389 self.set = set()
1390 1390 self.revs = set(revs)
1391 1391
1392 1392 # No need to worry about locality here because it will be accessed
1393 1393 # in the same order as the increasing window below.
1394 1394 def __contains__(self, value):
1395 1395 if value in self.set:
1396 1396 return True
1397 1397 elif not value in self.revs:
1398 1398 return False
1399 1399 else:
1400 1400 self.revs.discard(value)
1401 1401 ctx = change(value)
1402 1402 matches = filter(match, ctx.files())
1403 1403 if matches:
1404 1404 fncache[value] = matches
1405 1405 self.set.add(value)
1406 1406 return True
1407 1407 return False
1408 1408
1409 1409 def discard(self, value):
1410 1410 self.revs.discard(value)
1411 1411 self.set.discard(value)
1412 1412
1413 1413 wanted = lazywantedset()
1414 1414
1415 1415 class followfilter(object):
1416 1416 def __init__(self, onlyfirst=False):
1417 1417 self.startrev = nullrev
1418 1418 self.roots = set()
1419 1419 self.onlyfirst = onlyfirst
1420 1420
1421 1421 def match(self, rev):
1422 1422 def realparents(rev):
1423 1423 if self.onlyfirst:
1424 1424 return repo.changelog.parentrevs(rev)[0:1]
1425 1425 else:
1426 1426 return filter(lambda x: x != nullrev,
1427 1427 repo.changelog.parentrevs(rev))
1428 1428
1429 1429 if self.startrev == nullrev:
1430 1430 self.startrev = rev
1431 1431 return True
1432 1432
1433 1433 if rev > self.startrev:
1434 1434 # forward: all descendants
1435 1435 if not self.roots:
1436 1436 self.roots.add(self.startrev)
1437 1437 for parent in realparents(rev):
1438 1438 if parent in self.roots:
1439 1439 self.roots.add(rev)
1440 1440 return True
1441 1441 else:
1442 1442 # backwards: all parents
1443 1443 if not self.roots:
1444 1444 self.roots.update(realparents(self.startrev))
1445 1445 if rev in self.roots:
1446 1446 self.roots.remove(rev)
1447 1447 self.roots.update(realparents(rev))
1448 1448 return True
1449 1449
1450 1450 return False
1451 1451
1452 1452 # it might be worthwhile to do this in the iterator if the rev range
1453 1453 # is descending and the prune args are all within that range
1454 1454 for rev in opts.get('prune', ()):
1455 1455 rev = repo[rev].rev()
1456 1456 ff = followfilter()
1457 1457 stop = min(revs[0], revs[-1])
1458 1458 for x in xrange(rev, stop - 1, -1):
1459 1459 if ff.match(x):
1460 1460 wanted = wanted - [x]
1461 1461
1462 1462 # Now that wanted is correctly initialized, we can iterate over the
1463 1463 # revision range, yielding only revisions in wanted.
1464 1464 def iterate():
1465 1465 if follow and not match.files():
1466 1466 ff = followfilter(onlyfirst=opts.get('follow_first'))
1467 1467 def want(rev):
1468 1468 return ff.match(rev) and rev in wanted
1469 1469 else:
1470 1470 def want(rev):
1471 1471 return rev in wanted
1472 1472
1473 1473 it = iter(revs)
1474 1474 stopiteration = False
1475 1475 for windowsize in increasingwindows():
1476 1476 nrevs = []
1477 1477 for i in xrange(windowsize):
1478 1478 try:
1479 1479 rev = it.next()
1480 1480 if want(rev):
1481 1481 nrevs.append(rev)
1482 1482 except (StopIteration):
1483 1483 stopiteration = True
1484 1484 break
1485 1485 for rev in sorted(nrevs):
1486 1486 fns = fncache.get(rev)
1487 1487 ctx = change(rev)
1488 1488 if not fns:
1489 1489 def fns_generator():
1490 1490 for f in ctx.files():
1491 1491 if match(f):
1492 1492 yield f
1493 1493 fns = fns_generator()
1494 1494 prepare(ctx, fns)
1495 1495 for rev in nrevs:
1496 1496 yield change(rev)
1497 1497
1498 1498 if stopiteration:
1499 1499 break
1500 1500
1501 1501 return iterate()
1502 1502
1503 1503 def _makelogfilematcher(repo, files, followfirst):
1504 1504 # When displaying a revision with --patch --follow FILE, we have
1505 1505 # to know which file of the revision must be diffed. With
1506 1506 # --follow, we want the names of the ancestors of FILE in the
1507 1507 # revision, stored in "fcache". "fcache" is populated by
1508 1508 # reproducing the graph traversal already done by --follow revset
1509 1509 # and relating linkrevs to file names (which is not "correct" but
1510 1510 # good enough).
1511 1511 fcache = {}
1512 1512 fcacheready = [False]
1513 1513 pctx = repo['.']
1514 1514
1515 1515 def populate():
1516 1516 for fn in files:
1517 1517 for i in ((pctx[fn],), pctx[fn].ancestors(followfirst=followfirst)):
1518 1518 for c in i:
1519 1519 fcache.setdefault(c.linkrev(), set()).add(c.path())
1520 1520
1521 1521 def filematcher(rev):
1522 1522 if not fcacheready[0]:
1523 1523 # Lazy initialization
1524 1524 fcacheready[0] = True
1525 1525 populate()
1526 1526 return scmutil.matchfiles(repo, fcache.get(rev, []))
1527 1527
1528 1528 return filematcher
1529 1529
1530 1530 def _makelogrevset(repo, pats, opts, revs):
1531 1531 """Return (expr, filematcher) where expr is a revset string built
1532 1532 from log options and file patterns or None. If --stat or --patch
1533 1533 are not passed filematcher is None. Otherwise it is a callable
1534 1534 taking a revision number and returning a match objects filtering
1535 1535 the files to be detailed when displaying the revision.
1536 1536 """
1537 1537 opt2revset = {
1538 1538 'no_merges': ('not merge()', None),
1539 1539 'only_merges': ('merge()', None),
1540 1540 '_ancestors': ('ancestors(%(val)s)', None),
1541 1541 '_fancestors': ('_firstancestors(%(val)s)', None),
1542 1542 '_descendants': ('descendants(%(val)s)', None),
1543 1543 '_fdescendants': ('_firstdescendants(%(val)s)', None),
1544 1544 '_matchfiles': ('_matchfiles(%(val)s)', None),
1545 1545 'date': ('date(%(val)r)', None),
1546 1546 'branch': ('branch(%(val)r)', ' or '),
1547 1547 '_patslog': ('filelog(%(val)r)', ' or '),
1548 1548 '_patsfollow': ('follow(%(val)r)', ' or '),
1549 1549 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
1550 1550 'keyword': ('keyword(%(val)r)', ' or '),
1551 1551 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
1552 1552 'user': ('user(%(val)r)', ' or '),
1553 1553 }
1554 1554
1555 1555 opts = dict(opts)
1556 1556 # follow or not follow?
1557 1557 follow = opts.get('follow') or opts.get('follow_first')
1558 1558 followfirst = opts.get('follow_first') and 1 or 0
1559 1559 # --follow with FILE behaviour depends on revs...
1560 1560 it = iter(revs)
1561 1561 startrev = it.next()
1562 1562 try:
1563 1563 followdescendants = startrev < it.next()
1564 1564 except (StopIteration):
1565 1565 followdescendants = False
1566 1566
1567 1567 # branch and only_branch are really aliases and must be handled at
1568 1568 # the same time
1569 1569 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
1570 1570 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
1571 1571 # pats/include/exclude are passed to match.match() directly in
1572 1572 # _matchfiles() revset but walkchangerevs() builds its matcher with
1573 1573 # scmutil.match(). The difference is input pats are globbed on
1574 1574 # platforms without shell expansion (windows).
1575 1575 pctx = repo[None]
1576 1576 match, pats = scmutil.matchandpats(pctx, pats, opts)
1577 1577 slowpath = match.anypats() or (match.files() and opts.get('removed'))
1578 1578 if not slowpath:
1579 1579 for f in match.files():
1580 1580 if follow and f not in pctx:
1581 1581 # If the file exists, it may be a directory, so let it
1582 1582 # take the slow path.
1583 1583 if os.path.exists(repo.wjoin(f)):
1584 1584 slowpath = True
1585 1585 continue
1586 1586 else:
1587 1587 raise util.Abort(_('cannot follow file not in parent '
1588 1588 'revision: "%s"') % f)
1589 1589 filelog = repo.file(f)
1590 1590 if not filelog:
1591 1591 # A zero count may be a directory or deleted file, so
1592 1592 # try to find matching entries on the slow path.
1593 1593 if follow:
1594 1594 raise util.Abort(
1595 1595 _('cannot follow nonexistent file: "%s"') % f)
1596 1596 slowpath = True
1597 1597
1598 1598 # We decided to fall back to the slowpath because at least one
1599 1599 # of the paths was not a file. Check to see if at least one of them
1600 1600 # existed in history - in that case, we'll continue down the
1601 1601 # slowpath; otherwise, we can turn off the slowpath
1602 1602 if slowpath:
1603 1603 for path in match.files():
1604 1604 if path == '.' or path in repo.store:
1605 1605 break
1606 1606 else:
1607 1607 slowpath = False
1608 1608
1609 1609 if slowpath:
1610 1610 # See walkchangerevs() slow path.
1611 1611 #
1612 1612 # pats/include/exclude cannot be represented as separate
1613 1613 # revset expressions as their filtering logic applies at file
1614 1614 # level. For instance "-I a -X a" matches a revision touching
1615 1615 # "a" and "b" while "file(a) and not file(b)" does
1616 1616 # not. Besides, filesets are evaluated against the working
1617 1617 # directory.
1618 1618 matchargs = ['r:', 'd:relpath']
1619 1619 for p in pats:
1620 1620 matchargs.append('p:' + p)
1621 1621 for p in opts.get('include', []):
1622 1622 matchargs.append('i:' + p)
1623 1623 for p in opts.get('exclude', []):
1624 1624 matchargs.append('x:' + p)
1625 1625 matchargs = ','.join(('%r' % p) for p in matchargs)
1626 1626 opts['_matchfiles'] = matchargs
1627 1627 else:
1628 1628 if follow:
1629 1629 fpats = ('_patsfollow', '_patsfollowfirst')
1630 1630 fnopats = (('_ancestors', '_fancestors'),
1631 1631 ('_descendants', '_fdescendants'))
1632 1632 if pats:
1633 1633 # follow() revset interprets its file argument as a
1634 1634 # manifest entry, so use match.files(), not pats.
1635 1635 opts[fpats[followfirst]] = list(match.files())
1636 1636 else:
1637 1637 opts[fnopats[followdescendants][followfirst]] = str(startrev)
1638 1638 else:
1639 1639 opts['_patslog'] = list(pats)
1640 1640
1641 1641 filematcher = None
1642 1642 if opts.get('patch') or opts.get('stat'):
1643 1643 # When following files, track renames via a special matcher.
1644 1644 # If we're forced to take the slowpath it means we're following
1645 1645 # at least one pattern/directory, so don't bother with rename tracking.
1646 1646 if follow and not match.always() and not slowpath:
1647 1647 # _makelogfilematcher expects its files argument to be relative to
1648 1648 # the repo root, so use match.files(), not pats.
1649 1649 filematcher = _makelogfilematcher(repo, match.files(), followfirst)
1650 1650 else:
1651 1651 filematcher = lambda rev: match
1652 1652
1653 1653 expr = []
1654 1654 for op, val in opts.iteritems():
1655 1655 if not val:
1656 1656 continue
1657 1657 if op not in opt2revset:
1658 1658 continue
1659 1659 revop, andor = opt2revset[op]
1660 1660 if '%(val)' not in revop:
1661 1661 expr.append(revop)
1662 1662 else:
1663 1663 if not isinstance(val, list):
1664 1664 e = revop % {'val': val}
1665 1665 else:
1666 1666 e = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
1667 1667 expr.append(e)
1668 1668
1669 1669 if expr:
1670 1670 expr = '(' + ' and '.join(expr) + ')'
1671 1671 else:
1672 1672 expr = None
1673 1673 return expr, filematcher
1674 1674
1675 1675 def getgraphlogrevs(repo, pats, opts):
1676 1676 """Return (revs, expr, filematcher) where revs is an iterable of
1677 1677 revision numbers, expr is a revset string built from log options
1678 1678 and file patterns or None, and used to filter 'revs'. If --stat or
1679 1679 --patch are not passed filematcher is None. Otherwise it is a
1680 1680 callable taking a revision number and returning a match objects
1681 1681 filtering the files to be detailed when displaying the revision.
1682 1682 """
1683 1683 if not len(repo):
1684 1684 return [], None, None
1685 1685 limit = loglimit(opts)
1686 1686 # Default --rev value depends on --follow but --follow behaviour
1687 1687 # depends on revisions resolved from --rev...
1688 1688 follow = opts.get('follow') or opts.get('follow_first')
1689 1689 possiblyunsorted = False # whether revs might need sorting
1690 1690 if opts.get('rev'):
1691 1691 revs = scmutil.revrange(repo, opts['rev'])
1692 1692 # Don't sort here because _makelogrevset might depend on the
1693 1693 # order of revs
1694 1694 possiblyunsorted = True
1695 1695 else:
1696 1696 if follow and len(repo) > 0:
1697 1697 revs = repo.revs('reverse(:.)')
1698 1698 else:
1699 1699 revs = revset.spanset(repo)
1700 1700 revs.reverse()
1701 1701 if not revs:
1702 1702 return revset.baseset(), None, None
1703 1703 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
1704 1704 if possiblyunsorted:
1705 1705 revs.sort(reverse=True)
1706 1706 if expr:
1707 1707 # Revset matchers often operate faster on revisions in changelog
1708 1708 # order, because most filters deal with the changelog.
1709 1709 revs.reverse()
1710 1710 matcher = revset.match(repo.ui, expr)
1711 1711 # Revset matches can reorder revisions. "A or B" typically returns
1712 1712 # returns the revision matching A then the revision matching B. Sort
1713 1713 # again to fix that.
1714 1714 revs = matcher(repo, revs)
1715 1715 revs.sort(reverse=True)
1716 1716 if limit is not None:
1717 1717 limitedrevs = revset.baseset()
1718 1718 for idx, rev in enumerate(revs):
1719 1719 if idx >= limit:
1720 1720 break
1721 1721 limitedrevs.append(rev)
1722 1722 revs = limitedrevs
1723 1723
1724 1724 return revs, expr, filematcher
1725 1725
1726 1726 def getlogrevs(repo, pats, opts):
1727 1727 """Return (revs, expr, filematcher) where revs is an iterable of
1728 1728 revision numbers, expr is a revset string built from log options
1729 1729 and file patterns or None, and used to filter 'revs'. If --stat or
1730 1730 --patch are not passed filematcher is None. Otherwise it is a
1731 1731 callable taking a revision number and returning a match objects
1732 1732 filtering the files to be detailed when displaying the revision.
1733 1733 """
1734 1734 limit = loglimit(opts)
1735 1735 # Default --rev value depends on --follow but --follow behaviour
1736 1736 # depends on revisions resolved from --rev...
1737 1737 follow = opts.get('follow') or opts.get('follow_first')
1738 1738 if opts.get('rev'):
1739 1739 revs = scmutil.revrange(repo, opts['rev'])
1740 1740 elif follow:
1741 1741 revs = repo.revs('reverse(:.)')
1742 1742 else:
1743 1743 revs = revset.spanset(repo)
1744 1744 revs.reverse()
1745 1745 if not revs:
1746 1746 return revset.baseset([]), None, None
1747 1747 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
1748 1748 if expr:
1749 1749 # Revset matchers often operate faster on revisions in changelog
1750 1750 # order, because most filters deal with the changelog.
1751 1751 if not opts.get('rev'):
1752 1752 revs.reverse()
1753 1753 matcher = revset.match(repo.ui, expr)
1754 1754 # Revset matches can reorder revisions. "A or B" typically returns
1755 1755 # returns the revision matching A then the revision matching B. Sort
1756 1756 # again to fix that.
1757 1757 revs = matcher(repo, revs)
1758 1758 if not opts.get('rev'):
1759 1759 revs.sort(reverse=True)
1760 1760 if limit is not None:
1761 1761 count = 0
1762 1762 limitedrevs = revset.baseset([])
1763 1763 it = iter(revs)
1764 1764 while count < limit:
1765 1765 try:
1766 1766 limitedrevs.append(it.next())
1767 1767 except (StopIteration):
1768 1768 break
1769 1769 count += 1
1770 1770 revs = limitedrevs
1771 1771
1772 1772 return revs, expr, filematcher
1773 1773
1774 1774 def displaygraph(ui, dag, displayer, showparents, edgefn, getrenamed=None,
1775 1775 filematcher=None):
1776 1776 seen, state = [], graphmod.asciistate()
1777 1777 for rev, type, ctx, parents in dag:
1778 1778 char = 'o'
1779 1779 if ctx.node() in showparents:
1780 1780 char = '@'
1781 1781 elif ctx.obsolete():
1782 1782 char = 'x'
1783 1783 copies = None
1784 1784 if getrenamed and ctx.rev():
1785 1785 copies = []
1786 1786 for fn in ctx.files():
1787 1787 rename = getrenamed(fn, ctx.rev())
1788 1788 if rename:
1789 1789 copies.append((fn, rename[0]))
1790 1790 revmatchfn = None
1791 1791 if filematcher is not None:
1792 1792 revmatchfn = filematcher(ctx.rev())
1793 1793 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
1794 1794 lines = displayer.hunk.pop(rev).split('\n')
1795 1795 if not lines[-1]:
1796 1796 del lines[-1]
1797 1797 displayer.flush(rev)
1798 1798 edges = edgefn(type, char, lines, seen, rev, parents)
1799 1799 for type, char, lines, coldata in edges:
1800 1800 graphmod.ascii(ui, state, type, char, lines, coldata)
1801 1801 displayer.close()
1802 1802
1803 1803 def graphlog(ui, repo, *pats, **opts):
1804 1804 # Parameters are identical to log command ones
1805 1805 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts)
1806 1806 revdag = graphmod.dagwalker(repo, revs)
1807 1807
1808 1808 getrenamed = None
1809 1809 if opts.get('copies'):
1810 1810 endrev = None
1811 1811 if opts.get('rev'):
1812 1812 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
1813 1813 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
1814 1814 displayer = show_changeset(ui, repo, opts, buffered=True)
1815 1815 showparents = [ctx.node() for ctx in repo[None].parents()]
1816 1816 displaygraph(ui, revdag, displayer, showparents,
1817 1817 graphmod.asciiedges, getrenamed, filematcher)
1818 1818
1819 1819 def checkunsupportedgraphflags(pats, opts):
1820 1820 for op in ["newest_first"]:
1821 1821 if op in opts and opts[op]:
1822 1822 raise util.Abort(_("-G/--graph option is incompatible with --%s")
1823 1823 % op.replace("_", "-"))
1824 1824
1825 1825 def graphrevs(repo, nodes, opts):
1826 1826 limit = loglimit(opts)
1827 1827 nodes.reverse()
1828 1828 if limit is not None:
1829 1829 nodes = nodes[:limit]
1830 1830 return graphmod.nodes(repo, nodes)
1831 1831
1832 1832 def add(ui, repo, match, dryrun, listsubrepos, prefix, explicitonly):
1833 1833 join = lambda f: os.path.join(prefix, f)
1834 1834 bad = []
1835 1835 oldbad = match.bad
1836 1836 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1837 1837 names = []
1838 1838 wctx = repo[None]
1839 1839 cca = None
1840 1840 abort, warn = scmutil.checkportabilityalert(ui)
1841 1841 if abort or warn:
1842 1842 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
1843 1843 for f in repo.walk(match):
1844 1844 exact = match.exact(f)
1845 1845 if exact or not explicitonly and f not in repo.dirstate:
1846 1846 if cca:
1847 1847 cca(f)
1848 1848 names.append(f)
1849 1849 if ui.verbose or not exact:
1850 1850 ui.status(_('adding %s\n') % match.rel(join(f)))
1851 1851
1852 1852 for subpath in sorted(wctx.substate):
1853 1853 sub = wctx.sub(subpath)
1854 1854 try:
1855 1855 submatch = matchmod.narrowmatcher(subpath, match)
1856 1856 if listsubrepos:
1857 1857 bad.extend(sub.add(ui, submatch, dryrun, listsubrepos, prefix,
1858 1858 False))
1859 1859 else:
1860 1860 bad.extend(sub.add(ui, submatch, dryrun, listsubrepos, prefix,
1861 1861 True))
1862 1862 except error.LookupError:
1863 1863 ui.status(_("skipping missing subrepository: %s\n")
1864 1864 % join(subpath))
1865 1865
1866 1866 if not dryrun:
1867 1867 rejected = wctx.add(names, prefix)
1868 1868 bad.extend(f for f in rejected if f in match.files())
1869 1869 return bad
1870 1870
1871 1871 def forget(ui, repo, match, prefix, explicitonly):
1872 1872 join = lambda f: os.path.join(prefix, f)
1873 1873 bad = []
1874 1874 oldbad = match.bad
1875 1875 match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
1876 1876 wctx = repo[None]
1877 1877 forgot = []
1878 1878 s = repo.status(match=match, clean=True)
1879 1879 forget = sorted(s[0] + s[1] + s[3] + s[6])
1880 1880 if explicitonly:
1881 1881 forget = [f for f in forget if match.exact(f)]
1882 1882
1883 1883 for subpath in sorted(wctx.substate):
1884 1884 sub = wctx.sub(subpath)
1885 1885 try:
1886 1886 submatch = matchmod.narrowmatcher(subpath, match)
1887 1887 subbad, subforgot = sub.forget(ui, submatch, prefix)
1888 1888 bad.extend([subpath + '/' + f for f in subbad])
1889 1889 forgot.extend([subpath + '/' + f for f in subforgot])
1890 1890 except error.LookupError:
1891 1891 ui.status(_("skipping missing subrepository: %s\n")
1892 1892 % join(subpath))
1893 1893
1894 1894 if not explicitonly:
1895 1895 for f in match.files():
1896 1896 if f not in repo.dirstate and not os.path.isdir(match.rel(join(f))):
1897 1897 if f not in forgot:
1898 1898 if os.path.exists(match.rel(join(f))):
1899 1899 ui.warn(_('not removing %s: '
1900 1900 'file is already untracked\n')
1901 1901 % match.rel(join(f)))
1902 1902 bad.append(f)
1903 1903
1904 1904 for f in forget:
1905 1905 if ui.verbose or not match.exact(f):
1906 1906 ui.status(_('removing %s\n') % match.rel(join(f)))
1907 1907
1908 1908 rejected = wctx.forget(forget, prefix)
1909 1909 bad.extend(f for f in rejected if f in match.files())
1910 1910 forgot.extend(forget)
1911 1911 return bad, forgot
1912 1912
1913 1913 def cat(ui, repo, ctx, matcher, prefix, **opts):
1914 1914 err = 1
1915 1915
1916 1916 def write(path):
1917 1917 fp = makefileobj(repo, opts.get('output'), ctx.node(),
1918 1918 pathname=os.path.join(prefix, path))
1919 1919 data = ctx[path].data()
1920 1920 if opts.get('decode'):
1921 1921 data = repo.wwritedata(path, data)
1922 1922 fp.write(data)
1923 1923 fp.close()
1924 1924
1925 1925 # Automation often uses hg cat on single files, so special case it
1926 1926 # for performance to avoid the cost of parsing the manifest.
1927 1927 if len(matcher.files()) == 1 and not matcher.anypats():
1928 1928 file = matcher.files()[0]
1929 1929 mf = repo.manifest
1930 1930 mfnode = ctx._changeset[0]
1931 1931 if mf.find(mfnode, file)[0]:
1932 1932 write(file)
1933 1933 return 0
1934 1934
1935 1935 # Don't warn about "missing" files that are really in subrepos
1936 1936 bad = matcher.bad
1937 1937
1938 1938 def badfn(path, msg):
1939 1939 for subpath in ctx.substate:
1940 1940 if path.startswith(subpath):
1941 1941 return
1942 1942 bad(path, msg)
1943 1943
1944 1944 matcher.bad = badfn
1945 1945
1946 1946 for abs in ctx.walk(matcher):
1947 1947 write(abs)
1948 1948 err = 0
1949 1949
1950 1950 matcher.bad = bad
1951 1951
1952 1952 for subpath in sorted(ctx.substate):
1953 1953 sub = ctx.sub(subpath)
1954 1954 try:
1955 1955 submatch = matchmod.narrowmatcher(subpath, matcher)
1956 1956
1957 1957 if not sub.cat(ui, submatch, os.path.join(prefix, sub._path),
1958 1958 **opts):
1959 1959 err = 0
1960 1960 except error.RepoLookupError:
1961 1961 ui.status(_("skipping missing subrepository: %s\n")
1962 1962 % os.path.join(prefix, subpath))
1963 1963
1964 1964 return err
1965 1965
1966 1966 def duplicatecopies(repo, rev, fromrev, skiprev=None):
1967 1967 '''reproduce copies from fromrev to rev in the dirstate
1968 1968
1969 1969 If skiprev is specified, it's a revision that should be used to
1970 1970 filter copy records. Any copies that occur between fromrev and
1971 1971 skiprev will not be duplicated, even if they appear in the set of
1972 1972 copies between fromrev and rev.
1973 1973 '''
1974 1974 exclude = {}
1975 1975 if skiprev is not None:
1976 1976 exclude = copies.pathcopies(repo[fromrev], repo[skiprev])
1977 1977 for dst, src in copies.pathcopies(repo[fromrev], repo[rev]).iteritems():
1978 1978 # copies.pathcopies returns backward renames, so dst might not
1979 1979 # actually be in the dirstate
1980 1980 if dst in exclude:
1981 1981 continue
1982 1982 if repo.dirstate[dst] in "nma":
1983 1983 repo.dirstate.copy(src, dst)
1984 1984
1985 1985 def commit(ui, repo, commitfunc, pats, opts):
1986 1986 '''commit the specified files or all outstanding changes'''
1987 1987 date = opts.get('date')
1988 1988 if date:
1989 1989 opts['date'] = util.parsedate(date)
1990 1990 message = logmessage(ui, opts)
1991 1991
1992 1992 # extract addremove carefully -- this function can be called from a command
1993 1993 # that doesn't support addremove
1994 1994 if opts.get('addremove'):
1995 1995 scmutil.addremove(repo, pats, opts)
1996 1996
1997 1997 return commitfunc(ui, repo, message,
1998 1998 scmutil.match(repo[None], pats, opts), opts)
1999 1999
2000 2000 def amend(ui, repo, commitfunc, old, extra, pats, opts):
2001 2001 ui.note(_('amending changeset %s\n') % old)
2002 2002 base = old.p1()
2003 2003
2004 2004 wlock = lock = newid = None
2005 2005 try:
2006 2006 wlock = repo.wlock()
2007 2007 lock = repo.lock()
2008 2008 tr = repo.transaction('amend')
2009 2009 try:
2010 2010 # See if we got a message from -m or -l, if not, open the editor
2011 2011 # with the message of the changeset to amend
2012 2012 message = logmessage(ui, opts)
2013 2013 # ensure logfile does not conflict with later enforcement of the
2014 2014 # message. potential logfile content has been processed by
2015 2015 # `logmessage` anyway.
2016 2016 opts.pop('logfile')
2017 2017 # First, do a regular commit to record all changes in the working
2018 2018 # directory (if there are any)
2019 2019 ui.callhooks = False
2020 2020 currentbookmark = repo._bookmarkcurrent
2021 2021 try:
2022 2022 repo._bookmarkcurrent = None
2023 2023 opts['message'] = 'temporary amend commit for %s' % old
2024 2024 node = commit(ui, repo, commitfunc, pats, opts)
2025 2025 finally:
2026 2026 repo._bookmarkcurrent = currentbookmark
2027 2027 ui.callhooks = True
2028 2028 ctx = repo[node]
2029 2029
2030 2030 # Participating changesets:
2031 2031 #
2032 2032 # node/ctx o - new (intermediate) commit that contains changes
2033 2033 # | from working dir to go into amending commit
2034 2034 # | (or a workingctx if there were no changes)
2035 2035 # |
2036 2036 # old o - changeset to amend
2037 2037 # |
2038 2038 # base o - parent of amending changeset
2039 2039
2040 2040 # Update extra dict from amended commit (e.g. to preserve graft
2041 2041 # source)
2042 2042 extra.update(old.extra())
2043 2043
2044 2044 # Also update it from the intermediate commit or from the wctx
2045 2045 extra.update(ctx.extra())
2046 2046
2047 2047 if len(old.parents()) > 1:
2048 2048 # ctx.files() isn't reliable for merges, so fall back to the
2049 2049 # slower repo.status() method
2050 2050 files = set([fn for st in repo.status(base, old)[:3]
2051 2051 for fn in st])
2052 2052 else:
2053 2053 files = set(old.files())
2054 2054
2055 2055 # Second, we use either the commit we just did, or if there were no
2056 2056 # changes the parent of the working directory as the version of the
2057 2057 # files in the final amend commit
2058 2058 if node:
2059 2059 ui.note(_('copying changeset %s to %s\n') % (ctx, base))
2060 2060
2061 2061 user = ctx.user()
2062 2062 date = ctx.date()
2063 2063 # Recompute copies (avoid recording a -> b -> a)
2064 2064 copied = copies.pathcopies(base, ctx)
2065 2065
2066 2066 # Prune files which were reverted by the updates: if old
2067 2067 # introduced file X and our intermediate commit, node,
2068 2068 # renamed that file, then those two files are the same and
2069 2069 # we can discard X from our list of files. Likewise if X
2070 2070 # was deleted, it's no longer relevant
2071 2071 files.update(ctx.files())
2072 2072
2073 2073 def samefile(f):
2074 2074 if f in ctx.manifest():
2075 2075 a = ctx.filectx(f)
2076 2076 if f in base.manifest():
2077 2077 b = base.filectx(f)
2078 2078 return (not a.cmp(b)
2079 2079 and a.flags() == b.flags())
2080 2080 else:
2081 2081 return False
2082 2082 else:
2083 2083 return f not in base.manifest()
2084 2084 files = [f for f in files if not samefile(f)]
2085 2085
2086 2086 def filectxfn(repo, ctx_, path):
2087 2087 try:
2088 2088 fctx = ctx[path]
2089 2089 flags = fctx.flags()
2090 2090 mctx = context.memfilectx(repo,
2091 2091 fctx.path(), fctx.data(),
2092 2092 islink='l' in flags,
2093 2093 isexec='x' in flags,
2094 2094 copied=copied.get(path))
2095 2095 return mctx
2096 2096 except KeyError:
2097 2097 raise IOError
2098 2098 else:
2099 2099 ui.note(_('copying changeset %s to %s\n') % (old, base))
2100 2100
2101 2101 # Use version of files as in the old cset
2102 2102 def filectxfn(repo, ctx_, path):
2103 2103 try:
2104 2104 return old.filectx(path)
2105 2105 except KeyError:
2106 2106 raise IOError
2107 2107
2108 2108 user = opts.get('user') or old.user()
2109 2109 date = opts.get('date') or old.date()
2110 2110 editform = 'commit.amend'
2111 2111 editor = getcommiteditor(editform=editform, **opts)
2112 2112 if not message:
2113 2113 editor = getcommiteditor(edit=True, editform=editform)
2114 2114 message = old.description()
2115 2115
2116 2116 pureextra = extra.copy()
2117 2117 extra['amend_source'] = old.hex()
2118 2118
2119 2119 new = context.memctx(repo,
2120 2120 parents=[base.node(), old.p2().node()],
2121 2121 text=message,
2122 2122 files=files,
2123 2123 filectxfn=filectxfn,
2124 2124 user=user,
2125 2125 date=date,
2126 2126 extra=extra,
2127 2127 editor=editor)
2128 2128
2129 2129 newdesc = changelog.stripdesc(new.description())
2130 2130 if ((not node)
2131 2131 and newdesc == old.description()
2132 2132 and user == old.user()
2133 2133 and date == old.date()
2134 2134 and pureextra == old.extra()):
2135 2135 # nothing changed. continuing here would create a new node
2136 2136 # anyway because of the amend_source noise.
2137 2137 #
2138 2138 # This not what we expect from amend.
2139 2139 return old.node()
2140 2140
2141 2141 ph = repo.ui.config('phases', 'new-commit', phases.draft)
2142 2142 try:
2143 2143 if opts.get('secret'):
2144 2144 commitphase = 'secret'
2145 2145 else:
2146 2146 commitphase = old.phase()
2147 2147 repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend')
2148 2148 newid = repo.commitctx(new)
2149 2149 finally:
2150 2150 repo.ui.setconfig('phases', 'new-commit', ph, 'amend')
2151 2151 if newid != old.node():
2152 2152 # Reroute the working copy parent to the new changeset
2153 2153 repo.setparents(newid, nullid)
2154 2154
2155 2155 # Move bookmarks from old parent to amend commit
2156 2156 bms = repo.nodebookmarks(old.node())
2157 2157 if bms:
2158 2158 marks = repo._bookmarks
2159 2159 for bm in bms:
2160 2160 marks[bm] = newid
2161 2161 marks.write()
2162 2162 #commit the whole amend process
2163 2163 if obsolete._enabled and newid != old.node():
2164 2164 # mark the new changeset as successor of the rewritten one
2165 2165 new = repo[newid]
2166 2166 obs = [(old, (new,))]
2167 2167 if node:
2168 2168 obs.append((ctx, ()))
2169 2169
2170 2170 obsolete.createmarkers(repo, obs)
2171 2171 tr.close()
2172 2172 finally:
2173 2173 tr.release()
2174 2174 if (not obsolete._enabled) and newid != old.node():
2175 2175 # Strip the intermediate commit (if there was one) and the amended
2176 2176 # commit
2177 2177 if node:
2178 2178 ui.note(_('stripping intermediate changeset %s\n') % ctx)
2179 2179 ui.note(_('stripping amended changeset %s\n') % old)
2180 2180 repair.strip(ui, repo, old.node(), topic='amend-backup')
2181 2181 finally:
2182 2182 if newid is None:
2183 2183 repo.dirstate.invalidate()
2184 2184 lockmod.release(lock, wlock)
2185 2185 return newid
2186 2186
2187 2187 def commiteditor(repo, ctx, subs, editform=''):
2188 2188 if ctx.description():
2189 2189 return ctx.description()
2190 2190 return commitforceeditor(repo, ctx, subs, editform=editform)
2191 2191
2192 2192 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
2193 2193 editform=''):
2194 2194 if not extramsg:
2195 2195 extramsg = _("Leave message empty to abort commit.")
2196 2196
2197 2197 forms = [e for e in editform.split('.') if e]
2198 2198 forms.insert(0, 'changeset')
2199 2199 while forms:
2200 2200 tmpl = repo.ui.config('committemplate', '.'.join(forms))
2201 2201 if tmpl:
2202 2202 committext = buildcommittemplate(repo, ctx, subs, extramsg, tmpl)
2203 2203 break
2204 2204 forms.pop()
2205 2205 else:
2206 2206 committext = buildcommittext(repo, ctx, subs, extramsg)
2207 2207
2208 2208 # run editor in the repository root
2209 2209 olddir = os.getcwd()
2210 2210 os.chdir(repo.root)
2211 2211 text = repo.ui.edit(committext, ctx.user(), ctx.extra())
2212 2212 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
2213 2213 os.chdir(olddir)
2214 2214
2215 2215 if finishdesc:
2216 2216 text = finishdesc(text)
2217 2217 if not text.strip():
2218 2218 raise util.Abort(_("empty commit message"))
2219 2219
2220 2220 return text
2221 2221
2222 2222 def buildcommittemplate(repo, ctx, subs, extramsg, tmpl):
2223 2223 ui = repo.ui
2224 2224 tmpl, mapfile = gettemplate(ui, tmpl, None)
2225 2225
2226 2226 try:
2227 2227 t = changeset_templater(ui, repo, None, {}, tmpl, mapfile, False)
2228 2228 except SyntaxError, inst:
2229 2229 raise util.Abort(inst.args[0])
2230 2230
2231 for k, v in repo.ui.configitems('committemplate'):
2232 if k != 'changeset':
2233 t.t.cache[k] = v
2234
2231 2235 if not extramsg:
2232 2236 extramsg = '' # ensure that extramsg is string
2233 2237
2234 2238 ui.pushbuffer()
2235 2239 t.show(ctx, extramsg=extramsg)
2236 2240 return ui.popbuffer()
2237 2241
2238 2242 def buildcommittext(repo, ctx, subs, extramsg):
2239 2243 edittext = []
2240 2244 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
2241 2245 if ctx.description():
2242 2246 edittext.append(ctx.description())
2243 2247 edittext.append("")
2244 2248 edittext.append("") # Empty line between message and comments.
2245 2249 edittext.append(_("HG: Enter commit message."
2246 2250 " Lines beginning with 'HG:' are removed."))
2247 2251 edittext.append("HG: %s" % extramsg)
2248 2252 edittext.append("HG: --")
2249 2253 edittext.append(_("HG: user: %s") % ctx.user())
2250 2254 if ctx.p2():
2251 2255 edittext.append(_("HG: branch merge"))
2252 2256 if ctx.branch():
2253 2257 edittext.append(_("HG: branch '%s'") % ctx.branch())
2254 2258 if bookmarks.iscurrent(repo):
2255 2259 edittext.append(_("HG: bookmark '%s'") % repo._bookmarkcurrent)
2256 2260 edittext.extend([_("HG: subrepo %s") % s for s in subs])
2257 2261 edittext.extend([_("HG: added %s") % f for f in added])
2258 2262 edittext.extend([_("HG: changed %s") % f for f in modified])
2259 2263 edittext.extend([_("HG: removed %s") % f for f in removed])
2260 2264 if not added and not modified and not removed:
2261 2265 edittext.append(_("HG: no files changed"))
2262 2266 edittext.append("")
2263 2267
2264 2268 return "\n".join(edittext)
2265 2269
2266 2270 def commitstatus(repo, node, branch, bheads=None, opts={}):
2267 2271 ctx = repo[node]
2268 2272 parents = ctx.parents()
2269 2273
2270 2274 if (not opts.get('amend') and bheads and node not in bheads and not
2271 2275 [x for x in parents if x.node() in bheads and x.branch() == branch]):
2272 2276 repo.ui.status(_('created new head\n'))
2273 2277 # The message is not printed for initial roots. For the other
2274 2278 # changesets, it is printed in the following situations:
2275 2279 #
2276 2280 # Par column: for the 2 parents with ...
2277 2281 # N: null or no parent
2278 2282 # B: parent is on another named branch
2279 2283 # C: parent is a regular non head changeset
2280 2284 # H: parent was a branch head of the current branch
2281 2285 # Msg column: whether we print "created new head" message
2282 2286 # In the following, it is assumed that there already exists some
2283 2287 # initial branch heads of the current branch, otherwise nothing is
2284 2288 # printed anyway.
2285 2289 #
2286 2290 # Par Msg Comment
2287 2291 # N N y additional topo root
2288 2292 #
2289 2293 # B N y additional branch root
2290 2294 # C N y additional topo head
2291 2295 # H N n usual case
2292 2296 #
2293 2297 # B B y weird additional branch root
2294 2298 # C B y branch merge
2295 2299 # H B n merge with named branch
2296 2300 #
2297 2301 # C C y additional head from merge
2298 2302 # C H n merge with a head
2299 2303 #
2300 2304 # H H n head merge: head count decreases
2301 2305
2302 2306 if not opts.get('close_branch'):
2303 2307 for r in parents:
2304 2308 if r.closesbranch() and r.branch() == branch:
2305 2309 repo.ui.status(_('reopening closed branch head %d\n') % r)
2306 2310
2307 2311 if repo.ui.debugflag:
2308 2312 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
2309 2313 elif repo.ui.verbose:
2310 2314 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
2311 2315
2312 2316 def revert(ui, repo, ctx, parents, *pats, **opts):
2313 2317 parent, p2 = parents
2314 2318 node = ctx.node()
2315 2319
2316 2320 mf = ctx.manifest()
2317 2321 if node == p2:
2318 2322 parent = p2
2319 2323 if node == parent:
2320 2324 pmf = mf
2321 2325 else:
2322 2326 pmf = None
2323 2327
2324 2328 # need all matching names in dirstate and manifest of target rev,
2325 2329 # so have to walk both. do not print errors if files exist in one
2326 2330 # but not other.
2327 2331
2328 2332 # `names` is a mapping for all elements in working copy and target revision
2329 2333 # The mapping is in the form:
2330 2334 # <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
2331 2335 names = {}
2332 2336
2333 2337 wlock = repo.wlock()
2334 2338 try:
2335 2339 ## filling of the `names` mapping
2336 2340 # walk dirstate to fill `names`
2337 2341
2338 2342 m = scmutil.match(repo[None], pats, opts)
2339 2343 m.bad = lambda x, y: False
2340 2344 for abs in repo.walk(m):
2341 2345 names[abs] = m.rel(abs), m.exact(abs)
2342 2346
2343 2347 # walk target manifest to fill `names`
2344 2348
2345 2349 def badfn(path, msg):
2346 2350 if path in names:
2347 2351 return
2348 2352 if path in ctx.substate:
2349 2353 return
2350 2354 path_ = path + '/'
2351 2355 for f in names:
2352 2356 if f.startswith(path_):
2353 2357 return
2354 2358 ui.warn("%s: %s\n" % (m.rel(path), msg))
2355 2359
2356 2360 m = scmutil.match(ctx, pats, opts)
2357 2361 m.bad = badfn
2358 2362 for abs in ctx.walk(m):
2359 2363 if abs not in names:
2360 2364 names[abs] = m.rel(abs), m.exact(abs)
2361 2365
2362 2366 # get the list of subrepos that must be reverted
2363 2367 targetsubs = sorted(s for s in ctx.substate if m(s))
2364 2368
2365 2369 # Find status of all file in `names`. (Against working directory parent)
2366 2370 m = scmutil.matchfiles(repo, names)
2367 2371 changes = repo.status(node1=parent, match=m)[:4]
2368 2372 modified, added, removed, deleted = map(set, changes)
2369 2373
2370 2374 # if f is a rename, update `names` to also revert the source
2371 2375 cwd = repo.getcwd()
2372 2376 for f in added:
2373 2377 src = repo.dirstate.copied(f)
2374 2378 if src and src not in names and repo.dirstate[src] == 'r':
2375 2379 removed.add(src)
2376 2380 names[src] = (repo.pathto(src, cwd), True)
2377 2381
2378 2382 ## computation of the action to performs on `names` content.
2379 2383
2380 2384 def removeforget(abs):
2381 2385 if repo.dirstate[abs] == 'a':
2382 2386 return _('forgetting %s\n')
2383 2387 return _('removing %s\n')
2384 2388
2385 2389 # action to be actually performed by revert
2386 2390 # (<list of file>, message>) tuple
2387 2391 actions = {'revert': ([], _('reverting %s\n')),
2388 2392 'add': ([], _('adding %s\n')),
2389 2393 'remove': ([], removeforget),
2390 2394 'undelete': ([], _('undeleting %s\n'))}
2391 2395
2392 2396 disptable = (
2393 2397 # dispatch table:
2394 2398 # file state
2395 2399 # action if in target manifest
2396 2400 # action if not in target manifest
2397 2401 # make backup if in target manifest
2398 2402 # make backup if not in target manifest
2399 2403 (modified, (actions['revert'], True),
2400 2404 (actions['remove'], True)),
2401 2405 (added, (actions['revert'], True),
2402 2406 (actions['remove'], False)),
2403 2407 (removed, (actions['undelete'], True),
2404 2408 (None, False)),
2405 2409 (deleted, (actions['revert'], False),
2406 2410 (actions['remove'], False)),
2407 2411 )
2408 2412
2409 2413 for abs, (rel, exact) in sorted(names.items()):
2410 2414 # hash on file in target manifest (or None if missing from target)
2411 2415 mfentry = mf.get(abs)
2412 2416 # target file to be touch on disk (relative to cwd)
2413 2417 target = repo.wjoin(abs)
2414 2418 def handle(xlist, dobackup):
2415 2419 xlist[0].append(abs)
2416 2420 if (dobackup and not opts.get('no_backup') and
2417 2421 os.path.lexists(target) and
2418 2422 abs in ctx and repo[None][abs].cmp(ctx[abs])):
2419 2423 bakname = "%s.orig" % rel
2420 2424 ui.note(_('saving current version of %s as %s\n') %
2421 2425 (rel, bakname))
2422 2426 if not opts.get('dry_run'):
2423 2427 util.rename(target, bakname)
2424 2428 if ui.verbose or not exact:
2425 2429 msg = xlist[1]
2426 2430 if not isinstance(msg, basestring):
2427 2431 msg = msg(abs)
2428 2432 ui.status(msg % rel)
2429 2433 # search the entry in the dispatch table.
2430 2434 # if the file is in any of this sets, it was touched in the working
2431 2435 # directory parent and we are sure it needs to be reverted.
2432 2436 for table, hit, miss in disptable:
2433 2437 if abs not in table:
2434 2438 continue
2435 2439 # file has changed in dirstate
2436 2440 if mfentry:
2437 2441 handle(*hit)
2438 2442 elif miss[0] is not None:
2439 2443 handle(*miss)
2440 2444 break
2441 2445 else:
2442 2446 # Not touched in current dirstate.
2443 2447
2444 2448 # file is unknown in parent, restore older version or ignore.
2445 2449 if abs not in repo.dirstate:
2446 2450 if mfentry:
2447 2451 handle(actions['add'], True)
2448 2452 elif exact:
2449 2453 ui.warn(_('file not managed: %s\n') % rel)
2450 2454 continue
2451 2455
2452 2456 # parent is target, no changes mean no changes
2453 2457 if node == parent:
2454 2458 if exact:
2455 2459 ui.warn(_('no changes needed to %s\n') % rel)
2456 2460 continue
2457 2461 # no change in dirstate but parent and target may differ
2458 2462 if pmf is None:
2459 2463 # only need parent manifest in this unlikely case,
2460 2464 # so do not read by default
2461 2465 pmf = repo[parent].manifest()
2462 2466 if abs in pmf and mfentry:
2463 2467 # if version of file is same in parent and target
2464 2468 # manifests, do nothing
2465 2469 if (pmf[abs] != mfentry or
2466 2470 pmf.flags(abs) != mf.flags(abs)):
2467 2471 handle(actions['revert'], False)
2468 2472 else:
2469 2473 handle(actions['remove'], False)
2470 2474
2471 2475 if not opts.get('dry_run'):
2472 2476 _performrevert(repo, parents, ctx, actions)
2473 2477
2474 2478 if targetsubs:
2475 2479 # Revert the subrepos on the revert list
2476 2480 for sub in targetsubs:
2477 2481 ctx.sub(sub).revert(ui, ctx.substate[sub], *pats, **opts)
2478 2482 finally:
2479 2483 wlock.release()
2480 2484
2481 2485 def _performrevert(repo, parents, ctx, actions):
2482 2486 """function that actually perform all the actions computed for revert
2483 2487
2484 2488 This is an independent function to let extension to plug in and react to
2485 2489 the imminent revert.
2486 2490
2487 2491 Make sure you have the working directory locked when calling this function.
2488 2492 """
2489 2493 parent, p2 = parents
2490 2494 node = ctx.node()
2491 2495 def checkout(f):
2492 2496 fc = ctx[f]
2493 2497 repo.wwrite(f, fc.data(), fc.flags())
2494 2498
2495 2499 audit_path = pathutil.pathauditor(repo.root)
2496 2500 for f in actions['remove'][0]:
2497 2501 if repo.dirstate[f] == 'a':
2498 2502 repo.dirstate.drop(f)
2499 2503 continue
2500 2504 audit_path(f)
2501 2505 try:
2502 2506 util.unlinkpath(repo.wjoin(f))
2503 2507 except OSError:
2504 2508 pass
2505 2509 repo.dirstate.remove(f)
2506 2510
2507 2511 normal = None
2508 2512 if node == parent:
2509 2513 # We're reverting to our parent. If possible, we'd like status
2510 2514 # to report the file as clean. We have to use normallookup for
2511 2515 # merges to avoid losing information about merged/dirty files.
2512 2516 if p2 != nullid:
2513 2517 normal = repo.dirstate.normallookup
2514 2518 else:
2515 2519 normal = repo.dirstate.normal
2516 2520 for f in actions['revert'][0]:
2517 2521 checkout(f)
2518 2522 if normal:
2519 2523 normal(f)
2520 2524
2521 2525 for f in actions['add'][0]:
2522 2526 checkout(f)
2523 2527 repo.dirstate.add(f)
2524 2528
2525 2529 normal = repo.dirstate.normallookup
2526 2530 if node == parent and p2 == nullid:
2527 2531 normal = repo.dirstate.normal
2528 2532 for f in actions['undelete'][0]:
2529 2533 checkout(f)
2530 2534 normal(f)
2531 2535
2532 2536 copied = copies.pathcopies(repo[parent], ctx)
2533 2537
2534 2538 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
2535 2539 if f in copied:
2536 2540 repo.dirstate.copy(copied[f], f)
2537 2541
2538 2542 def command(table):
2539 2543 """Returns a function object to be used as a decorator for making commands.
2540 2544
2541 2545 This function receives a command table as its argument. The table should
2542 2546 be a dict.
2543 2547
2544 2548 The returned function can be used as a decorator for adding commands
2545 2549 to that command table. This function accepts multiple arguments to define
2546 2550 a command.
2547 2551
2548 2552 The first argument is the command name.
2549 2553
2550 2554 The options argument is an iterable of tuples defining command arguments.
2551 2555 See ``mercurial.fancyopts.fancyopts()`` for the format of each tuple.
2552 2556
2553 2557 The synopsis argument defines a short, one line summary of how to use the
2554 2558 command. This shows up in the help output.
2555 2559
2556 2560 The norepo argument defines whether the command does not require a
2557 2561 local repository. Most commands operate against a repository, thus the
2558 2562 default is False.
2559 2563
2560 2564 The optionalrepo argument defines whether the command optionally requires
2561 2565 a local repository.
2562 2566
2563 2567 The inferrepo argument defines whether to try to find a repository from the
2564 2568 command line arguments. If True, arguments will be examined for potential
2565 2569 repository locations. See ``findrepo()``. If a repository is found, it
2566 2570 will be used.
2567 2571 """
2568 2572 def cmd(name, options=(), synopsis=None, norepo=False, optionalrepo=False,
2569 2573 inferrepo=False):
2570 2574 def decorator(func):
2571 2575 if synopsis:
2572 2576 table[name] = func, list(options), synopsis
2573 2577 else:
2574 2578 table[name] = func, list(options)
2575 2579
2576 2580 if norepo:
2577 2581 # Avoid import cycle.
2578 2582 import commands
2579 2583 commands.norepo += ' %s' % ' '.join(parsealiases(name))
2580 2584
2581 2585 if optionalrepo:
2582 2586 import commands
2583 2587 commands.optionalrepo += ' %s' % ' '.join(parsealiases(name))
2584 2588
2585 2589 if inferrepo:
2586 2590 import commands
2587 2591 commands.inferrepo += ' %s' % ' '.join(parsealiases(name))
2588 2592
2589 2593 return func
2590 2594 return decorator
2591 2595
2592 2596 return cmd
2593 2597
2594 2598 # a list of (ui, repo, otherpeer, opts, missing) functions called by
2595 2599 # commands.outgoing. "missing" is "missing" of the result of
2596 2600 # "findcommonoutgoing()"
2597 2601 outgoinghooks = util.hooks()
2598 2602
2599 2603 # a list of (ui, repo) functions called by commands.summary
2600 2604 summaryhooks = util.hooks()
2601 2605
2602 2606 # a list of (ui, repo, opts, changes) functions called by commands.summary.
2603 2607 #
2604 2608 # functions should return tuple of booleans below, if 'changes' is None:
2605 2609 # (whether-incomings-are-needed, whether-outgoings-are-needed)
2606 2610 #
2607 2611 # otherwise, 'changes' is a tuple of tuples below:
2608 2612 # - (sourceurl, sourcebranch, sourcepeer, incoming)
2609 2613 # - (desturl, destbranch, destpeer, outgoing)
2610 2614 summaryremotehooks = util.hooks()
2611 2615
2612 2616 # A list of state files kept by multistep operations like graft.
2613 2617 # Since graft cannot be aborted, it is considered 'clearable' by update.
2614 2618 # note: bisect is intentionally excluded
2615 2619 # (state file, clearable, allowcommit, error, hint)
2616 2620 unfinishedstates = [
2617 2621 ('graftstate', True, False, _('graft in progress'),
2618 2622 _("use 'hg graft --continue' or 'hg update' to abort")),
2619 2623 ('updatestate', True, False, _('last update was interrupted'),
2620 2624 _("use 'hg update' to get a consistent checkout"))
2621 2625 ]
2622 2626
2623 2627 def checkunfinished(repo, commit=False):
2624 2628 '''Look for an unfinished multistep operation, like graft, and abort
2625 2629 if found. It's probably good to check this right before
2626 2630 bailifchanged().
2627 2631 '''
2628 2632 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2629 2633 if commit and allowcommit:
2630 2634 continue
2631 2635 if repo.vfs.exists(f):
2632 2636 raise util.Abort(msg, hint=hint)
2633 2637
2634 2638 def clearunfinished(repo):
2635 2639 '''Check for unfinished operations (as above), and clear the ones
2636 2640 that are clearable.
2637 2641 '''
2638 2642 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2639 2643 if not clearable and repo.vfs.exists(f):
2640 2644 raise util.Abort(msg, hint=hint)
2641 2645 for f, clearable, allowcommit, msg, hint in unfinishedstates:
2642 2646 if clearable and repo.vfs.exists(f):
2643 2647 util.unlink(repo.join(f))
@@ -1,1668 +1,1679 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 | (All) ``<repo>/.hg/hgrc``
32 32
33 33 Per-repository configuration options that only apply in a
34 34 particular repository. This file is not version-controlled, and
35 35 will not get transferred during a "clone" operation. Options in
36 36 this file override options in all other configuration files. On
37 37 Plan 9 and Unix, most of this file will be ignored if it doesn't
38 38 belong to a trusted user or to a trusted group. See the documentation
39 39 for the ``[trusted]`` section below for more details.
40 40
41 41 | (Plan 9) ``$home/lib/hgrc``
42 42 | (Unix) ``$HOME/.hgrc``
43 43 | (Windows) ``%USERPROFILE%\.hgrc``
44 44 | (Windows) ``%USERPROFILE%\Mercurial.ini``
45 45 | (Windows) ``%HOME%\.hgrc``
46 46 | (Windows) ``%HOME%\Mercurial.ini``
47 47
48 48 Per-user configuration file(s), for the user running Mercurial. On
49 49 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
50 50 files apply to all Mercurial commands executed by this user in any
51 51 directory. Options in these files override per-system and per-installation
52 52 options.
53 53
54 54 | (Plan 9) ``/lib/mercurial/hgrc``
55 55 | (Plan 9) ``/lib/mercurial/hgrc.d/*.rc``
56 56 | (Unix) ``/etc/mercurial/hgrc``
57 57 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
58 58
59 59 Per-system configuration files, for the system on which Mercurial
60 60 is running. Options in these files apply to all Mercurial commands
61 61 executed by any user in any directory. Options in these files
62 62 override per-installation options.
63 63
64 64 | (Plan 9) ``<install-root>/lib/mercurial/hgrc``
65 65 | (Plan 9) ``<install-root>/lib/mercurial/hgrc.d/*.rc``
66 66 | (Unix) ``<install-root>/etc/mercurial/hgrc``
67 67 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
68 68
69 69 Per-installation configuration files, searched for in the
70 70 directory where Mercurial is installed. ``<install-root>`` is the
71 71 parent directory of the **hg** executable (or symlink) being run. For
72 72 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
73 73 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
74 74 to all Mercurial commands executed by any user in any directory.
75 75
76 76 | (Windows) ``<install-dir>\Mercurial.ini`` **or**
77 77 | (Windows) ``<install-dir>\hgrc.d\*.rc`` **or**
78 78 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
79 79
80 80 Per-installation/system configuration files, for the system on
81 81 which Mercurial is running. Options in these files apply to all
82 82 Mercurial commands executed by any user in any directory. Registry
83 83 keys contain PATH-like strings, every part of which must reference
84 84 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
85 85 be read. Mercurial checks each of these locations in the specified
86 86 order until one or more configuration files are detected.
87 87
88 88 .. note::
89 89
90 90 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
91 91 is used when running 32-bit Python on 64-bit Windows.
92 92
93 93 Syntax
94 94 ======
95 95
96 96 A configuration file consists of sections, led by a ``[section]`` header
97 97 and followed by ``name = value`` entries (sometimes called
98 98 ``configuration keys``)::
99 99
100 100 [spam]
101 101 eggs=ham
102 102 green=
103 103 eggs
104 104
105 105 Each line contains one entry. If the lines that follow are indented,
106 106 they are treated as continuations of that entry. Leading whitespace is
107 107 removed from values. Empty lines are skipped. Lines beginning with
108 108 ``#`` or ``;`` are ignored and may be used to provide comments.
109 109
110 110 Configuration keys can be set multiple times, in which case Mercurial
111 111 will use the value that was configured last. As an example::
112 112
113 113 [spam]
114 114 eggs=large
115 115 ham=serrano
116 116 eggs=small
117 117
118 118 This would set the configuration key named ``eggs`` to ``small``.
119 119
120 120 It is also possible to define a section multiple times. A section can
121 121 be redefined on the same and/or on different configuration files. For
122 122 example::
123 123
124 124 [foo]
125 125 eggs=large
126 126 ham=serrano
127 127 eggs=small
128 128
129 129 [bar]
130 130 eggs=ham
131 131 green=
132 132 eggs
133 133
134 134 [foo]
135 135 ham=prosciutto
136 136 eggs=medium
137 137 bread=toasted
138 138
139 139 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
140 140 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
141 141 respectively. As you can see there only thing that matters is the last
142 142 value that was set for each of the configuration keys.
143 143
144 144 If a configuration key is set multiple times in different
145 145 configuration files the final value will depend on the order in which
146 146 the different configuration files are read, with settings from earlier
147 147 paths overriding later ones as described on the ``Files`` section
148 148 above.
149 149
150 150 A line of the form ``%include file`` will include ``file`` into the
151 151 current configuration file. The inclusion is recursive, which means
152 152 that included files can include other files. Filenames are relative to
153 153 the configuration file in which the ``%include`` directive is found.
154 154 Environment variables and ``~user`` constructs are expanded in
155 155 ``file``. This lets you do something like::
156 156
157 157 %include ~/.hgrc.d/$HOST.rc
158 158
159 159 to include a different configuration file on each computer you use.
160 160
161 161 A line with ``%unset name`` will remove ``name`` from the current
162 162 section, if it has been set previously.
163 163
164 164 The values are either free-form text strings, lists of text strings,
165 165 or Boolean values. Boolean values can be set to true using any of "1",
166 166 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
167 167 (all case insensitive).
168 168
169 169 List values are separated by whitespace or comma, except when values are
170 170 placed in double quotation marks::
171 171
172 172 allow_read = "John Doe, PhD", brian, betty
173 173
174 174 Quotation marks can be escaped by prefixing them with a backslash. Only
175 175 quotation marks at the beginning of a word is counted as a quotation
176 176 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
177 177
178 178 Sections
179 179 ========
180 180
181 181 This section describes the different sections that may appear in a
182 182 Mercurial configuration file, the purpose of each section, its possible
183 183 keys, and their possible values.
184 184
185 185 ``alias``
186 186 ---------
187 187
188 188 Defines command aliases.
189 189 Aliases allow you to define your own commands in terms of other
190 190 commands (or aliases), optionally including arguments. Positional
191 191 arguments in the form of ``$1``, ``$2``, etc in the alias definition
192 192 are expanded by Mercurial before execution. Positional arguments not
193 193 already used by ``$N`` in the definition are put at the end of the
194 194 command to be executed.
195 195
196 196 Alias definitions consist of lines of the form::
197 197
198 198 <alias> = <command> [<argument>]...
199 199
200 200 For example, this definition::
201 201
202 202 latest = log --limit 5
203 203
204 204 creates a new command ``latest`` that shows only the five most recent
205 205 changesets. You can define subsequent aliases using earlier ones::
206 206
207 207 stable5 = latest -b stable
208 208
209 209 .. note::
210 210
211 211 It is possible to create aliases with the same names as
212 212 existing commands, which will then override the original
213 213 definitions. This is almost always a bad idea!
214 214
215 215 An alias can start with an exclamation point (``!``) to make it a
216 216 shell alias. A shell alias is executed with the shell and will let you
217 217 run arbitrary commands. As an example, ::
218 218
219 219 echo = !echo $@
220 220
221 221 will let you do ``hg echo foo`` to have ``foo`` printed in your
222 222 terminal. A better example might be::
223 223
224 224 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
225 225
226 226 which will make ``hg purge`` delete all unknown files in the
227 227 repository in the same manner as the purge extension.
228 228
229 229 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
230 230 expand to the command arguments. Unmatched arguments are
231 231 removed. ``$0`` expands to the alias name and ``$@`` expands to all
232 232 arguments separated by a space. These expansions happen before the
233 233 command is passed to the shell.
234 234
235 235 Shell aliases are executed in an environment where ``$HG`` expands to
236 236 the path of the Mercurial that was used to execute the alias. This is
237 237 useful when you want to call further Mercurial commands in a shell
238 238 alias, as was done above for the purge alias. In addition,
239 239 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
240 240 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
241 241
242 242 .. note::
243 243
244 244 Some global configuration options such as ``-R`` are
245 245 processed before shell aliases and will thus not be passed to
246 246 aliases.
247 247
248 248
249 249 ``annotate``
250 250 ------------
251 251
252 252 Settings used when displaying file annotations. All values are
253 253 Booleans and default to False. See ``diff`` section for related
254 254 options for the diff command.
255 255
256 256 ``ignorews``
257 257 Ignore white space when comparing lines.
258 258
259 259 ``ignorewsamount``
260 260 Ignore changes in the amount of white space.
261 261
262 262 ``ignoreblanklines``
263 263 Ignore changes whose lines are all blank.
264 264
265 265
266 266 ``auth``
267 267 --------
268 268
269 269 Authentication credentials for HTTP authentication. This section
270 270 allows you to store usernames and passwords for use when logging
271 271 *into* HTTP servers. See the ``[web]`` configuration section if
272 272 you want to configure *who* can login to your HTTP server.
273 273
274 274 Each line has the following format::
275 275
276 276 <name>.<argument> = <value>
277 277
278 278 where ``<name>`` is used to group arguments into authentication
279 279 entries. Example::
280 280
281 281 foo.prefix = hg.intevation.org/mercurial
282 282 foo.username = foo
283 283 foo.password = bar
284 284 foo.schemes = http https
285 285
286 286 bar.prefix = secure.example.org
287 287 bar.key = path/to/file.key
288 288 bar.cert = path/to/file.cert
289 289 bar.schemes = https
290 290
291 291 Supported arguments:
292 292
293 293 ``prefix``
294 294 Either ``*`` or a URI prefix with or without the scheme part.
295 295 The authentication entry with the longest matching prefix is used
296 296 (where ``*`` matches everything and counts as a match of length
297 297 1). If the prefix doesn't include a scheme, the match is performed
298 298 against the URI with its scheme stripped as well, and the schemes
299 299 argument, q.v., is then subsequently consulted.
300 300
301 301 ``username``
302 302 Optional. Username to authenticate with. If not given, and the
303 303 remote site requires basic or digest authentication, the user will
304 304 be prompted for it. Environment variables are expanded in the
305 305 username letting you do ``foo.username = $USER``. If the URI
306 306 includes a username, only ``[auth]`` entries with a matching
307 307 username or without a username will be considered.
308 308
309 309 ``password``
310 310 Optional. Password to authenticate with. If not given, and the
311 311 remote site requires basic or digest authentication, the user
312 312 will be prompted for it.
313 313
314 314 ``key``
315 315 Optional. PEM encoded client certificate key file. Environment
316 316 variables are expanded in the filename.
317 317
318 318 ``cert``
319 319 Optional. PEM encoded client certificate chain file. Environment
320 320 variables are expanded in the filename.
321 321
322 322 ``schemes``
323 323 Optional. Space separated list of URI schemes to use this
324 324 authentication entry with. Only used if the prefix doesn't include
325 325 a scheme. Supported schemes are http and https. They will match
326 326 static-http and static-https respectively, as well.
327 327 Default: https.
328 328
329 329 If no suitable authentication entry is found, the user is prompted
330 330 for credentials as usual if required by the remote.
331 331
332 332
333 333 ``committemplate``
334 334 ------------------
335 335
336 336 ``changeset`` configuration in this section is used as the template to
337 337 customize the text shown in the editor when committing.
338 338
339 339 In addition to pre-defined template keywords, commit log specific one
340 340 below can be used for customization:
341 341
342 342 ``extramsg``
343 343 String: Extra message (typically 'Leave message empty to abort
344 344 commit.'). This may be changed by some commands or extensions.
345 345
346 346 For example, the template configuration below shows as same text as
347 347 one shown by default::
348 348
349 349 [committemplate]
350 350 changeset = {desc}\n\n
351 351 HG: Enter commit message. Lines beginning with 'HG:' are removed.
352 352 HG: {extramsg}
353 353 HG: --
354 354 HG: user: {author}\n{ifeq(p2rev, "-1", "",
355 355 "HG: branch merge\n")
356 356 }HG: branch '{branch}'\n{if(currentbookmark,
357 357 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
358 358 "HG: subrepo {subrepo}\n" }{file_adds %
359 359 "HG: added {file}\n" }{file_mods %
360 360 "HG: changed {file}\n" }{file_dels %
361 361 "HG: removed {file}\n" }{if(files, "",
362 362 "HG: no files changed\n")}
363 363
364 364 .. note::
365 365
366 366 For some problematic encodings (see :hg:`help win32mbcs` for
367 367 detail), this customization should be configured carefully, to
368 368 avoid showing broken characters.
369 369
370 370 For example, if multibyte character ending with backslash (0x5c) is
371 371 followed by ASCII character 'n' in the customized template,
372 372 sequence of backslash and 'n' is treated as line-feed unexpectedly
373 373 (and multibyte character is broken, too).
374 374
375 375 Customized template is used for commands below (``--edit`` may be
376 376 required):
377 377
378 378 - :hg:`backout`
379 379 - :hg:`commit`
380 380 - :hg:`fetch` (for merge commit only)
381 381 - :hg:`graft`
382 382 - :hg:`histedit`
383 383 - :hg:`import`
384 384 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
385 385 - :hg:`rebase`
386 386 - :hg:`shelve`
387 387 - :hg:`sign`
388 388 - :hg:`tag`
389 389 - :hg:`transplant`
390 390
391 391 Configuring items below instead of ``changeset`` allows showing
392 392 customized message only for specific actions, or showing different
393 393 messages for each actions.
394 394
395 395 - ``changeset.backout`` for :hg:`backout`
396 396 - ``changeset.commit.amend`` for :hg:`commit --amend`
397 397 - ``changeset.commit.normal`` for :hg:`commit` without ``--amend``
398 398 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
399 399 - ``changeset.gpg.sign`` for :hg:`sign`
400 400 - ``changeset.graft`` for :hg:`graft`
401 401 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
402 402 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
403 403 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
404 404 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
405 405 - ``changeset.import.bypass`` for :hg:`import --bypass`
406 406 - ``changeset.import.normal`` for :hg:`import` without ``--bypass``
407 407 - ``changeset.mq.qnew`` for :hg:`qnew`
408 408 - ``changeset.mq.qfold`` for :hg:`qfold`
409 409 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
410 410 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
411 411 - ``changeset.rebase.normal`` for :hg:`rebase` without ``--collapse``
412 412 - ``changeset.shelve.shelve`` for :hg:`shelve`
413 413 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
414 414 - ``changeset.tag.remove`` for :hg:`tag --remove`
415 415 - ``changeset.transplant`` for :hg:`transplant`
416 416
417 417 These dot-separated lists of names are treated as hierarchical ones.
418 418 For example, ``changeset.tag.remove`` customizes the commit message
419 419 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
420 420 commit message for :hg:`tag` regardless of ``--remove`` option.
421 421
422 In this section, items other than ``changeset`` can be referred from
423 others. For example, the configuration to list committed files up
424 below can be referred as ``{listupfiles}``::
425
426 [committemplate]
427 listupfiles = {file_adds %
428 "HG: added {file}\n" }{file_mods %
429 "HG: changed {file}\n" }{file_dels %
430 "HG: removed {file}\n" }{if(files, "",
431 "HG: no files changed\n")}
432
422 433 ``decode/encode``
423 434 -----------------
424 435
425 436 Filters for transforming files on checkout/checkin. This would
426 437 typically be used for newline processing or other
427 438 localization/canonicalization of files.
428 439
429 440 Filters consist of a filter pattern followed by a filter command.
430 441 Filter patterns are globs by default, rooted at the repository root.
431 442 For example, to match any file ending in ``.txt`` in the root
432 443 directory only, use the pattern ``*.txt``. To match any file ending
433 444 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
434 445 For each file only the first matching filter applies.
435 446
436 447 The filter command can start with a specifier, either ``pipe:`` or
437 448 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
438 449
439 450 A ``pipe:`` command must accept data on stdin and return the transformed
440 451 data on stdout.
441 452
442 453 Pipe example::
443 454
444 455 [encode]
445 456 # uncompress gzip files on checkin to improve delta compression
446 457 # note: not necessarily a good idea, just an example
447 458 *.gz = pipe: gunzip
448 459
449 460 [decode]
450 461 # recompress gzip files when writing them to the working dir (we
451 462 # can safely omit "pipe:", because it's the default)
452 463 *.gz = gzip
453 464
454 465 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
455 466 with the name of a temporary file that contains the data to be
456 467 filtered by the command. The string ``OUTFILE`` is replaced with the name
457 468 of an empty temporary file, where the filtered data must be written by
458 469 the command.
459 470
460 471 .. note::
461 472
462 473 The tempfile mechanism is recommended for Windows systems,
463 474 where the standard shell I/O redirection operators often have
464 475 strange effects and may corrupt the contents of your files.
465 476
466 477 This filter mechanism is used internally by the ``eol`` extension to
467 478 translate line ending characters between Windows (CRLF) and Unix (LF)
468 479 format. We suggest you use the ``eol`` extension for convenience.
469 480
470 481
471 482 ``defaults``
472 483 ------------
473 484
474 485 (defaults are deprecated. Don't use them. Use aliases instead)
475 486
476 487 Use the ``[defaults]`` section to define command defaults, i.e. the
477 488 default options/arguments to pass to the specified commands.
478 489
479 490 The following example makes :hg:`log` run in verbose mode, and
480 491 :hg:`status` show only the modified files, by default::
481 492
482 493 [defaults]
483 494 log = -v
484 495 status = -m
485 496
486 497 The actual commands, instead of their aliases, must be used when
487 498 defining command defaults. The command defaults will also be applied
488 499 to the aliases of the commands defined.
489 500
490 501
491 502 ``diff``
492 503 --------
493 504
494 505 Settings used when displaying diffs. Everything except for ``unified``
495 506 is a Boolean and defaults to False. See ``annotate`` section for
496 507 related options for the annotate command.
497 508
498 509 ``git``
499 510 Use git extended diff format.
500 511
501 512 ``nodates``
502 513 Don't include dates in diff headers.
503 514
504 515 ``showfunc``
505 516 Show which function each change is in.
506 517
507 518 ``ignorews``
508 519 Ignore white space when comparing lines.
509 520
510 521 ``ignorewsamount``
511 522 Ignore changes in the amount of white space.
512 523
513 524 ``ignoreblanklines``
514 525 Ignore changes whose lines are all blank.
515 526
516 527 ``unified``
517 528 Number of lines of context to show.
518 529
519 530 ``email``
520 531 ---------
521 532
522 533 Settings for extensions that send email messages.
523 534
524 535 ``from``
525 536 Optional. Email address to use in "From" header and SMTP envelope
526 537 of outgoing messages.
527 538
528 539 ``to``
529 540 Optional. Comma-separated list of recipients' email addresses.
530 541
531 542 ``cc``
532 543 Optional. Comma-separated list of carbon copy recipients'
533 544 email addresses.
534 545
535 546 ``bcc``
536 547 Optional. Comma-separated list of blind carbon copy recipients'
537 548 email addresses.
538 549
539 550 ``method``
540 551 Optional. Method to use to send email messages. If value is ``smtp``
541 552 (default), use SMTP (see the ``[smtp]`` section for configuration).
542 553 Otherwise, use as name of program to run that acts like sendmail
543 554 (takes ``-f`` option for sender, list of recipients on command line,
544 555 message on stdin). Normally, setting this to ``sendmail`` or
545 556 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
546 557
547 558 ``charsets``
548 559 Optional. Comma-separated list of character sets considered
549 560 convenient for recipients. Addresses, headers, and parts not
550 561 containing patches of outgoing messages will be encoded in the
551 562 first character set to which conversion from local encoding
552 563 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
553 564 conversion fails, the text in question is sent as is. Defaults to
554 565 empty (explicit) list.
555 566
556 567 Order of outgoing email character sets:
557 568
558 569 1. ``us-ascii``: always first, regardless of settings
559 570 2. ``email.charsets``: in order given by user
560 571 3. ``ui.fallbackencoding``: if not in email.charsets
561 572 4. ``$HGENCODING``: if not in email.charsets
562 573 5. ``utf-8``: always last, regardless of settings
563 574
564 575 Email example::
565 576
566 577 [email]
567 578 from = Joseph User <joe.user@example.com>
568 579 method = /usr/sbin/sendmail
569 580 # charsets for western Europeans
570 581 # us-ascii, utf-8 omitted, as they are tried first and last
571 582 charsets = iso-8859-1, iso-8859-15, windows-1252
572 583
573 584
574 585 ``extensions``
575 586 --------------
576 587
577 588 Mercurial has an extension mechanism for adding new features. To
578 589 enable an extension, create an entry for it in this section.
579 590
580 591 If you know that the extension is already in Python's search path,
581 592 you can give the name of the module, followed by ``=``, with nothing
582 593 after the ``=``.
583 594
584 595 Otherwise, give a name that you choose, followed by ``=``, followed by
585 596 the path to the ``.py`` file (including the file name extension) that
586 597 defines the extension.
587 598
588 599 To explicitly disable an extension that is enabled in an hgrc of
589 600 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
590 601 or ``foo = !`` when path is not supplied.
591 602
592 603 Example for ``~/.hgrc``::
593 604
594 605 [extensions]
595 606 # (the progress extension will get loaded from Mercurial's path)
596 607 progress =
597 608 # (this extension will get loaded from the file specified)
598 609 myfeature = ~/.hgext/myfeature.py
599 610
600 611
601 612 ``format``
602 613 ----------
603 614
604 615 ``usestore``
605 616 Enable or disable the "store" repository format which improves
606 617 compatibility with systems that fold case or otherwise mangle
607 618 filenames. Enabled by default. Disabling this option will allow
608 619 you to store longer filenames in some situations at the expense of
609 620 compatibility and ensures that the on-disk format of newly created
610 621 repositories will be compatible with Mercurial before version 0.9.4.
611 622
612 623 ``usefncache``
613 624 Enable or disable the "fncache" repository format which enhances
614 625 the "store" repository format (which has to be enabled to use
615 626 fncache) to allow longer filenames and avoids using Windows
616 627 reserved names, e.g. "nul". Enabled by default. Disabling this
617 628 option ensures that the on-disk format of newly created
618 629 repositories will be compatible with Mercurial before version 1.1.
619 630
620 631 ``dotencode``
621 632 Enable or disable the "dotencode" repository format which enhances
622 633 the "fncache" repository format (which has to be enabled to use
623 634 dotencode) to avoid issues with filenames starting with ._ on
624 635 Mac OS X and spaces on Windows. Enabled by default. Disabling this
625 636 option ensures that the on-disk format of newly created
626 637 repositories will be compatible with Mercurial before version 1.7.
627 638
628 639 ``graph``
629 640 ---------
630 641
631 642 Web graph view configuration. This section let you change graph
632 643 elements display properties by branches, for instance to make the
633 644 ``default`` branch stand out.
634 645
635 646 Each line has the following format::
636 647
637 648 <branch>.<argument> = <value>
638 649
639 650 where ``<branch>`` is the name of the branch being
640 651 customized. Example::
641 652
642 653 [graph]
643 654 # 2px width
644 655 default.width = 2
645 656 # red color
646 657 default.color = FF0000
647 658
648 659 Supported arguments:
649 660
650 661 ``width``
651 662 Set branch edges width in pixels.
652 663
653 664 ``color``
654 665 Set branch edges color in hexadecimal RGB notation.
655 666
656 667 ``hooks``
657 668 ---------
658 669
659 670 Commands or Python functions that get automatically executed by
660 671 various actions such as starting or finishing a commit. Multiple
661 672 hooks can be run for the same action by appending a suffix to the
662 673 action. Overriding a site-wide hook can be done by changing its
663 674 value or setting it to an empty string. Hooks can be prioritized
664 675 by adding a prefix of ``priority`` to the hook name on a new line
665 676 and setting the priority. The default priority is 0 if
666 677 not specified.
667 678
668 679 Example ``.hg/hgrc``::
669 680
670 681 [hooks]
671 682 # update working directory after adding changesets
672 683 changegroup.update = hg update
673 684 # do not use the site-wide hook
674 685 incoming =
675 686 incoming.email = /my/email/hook
676 687 incoming.autobuild = /my/build/hook
677 688 # force autobuild hook to run before other incoming hooks
678 689 priority.incoming.autobuild = 1
679 690
680 691 Most hooks are run with environment variables set that give useful
681 692 additional information. For each hook below, the environment
682 693 variables it is passed are listed with names of the form ``$HG_foo``.
683 694
684 695 ``changegroup``
685 696 Run after a changegroup has been added via push, pull or unbundle.
686 697 ID of the first new changeset is in ``$HG_NODE``. URL from which
687 698 changes came is in ``$HG_URL``.
688 699
689 700 ``commit``
690 701 Run after a changeset has been created in the local repository. ID
691 702 of the newly created changeset is in ``$HG_NODE``. Parent changeset
692 703 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
693 704
694 705 ``incoming``
695 706 Run after a changeset has been pulled, pushed, or unbundled into
696 707 the local repository. The ID of the newly arrived changeset is in
697 708 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
698 709
699 710 ``outgoing``
700 711 Run after sending changes from local repository to another. ID of
701 712 first changeset sent is in ``$HG_NODE``. Source of operation is in
702 713 ``$HG_SOURCE``; see "preoutgoing" hook for description.
703 714
704 715 ``post-<command>``
705 716 Run after successful invocations of the associated command. The
706 717 contents of the command line are passed as ``$HG_ARGS`` and the result
707 718 code in ``$HG_RESULT``. Parsed command line arguments are passed as
708 719 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
709 720 the python data internally passed to <command>. ``$HG_OPTS`` is a
710 721 dictionary of options (with unspecified options set to their defaults).
711 722 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
712 723
713 724 ``pre-<command>``
714 725 Run before executing the associated command. The contents of the
715 726 command line are passed as ``$HG_ARGS``. Parsed command line arguments
716 727 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
717 728 representations of the data internally passed to <command>. ``$HG_OPTS``
718 729 is a dictionary of options (with unspecified options set to their
719 730 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
720 731 failure, the command doesn't execute and Mercurial returns the failure
721 732 code.
722 733
723 734 ``prechangegroup``
724 735 Run before a changegroup is added via push, pull or unbundle. Exit
725 736 status 0 allows the changegroup to proceed. Non-zero status will
726 737 cause the push, pull or unbundle to fail. URL from which changes
727 738 will come is in ``$HG_URL``.
728 739
729 740 ``precommit``
730 741 Run before starting a local commit. Exit status 0 allows the
731 742 commit to proceed. Non-zero status will cause the commit to fail.
732 743 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
733 744
734 745 ``prelistkeys``
735 746 Run before listing pushkeys (like bookmarks) in the
736 747 repository. Non-zero status will cause failure. The key namespace is
737 748 in ``$HG_NAMESPACE``.
738 749
739 750 ``preoutgoing``
740 751 Run before collecting changes to send from the local repository to
741 752 another. Non-zero status will cause failure. This lets you prevent
742 753 pull over HTTP or SSH. Also prevents against local pull, push
743 754 (outbound) or bundle commands, but not effective, since you can
744 755 just copy files instead then. Source of operation is in
745 756 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
746 757 SSH or HTTP repository. If "push", "pull" or "bundle", operation
747 758 is happening on behalf of repository on same system.
748 759
749 760 ``prepushkey``
750 761 Run before a pushkey (like a bookmark) is added to the
751 762 repository. Non-zero status will cause the key to be rejected. The
752 763 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
753 764 the old value (if any) is in ``$HG_OLD``, and the new value is in
754 765 ``$HG_NEW``.
755 766
756 767 ``pretag``
757 768 Run before creating a tag. Exit status 0 allows the tag to be
758 769 created. Non-zero status will cause the tag to fail. ID of
759 770 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
760 771 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
761 772
762 773 ``pretxnchangegroup``
763 774 Run after a changegroup has been added via push, pull or unbundle,
764 775 but before the transaction has been committed. Changegroup is
765 776 visible to hook program. This lets you validate incoming changes
766 777 before accepting them. Passed the ID of the first new changeset in
767 778 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
768 779 status will cause the transaction to be rolled back and the push,
769 780 pull or unbundle will fail. URL that was source of changes is in
770 781 ``$HG_URL``.
771 782
772 783 ``pretxncommit``
773 784 Run after a changeset has been created but the transaction not yet
774 785 committed. Changeset is visible to hook program. This lets you
775 786 validate commit message and changes. Exit status 0 allows the
776 787 commit to proceed. Non-zero status will cause the transaction to
777 788 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
778 789 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
779 790
780 791 ``preupdate``
781 792 Run before updating the working directory. Exit status 0 allows
782 793 the update to proceed. Non-zero status will prevent the update.
783 794 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
784 795 of second new parent is in ``$HG_PARENT2``.
785 796
786 797 ``listkeys``
787 798 Run after listing pushkeys (like bookmarks) in the repository. The
788 799 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
789 800 dictionary containing the keys and values.
790 801
791 802 ``pushkey``
792 803 Run after a pushkey (like a bookmark) is added to the
793 804 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
794 805 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
795 806 value is in ``$HG_NEW``.
796 807
797 808 ``tag``
798 809 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
799 810 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
800 811 repository if ``$HG_LOCAL=0``.
801 812
802 813 ``update``
803 814 Run after updating the working directory. Changeset ID of first
804 815 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
805 816 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
806 817 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
807 818
808 819 .. note::
809 820
810 821 It is generally better to use standard hooks rather than the
811 822 generic pre- and post- command hooks as they are guaranteed to be
812 823 called in the appropriate contexts for influencing transactions.
813 824 Also, hooks like "commit" will be called in all contexts that
814 825 generate a commit (e.g. tag) and not just the commit command.
815 826
816 827 .. note::
817 828
818 829 Environment variables with empty values may not be passed to
819 830 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
820 831 will have an empty value under Unix-like platforms for non-merge
821 832 changesets, while it will not be available at all under Windows.
822 833
823 834 The syntax for Python hooks is as follows::
824 835
825 836 hookname = python:modulename.submodule.callable
826 837 hookname = python:/path/to/python/module.py:callable
827 838
828 839 Python hooks are run within the Mercurial process. Each hook is
829 840 called with at least three keyword arguments: a ui object (keyword
830 841 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
831 842 keyword that tells what kind of hook is used. Arguments listed as
832 843 environment variables above are passed as keyword arguments, with no
833 844 ``HG_`` prefix, and names in lower case.
834 845
835 846 If a Python hook returns a "true" value or raises an exception, this
836 847 is treated as a failure.
837 848
838 849
839 850 ``hostfingerprints``
840 851 --------------------
841 852
842 853 Fingerprints of the certificates of known HTTPS servers.
843 854 A HTTPS connection to a server with a fingerprint configured here will
844 855 only succeed if the servers certificate matches the fingerprint.
845 856 This is very similar to how ssh known hosts works.
846 857 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
847 858 The CA chain and web.cacerts is not used for servers with a fingerprint.
848 859
849 860 For example::
850 861
851 862 [hostfingerprints]
852 863 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
853 864
854 865 This feature is only supported when using Python 2.6 or later.
855 866
856 867
857 868 ``http_proxy``
858 869 --------------
859 870
860 871 Used to access web-based Mercurial repositories through a HTTP
861 872 proxy.
862 873
863 874 ``host``
864 875 Host name and (optional) port of the proxy server, for example
865 876 "myproxy:8000".
866 877
867 878 ``no``
868 879 Optional. Comma-separated list of host names that should bypass
869 880 the proxy.
870 881
871 882 ``passwd``
872 883 Optional. Password to authenticate with at the proxy server.
873 884
874 885 ``user``
875 886 Optional. User name to authenticate with at the proxy server.
876 887
877 888 ``always``
878 889 Optional. Always use the proxy, even for localhost and any entries
879 890 in ``http_proxy.no``. True or False. Default: False.
880 891
881 892 ``merge-patterns``
882 893 ------------------
883 894
884 895 This section specifies merge tools to associate with particular file
885 896 patterns. Tools matched here will take precedence over the default
886 897 merge tool. Patterns are globs by default, rooted at the repository
887 898 root.
888 899
889 900 Example::
890 901
891 902 [merge-patterns]
892 903 **.c = kdiff3
893 904 **.jpg = myimgmerge
894 905
895 906 ``merge-tools``
896 907 ---------------
897 908
898 909 This section configures external merge tools to use for file-level
899 910 merges. This section has likely been preconfigured at install time.
900 911 Use :hg:`config merge-tools` to check the existing configuration.
901 912 Also see :hg:`help merge-tools` for more details.
902 913
903 914 Example ``~/.hgrc``::
904 915
905 916 [merge-tools]
906 917 # Override stock tool location
907 918 kdiff3.executable = ~/bin/kdiff3
908 919 # Specify command line
909 920 kdiff3.args = $base $local $other -o $output
910 921 # Give higher priority
911 922 kdiff3.priority = 1
912 923
913 924 # Changing the priority of preconfigured tool
914 925 vimdiff.priority = 0
915 926
916 927 # Define new tool
917 928 myHtmlTool.args = -m $local $other $base $output
918 929 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
919 930 myHtmlTool.priority = 1
920 931
921 932 Supported arguments:
922 933
923 934 ``priority``
924 935 The priority in which to evaluate this tool.
925 936 Default: 0.
926 937
927 938 ``executable``
928 939 Either just the name of the executable or its pathname. On Windows,
929 940 the path can use environment variables with ${ProgramFiles} syntax.
930 941 Default: the tool name.
931 942
932 943 ``args``
933 944 The arguments to pass to the tool executable. You can refer to the
934 945 files being merged as well as the output file through these
935 946 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
936 947 of ``$local`` and ``$other`` can vary depending on which action is being
937 948 performed. During and update or merge, ``$local`` represents the original
938 949 state of the file, while ``$other`` represents the commit you are updating
939 950 to or the commit you are merging with. During a rebase ``$local``
940 951 represents the destination of the rebase, and ``$other`` represents the
941 952 commit being rebased.
942 953 Default: ``$local $base $other``
943 954
944 955 ``premerge``
945 956 Attempt to run internal non-interactive 3-way merge tool before
946 957 launching external tool. Options are ``true``, ``false``, or ``keep``
947 958 to leave markers in the file if the premerge fails.
948 959 Default: True
949 960
950 961 ``binary``
951 962 This tool can merge binary files. Defaults to False, unless tool
952 963 was selected by file pattern match.
953 964
954 965 ``symlink``
955 966 This tool can merge symlinks. Defaults to False, even if tool was
956 967 selected by file pattern match.
957 968
958 969 ``check``
959 970 A list of merge success-checking options:
960 971
961 972 ``changed``
962 973 Ask whether merge was successful when the merged file shows no changes.
963 974 ``conflicts``
964 975 Check whether there are conflicts even though the tool reported success.
965 976 ``prompt``
966 977 Always prompt for merge success, regardless of success reported by tool.
967 978
968 979 ``fixeol``
969 980 Attempt to fix up EOL changes caused by the merge tool.
970 981 Default: False
971 982
972 983 ``gui``
973 984 This tool requires a graphical interface to run. Default: False
974 985
975 986 ``regkey``
976 987 Windows registry key which describes install location of this
977 988 tool. Mercurial will search for this key first under
978 989 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
979 990 Default: None
980 991
981 992 ``regkeyalt``
982 993 An alternate Windows registry key to try if the first key is not
983 994 found. The alternate key uses the same ``regname`` and ``regappend``
984 995 semantics of the primary key. The most common use for this key
985 996 is to search for 32bit applications on 64bit operating systems.
986 997 Default: None
987 998
988 999 ``regname``
989 1000 Name of value to read from specified registry key. Defaults to the
990 1001 unnamed (default) value.
991 1002
992 1003 ``regappend``
993 1004 String to append to the value read from the registry, typically
994 1005 the executable name of the tool.
995 1006 Default: None
996 1007
997 1008
998 1009 ``patch``
999 1010 ---------
1000 1011
1001 1012 Settings used when applying patches, for instance through the 'import'
1002 1013 command or with Mercurial Queues extension.
1003 1014
1004 1015 ``eol``
1005 1016 When set to 'strict' patch content and patched files end of lines
1006 1017 are preserved. When set to ``lf`` or ``crlf``, both files end of
1007 1018 lines are ignored when patching and the result line endings are
1008 1019 normalized to either LF (Unix) or CRLF (Windows). When set to
1009 1020 ``auto``, end of lines are again ignored while patching but line
1010 1021 endings in patched files are normalized to their original setting
1011 1022 on a per-file basis. If target file does not exist or has no end
1012 1023 of line, patch line endings are preserved.
1013 1024 Default: strict.
1014 1025
1015 1026
1016 1027 ``paths``
1017 1028 ---------
1018 1029
1019 1030 Assigns symbolic names to repositories. The left side is the
1020 1031 symbolic name, and the right gives the directory or URL that is the
1021 1032 location of the repository. Default paths can be declared by setting
1022 1033 the following entries.
1023 1034
1024 1035 ``default``
1025 1036 Directory or URL to use when pulling if no source is specified.
1026 1037 Default is set to repository from which the current repository was
1027 1038 cloned.
1028 1039
1029 1040 ``default-push``
1030 1041 Optional. Directory or URL to use when pushing if no destination
1031 1042 is specified.
1032 1043
1033 1044 Custom paths can be defined by assigning the path to a name that later can be
1034 1045 used from the command line. Example::
1035 1046
1036 1047 [paths]
1037 1048 my_path = http://example.com/path
1038 1049
1039 1050 To push to the path defined in ``my_path`` run the command::
1040 1051
1041 1052 hg push my_path
1042 1053
1043 1054
1044 1055 ``phases``
1045 1056 ----------
1046 1057
1047 1058 Specifies default handling of phases. See :hg:`help phases` for more
1048 1059 information about working with phases.
1049 1060
1050 1061 ``publish``
1051 1062 Controls draft phase behavior when working as a server. When true,
1052 1063 pushed changesets are set to public in both client and server and
1053 1064 pulled or cloned changesets are set to public in the client.
1054 1065 Default: True
1055 1066
1056 1067 ``new-commit``
1057 1068 Phase of newly-created commits.
1058 1069 Default: draft
1059 1070
1060 1071 ``checksubrepos``
1061 1072 Check the phase of the current revision of each subrepository. Allowed
1062 1073 values are "ignore", "follow" and "abort". For settings other than
1063 1074 "ignore", the phase of the current revision of each subrepository is
1064 1075 checked before committing the parent repository. If any of those phases is
1065 1076 greater than the phase of the parent repository (e.g. if a subrepo is in a
1066 1077 "secret" phase while the parent repo is in "draft" phase), the commit is
1067 1078 either aborted (if checksubrepos is set to "abort") or the higher phase is
1068 1079 used for the parent repository commit (if set to "follow").
1069 1080 Default: "follow"
1070 1081
1071 1082
1072 1083 ``profiling``
1073 1084 -------------
1074 1085
1075 1086 Specifies profiling type, format, and file output. Two profilers are
1076 1087 supported: an instrumenting profiler (named ``ls``), and a sampling
1077 1088 profiler (named ``stat``).
1078 1089
1079 1090 In this section description, 'profiling data' stands for the raw data
1080 1091 collected during profiling, while 'profiling report' stands for a
1081 1092 statistical text report generated from the profiling data. The
1082 1093 profiling is done using lsprof.
1083 1094
1084 1095 ``type``
1085 1096 The type of profiler to use.
1086 1097 Default: ls.
1087 1098
1088 1099 ``ls``
1089 1100 Use Python's built-in instrumenting profiler. This profiler
1090 1101 works on all platforms, but each line number it reports is the
1091 1102 first line of a function. This restriction makes it difficult to
1092 1103 identify the expensive parts of a non-trivial function.
1093 1104 ``stat``
1094 1105 Use a third-party statistical profiler, statprof. This profiler
1095 1106 currently runs only on Unix systems, and is most useful for
1096 1107 profiling commands that run for longer than about 0.1 seconds.
1097 1108
1098 1109 ``format``
1099 1110 Profiling format. Specific to the ``ls`` instrumenting profiler.
1100 1111 Default: text.
1101 1112
1102 1113 ``text``
1103 1114 Generate a profiling report. When saving to a file, it should be
1104 1115 noted that only the report is saved, and the profiling data is
1105 1116 not kept.
1106 1117 ``kcachegrind``
1107 1118 Format profiling data for kcachegrind use: when saving to a
1108 1119 file, the generated file can directly be loaded into
1109 1120 kcachegrind.
1110 1121
1111 1122 ``frequency``
1112 1123 Sampling frequency. Specific to the ``stat`` sampling profiler.
1113 1124 Default: 1000.
1114 1125
1115 1126 ``output``
1116 1127 File path where profiling data or report should be saved. If the
1117 1128 file exists, it is replaced. Default: None, data is printed on
1118 1129 stderr
1119 1130
1120 1131 ``sort``
1121 1132 Sort field. Specific to the ``ls`` instrumenting profiler.
1122 1133 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1123 1134 ``inlinetime``.
1124 1135 Default: inlinetime.
1125 1136
1126 1137 ``limit``
1127 1138 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1128 1139 Default: 30.
1129 1140
1130 1141 ``nested``
1131 1142 Show at most this number of lines of drill-down info after each main entry.
1132 1143 This can help explain the difference between Total and Inline.
1133 1144 Specific to the ``ls`` instrumenting profiler.
1134 1145 Default: 5.
1135 1146
1136 1147 ``revsetalias``
1137 1148 ---------------
1138 1149
1139 1150 Alias definitions for revsets. See :hg:`help revsets` for details.
1140 1151
1141 1152 ``server``
1142 1153 ----------
1143 1154
1144 1155 Controls generic server settings.
1145 1156
1146 1157 ``uncompressed``
1147 1158 Whether to allow clients to clone a repository using the
1148 1159 uncompressed streaming protocol. This transfers about 40% more
1149 1160 data than a regular clone, but uses less memory and CPU on both
1150 1161 server and client. Over a LAN (100 Mbps or better) or a very fast
1151 1162 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1152 1163 regular clone. Over most WAN connections (anything slower than
1153 1164 about 6 Mbps), uncompressed streaming is slower, because of the
1154 1165 extra data transfer overhead. This mode will also temporarily hold
1155 1166 the write lock while determining what data to transfer.
1156 1167 Default is True.
1157 1168
1158 1169 ``preferuncompressed``
1159 1170 When set, clients will try to use the uncompressed streaming
1160 1171 protocol. Default is False.
1161 1172
1162 1173 ``validate``
1163 1174 Whether to validate the completeness of pushed changesets by
1164 1175 checking that all new file revisions specified in manifests are
1165 1176 present. Default is False.
1166 1177
1167 1178 ``smtp``
1168 1179 --------
1169 1180
1170 1181 Configuration for extensions that need to send email messages.
1171 1182
1172 1183 ``host``
1173 1184 Host name of mail server, e.g. "mail.example.com".
1174 1185
1175 1186 ``port``
1176 1187 Optional. Port to connect to on mail server. Default: 465 (if
1177 1188 ``tls`` is smtps) or 25 (otherwise).
1178 1189
1179 1190 ``tls``
1180 1191 Optional. Method to enable TLS when connecting to mail server: starttls,
1181 1192 smtps or none. Default: none.
1182 1193
1183 1194 ``verifycert``
1184 1195 Optional. Verification for the certificate of mail server, when
1185 1196 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1186 1197 "strict" or "loose", the certificate is verified as same as the
1187 1198 verification for HTTPS connections (see ``[hostfingerprints]`` and
1188 1199 ``[web] cacerts`` also). For "strict", sending email is also
1189 1200 aborted, if there is no configuration for mail server in
1190 1201 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1191 1202 :hg:`email` overwrites this as "loose". Default: "strict".
1192 1203
1193 1204 ``username``
1194 1205 Optional. User name for authenticating with the SMTP server.
1195 1206 Default: none.
1196 1207
1197 1208 ``password``
1198 1209 Optional. Password for authenticating with the SMTP server. If not
1199 1210 specified, interactive sessions will prompt the user for a
1200 1211 password; non-interactive sessions will fail. Default: none.
1201 1212
1202 1213 ``local_hostname``
1203 1214 Optional. It's the hostname that the sender can use to identify
1204 1215 itself to the MTA.
1205 1216
1206 1217
1207 1218 ``subpaths``
1208 1219 ------------
1209 1220
1210 1221 Subrepository source URLs can go stale if a remote server changes name
1211 1222 or becomes temporarily unavailable. This section lets you define
1212 1223 rewrite rules of the form::
1213 1224
1214 1225 <pattern> = <replacement>
1215 1226
1216 1227 where ``pattern`` is a regular expression matching a subrepository
1217 1228 source URL and ``replacement`` is the replacement string used to
1218 1229 rewrite it. Groups can be matched in ``pattern`` and referenced in
1219 1230 ``replacements``. For instance::
1220 1231
1221 1232 http://server/(.*)-hg/ = http://hg.server/\1/
1222 1233
1223 1234 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1224 1235
1225 1236 Relative subrepository paths are first made absolute, and the
1226 1237 rewrite rules are then applied on the full (absolute) path. The rules
1227 1238 are applied in definition order.
1228 1239
1229 1240 ``trusted``
1230 1241 -----------
1231 1242
1232 1243 Mercurial will not use the settings in the
1233 1244 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1234 1245 user or to a trusted group, as various hgrc features allow arbitrary
1235 1246 commands to be run. This issue is often encountered when configuring
1236 1247 hooks or extensions for shared repositories or servers. However,
1237 1248 the web interface will use some safe settings from the ``[web]``
1238 1249 section.
1239 1250
1240 1251 This section specifies what users and groups are trusted. The
1241 1252 current user is always trusted. To trust everybody, list a user or a
1242 1253 group with name ``*``. These settings must be placed in an
1243 1254 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1244 1255 user or service running Mercurial.
1245 1256
1246 1257 ``users``
1247 1258 Comma-separated list of trusted users.
1248 1259
1249 1260 ``groups``
1250 1261 Comma-separated list of trusted groups.
1251 1262
1252 1263
1253 1264 ``ui``
1254 1265 ------
1255 1266
1256 1267 User interface controls.
1257 1268
1258 1269 ``archivemeta``
1259 1270 Whether to include the .hg_archival.txt file containing meta data
1260 1271 (hashes for the repository base and for tip) in archives created
1261 1272 by the :hg:`archive` command or downloaded via hgweb.
1262 1273 Default is True.
1263 1274
1264 1275 ``askusername``
1265 1276 Whether to prompt for a username when committing. If True, and
1266 1277 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1267 1278 be prompted to enter a username. If no username is entered, the
1268 1279 default ``USER@HOST`` is used instead.
1269 1280 Default is False.
1270 1281
1271 1282 ``commitsubrepos``
1272 1283 Whether to commit modified subrepositories when committing the
1273 1284 parent repository. If False and one subrepository has uncommitted
1274 1285 changes, abort the commit.
1275 1286 Default is False.
1276 1287
1277 1288 ``debug``
1278 1289 Print debugging information. True or False. Default is False.
1279 1290
1280 1291 ``editor``
1281 1292 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1282 1293
1283 1294 ``fallbackencoding``
1284 1295 Encoding to try if it's not possible to decode the changelog using
1285 1296 UTF-8. Default is ISO-8859-1.
1286 1297
1287 1298 ``ignore``
1288 1299 A file to read per-user ignore patterns from. This file should be
1289 1300 in the same format as a repository-wide .hgignore file. This
1290 1301 option supports hook syntax, so if you want to specify multiple
1291 1302 ignore files, you can do so by setting something like
1292 1303 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1293 1304 format, see the ``hgignore(5)`` man page.
1294 1305
1295 1306 ``interactive``
1296 1307 Allow to prompt the user. True or False. Default is True.
1297 1308
1298 1309 ``logtemplate``
1299 1310 Template string for commands that print changesets.
1300 1311
1301 1312 ``merge``
1302 1313 The conflict resolution program to use during a manual merge.
1303 1314 For more information on merge tools see :hg:`help merge-tools`.
1304 1315 For configuring merge tools see the ``[merge-tools]`` section.
1305 1316
1306 1317 ``mergemarkers``
1307 1318 Sets the merge conflict marker label styling. The ``detailed``
1308 1319 style uses the ``mergemarkertemplate`` setting to style the labels.
1309 1320 The ``basic`` style just uses 'local' and 'other' as the marker label.
1310 1321 One of ``basic`` or ``detailed``.
1311 1322 Default is ``basic``.
1312 1323
1313 1324 ``mergemarkertemplate``
1314 1325 The template used to print the commit description next to each conflict
1315 1326 marker during merge conflicts. See :hg:`help templates` for the template
1316 1327 format.
1317 1328 Defaults to showing the hash, tags, branches, bookmarks, author, and
1318 1329 the first line of the commit description.
1319 1330 You have to pay attention to encodings of managed files, if you
1320 1331 use non-ASCII characters in tags, branches, bookmarks, author
1321 1332 and/or commit descriptions. At template expansion, non-ASCII
1322 1333 characters use the encoding specified by ``--encoding`` global
1323 1334 option, ``HGENCODING`` or other locale setting environment
1324 1335 variables. The difference of encoding between merged file and
1325 1336 conflict markers causes serious problem.
1326 1337
1327 1338 ``portablefilenames``
1328 1339 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1329 1340 Default is ``warn``.
1330 1341 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1331 1342 platforms, if a file with a non-portable filename is added (e.g. a file
1332 1343 with a name that can't be created on Windows because it contains reserved
1333 1344 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1334 1345 collision with an existing file).
1335 1346 If set to ``ignore`` (or ``false``), no warning is printed.
1336 1347 If set to ``abort``, the command is aborted.
1337 1348 On Windows, this configuration option is ignored and the command aborted.
1338 1349
1339 1350 ``quiet``
1340 1351 Reduce the amount of output printed. True or False. Default is False.
1341 1352
1342 1353 ``remotecmd``
1343 1354 remote command to use for clone/push/pull operations. Default is ``hg``.
1344 1355
1345 1356 ``reportoldssl``
1346 1357 Warn if an SSL certificate is unable to be due to using Python
1347 1358 2.5 or earlier. True or False. Default is True.
1348 1359
1349 1360 ``report_untrusted``
1350 1361 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1351 1362 trusted user or group. True or False. Default is True.
1352 1363
1353 1364 ``slash``
1354 1365 Display paths using a slash (``/``) as the path separator. This
1355 1366 only makes a difference on systems where the default path
1356 1367 separator is not the slash character (e.g. Windows uses the
1357 1368 backslash character (``\``)).
1358 1369 Default is False.
1359 1370
1360 1371 ``ssh``
1361 1372 command to use for SSH connections. Default is ``ssh``.
1362 1373
1363 1374 ``strict``
1364 1375 Require exact command names, instead of allowing unambiguous
1365 1376 abbreviations. True or False. Default is False.
1366 1377
1367 1378 ``style``
1368 1379 Name of style to use for command output.
1369 1380
1370 1381 ``timeout``
1371 1382 The timeout used when a lock is held (in seconds), a negative value
1372 1383 means no timeout. Default is 600.
1373 1384
1374 1385 ``traceback``
1375 1386 Mercurial always prints a traceback when an unknown exception
1376 1387 occurs. Setting this to True will make Mercurial print a traceback
1377 1388 on all exceptions, even those recognized by Mercurial (such as
1378 1389 IOError or MemoryError). Default is False.
1379 1390
1380 1391 ``username``
1381 1392 The committer of a changeset created when running "commit".
1382 1393 Typically a person's name and email address, e.g. ``Fred Widget
1383 1394 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1384 1395 the username in hgrc is empty, it has to be specified manually or
1385 1396 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1386 1397 ``username =`` in the system hgrc). Environment variables in the
1387 1398 username are expanded.
1388 1399
1389 1400 ``verbose``
1390 1401 Increase the amount of output printed. True or False. Default is False.
1391 1402
1392 1403
1393 1404 ``web``
1394 1405 -------
1395 1406
1396 1407 Web interface configuration. The settings in this section apply to
1397 1408 both the builtin webserver (started by :hg:`serve`) and the script you
1398 1409 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1399 1410 and WSGI).
1400 1411
1401 1412 The Mercurial webserver does no authentication (it does not prompt for
1402 1413 usernames and passwords to validate *who* users are), but it does do
1403 1414 authorization (it grants or denies access for *authenticated users*
1404 1415 based on settings in this section). You must either configure your
1405 1416 webserver to do authentication for you, or disable the authorization
1406 1417 checks.
1407 1418
1408 1419 For a quick setup in a trusted environment, e.g., a private LAN, where
1409 1420 you want it to accept pushes from anybody, you can use the following
1410 1421 command line::
1411 1422
1412 1423 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1413 1424
1414 1425 Note that this will allow anybody to push anything to the server and
1415 1426 that this should not be used for public servers.
1416 1427
1417 1428 The full set of options is:
1418 1429
1419 1430 ``accesslog``
1420 1431 Where to output the access log. Default is stdout.
1421 1432
1422 1433 ``address``
1423 1434 Interface address to bind to. Default is all.
1424 1435
1425 1436 ``allow_archive``
1426 1437 List of archive format (bz2, gz, zip) allowed for downloading.
1427 1438 Default is empty.
1428 1439
1429 1440 ``allowbz2``
1430 1441 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1431 1442 revisions.
1432 1443 Default is False.
1433 1444
1434 1445 ``allowgz``
1435 1446 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1436 1447 revisions.
1437 1448 Default is False.
1438 1449
1439 1450 ``allowpull``
1440 1451 Whether to allow pulling from the repository. Default is True.
1441 1452
1442 1453 ``allow_push``
1443 1454 Whether to allow pushing to the repository. If empty or not set,
1444 1455 push is not allowed. If the special value ``*``, any remote user can
1445 1456 push, including unauthenticated users. Otherwise, the remote user
1446 1457 must have been authenticated, and the authenticated user name must
1447 1458 be present in this list. The contents of the allow_push list are
1448 1459 examined after the deny_push list.
1449 1460
1450 1461 ``allow_read``
1451 1462 If the user has not already been denied repository access due to
1452 1463 the contents of deny_read, this list determines whether to grant
1453 1464 repository access to the user. If this list is not empty, and the
1454 1465 user is unauthenticated or not present in the list, then access is
1455 1466 denied for the user. If the list is empty or not set, then access
1456 1467 is permitted to all users by default. Setting allow_read to the
1457 1468 special value ``*`` is equivalent to it not being set (i.e. access
1458 1469 is permitted to all users). The contents of the allow_read list are
1459 1470 examined after the deny_read list.
1460 1471
1461 1472 ``allowzip``
1462 1473 (DEPRECATED) Whether to allow .zip downloading of repository
1463 1474 revisions. Default is False. This feature creates temporary files.
1464 1475
1465 1476 ``archivesubrepos``
1466 1477 Whether to recurse into subrepositories when archiving. Default is
1467 1478 False.
1468 1479
1469 1480 ``baseurl``
1470 1481 Base URL to use when publishing URLs in other locations, so
1471 1482 third-party tools like email notification hooks can construct
1472 1483 URLs. Example: ``http://hgserver/repos/``.
1473 1484
1474 1485 ``cacerts``
1475 1486 Path to file containing a list of PEM encoded certificate
1476 1487 authority certificates. Environment variables and ``~user``
1477 1488 constructs are expanded in the filename. If specified on the
1478 1489 client, then it will verify the identity of remote HTTPS servers
1479 1490 with these certificates.
1480 1491
1481 1492 This feature is only supported when using Python 2.6 or later. If you wish
1482 1493 to use it with earlier versions of Python, install the backported
1483 1494 version of the ssl library that is available from
1484 1495 ``http://pypi.python.org``.
1485 1496
1486 1497 To disable SSL verification temporarily, specify ``--insecure`` from
1487 1498 command line.
1488 1499
1489 1500 You can use OpenSSL's CA certificate file if your platform has
1490 1501 one. On most Linux systems this will be
1491 1502 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1492 1503 generate this file manually. The form must be as follows::
1493 1504
1494 1505 -----BEGIN CERTIFICATE-----
1495 1506 ... (certificate in base64 PEM encoding) ...
1496 1507 -----END CERTIFICATE-----
1497 1508 -----BEGIN CERTIFICATE-----
1498 1509 ... (certificate in base64 PEM encoding) ...
1499 1510 -----END CERTIFICATE-----
1500 1511
1501 1512 ``cache``
1502 1513 Whether to support caching in hgweb. Defaults to True.
1503 1514
1504 1515 ``collapse``
1505 1516 With ``descend`` enabled, repositories in subdirectories are shown at
1506 1517 a single level alongside repositories in the current path. With
1507 1518 ``collapse`` also enabled, repositories residing at a deeper level than
1508 1519 the current path are grouped behind navigable directory entries that
1509 1520 lead to the locations of these repositories. In effect, this setting
1510 1521 collapses each collection of repositories found within a subdirectory
1511 1522 into a single entry for that subdirectory. Default is False.
1512 1523
1513 1524 ``comparisoncontext``
1514 1525 Number of lines of context to show in side-by-side file comparison. If
1515 1526 negative or the value ``full``, whole files are shown. Default is 5.
1516 1527 This setting can be overridden by a ``context`` request parameter to the
1517 1528 ``comparison`` command, taking the same values.
1518 1529
1519 1530 ``contact``
1520 1531 Name or email address of the person in charge of the repository.
1521 1532 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1522 1533
1523 1534 ``deny_push``
1524 1535 Whether to deny pushing to the repository. If empty or not set,
1525 1536 push is not denied. If the special value ``*``, all remote users are
1526 1537 denied push. Otherwise, unauthenticated users are all denied, and
1527 1538 any authenticated user name present in this list is also denied. The
1528 1539 contents of the deny_push list are examined before the allow_push list.
1529 1540
1530 1541 ``deny_read``
1531 1542 Whether to deny reading/viewing of the repository. If this list is
1532 1543 not empty, unauthenticated users are all denied, and any
1533 1544 authenticated user name present in this list is also denied access to
1534 1545 the repository. If set to the special value ``*``, all remote users
1535 1546 are denied access (rarely needed ;). If deny_read is empty or not set,
1536 1547 the determination of repository access depends on the presence and
1537 1548 content of the allow_read list (see description). If both
1538 1549 deny_read and allow_read are empty or not set, then access is
1539 1550 permitted to all users by default. If the repository is being
1540 1551 served via hgwebdir, denied users will not be able to see it in
1541 1552 the list of repositories. The contents of the deny_read list have
1542 1553 priority over (are examined before) the contents of the allow_read
1543 1554 list.
1544 1555
1545 1556 ``descend``
1546 1557 hgwebdir indexes will not descend into subdirectories. Only repositories
1547 1558 directly in the current path will be shown (other repositories are still
1548 1559 available from the index corresponding to their containing path).
1549 1560
1550 1561 ``description``
1551 1562 Textual description of the repository's purpose or contents.
1552 1563 Default is "unknown".
1553 1564
1554 1565 ``encoding``
1555 1566 Character encoding name. Default is the current locale charset.
1556 1567 Example: "UTF-8"
1557 1568
1558 1569 ``errorlog``
1559 1570 Where to output the error log. Default is stderr.
1560 1571
1561 1572 ``guessmime``
1562 1573 Control MIME types for raw download of file content.
1563 1574 Set to True to let hgweb guess the content type from the file
1564 1575 extension. This will serve HTML files as ``text/html`` and might
1565 1576 allow cross-site scripting attacks when serving untrusted
1566 1577 repositories. Default is False.
1567 1578
1568 1579 ``hidden``
1569 1580 Whether to hide the repository in the hgwebdir index.
1570 1581 Default is False.
1571 1582
1572 1583 ``ipv6``
1573 1584 Whether to use IPv6. Default is False.
1574 1585
1575 1586 ``logoimg``
1576 1587 File name of the logo image that some templates display on each page.
1577 1588 The file name is relative to ``staticurl``. That is, the full path to
1578 1589 the logo image is "staticurl/logoimg".
1579 1590 If unset, ``hglogo.png`` will be used.
1580 1591
1581 1592 ``logourl``
1582 1593 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1583 1594 will be used.
1584 1595
1585 1596 ``maxchanges``
1586 1597 Maximum number of changes to list on the changelog. Default is 10.
1587 1598
1588 1599 ``maxfiles``
1589 1600 Maximum number of files to list per changeset. Default is 10.
1590 1601
1591 1602 ``maxshortchanges``
1592 1603 Maximum number of changes to list on the shortlog, graph or filelog
1593 1604 pages. Default is 60.
1594 1605
1595 1606 ``name``
1596 1607 Repository name to use in the web interface. Default is current
1597 1608 working directory.
1598 1609
1599 1610 ``port``
1600 1611 Port to listen on. Default is 8000.
1601 1612
1602 1613 ``prefix``
1603 1614 Prefix path to serve from. Default is '' (server root).
1604 1615
1605 1616 ``push_ssl``
1606 1617 Whether to require that inbound pushes be transported over SSL to
1607 1618 prevent password sniffing. Default is True.
1608 1619
1609 1620 ``staticurl``
1610 1621 Base URL to use for static files. If unset, static files (e.g. the
1611 1622 hgicon.png favicon) will be served by the CGI script itself. Use
1612 1623 this setting to serve them directly with the HTTP server.
1613 1624 Example: ``http://hgserver/static/``.
1614 1625
1615 1626 ``stripes``
1616 1627 How many lines a "zebra stripe" should span in multi-line output.
1617 1628 Default is 1; set to 0 to disable.
1618 1629
1619 1630 ``style``
1620 1631 Which template map style to use.
1621 1632
1622 1633 ``templates``
1623 1634 Where to find the HTML templates. Default is install path.
1624 1635
1625 1636 ``websub``
1626 1637 ----------
1627 1638
1628 1639 Web substitution filter definition. You can use this section to
1629 1640 define a set of regular expression substitution patterns which
1630 1641 let you automatically modify the hgweb server output.
1631 1642
1632 1643 The default hgweb templates only apply these substitution patterns
1633 1644 on the revision description fields. You can apply them anywhere
1634 1645 you want when you create your own templates by adding calls to the
1635 1646 "websub" filter (usually after calling the "escape" filter).
1636 1647
1637 1648 This can be used, for example, to convert issue references to links
1638 1649 to your issue tracker, or to convert "markdown-like" syntax into
1639 1650 HTML (see the examples below).
1640 1651
1641 1652 Each entry in this section names a substitution filter.
1642 1653 The value of each entry defines the substitution expression itself.
1643 1654 The websub expressions follow the old interhg extension syntax,
1644 1655 which in turn imitates the Unix sed replacement syntax::
1645 1656
1646 1657 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1647 1658
1648 1659 You can use any separator other than "/". The final "i" is optional
1649 1660 and indicates that the search must be case insensitive.
1650 1661
1651 1662 Examples::
1652 1663
1653 1664 [websub]
1654 1665 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1655 1666 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1656 1667 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1657 1668
1658 1669 ``worker``
1659 1670 ----------
1660 1671
1661 1672 Parallel master/worker configuration. We currently perform working
1662 1673 directory updates in parallel on Unix-like systems, which greatly
1663 1674 helps performance.
1664 1675
1665 1676 ``numcpus``
1666 1677 Number of CPUs to use for parallel operations. Default is 4 or the
1667 1678 number of CPUs on the system, whichever is larger. A zero or
1668 1679 negative value is treated as ``use the default``.
@@ -1,191 +1,193 b''
1 1 Environment setup for MQ
2 2
3 3 $ echo "[extensions]" >> $HGRCPATH
4 4 $ echo "mq=" >> $HGRCPATH
5 5 $ hg init
6 6 $ hg qinit
7 7
8 8 Should fail if no patches applied
9 9 (this tests also that editor is not invoked if '--edit' is not
10 10 specified)
11 11
12 12 $ hg qrefresh
13 13 no patches applied
14 14 [1]
15 15 $ hg qrefresh -e
16 16 no patches applied
17 17 [1]
18 18 $ hg qnew -m "First commit message" first-patch
19 19 $ echo aaaa > file
20 20 $ hg add file
21 21 $ HGEDITOR=cat hg qrefresh
22 22
23 23 Should display 'First commit message'
24 24
25 25 $ hg log -l1 --template "{desc}\n"
26 26 First commit message
27 27
28 28 Testing changing message with -m
29 29 (this tests also that '--edit' can be used with '--message', and
30 30 that '[committemplate] changeset' definition and commit log specific
31 31 template keyword 'extramsg' work well)
32 32
33 33 $ cat >> .hg/hgrc <<EOF
34 34 > [committemplate]
35 > listupfiles = {file_adds %
36 > "HG: added {file}\n" }{file_mods %
37 > "HG: changed {file}\n" }{file_dels %
38 > "HG: removed {file}\n" }{if(files, "",
39 > "HG: no files changed\n")}
40 >
35 41 > changeset = HG: this is customized commit template
36 42 > {desc}\n\n
37 43 > HG: Enter commit message. Lines beginning with 'HG:' are removed.
38 44 > HG: {extramsg}
39 45 > HG: --
40 46 > HG: user: {author}
41 > HG: branch '{branch}'\n{file_adds %
42 > "HG: added {file}\n" }{file_mods %
43 > "HG: changed {file}\n" }{file_dels %
44 > "HG: removed {file}\n" }{if(files, "",
45 > "HG: no files changed\n")}
47 > HG: branch '{branch}'\n{listupfiles}
46 48 > EOF
47 49
48 50 $ echo bbbb > file
49 51 $ HGEDITOR=cat hg qrefresh -m "Second commit message" -e
50 52 HG: this is customized commit template
51 53 Second commit message
52 54
53 55
54 56 HG: Enter commit message. Lines beginning with 'HG:' are removed.
55 57 HG: Leave message empty to use default message.
56 58 HG: --
57 59 HG: user: test
58 60 HG: branch 'default'
59 61 HG: added file
60 62
61 63 $ cat >> .hg/hgrc <<EOF
62 64 > # disable customizing for subsequent tests
63 65 > [committemplate]
64 66 > changeset =
65 67 > EOF
66 68
67 69 Should display 'Second commit message'
68 70
69 71 $ hg log -l1 --template "{desc}\n"
70 72 Second commit message
71 73
72 74 Testing changing message with -l
73 75
74 76 $ echo "Third commit message" > logfile
75 77 $ echo " This is the 3rd log message" >> logfile
76 78 $ echo bbbb > file
77 79 $ hg qrefresh -l logfile
78 80
79 81 Should display 'Third commit message\\\n This is the 3rd log message'
80 82
81 83 $ hg log -l1 --template "{desc}\n"
82 84 Third commit message
83 85 This is the 3rd log message
84 86
85 87 Testing changing message with -l-
86 88
87 89 $ hg qnew -m "First commit message" second-patch
88 90 $ echo aaaa > file2
89 91 $ hg add file2
90 92 $ echo bbbb > file2
91 93 $ (echo "Fifth commit message"; echo " This is the 5th log message") | hg qrefresh -l-
92 94
93 95 Should display 'Fifth commit message\\\n This is the 5th log message'
94 96
95 97 $ hg log -l1 --template "{desc}\n"
96 98 Fifth commit message
97 99 This is the 5th log message
98 100
99 101 Test saving last-message.txt:
100 102
101 103 $ cat > $TESTTMP/editor.sh << EOF
102 104 > echo "==== before editing"
103 105 > cat \$1
104 106 > echo "===="
105 107 > (echo; echo "test saving last-message.txt") >> \$1
106 108 > EOF
107 109
108 110 $ cat > $TESTTMP/commitfailure.py <<EOF
109 111 > from mercurial import util
110 112 > def reposetup(ui, repo):
111 113 > class commitfailure(repo.__class__):
112 114 > def commit(self, *args, **kwargs):
113 115 > raise util.Abort('emulating unexpected abort')
114 116 > repo.__class__ = commitfailure
115 117 > EOF
116 118
117 119 $ cat >> .hg/hgrc <<EOF
118 120 > [extensions]
119 121 > # this failure occurs before editor invocation
120 122 > commitfailure = $TESTTMP/commitfailure.py
121 123 > EOF
122 124
123 125 $ hg qapplied
124 126 first-patch
125 127 second-patch
126 128 $ hg tip --template "{files}\n"
127 129 file2
128 130
129 131 (test that editor is not invoked before transaction starting)
130 132
131 133 $ rm -f .hg/last-message.txt
132 134 $ HGEDITOR="sh $TESTTMP/editor.sh" hg qrefresh -e
133 135 refresh interrupted while patch was popped! (revert --all, qpush to recover)
134 136 abort: emulating unexpected abort
135 137 [255]
136 138 $ test -f .hg/last-message.txt
137 139 [1]
138 140
139 141 (reset applied patches and directory status)
140 142
141 143 $ cat >> .hg/hgrc <<EOF
142 144 > [extensions]
143 145 > commitfailure = !
144 146 > EOF
145 147
146 148 $ hg qapplied
147 149 first-patch
148 150 $ hg status -A file2
149 151 ? file2
150 152 $ rm file2
151 153 $ hg qpush -q second-patch
152 154 now at: second-patch
153 155
154 156 (test that editor is invoked and commit message is saved into
155 157 "last-message.txt")
156 158
157 159 $ cat >> .hg/hgrc <<EOF
158 160 > [hooks]
159 161 > # this failure occurs after editor invocation
160 162 > pretxncommit.unexpectedabort = false
161 163 > EOF
162 164
163 165 $ rm -f .hg/last-message.txt
164 166 $ hg status --rev "second-patch^1" -arm
165 167 A file2
166 168 $ HGEDITOR="sh $TESTTMP/editor.sh" hg qrefresh -e
167 169 ==== before editing
168 170 Fifth commit message
169 171 This is the 5th log message
170 172
171 173
172 174 HG: Enter commit message. Lines beginning with 'HG:' are removed.
173 175 HG: Leave message empty to use default message.
174 176 HG: --
175 177 HG: user: test
176 178 HG: branch 'default'
177 179 HG: added file2
178 180 ====
179 181 transaction abort!
180 182 rollback completed
181 183 note: commit message saved in .hg/last-message.txt
182 184 refresh interrupted while patch was popped! (revert --all, qpush to recover)
183 185 abort: pretxncommit.unexpectedabort hook exited with status 1
184 186 [255]
185 187 $ cat .hg/last-message.txt
186 188 Fifth commit message
187 189 This is the 5th log message
188 190
189 191
190 192
191 193 test saving last-message.txt
General Comments 0
You need to be logged in to leave comments. Login now