##// END OF EJS Templates
showconfig: don't accept multiple sections and one config item...
Brodie Rao -
r12697:14853ca7 default
parent child Browse files
Show More
@@ -1,4449 +1,4451 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import hex, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _, gettext
11 11 import os, re, sys, difflib, time, tempfile
12 12 import hg, util, revlog, extensions, copies, error
13 13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 15 import merge as mergemod
16 16 import minirst, revset
17 17 import dagparser
18 18
19 19 # Commands start here, listed alphabetically
20 20
21 21 def add(ui, repo, *pats, **opts):
22 22 """add the specified files on the next commit
23 23
24 24 Schedule files to be version controlled and added to the
25 25 repository.
26 26
27 27 The files will be added to the repository at the next commit. To
28 28 undo an add before that, see :hg:`forget`.
29 29
30 30 If no names are given, add all files to the repository.
31 31
32 32 .. container:: verbose
33 33
34 34 An example showing how new (unknown) files are added
35 35 automatically by :hg:`add`::
36 36
37 37 $ ls
38 38 foo.c
39 39 $ hg status
40 40 ? foo.c
41 41 $ hg add
42 42 adding foo.c
43 43 $ hg status
44 44 A foo.c
45 45
46 46 Returns 0 if all files are successfully added.
47 47 """
48 48
49 49 m = cmdutil.match(repo, pats, opts)
50 50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 51 opts.get('subrepos'), prefix="")
52 52 return rejected and 1 or 0
53 53
54 54 def addremove(ui, repo, *pats, **opts):
55 55 """add all new files, delete all missing files
56 56
57 57 Add all new files and remove all missing files from the
58 58 repository.
59 59
60 60 New files are ignored if they match any of the patterns in
61 61 .hgignore. As with add, these changes take effect at the next
62 62 commit.
63 63
64 64 Use the -s/--similarity option to detect renamed files. With a
65 65 parameter greater than 0, this compares every removed file with
66 66 every added file and records those similar enough as renames. This
67 67 option takes a percentage between 0 (disabled) and 100 (files must
68 68 be identical) as its parameter. Detecting renamed files this way
69 69 can be expensive. After using this option, :hg:`status -C` can be
70 70 used to check which files were identified as moved or renamed.
71 71
72 72 Returns 0 if all files are successfully added.
73 73 """
74 74 try:
75 75 sim = float(opts.get('similarity') or 100)
76 76 except ValueError:
77 77 raise util.Abort(_('similarity must be a number'))
78 78 if sim < 0 or sim > 100:
79 79 raise util.Abort(_('similarity must be between 0 and 100'))
80 80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81 81
82 82 def annotate(ui, repo, *pats, **opts):
83 83 """show changeset information by line for each file
84 84
85 85 List changes in files, showing the revision id responsible for
86 86 each line
87 87
88 88 This command is useful for discovering when a change was made and
89 89 by whom.
90 90
91 91 Without the -a/--text option, annotate will avoid processing files
92 92 it detects as binary. With -a, annotate will annotate the file
93 93 anyway, although the results will probably be neither useful
94 94 nor desirable.
95 95
96 96 Returns 0 on success.
97 97 """
98 98 if opts.get('follow'):
99 99 # --follow is deprecated and now just an alias for -f/--file
100 100 # to mimic the behavior of Mercurial before version 1.5
101 101 opts['file'] = 1
102 102
103 103 datefunc = ui.quiet and util.shortdate or util.datestr
104 104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105 105
106 106 if not pats:
107 107 raise util.Abort(_('at least one filename or pattern is required'))
108 108
109 109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 110 ('number', lambda x: str(x[0].rev())),
111 111 ('changeset', lambda x: short(x[0].node())),
112 112 ('date', getdate),
113 113 ('file', lambda x: x[0].path()),
114 114 ]
115 115
116 116 if (not opts.get('user') and not opts.get('changeset')
117 117 and not opts.get('date') and not opts.get('file')):
118 118 opts['number'] = 1
119 119
120 120 linenumber = opts.get('line_number') is not None
121 121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123 123
124 124 funcmap = [func for op, func in opmap if opts.get(op)]
125 125 if linenumber:
126 126 lastfunc = funcmap[-1]
127 127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128 128
129 129 ctx = repo[opts.get('rev')]
130 130 m = cmdutil.match(repo, pats, opts)
131 131 follow = not opts.get('no_follow')
132 132 for abs in ctx.walk(m):
133 133 fctx = ctx[abs]
134 134 if not opts.get('text') and util.binary(fctx.data()):
135 135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 136 continue
137 137
138 138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 139 pieces = []
140 140
141 141 for f in funcmap:
142 142 l = [f(n) for n, dummy in lines]
143 143 if l:
144 144 sized = [(x, encoding.colwidth(x)) for x in l]
145 145 ml = max([w for x, w in sized])
146 146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147 147
148 148 if pieces:
149 149 for p, l in zip(zip(*pieces), lines):
150 150 ui.write("%s: %s" % (" ".join(p), l[1]))
151 151
152 152 def archive(ui, repo, dest, **opts):
153 153 '''create an unversioned archive of a repository revision
154 154
155 155 By default, the revision used is the parent of the working
156 156 directory; use -r/--rev to specify a different revision.
157 157
158 158 The archive type is automatically detected based on file
159 159 extension (or override using -t/--type).
160 160
161 161 Valid types are:
162 162
163 163 :``files``: a directory full of files (default)
164 164 :``tar``: tar archive, uncompressed
165 165 :``tbz2``: tar archive, compressed using bzip2
166 166 :``tgz``: tar archive, compressed using gzip
167 167 :``uzip``: zip archive, uncompressed
168 168 :``zip``: zip archive, compressed using deflate
169 169
170 170 The exact name of the destination archive or directory is given
171 171 using a format string; see :hg:`help export` for details.
172 172
173 173 Each member added to an archive file has a directory prefix
174 174 prepended. Use -p/--prefix to specify a format string for the
175 175 prefix. The default is the basename of the archive, with suffixes
176 176 removed.
177 177
178 178 Returns 0 on success.
179 179 '''
180 180
181 181 ctx = repo[opts.get('rev')]
182 182 if not ctx:
183 183 raise util.Abort(_('no working directory: please specify a revision'))
184 184 node = ctx.node()
185 185 dest = cmdutil.make_filename(repo, dest, node)
186 186 if os.path.realpath(dest) == repo.root:
187 187 raise util.Abort(_('repository root cannot be destination'))
188 188
189 189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 190 prefix = opts.get('prefix')
191 191
192 192 if dest == '-':
193 193 if kind == 'files':
194 194 raise util.Abort(_('cannot archive plain files to stdout'))
195 195 dest = sys.stdout
196 196 if not prefix:
197 197 prefix = os.path.basename(repo.root) + '-%h'
198 198
199 199 prefix = cmdutil.make_filename(repo, prefix, node)
200 200 matchfn = cmdutil.match(repo, [], opts)
201 201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 202 matchfn, prefix, subrepos=opts.get('subrepos'))
203 203
204 204 def backout(ui, repo, node=None, rev=None, **opts):
205 205 '''reverse effect of earlier changeset
206 206
207 207 Commit the backed out changes as a new changeset. The new
208 208 changeset is a child of the backed out changeset.
209 209
210 210 If you backout a changeset other than the tip, a new head is
211 211 created. This head will be the new tip and you should merge this
212 212 backout changeset with another head.
213 213
214 214 The --merge option remembers the parent of the working directory
215 215 before starting the backout, then merges the new head with that
216 216 changeset afterwards. This saves you from doing the merge by hand.
217 217 The result of this merge is not committed, as with a normal merge.
218 218
219 219 See :hg:`help dates` for a list of formats valid for -d/--date.
220 220
221 221 Returns 0 on success.
222 222 '''
223 223 if rev and node:
224 224 raise util.Abort(_("please specify just one revision"))
225 225
226 226 if not rev:
227 227 rev = node
228 228
229 229 if not rev:
230 230 raise util.Abort(_("please specify a revision to backout"))
231 231
232 232 date = opts.get('date')
233 233 if date:
234 234 opts['date'] = util.parsedate(date)
235 235
236 236 cmdutil.bail_if_changed(repo)
237 237 node = repo.lookup(rev)
238 238
239 239 op1, op2 = repo.dirstate.parents()
240 240 a = repo.changelog.ancestor(op1, node)
241 241 if a != node:
242 242 raise util.Abort(_('cannot backout change on a different branch'))
243 243
244 244 p1, p2 = repo.changelog.parents(node)
245 245 if p1 == nullid:
246 246 raise util.Abort(_('cannot backout a change with no parents'))
247 247 if p2 != nullid:
248 248 if not opts.get('parent'):
249 249 raise util.Abort(_('cannot backout a merge changeset without '
250 250 '--parent'))
251 251 p = repo.lookup(opts['parent'])
252 252 if p not in (p1, p2):
253 253 raise util.Abort(_('%s is not a parent of %s') %
254 254 (short(p), short(node)))
255 255 parent = p
256 256 else:
257 257 if opts.get('parent'):
258 258 raise util.Abort(_('cannot use --parent on non-merge changeset'))
259 259 parent = p1
260 260
261 261 # the backout should appear on the same branch
262 262 branch = repo.dirstate.branch()
263 263 hg.clean(repo, node, show_stats=False)
264 264 repo.dirstate.setbranch(branch)
265 265 revert_opts = opts.copy()
266 266 revert_opts['date'] = None
267 267 revert_opts['all'] = True
268 268 revert_opts['rev'] = hex(parent)
269 269 revert_opts['no_backup'] = None
270 270 revert(ui, repo, **revert_opts)
271 271 commit_opts = opts.copy()
272 272 commit_opts['addremove'] = False
273 273 if not commit_opts['message'] and not commit_opts['logfile']:
274 274 # we don't translate commit messages
275 275 commit_opts['message'] = "Backed out changeset %s" % short(node)
276 276 commit_opts['force_editor'] = True
277 277 commit(ui, repo, **commit_opts)
278 278 def nice(node):
279 279 return '%d:%s' % (repo.changelog.rev(node), short(node))
280 280 ui.status(_('changeset %s backs out changeset %s\n') %
281 281 (nice(repo.changelog.tip()), nice(node)))
282 282 if op1 != node:
283 283 hg.clean(repo, op1, show_stats=False)
284 284 if opts.get('merge'):
285 285 ui.status(_('merging with changeset %s\n')
286 286 % nice(repo.changelog.tip()))
287 287 hg.merge(repo, hex(repo.changelog.tip()))
288 288 else:
289 289 ui.status(_('the backout changeset is a new head - '
290 290 'do not forget to merge\n'))
291 291 ui.status(_('(use "backout --merge" '
292 292 'if you want to auto-merge)\n'))
293 293
294 294 def bisect(ui, repo, rev=None, extra=None, command=None,
295 295 reset=None, good=None, bad=None, skip=None, noupdate=None):
296 296 """subdivision search of changesets
297 297
298 298 This command helps to find changesets which introduce problems. To
299 299 use, mark the earliest changeset you know exhibits the problem as
300 300 bad, then mark the latest changeset which is free from the problem
301 301 as good. Bisect will update your working directory to a revision
302 302 for testing (unless the -U/--noupdate option is specified). Once
303 303 you have performed tests, mark the working directory as good or
304 304 bad, and bisect will either update to another candidate changeset
305 305 or announce that it has found the bad revision.
306 306
307 307 As a shortcut, you can also use the revision argument to mark a
308 308 revision as good or bad without checking it out first.
309 309
310 310 If you supply a command, it will be used for automatic bisection.
311 311 Its exit status will be used to mark revisions as good or bad:
312 312 status 0 means good, 125 means to skip the revision, 127
313 313 (command not found) will abort the bisection, and any other
314 314 non-zero exit status means the revision is bad.
315 315
316 316 Returns 0 on success.
317 317 """
318 318 def print_result(nodes, good):
319 319 displayer = cmdutil.show_changeset(ui, repo, {})
320 320 if len(nodes) == 1:
321 321 # narrowed it down to a single revision
322 322 if good:
323 323 ui.write(_("The first good revision is:\n"))
324 324 else:
325 325 ui.write(_("The first bad revision is:\n"))
326 326 displayer.show(repo[nodes[0]])
327 327 parents = repo[nodes[0]].parents()
328 328 if len(parents) > 1:
329 329 side = good and state['bad'] or state['good']
330 330 num = len(set(i.node() for i in parents) & set(side))
331 331 if num == 1:
332 332 common = parents[0].ancestor(parents[1])
333 333 ui.write(_('Not all ancestors of this changeset have been'
334 334 ' checked.\nTo check the other ancestors, start'
335 335 ' from the common ancestor, %s.\n' % common))
336 336 else:
337 337 # multiple possible revisions
338 338 if good:
339 339 ui.write(_("Due to skipped revisions, the first "
340 340 "good revision could be any of:\n"))
341 341 else:
342 342 ui.write(_("Due to skipped revisions, the first "
343 343 "bad revision could be any of:\n"))
344 344 for n in nodes:
345 345 displayer.show(repo[n])
346 346 displayer.close()
347 347
348 348 def check_state(state, interactive=True):
349 349 if not state['good'] or not state['bad']:
350 350 if (good or bad or skip or reset) and interactive:
351 351 return
352 352 if not state['good']:
353 353 raise util.Abort(_('cannot bisect (no known good revisions)'))
354 354 else:
355 355 raise util.Abort(_('cannot bisect (no known bad revisions)'))
356 356 return True
357 357
358 358 # backward compatibility
359 359 if rev in "good bad reset init".split():
360 360 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
361 361 cmd, rev, extra = rev, extra, None
362 362 if cmd == "good":
363 363 good = True
364 364 elif cmd == "bad":
365 365 bad = True
366 366 else:
367 367 reset = True
368 368 elif extra or good + bad + skip + reset + bool(command) > 1:
369 369 raise util.Abort(_('incompatible arguments'))
370 370
371 371 if reset:
372 372 p = repo.join("bisect.state")
373 373 if os.path.exists(p):
374 374 os.unlink(p)
375 375 return
376 376
377 377 state = hbisect.load_state(repo)
378 378
379 379 if command:
380 380 changesets = 1
381 381 try:
382 382 while changesets:
383 383 # update state
384 384 status = util.system(command)
385 385 if status == 125:
386 386 transition = "skip"
387 387 elif status == 0:
388 388 transition = "good"
389 389 # status < 0 means process was killed
390 390 elif status == 127:
391 391 raise util.Abort(_("failed to execute %s") % command)
392 392 elif status < 0:
393 393 raise util.Abort(_("%s killed") % command)
394 394 else:
395 395 transition = "bad"
396 396 ctx = repo[rev or '.']
397 397 state[transition].append(ctx.node())
398 398 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
399 399 check_state(state, interactive=False)
400 400 # bisect
401 401 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
402 402 # update to next check
403 403 cmdutil.bail_if_changed(repo)
404 404 hg.clean(repo, nodes[0], show_stats=False)
405 405 finally:
406 406 hbisect.save_state(repo, state)
407 407 print_result(nodes, good)
408 408 return
409 409
410 410 # update state
411 411
412 412 if rev:
413 413 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
414 414 else:
415 415 nodes = [repo.lookup('.')]
416 416
417 417 if good or bad or skip:
418 418 if good:
419 419 state['good'] += nodes
420 420 elif bad:
421 421 state['bad'] += nodes
422 422 elif skip:
423 423 state['skip'] += nodes
424 424 hbisect.save_state(repo, state)
425 425
426 426 if not check_state(state):
427 427 return
428 428
429 429 # actually bisect
430 430 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
431 431 if changesets == 0:
432 432 print_result(nodes, good)
433 433 else:
434 434 assert len(nodes) == 1 # only a single node can be tested next
435 435 node = nodes[0]
436 436 # compute the approximate number of remaining tests
437 437 tests, size = 0, 2
438 438 while size <= changesets:
439 439 tests, size = tests + 1, size * 2
440 440 rev = repo.changelog.rev(node)
441 441 ui.write(_("Testing changeset %d:%s "
442 442 "(%d changesets remaining, ~%d tests)\n")
443 443 % (rev, short(node), changesets, tests))
444 444 if not noupdate:
445 445 cmdutil.bail_if_changed(repo)
446 446 return hg.clean(repo, node)
447 447
448 448 def branch(ui, repo, label=None, **opts):
449 449 """set or show the current branch name
450 450
451 451 With no argument, show the current branch name. With one argument,
452 452 set the working directory branch name (the branch will not exist
453 453 in the repository until the next commit). Standard practice
454 454 recommends that primary development take place on the 'default'
455 455 branch.
456 456
457 457 Unless -f/--force is specified, branch will not let you set a
458 458 branch name that already exists, even if it's inactive.
459 459
460 460 Use -C/--clean to reset the working directory branch to that of
461 461 the parent of the working directory, negating a previous branch
462 462 change.
463 463
464 464 Use the command :hg:`update` to switch to an existing branch. Use
465 465 :hg:`commit --close-branch` to mark this branch as closed.
466 466
467 467 Returns 0 on success.
468 468 """
469 469
470 470 if opts.get('clean'):
471 471 label = repo[None].parents()[0].branch()
472 472 repo.dirstate.setbranch(label)
473 473 ui.status(_('reset working directory to branch %s\n') % label)
474 474 elif label:
475 475 utflabel = encoding.fromlocal(label)
476 476 if not opts.get('force') and utflabel in repo.branchtags():
477 477 if label not in [p.branch() for p in repo.parents()]:
478 478 raise util.Abort(_('a branch of the same name already exists'
479 479 " (use 'hg update' to switch to it)"))
480 480 repo.dirstate.setbranch(utflabel)
481 481 ui.status(_('marked working directory as branch %s\n') % label)
482 482 else:
483 483 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
484 484
485 485 def branches(ui, repo, active=False, closed=False):
486 486 """list repository named branches
487 487
488 488 List the repository's named branches, indicating which ones are
489 489 inactive. If -c/--closed is specified, also list branches which have
490 490 been marked closed (see :hg:`commit --close-branch`).
491 491
492 492 If -a/--active is specified, only show active branches. A branch
493 493 is considered active if it contains repository heads.
494 494
495 495 Use the command :hg:`update` to switch to an existing branch.
496 496
497 497 Returns 0.
498 498 """
499 499
500 500 hexfunc = ui.debugflag and hex or short
501 501 activebranches = [repo[n].branch() for n in repo.heads()]
502 502 def testactive(tag, node):
503 503 realhead = tag in activebranches
504 504 open = node in repo.branchheads(tag, closed=False)
505 505 return realhead and open
506 506 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
507 507 for tag, node in repo.branchtags().items()],
508 508 reverse=True)
509 509
510 510 for isactive, node, tag in branches:
511 511 if (not active) or isactive:
512 512 encodedtag = encoding.tolocal(tag)
513 513 if ui.quiet:
514 514 ui.write("%s\n" % encodedtag)
515 515 else:
516 516 hn = repo.lookup(node)
517 517 if isactive:
518 518 label = 'branches.active'
519 519 notice = ''
520 520 elif hn not in repo.branchheads(tag, closed=False):
521 521 if not closed:
522 522 continue
523 523 label = 'branches.closed'
524 524 notice = _(' (closed)')
525 525 else:
526 526 label = 'branches.inactive'
527 527 notice = _(' (inactive)')
528 528 if tag == repo.dirstate.branch():
529 529 label = 'branches.current'
530 530 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
531 531 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
532 532 encodedtag = ui.label(encodedtag, label)
533 533 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
534 534
535 535 def bundle(ui, repo, fname, dest=None, **opts):
536 536 """create a changegroup file
537 537
538 538 Generate a compressed changegroup file collecting changesets not
539 539 known to be in another repository.
540 540
541 541 If you omit the destination repository, then hg assumes the
542 542 destination will have all the nodes you specify with --base
543 543 parameters. To create a bundle containing all changesets, use
544 544 -a/--all (or --base null).
545 545
546 546 You can change compression method with the -t/--type option.
547 547 The available compression methods are: none, bzip2, and
548 548 gzip (by default, bundles are compressed using bzip2).
549 549
550 550 The bundle file can then be transferred using conventional means
551 551 and applied to another repository with the unbundle or pull
552 552 command. This is useful when direct push and pull are not
553 553 available or when exporting an entire repository is undesirable.
554 554
555 555 Applying bundles preserves all changeset contents including
556 556 permissions, copy/rename information, and revision history.
557 557
558 558 Returns 0 on success, 1 if no changes found.
559 559 """
560 560 revs = opts.get('rev') or None
561 561 if opts.get('all'):
562 562 base = ['null']
563 563 else:
564 564 base = opts.get('base')
565 565 if base:
566 566 if dest:
567 567 raise util.Abort(_("--base is incompatible with specifying "
568 568 "a destination"))
569 569 base = [repo.lookup(rev) for rev in base]
570 570 # create the right base
571 571 # XXX: nodesbetween / changegroup* should be "fixed" instead
572 572 o = []
573 573 has = set((nullid,))
574 574 for n in base:
575 575 has.update(repo.changelog.reachable(n))
576 576 if revs:
577 577 revs = [repo.lookup(rev) for rev in revs]
578 578 visit = revs[:]
579 579 has.difference_update(visit)
580 580 else:
581 581 visit = repo.changelog.heads()
582 582 seen = {}
583 583 while visit:
584 584 n = visit.pop(0)
585 585 parents = [p for p in repo.changelog.parents(n) if p not in has]
586 586 if len(parents) == 0:
587 587 if n not in has:
588 588 o.append(n)
589 589 else:
590 590 for p in parents:
591 591 if p not in seen:
592 592 seen[p] = 1
593 593 visit.append(p)
594 594 else:
595 595 dest = ui.expandpath(dest or 'default-push', dest or 'default')
596 596 dest, branches = hg.parseurl(dest, opts.get('branch'))
597 597 other = hg.repository(hg.remoteui(repo, opts), dest)
598 598 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
599 599 if revs:
600 600 revs = [repo.lookup(rev) for rev in revs]
601 601 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
602 602
603 603 if not o:
604 604 ui.status(_("no changes found\n"))
605 605 return 1
606 606
607 607 if revs:
608 608 cg = repo.changegroupsubset(o, revs, 'bundle')
609 609 else:
610 610 cg = repo.changegroup(o, 'bundle')
611 611
612 612 bundletype = opts.get('type', 'bzip2').lower()
613 613 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
614 614 bundletype = btypes.get(bundletype)
615 615 if bundletype not in changegroup.bundletypes:
616 616 raise util.Abort(_('unknown bundle type specified with --type'))
617 617
618 618 changegroup.writebundle(cg, fname, bundletype)
619 619
620 620 def cat(ui, repo, file1, *pats, **opts):
621 621 """output the current or given revision of files
622 622
623 623 Print the specified files as they were at the given revision. If
624 624 no revision is given, the parent of the working directory is used,
625 625 or tip if no revision is checked out.
626 626
627 627 Output may be to a file, in which case the name of the file is
628 628 given using a format string. The formatting rules are the same as
629 629 for the export command, with the following additions:
630 630
631 631 :``%s``: basename of file being printed
632 632 :``%d``: dirname of file being printed, or '.' if in repository root
633 633 :``%p``: root-relative path name of file being printed
634 634
635 635 Returns 0 on success.
636 636 """
637 637 ctx = cmdutil.revsingle(repo, opts.get('rev'))
638 638 err = 1
639 639 m = cmdutil.match(repo, (file1,) + pats, opts)
640 640 for abs in ctx.walk(m):
641 641 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
642 642 data = ctx[abs].data()
643 643 if opts.get('decode'):
644 644 data = repo.wwritedata(abs, data)
645 645 fp.write(data)
646 646 err = 0
647 647 return err
648 648
649 649 def clone(ui, source, dest=None, **opts):
650 650 """make a copy of an existing repository
651 651
652 652 Create a copy of an existing repository in a new directory.
653 653
654 654 If no destination directory name is specified, it defaults to the
655 655 basename of the source.
656 656
657 657 The location of the source is added to the new repository's
658 658 .hg/hgrc file, as the default to be used for future pulls.
659 659
660 660 See :hg:`help urls` for valid source format details.
661 661
662 662 It is possible to specify an ``ssh://`` URL as the destination, but no
663 663 .hg/hgrc and working directory will be created on the remote side.
664 664 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
665 665
666 666 A set of changesets (tags, or branch names) to pull may be specified
667 667 by listing each changeset (tag, or branch name) with -r/--rev.
668 668 If -r/--rev is used, the cloned repository will contain only a subset
669 669 of the changesets of the source repository. Only the set of changesets
670 670 defined by all -r/--rev options (including all their ancestors)
671 671 will be pulled into the destination repository.
672 672 No subsequent changesets (including subsequent tags) will be present
673 673 in the destination.
674 674
675 675 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
676 676 local source repositories.
677 677
678 678 For efficiency, hardlinks are used for cloning whenever the source
679 679 and destination are on the same filesystem (note this applies only
680 680 to the repository data, not to the working directory). Some
681 681 filesystems, such as AFS, implement hardlinking incorrectly, but
682 682 do not report errors. In these cases, use the --pull option to
683 683 avoid hardlinking.
684 684
685 685 In some cases, you can clone repositories and the working directory
686 686 using full hardlinks with ::
687 687
688 688 $ cp -al REPO REPOCLONE
689 689
690 690 This is the fastest way to clone, but it is not always safe. The
691 691 operation is not atomic (making sure REPO is not modified during
692 692 the operation is up to you) and you have to make sure your editor
693 693 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
694 694 this is not compatible with certain extensions that place their
695 695 metadata under the .hg directory, such as mq.
696 696
697 697 Mercurial will update the working directory to the first applicable
698 698 revision from this list:
699 699
700 700 a) null if -U or the source repository has no changesets
701 701 b) if -u . and the source repository is local, the first parent of
702 702 the source repository's working directory
703 703 c) the changeset specified with -u (if a branch name, this means the
704 704 latest head of that branch)
705 705 d) the changeset specified with -r
706 706 e) the tipmost head specified with -b
707 707 f) the tipmost head specified with the url#branch source syntax
708 708 g) the tipmost head of the default branch
709 709 h) tip
710 710
711 711 Returns 0 on success.
712 712 """
713 713 if opts.get('noupdate') and opts.get('updaterev'):
714 714 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
715 715
716 716 r = hg.clone(hg.remoteui(ui, opts), source, dest,
717 717 pull=opts.get('pull'),
718 718 stream=opts.get('uncompressed'),
719 719 rev=opts.get('rev'),
720 720 update=opts.get('updaterev') or not opts.get('noupdate'),
721 721 branch=opts.get('branch'))
722 722
723 723 return r is None
724 724
725 725 def commit(ui, repo, *pats, **opts):
726 726 """commit the specified files or all outstanding changes
727 727
728 728 Commit changes to the given files into the repository. Unlike a
729 729 centralized RCS, this operation is a local operation. See
730 730 :hg:`push` for a way to actively distribute your changes.
731 731
732 732 If a list of files is omitted, all changes reported by :hg:`status`
733 733 will be committed.
734 734
735 735 If you are committing the result of a merge, do not provide any
736 736 filenames or -I/-X filters.
737 737
738 738 If no commit message is specified, Mercurial starts your
739 739 configured editor where you can enter a message. In case your
740 740 commit fails, you will find a backup of your message in
741 741 ``.hg/last-message.txt``.
742 742
743 743 See :hg:`help dates` for a list of formats valid for -d/--date.
744 744
745 745 Returns 0 on success, 1 if nothing changed.
746 746 """
747 747 extra = {}
748 748 if opts.get('close_branch'):
749 749 if repo['.'].node() not in repo.branchheads():
750 750 # The topo heads set is included in the branch heads set of the
751 751 # current branch, so it's sufficient to test branchheads
752 752 raise util.Abort(_('can only close branch heads'))
753 753 extra['close'] = 1
754 754 e = cmdutil.commiteditor
755 755 if opts.get('force_editor'):
756 756 e = cmdutil.commitforceeditor
757 757
758 758 def commitfunc(ui, repo, message, match, opts):
759 759 return repo.commit(message, opts.get('user'), opts.get('date'), match,
760 760 editor=e, extra=extra)
761 761
762 762 branch = repo[None].branch()
763 763 bheads = repo.branchheads(branch)
764 764
765 765 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
766 766 if not node:
767 767 ui.status(_("nothing changed\n"))
768 768 return 1
769 769
770 770 ctx = repo[node]
771 771 parents = ctx.parents()
772 772
773 773 if bheads and not [x for x in parents
774 774 if x.node() in bheads and x.branch() == branch]:
775 775 ui.status(_('created new head\n'))
776 776 # The message is not printed for initial roots. For the other
777 777 # changesets, it is printed in the following situations:
778 778 #
779 779 # Par column: for the 2 parents with ...
780 780 # N: null or no parent
781 781 # B: parent is on another named branch
782 782 # C: parent is a regular non head changeset
783 783 # H: parent was a branch head of the current branch
784 784 # Msg column: whether we print "created new head" message
785 785 # In the following, it is assumed that there already exists some
786 786 # initial branch heads of the current branch, otherwise nothing is
787 787 # printed anyway.
788 788 #
789 789 # Par Msg Comment
790 790 # NN y additional topo root
791 791 #
792 792 # BN y additional branch root
793 793 # CN y additional topo head
794 794 # HN n usual case
795 795 #
796 796 # BB y weird additional branch root
797 797 # CB y branch merge
798 798 # HB n merge with named branch
799 799 #
800 800 # CC y additional head from merge
801 801 # CH n merge with a head
802 802 #
803 803 # HH n head merge: head count decreases
804 804
805 805 if not opts.get('close_branch'):
806 806 for r in parents:
807 807 if r.extra().get('close') and r.branch() == branch:
808 808 ui.status(_('reopening closed branch head %d\n') % r)
809 809
810 810 if ui.debugflag:
811 811 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
812 812 elif ui.verbose:
813 813 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
814 814
815 815 def copy(ui, repo, *pats, **opts):
816 816 """mark files as copied for the next commit
817 817
818 818 Mark dest as having copies of source files. If dest is a
819 819 directory, copies are put in that directory. If dest is a file,
820 820 the source must be a single file.
821 821
822 822 By default, this command copies the contents of files as they
823 823 exist in the working directory. If invoked with -A/--after, the
824 824 operation is recorded, but no copying is performed.
825 825
826 826 This command takes effect with the next commit. To undo a copy
827 827 before that, see :hg:`revert`.
828 828
829 829 Returns 0 on success, 1 if errors are encountered.
830 830 """
831 831 wlock = repo.wlock(False)
832 832 try:
833 833 return cmdutil.copy(ui, repo, pats, opts)
834 834 finally:
835 835 wlock.release()
836 836
837 837 def debugancestor(ui, repo, *args):
838 838 """find the ancestor revision of two revisions in a given index"""
839 839 if len(args) == 3:
840 840 index, rev1, rev2 = args
841 841 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
842 842 lookup = r.lookup
843 843 elif len(args) == 2:
844 844 if not repo:
845 845 raise util.Abort(_("there is no Mercurial repository here "
846 846 "(.hg not found)"))
847 847 rev1, rev2 = args
848 848 r = repo.changelog
849 849 lookup = repo.lookup
850 850 else:
851 851 raise util.Abort(_('either two or three arguments required'))
852 852 a = r.ancestor(lookup(rev1), lookup(rev2))
853 853 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
854 854
855 855 def debugbuilddag(ui, repo, text,
856 856 mergeable_file=False,
857 857 appended_file=False,
858 858 overwritten_file=False,
859 859 new_file=False):
860 860 """builds a repo with a given dag from scratch in the current empty repo
861 861
862 862 Elements:
863 863
864 864 - "+n" is a linear run of n nodes based on the current default parent
865 865 - "." is a single node based on the current default parent
866 866 - "$" resets the default parent to null (implied at the start);
867 867 otherwise the default parent is always the last node created
868 868 - "<p" sets the default parent to the backref p
869 869 - "*p" is a fork at parent p, which is a backref
870 870 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
871 871 - "/p2" is a merge of the preceding node and p2
872 872 - ":tag" defines a local tag for the preceding node
873 873 - "@branch" sets the named branch for subsequent nodes
874 874 - "!command" runs the command using your shell
875 875 - "!!my command\\n" is like "!", but to the end of the line
876 876 - "#...\\n" is a comment up to the end of the line
877 877
878 878 Whitespace between the above elements is ignored.
879 879
880 880 A backref is either
881 881
882 882 - a number n, which references the node curr-n, where curr is the current
883 883 node, or
884 884 - the name of a local tag you placed earlier using ":tag", or
885 885 - empty to denote the default parent.
886 886
887 887 All string valued-elements are either strictly alphanumeric, or must
888 888 be enclosed in double quotes ("..."), with "\\" as escape character.
889 889
890 890 Note that the --overwritten-file and --appended-file options imply the
891 891 use of "HGMERGE=internal:local" during DAG buildup.
892 892 """
893 893
894 894 if not (mergeable_file or appended_file or overwritten_file or new_file):
895 895 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
896 896
897 897 if len(repo.changelog) > 0:
898 898 raise util.Abort(_('repository is not empty'))
899 899
900 900 if overwritten_file or appended_file:
901 901 # we don't want to fail in merges during buildup
902 902 os.environ['HGMERGE'] = 'internal:local'
903 903
904 904 def writefile(fname, text, fmode="wb"):
905 905 f = open(fname, fmode)
906 906 try:
907 907 f.write(text)
908 908 finally:
909 909 f.close()
910 910
911 911 if mergeable_file:
912 912 linesperrev = 2
913 913 # determine number of revs in DAG
914 914 n = 0
915 915 for type, data in dagparser.parsedag(text):
916 916 if type == 'n':
917 917 n += 1
918 918 # make a file with k lines per rev
919 919 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
920 920 + "\n")
921 921
922 922 at = -1
923 923 atbranch = 'default'
924 924 for type, data in dagparser.parsedag(text):
925 925 if type == 'n':
926 926 ui.status('node %s\n' % str(data))
927 927 id, ps = data
928 928 p1 = ps[0]
929 929 if p1 != at:
930 930 update(ui, repo, node=p1, clean=True)
931 931 at = p1
932 932 if repo.dirstate.branch() != atbranch:
933 933 branch(ui, repo, atbranch, force=True)
934 934 if len(ps) > 1:
935 935 p2 = ps[1]
936 936 merge(ui, repo, node=p2)
937 937
938 938 if mergeable_file:
939 939 f = open("mf", "rb+")
940 940 try:
941 941 lines = f.read().split("\n")
942 942 lines[id * linesperrev] += " r%i" % id
943 943 f.seek(0)
944 944 f.write("\n".join(lines))
945 945 finally:
946 946 f.close()
947 947
948 948 if appended_file:
949 949 writefile("af", "r%i\n" % id, "ab")
950 950
951 951 if overwritten_file:
952 952 writefile("of", "r%i\n" % id)
953 953
954 954 if new_file:
955 955 writefile("nf%i" % id, "r%i\n" % id)
956 956
957 957 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
958 958 at = id
959 959 elif type == 'l':
960 960 id, name = data
961 961 ui.status('tag %s\n' % name)
962 962 tag(ui, repo, name, local=True)
963 963 elif type == 'a':
964 964 ui.status('branch %s\n' % data)
965 965 atbranch = data
966 966 elif type in 'cC':
967 967 r = util.system(data, cwd=repo.root)
968 968 if r:
969 969 desc, r = util.explain_exit(r)
970 970 raise util.Abort(_('%s command %s') % (data, desc))
971 971
972 972 def debugcommands(ui, cmd='', *args):
973 973 """list all available commands and options"""
974 974 for cmd, vals in sorted(table.iteritems()):
975 975 cmd = cmd.split('|')[0].strip('^')
976 976 opts = ', '.join([i[1] for i in vals[1]])
977 977 ui.write('%s: %s\n' % (cmd, opts))
978 978
979 979 def debugcomplete(ui, cmd='', **opts):
980 980 """returns the completion list associated with the given command"""
981 981
982 982 if opts.get('options'):
983 983 options = []
984 984 otables = [globalopts]
985 985 if cmd:
986 986 aliases, entry = cmdutil.findcmd(cmd, table, False)
987 987 otables.append(entry[1])
988 988 for t in otables:
989 989 for o in t:
990 990 if "(DEPRECATED)" in o[3]:
991 991 continue
992 992 if o[0]:
993 993 options.append('-%s' % o[0])
994 994 options.append('--%s' % o[1])
995 995 ui.write("%s\n" % "\n".join(options))
996 996 return
997 997
998 998 cmdlist = cmdutil.findpossible(cmd, table)
999 999 if ui.verbose:
1000 1000 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1001 1001 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1002 1002
1003 1003 def debugfsinfo(ui, path = "."):
1004 1004 """show information detected about current filesystem"""
1005 1005 open('.debugfsinfo', 'w').write('')
1006 1006 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1007 1007 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1008 1008 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1009 1009 and 'yes' or 'no'))
1010 1010 os.unlink('.debugfsinfo')
1011 1011
1012 1012 def debugrebuildstate(ui, repo, rev="tip"):
1013 1013 """rebuild the dirstate as it would look like for the given revision"""
1014 1014 ctx = repo[rev]
1015 1015 wlock = repo.wlock()
1016 1016 try:
1017 1017 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1018 1018 finally:
1019 1019 wlock.release()
1020 1020
1021 1021 def debugcheckstate(ui, repo):
1022 1022 """validate the correctness of the current dirstate"""
1023 1023 parent1, parent2 = repo.dirstate.parents()
1024 1024 m1 = repo[parent1].manifest()
1025 1025 m2 = repo[parent2].manifest()
1026 1026 errors = 0
1027 1027 for f in repo.dirstate:
1028 1028 state = repo.dirstate[f]
1029 1029 if state in "nr" and f not in m1:
1030 1030 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1031 1031 errors += 1
1032 1032 if state in "a" and f in m1:
1033 1033 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1034 1034 errors += 1
1035 1035 if state in "m" and f not in m1 and f not in m2:
1036 1036 ui.warn(_("%s in state %s, but not in either manifest\n") %
1037 1037 (f, state))
1038 1038 errors += 1
1039 1039 for f in m1:
1040 1040 state = repo.dirstate[f]
1041 1041 if state not in "nrm":
1042 1042 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1043 1043 errors += 1
1044 1044 if errors:
1045 1045 error = _(".hg/dirstate inconsistent with current parent's manifest")
1046 1046 raise util.Abort(error)
1047 1047
1048 1048 def showconfig(ui, repo, *values, **opts):
1049 1049 """show combined config settings from all hgrc files
1050 1050
1051 1051 With no arguments, print names and values of all config items.
1052 1052
1053 1053 With one argument of the form section.name, print just the value
1054 1054 of that config item.
1055 1055
1056 1056 With multiple arguments, print names and values of all config
1057 1057 items with matching section names.
1058 1058
1059 1059 With --debug, the source (filename and line number) is printed
1060 1060 for each config item.
1061 1061
1062 1062 Returns 0 on success.
1063 1063 """
1064 1064
1065 1065 for f in util.rcpath():
1066 1066 ui.debug(_('read config from: %s\n') % f)
1067 1067 untrusted = bool(opts.get('untrusted'))
1068 1068 if values:
1069 if len([v for v in values if '.' in v]) > 1:
1069 sections = [v for v in values if '.' not in v]
1070 items = [v for v in values if '.' in v]
1071 if len(items) > 1 or items and sections:
1070 1072 raise util.Abort(_('only one config item permitted'))
1071 1073 for section, name, value in ui.walkconfig(untrusted=untrusted):
1072 1074 sectname = section + '.' + name
1073 1075 if values:
1074 1076 for v in values:
1075 1077 if v == section:
1076 1078 ui.debug('%s: ' %
1077 1079 ui.configsource(section, name, untrusted))
1078 1080 ui.write('%s=%s\n' % (sectname, value))
1079 1081 elif v == sectname:
1080 1082 ui.debug('%s: ' %
1081 1083 ui.configsource(section, name, untrusted))
1082 1084 ui.write(value, '\n')
1083 1085 else:
1084 1086 ui.debug('%s: ' %
1085 1087 ui.configsource(section, name, untrusted))
1086 1088 ui.write('%s=%s\n' % (sectname, value))
1087 1089
1088 1090 def debugpushkey(ui, repopath, namespace, *keyinfo):
1089 1091 '''access the pushkey key/value protocol
1090 1092
1091 1093 With two args, list the keys in the given namespace.
1092 1094
1093 1095 With five args, set a key to new if it currently is set to old.
1094 1096 Reports success or failure.
1095 1097 '''
1096 1098
1097 1099 target = hg.repository(ui, repopath)
1098 1100 if keyinfo:
1099 1101 key, old, new = keyinfo
1100 1102 r = target.pushkey(namespace, key, old, new)
1101 1103 ui.status(str(r) + '\n')
1102 1104 return not(r)
1103 1105 else:
1104 1106 for k, v in target.listkeys(namespace).iteritems():
1105 1107 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1106 1108 v.encode('string-escape')))
1107 1109
1108 1110 def debugrevspec(ui, repo, expr):
1109 1111 '''parse and apply a revision specification'''
1110 1112 if ui.verbose:
1111 1113 tree = revset.parse(expr)
1112 1114 ui.note(tree, "\n")
1113 1115 func = revset.match(expr)
1114 1116 for c in func(repo, range(len(repo))):
1115 1117 ui.write("%s\n" % c)
1116 1118
1117 1119 def debugsetparents(ui, repo, rev1, rev2=None):
1118 1120 """manually set the parents of the current working directory
1119 1121
1120 1122 This is useful for writing repository conversion tools, but should
1121 1123 be used with care.
1122 1124
1123 1125 Returns 0 on success.
1124 1126 """
1125 1127
1126 1128 if not rev2:
1127 1129 rev2 = hex(nullid)
1128 1130
1129 1131 wlock = repo.wlock()
1130 1132 try:
1131 1133 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1132 1134 finally:
1133 1135 wlock.release()
1134 1136
1135 1137 def debugstate(ui, repo, nodates=None):
1136 1138 """show the contents of the current dirstate"""
1137 1139 timestr = ""
1138 1140 showdate = not nodates
1139 1141 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1140 1142 if showdate:
1141 1143 if ent[3] == -1:
1142 1144 # Pad or slice to locale representation
1143 1145 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1144 1146 time.localtime(0)))
1145 1147 timestr = 'unset'
1146 1148 timestr = (timestr[:locale_len] +
1147 1149 ' ' * (locale_len - len(timestr)))
1148 1150 else:
1149 1151 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1150 1152 time.localtime(ent[3]))
1151 1153 if ent[1] & 020000:
1152 1154 mode = 'lnk'
1153 1155 else:
1154 1156 mode = '%3o' % (ent[1] & 0777)
1155 1157 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1156 1158 for f in repo.dirstate.copies():
1157 1159 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1158 1160
1159 1161 def debugsub(ui, repo, rev=None):
1160 1162 if rev == '':
1161 1163 rev = None
1162 1164 for k, v in sorted(repo[rev].substate.items()):
1163 1165 ui.write('path %s\n' % k)
1164 1166 ui.write(' source %s\n' % v[0])
1165 1167 ui.write(' revision %s\n' % v[1])
1166 1168
1167 1169 def debugdag(ui, repo, file_=None, *revs, **opts):
1168 1170 """format the changelog or an index DAG as a concise textual description
1169 1171
1170 1172 If you pass a revlog index, the revlog's DAG is emitted. If you list
1171 1173 revision numbers, they get labelled in the output as rN.
1172 1174
1173 1175 Otherwise, the changelog DAG of the current repo is emitted.
1174 1176 """
1175 1177 spaces = opts.get('spaces')
1176 1178 dots = opts.get('dots')
1177 1179 if file_:
1178 1180 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1179 1181 revs = set((int(r) for r in revs))
1180 1182 def events():
1181 1183 for r in rlog:
1182 1184 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1183 1185 if r in revs:
1184 1186 yield 'l', (r, "r%i" % r)
1185 1187 elif repo:
1186 1188 cl = repo.changelog
1187 1189 tags = opts.get('tags')
1188 1190 branches = opts.get('branches')
1189 1191 if tags:
1190 1192 labels = {}
1191 1193 for l, n in repo.tags().items():
1192 1194 labels.setdefault(cl.rev(n), []).append(l)
1193 1195 def events():
1194 1196 b = "default"
1195 1197 for r in cl:
1196 1198 if branches:
1197 1199 newb = cl.read(cl.node(r))[5]['branch']
1198 1200 if newb != b:
1199 1201 yield 'a', newb
1200 1202 b = newb
1201 1203 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1202 1204 if tags:
1203 1205 ls = labels.get(r)
1204 1206 if ls:
1205 1207 for l in ls:
1206 1208 yield 'l', (r, l)
1207 1209 else:
1208 1210 raise util.Abort(_('need repo for changelog dag'))
1209 1211
1210 1212 for line in dagparser.dagtextlines(events(),
1211 1213 addspaces=spaces,
1212 1214 wraplabels=True,
1213 1215 wrapannotations=True,
1214 1216 wrapnonlinear=dots,
1215 1217 usedots=dots,
1216 1218 maxlinewidth=70):
1217 1219 ui.write(line)
1218 1220 ui.write("\n")
1219 1221
1220 1222 def debugdata(ui, repo, file_, rev):
1221 1223 """dump the contents of a data file revision"""
1222 1224 r = None
1223 1225 if repo:
1224 1226 filelog = repo.file(file_)
1225 1227 if len(filelog):
1226 1228 r = filelog
1227 1229 if not r:
1228 1230 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1229 1231 try:
1230 1232 ui.write(r.revision(r.lookup(rev)))
1231 1233 except KeyError:
1232 1234 raise util.Abort(_('invalid revision identifier %s') % rev)
1233 1235
1234 1236 def debugdate(ui, date, range=None, **opts):
1235 1237 """parse and display a date"""
1236 1238 if opts["extended"]:
1237 1239 d = util.parsedate(date, util.extendeddateformats)
1238 1240 else:
1239 1241 d = util.parsedate(date)
1240 1242 ui.write("internal: %s %s\n" % d)
1241 1243 ui.write("standard: %s\n" % util.datestr(d))
1242 1244 if range:
1243 1245 m = util.matchdate(range)
1244 1246 ui.write("match: %s\n" % m(d[0]))
1245 1247
1246 1248 def debugindex(ui, repo, file_):
1247 1249 """dump the contents of an index file"""
1248 1250 r = None
1249 1251 if repo:
1250 1252 filelog = repo.file(file_)
1251 1253 if len(filelog):
1252 1254 r = filelog
1253 1255 if not r:
1254 1256 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1255 1257 ui.write(" rev offset length base linkrev"
1256 1258 " nodeid p1 p2\n")
1257 1259 for i in r:
1258 1260 node = r.node(i)
1259 1261 try:
1260 1262 pp = r.parents(node)
1261 1263 except:
1262 1264 pp = [nullid, nullid]
1263 1265 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1264 1266 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1265 1267 short(node), short(pp[0]), short(pp[1])))
1266 1268
1267 1269 def debugindexdot(ui, repo, file_):
1268 1270 """dump an index DAG as a graphviz dot file"""
1269 1271 r = None
1270 1272 if repo:
1271 1273 filelog = repo.file(file_)
1272 1274 if len(filelog):
1273 1275 r = filelog
1274 1276 if not r:
1275 1277 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1276 1278 ui.write("digraph G {\n")
1277 1279 for i in r:
1278 1280 node = r.node(i)
1279 1281 pp = r.parents(node)
1280 1282 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1281 1283 if pp[1] != nullid:
1282 1284 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1283 1285 ui.write("}\n")
1284 1286
1285 1287 def debuginstall(ui):
1286 1288 '''test Mercurial installation
1287 1289
1288 1290 Returns 0 on success.
1289 1291 '''
1290 1292
1291 1293 def writetemp(contents):
1292 1294 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1293 1295 f = os.fdopen(fd, "wb")
1294 1296 f.write(contents)
1295 1297 f.close()
1296 1298 return name
1297 1299
1298 1300 problems = 0
1299 1301
1300 1302 # encoding
1301 1303 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1302 1304 try:
1303 1305 encoding.fromlocal("test")
1304 1306 except util.Abort, inst:
1305 1307 ui.write(" %s\n" % inst)
1306 1308 ui.write(_(" (check that your locale is properly set)\n"))
1307 1309 problems += 1
1308 1310
1309 1311 # compiled modules
1310 1312 ui.status(_("Checking installed modules (%s)...\n")
1311 1313 % os.path.dirname(__file__))
1312 1314 try:
1313 1315 import bdiff, mpatch, base85, osutil
1314 1316 except Exception, inst:
1315 1317 ui.write(" %s\n" % inst)
1316 1318 ui.write(_(" One or more extensions could not be found"))
1317 1319 ui.write(_(" (check that you compiled the extensions)\n"))
1318 1320 problems += 1
1319 1321
1320 1322 # templates
1321 1323 ui.status(_("Checking templates...\n"))
1322 1324 try:
1323 1325 import templater
1324 1326 templater.templater(templater.templatepath("map-cmdline.default"))
1325 1327 except Exception, inst:
1326 1328 ui.write(" %s\n" % inst)
1327 1329 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1328 1330 problems += 1
1329 1331
1330 1332 # patch
1331 1333 ui.status(_("Checking patch...\n"))
1332 1334 patchproblems = 0
1333 1335 a = "1\n2\n3\n4\n"
1334 1336 b = "1\n2\n3\ninsert\n4\n"
1335 1337 fa = writetemp(a)
1336 1338 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1337 1339 os.path.basename(fa))
1338 1340 fd = writetemp(d)
1339 1341
1340 1342 files = {}
1341 1343 try:
1342 1344 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1343 1345 except util.Abort, e:
1344 1346 ui.write(_(" patch call failed:\n"))
1345 1347 ui.write(" " + str(e) + "\n")
1346 1348 patchproblems += 1
1347 1349 else:
1348 1350 if list(files) != [os.path.basename(fa)]:
1349 1351 ui.write(_(" unexpected patch output!\n"))
1350 1352 patchproblems += 1
1351 1353 a = open(fa).read()
1352 1354 if a != b:
1353 1355 ui.write(_(" patch test failed!\n"))
1354 1356 patchproblems += 1
1355 1357
1356 1358 if patchproblems:
1357 1359 if ui.config('ui', 'patch'):
1358 1360 ui.write(_(" (Current patch tool may be incompatible with patch,"
1359 1361 " or misconfigured. Please check your configuration"
1360 1362 " file)\n"))
1361 1363 else:
1362 1364 ui.write(_(" Internal patcher failure, please report this error"
1363 1365 " to http://mercurial.selenic.com/bts/\n"))
1364 1366 problems += patchproblems
1365 1367
1366 1368 os.unlink(fa)
1367 1369 os.unlink(fd)
1368 1370
1369 1371 # editor
1370 1372 ui.status(_("Checking commit editor...\n"))
1371 1373 editor = ui.geteditor()
1372 1374 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1373 1375 if not cmdpath:
1374 1376 if editor == 'vi':
1375 1377 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1376 1378 ui.write(_(" (specify a commit editor in your configuration"
1377 1379 " file)\n"))
1378 1380 else:
1379 1381 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1380 1382 ui.write(_(" (specify a commit editor in your configuration"
1381 1383 " file)\n"))
1382 1384 problems += 1
1383 1385
1384 1386 # check username
1385 1387 ui.status(_("Checking username...\n"))
1386 1388 try:
1387 1389 ui.username()
1388 1390 except util.Abort, e:
1389 1391 ui.write(" %s\n" % e)
1390 1392 ui.write(_(" (specify a username in your configuration file)\n"))
1391 1393 problems += 1
1392 1394
1393 1395 if not problems:
1394 1396 ui.status(_("No problems detected\n"))
1395 1397 else:
1396 1398 ui.write(_("%s problems detected,"
1397 1399 " please check your install!\n") % problems)
1398 1400
1399 1401 return problems
1400 1402
1401 1403 def debugrename(ui, repo, file1, *pats, **opts):
1402 1404 """dump rename information"""
1403 1405
1404 1406 ctx = repo[opts.get('rev')]
1405 1407 m = cmdutil.match(repo, (file1,) + pats, opts)
1406 1408 for abs in ctx.walk(m):
1407 1409 fctx = ctx[abs]
1408 1410 o = fctx.filelog().renamed(fctx.filenode())
1409 1411 rel = m.rel(abs)
1410 1412 if o:
1411 1413 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1412 1414 else:
1413 1415 ui.write(_("%s not renamed\n") % rel)
1414 1416
1415 1417 def debugwalk(ui, repo, *pats, **opts):
1416 1418 """show how files match on given patterns"""
1417 1419 m = cmdutil.match(repo, pats, opts)
1418 1420 items = list(repo.walk(m))
1419 1421 if not items:
1420 1422 return
1421 1423 fmt = 'f %%-%ds %%-%ds %%s' % (
1422 1424 max([len(abs) for abs in items]),
1423 1425 max([len(m.rel(abs)) for abs in items]))
1424 1426 for abs in items:
1425 1427 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1426 1428 ui.write("%s\n" % line.rstrip())
1427 1429
1428 1430 def diff(ui, repo, *pats, **opts):
1429 1431 """diff repository (or selected files)
1430 1432
1431 1433 Show differences between revisions for the specified files.
1432 1434
1433 1435 Differences between files are shown using the unified diff format.
1434 1436
1435 1437 .. note::
1436 1438 diff may generate unexpected results for merges, as it will
1437 1439 default to comparing against the working directory's first
1438 1440 parent changeset if no revisions are specified.
1439 1441
1440 1442 When two revision arguments are given, then changes are shown
1441 1443 between those revisions. If only one revision is specified then
1442 1444 that revision is compared to the working directory, and, when no
1443 1445 revisions are specified, the working directory files are compared
1444 1446 to its parent.
1445 1447
1446 1448 Alternatively you can specify -c/--change with a revision to see
1447 1449 the changes in that changeset relative to its first parent.
1448 1450
1449 1451 Without the -a/--text option, diff will avoid generating diffs of
1450 1452 files it detects as binary. With -a, diff will generate a diff
1451 1453 anyway, probably with undesirable results.
1452 1454
1453 1455 Use the -g/--git option to generate diffs in the git extended diff
1454 1456 format. For more information, read :hg:`help diffs`.
1455 1457
1456 1458 Returns 0 on success.
1457 1459 """
1458 1460
1459 1461 revs = opts.get('rev')
1460 1462 change = opts.get('change')
1461 1463 stat = opts.get('stat')
1462 1464 reverse = opts.get('reverse')
1463 1465
1464 1466 if revs and change:
1465 1467 msg = _('cannot specify --rev and --change at the same time')
1466 1468 raise util.Abort(msg)
1467 1469 elif change:
1468 1470 node2 = repo.lookup(change)
1469 1471 node1 = repo[node2].parents()[0].node()
1470 1472 else:
1471 1473 node1, node2 = cmdutil.revpair(repo, revs)
1472 1474
1473 1475 if reverse:
1474 1476 node1, node2 = node2, node1
1475 1477
1476 1478 diffopts = patch.diffopts(ui, opts)
1477 1479 m = cmdutil.match(repo, pats, opts)
1478 1480 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1479 1481 listsubrepos=opts.get('subrepos'))
1480 1482
1481 1483 def export(ui, repo, *changesets, **opts):
1482 1484 """dump the header and diffs for one or more changesets
1483 1485
1484 1486 Print the changeset header and diffs for one or more revisions.
1485 1487
1486 1488 The information shown in the changeset header is: author, date,
1487 1489 branch name (if non-default), changeset hash, parent(s) and commit
1488 1490 comment.
1489 1491
1490 1492 .. note::
1491 1493 export may generate unexpected diff output for merge
1492 1494 changesets, as it will compare the merge changeset against its
1493 1495 first parent only.
1494 1496
1495 1497 Output may be to a file, in which case the name of the file is
1496 1498 given using a format string. The formatting rules are as follows:
1497 1499
1498 1500 :``%%``: literal "%" character
1499 1501 :``%H``: changeset hash (40 hexadecimal digits)
1500 1502 :``%N``: number of patches being generated
1501 1503 :``%R``: changeset revision number
1502 1504 :``%b``: basename of the exporting repository
1503 1505 :``%h``: short-form changeset hash (12 hexadecimal digits)
1504 1506 :``%n``: zero-padded sequence number, starting at 1
1505 1507 :``%r``: zero-padded changeset revision number
1506 1508
1507 1509 Without the -a/--text option, export will avoid generating diffs
1508 1510 of files it detects as binary. With -a, export will generate a
1509 1511 diff anyway, probably with undesirable results.
1510 1512
1511 1513 Use the -g/--git option to generate diffs in the git extended diff
1512 1514 format. See :hg:`help diffs` for more information.
1513 1515
1514 1516 With the --switch-parent option, the diff will be against the
1515 1517 second parent. It can be useful to review a merge.
1516 1518
1517 1519 Returns 0 on success.
1518 1520 """
1519 1521 changesets += tuple(opts.get('rev', []))
1520 1522 if not changesets:
1521 1523 raise util.Abort(_("export requires at least one changeset"))
1522 1524 revs = cmdutil.revrange(repo, changesets)
1523 1525 if len(revs) > 1:
1524 1526 ui.note(_('exporting patches:\n'))
1525 1527 else:
1526 1528 ui.note(_('exporting patch:\n'))
1527 1529 cmdutil.export(repo, revs, template=opts.get('output'),
1528 1530 switch_parent=opts.get('switch_parent'),
1529 1531 opts=patch.diffopts(ui, opts))
1530 1532
1531 1533 def forget(ui, repo, *pats, **opts):
1532 1534 """forget the specified files on the next commit
1533 1535
1534 1536 Mark the specified files so they will no longer be tracked
1535 1537 after the next commit.
1536 1538
1537 1539 This only removes files from the current branch, not from the
1538 1540 entire project history, and it does not delete them from the
1539 1541 working directory.
1540 1542
1541 1543 To undo a forget before the next commit, see :hg:`add`.
1542 1544
1543 1545 Returns 0 on success.
1544 1546 """
1545 1547
1546 1548 if not pats:
1547 1549 raise util.Abort(_('no files specified'))
1548 1550
1549 1551 m = cmdutil.match(repo, pats, opts)
1550 1552 s = repo.status(match=m, clean=True)
1551 1553 forget = sorted(s[0] + s[1] + s[3] + s[6])
1552 1554 errs = 0
1553 1555
1554 1556 for f in m.files():
1555 1557 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1556 1558 ui.warn(_('not removing %s: file is already untracked\n')
1557 1559 % m.rel(f))
1558 1560 errs = 1
1559 1561
1560 1562 for f in forget:
1561 1563 if ui.verbose or not m.exact(f):
1562 1564 ui.status(_('removing %s\n') % m.rel(f))
1563 1565
1564 1566 repo[None].remove(forget, unlink=False)
1565 1567 return errs
1566 1568
1567 1569 def grep(ui, repo, pattern, *pats, **opts):
1568 1570 """search for a pattern in specified files and revisions
1569 1571
1570 1572 Search revisions of files for a regular expression.
1571 1573
1572 1574 This command behaves differently than Unix grep. It only accepts
1573 1575 Python/Perl regexps. It searches repository history, not the
1574 1576 working directory. It always prints the revision number in which a
1575 1577 match appears.
1576 1578
1577 1579 By default, grep only prints output for the first revision of a
1578 1580 file in which it finds a match. To get it to print every revision
1579 1581 that contains a change in match status ("-" for a match that
1580 1582 becomes a non-match, or "+" for a non-match that becomes a match),
1581 1583 use the --all flag.
1582 1584
1583 1585 Returns 0 if a match is found, 1 otherwise.
1584 1586 """
1585 1587 reflags = 0
1586 1588 if opts.get('ignore_case'):
1587 1589 reflags |= re.I
1588 1590 try:
1589 1591 regexp = re.compile(pattern, reflags)
1590 1592 except re.error, inst:
1591 1593 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1592 1594 return 1
1593 1595 sep, eol = ':', '\n'
1594 1596 if opts.get('print0'):
1595 1597 sep = eol = '\0'
1596 1598
1597 1599 getfile = util.lrucachefunc(repo.file)
1598 1600
1599 1601 def matchlines(body):
1600 1602 begin = 0
1601 1603 linenum = 0
1602 1604 while True:
1603 1605 match = regexp.search(body, begin)
1604 1606 if not match:
1605 1607 break
1606 1608 mstart, mend = match.span()
1607 1609 linenum += body.count('\n', begin, mstart) + 1
1608 1610 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1609 1611 begin = body.find('\n', mend) + 1 or len(body)
1610 1612 lend = begin - 1
1611 1613 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1612 1614
1613 1615 class linestate(object):
1614 1616 def __init__(self, line, linenum, colstart, colend):
1615 1617 self.line = line
1616 1618 self.linenum = linenum
1617 1619 self.colstart = colstart
1618 1620 self.colend = colend
1619 1621
1620 1622 def __hash__(self):
1621 1623 return hash((self.linenum, self.line))
1622 1624
1623 1625 def __eq__(self, other):
1624 1626 return self.line == other.line
1625 1627
1626 1628 matches = {}
1627 1629 copies = {}
1628 1630 def grepbody(fn, rev, body):
1629 1631 matches[rev].setdefault(fn, [])
1630 1632 m = matches[rev][fn]
1631 1633 for lnum, cstart, cend, line in matchlines(body):
1632 1634 s = linestate(line, lnum, cstart, cend)
1633 1635 m.append(s)
1634 1636
1635 1637 def difflinestates(a, b):
1636 1638 sm = difflib.SequenceMatcher(None, a, b)
1637 1639 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1638 1640 if tag == 'insert':
1639 1641 for i in xrange(blo, bhi):
1640 1642 yield ('+', b[i])
1641 1643 elif tag == 'delete':
1642 1644 for i in xrange(alo, ahi):
1643 1645 yield ('-', a[i])
1644 1646 elif tag == 'replace':
1645 1647 for i in xrange(alo, ahi):
1646 1648 yield ('-', a[i])
1647 1649 for i in xrange(blo, bhi):
1648 1650 yield ('+', b[i])
1649 1651
1650 1652 def display(fn, ctx, pstates, states):
1651 1653 rev = ctx.rev()
1652 1654 datefunc = ui.quiet and util.shortdate or util.datestr
1653 1655 found = False
1654 1656 filerevmatches = {}
1655 1657 if opts.get('all'):
1656 1658 iter = difflinestates(pstates, states)
1657 1659 else:
1658 1660 iter = [('', l) for l in states]
1659 1661 for change, l in iter:
1660 1662 cols = [fn, str(rev)]
1661 1663 before, match, after = None, None, None
1662 1664 if opts.get('line_number'):
1663 1665 cols.append(str(l.linenum))
1664 1666 if opts.get('all'):
1665 1667 cols.append(change)
1666 1668 if opts.get('user'):
1667 1669 cols.append(ui.shortuser(ctx.user()))
1668 1670 if opts.get('date'):
1669 1671 cols.append(datefunc(ctx.date()))
1670 1672 if opts.get('files_with_matches'):
1671 1673 c = (fn, rev)
1672 1674 if c in filerevmatches:
1673 1675 continue
1674 1676 filerevmatches[c] = 1
1675 1677 else:
1676 1678 before = l.line[:l.colstart]
1677 1679 match = l.line[l.colstart:l.colend]
1678 1680 after = l.line[l.colend:]
1679 1681 ui.write(sep.join(cols))
1680 1682 if before is not None:
1681 1683 ui.write(sep + before)
1682 1684 ui.write(match, label='grep.match')
1683 1685 ui.write(after)
1684 1686 ui.write(eol)
1685 1687 found = True
1686 1688 return found
1687 1689
1688 1690 skip = {}
1689 1691 revfiles = {}
1690 1692 matchfn = cmdutil.match(repo, pats, opts)
1691 1693 found = False
1692 1694 follow = opts.get('follow')
1693 1695
1694 1696 def prep(ctx, fns):
1695 1697 rev = ctx.rev()
1696 1698 pctx = ctx.parents()[0]
1697 1699 parent = pctx.rev()
1698 1700 matches.setdefault(rev, {})
1699 1701 matches.setdefault(parent, {})
1700 1702 files = revfiles.setdefault(rev, [])
1701 1703 for fn in fns:
1702 1704 flog = getfile(fn)
1703 1705 try:
1704 1706 fnode = ctx.filenode(fn)
1705 1707 except error.LookupError:
1706 1708 continue
1707 1709
1708 1710 copied = flog.renamed(fnode)
1709 1711 copy = follow and copied and copied[0]
1710 1712 if copy:
1711 1713 copies.setdefault(rev, {})[fn] = copy
1712 1714 if fn in skip:
1713 1715 if copy:
1714 1716 skip[copy] = True
1715 1717 continue
1716 1718 files.append(fn)
1717 1719
1718 1720 if fn not in matches[rev]:
1719 1721 grepbody(fn, rev, flog.read(fnode))
1720 1722
1721 1723 pfn = copy or fn
1722 1724 if pfn not in matches[parent]:
1723 1725 try:
1724 1726 fnode = pctx.filenode(pfn)
1725 1727 grepbody(pfn, parent, flog.read(fnode))
1726 1728 except error.LookupError:
1727 1729 pass
1728 1730
1729 1731 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1730 1732 rev = ctx.rev()
1731 1733 parent = ctx.parents()[0].rev()
1732 1734 for fn in sorted(revfiles.get(rev, [])):
1733 1735 states = matches[rev][fn]
1734 1736 copy = copies.get(rev, {}).get(fn)
1735 1737 if fn in skip:
1736 1738 if copy:
1737 1739 skip[copy] = True
1738 1740 continue
1739 1741 pstates = matches.get(parent, {}).get(copy or fn, [])
1740 1742 if pstates or states:
1741 1743 r = display(fn, ctx, pstates, states)
1742 1744 found = found or r
1743 1745 if r and not opts.get('all'):
1744 1746 skip[fn] = True
1745 1747 if copy:
1746 1748 skip[copy] = True
1747 1749 del matches[rev]
1748 1750 del revfiles[rev]
1749 1751
1750 1752 return not found
1751 1753
1752 1754 def heads(ui, repo, *branchrevs, **opts):
1753 1755 """show current repository heads or show branch heads
1754 1756
1755 1757 With no arguments, show all repository branch heads.
1756 1758
1757 1759 Repository "heads" are changesets with no child changesets. They are
1758 1760 where development generally takes place and are the usual targets
1759 1761 for update and merge operations. Branch heads are changesets that have
1760 1762 no child changeset on the same branch.
1761 1763
1762 1764 If one or more REVs are given, only branch heads on the branches
1763 1765 associated with the specified changesets are shown.
1764 1766
1765 1767 If -c/--closed is specified, also show branch heads marked closed
1766 1768 (see :hg:`commit --close-branch`).
1767 1769
1768 1770 If STARTREV is specified, only those heads that are descendants of
1769 1771 STARTREV will be displayed.
1770 1772
1771 1773 If -t/--topo is specified, named branch mechanics will be ignored and only
1772 1774 changesets without children will be shown.
1773 1775
1774 1776 Returns 0 if matching heads are found, 1 if not.
1775 1777 """
1776 1778
1777 1779 if opts.get('rev'):
1778 1780 start = repo.lookup(opts['rev'])
1779 1781 else:
1780 1782 start = None
1781 1783
1782 1784 if opts.get('topo'):
1783 1785 heads = [repo[h] for h in repo.heads(start)]
1784 1786 else:
1785 1787 heads = []
1786 1788 for b, ls in repo.branchmap().iteritems():
1787 1789 if start is None:
1788 1790 heads += [repo[h] for h in ls]
1789 1791 continue
1790 1792 startrev = repo.changelog.rev(start)
1791 1793 descendants = set(repo.changelog.descendants(startrev))
1792 1794 descendants.add(startrev)
1793 1795 rev = repo.changelog.rev
1794 1796 heads += [repo[h] for h in ls if rev(h) in descendants]
1795 1797
1796 1798 if branchrevs:
1797 1799 decode, encode = encoding.fromlocal, encoding.tolocal
1798 1800 branches = set(repo[decode(br)].branch() for br in branchrevs)
1799 1801 heads = [h for h in heads if h.branch() in branches]
1800 1802
1801 1803 if not opts.get('closed'):
1802 1804 heads = [h for h in heads if not h.extra().get('close')]
1803 1805
1804 1806 if opts.get('active') and branchrevs:
1805 1807 dagheads = repo.heads(start)
1806 1808 heads = [h for h in heads if h.node() in dagheads]
1807 1809
1808 1810 if branchrevs:
1809 1811 haveheads = set(h.branch() for h in heads)
1810 1812 if branches - haveheads:
1811 1813 headless = ', '.join(encode(b) for b in branches - haveheads)
1812 1814 msg = _('no open branch heads found on branches %s')
1813 1815 if opts.get('rev'):
1814 1816 msg += _(' (started at %s)' % opts['rev'])
1815 1817 ui.warn((msg + '\n') % headless)
1816 1818
1817 1819 if not heads:
1818 1820 return 1
1819 1821
1820 1822 heads = sorted(heads, key=lambda x: -x.rev())
1821 1823 displayer = cmdutil.show_changeset(ui, repo, opts)
1822 1824 for ctx in heads:
1823 1825 displayer.show(ctx)
1824 1826 displayer.close()
1825 1827
1826 1828 def help_(ui, name=None, with_version=False, unknowncmd=False):
1827 1829 """show help for a given topic or a help overview
1828 1830
1829 1831 With no arguments, print a list of commands with short help messages.
1830 1832
1831 1833 Given a topic, extension, or command name, print help for that
1832 1834 topic.
1833 1835
1834 1836 Returns 0 if successful.
1835 1837 """
1836 1838 option_lists = []
1837 1839 textwidth = ui.termwidth() - 2
1838 1840
1839 1841 def addglobalopts(aliases):
1840 1842 if ui.verbose:
1841 1843 option_lists.append((_("global options:"), globalopts))
1842 1844 if name == 'shortlist':
1843 1845 option_lists.append((_('use "hg help" for the full list '
1844 1846 'of commands'), ()))
1845 1847 else:
1846 1848 if name == 'shortlist':
1847 1849 msg = _('use "hg help" for the full list of commands '
1848 1850 'or "hg -v" for details')
1849 1851 elif aliases:
1850 1852 msg = _('use "hg -v help%s" to show aliases and '
1851 1853 'global options') % (name and " " + name or "")
1852 1854 else:
1853 1855 msg = _('use "hg -v help %s" to show global options') % name
1854 1856 option_lists.append((msg, ()))
1855 1857
1856 1858 def helpcmd(name):
1857 1859 if with_version:
1858 1860 version_(ui)
1859 1861 ui.write('\n')
1860 1862
1861 1863 try:
1862 1864 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1863 1865 except error.AmbiguousCommand, inst:
1864 1866 # py3k fix: except vars can't be used outside the scope of the
1865 1867 # except block, nor can be used inside a lambda. python issue4617
1866 1868 prefix = inst.args[0]
1867 1869 select = lambda c: c.lstrip('^').startswith(prefix)
1868 1870 helplist(_('list of commands:\n\n'), select)
1869 1871 return
1870 1872
1871 1873 # check if it's an invalid alias and display its error if it is
1872 1874 if getattr(entry[0], 'badalias', False):
1873 1875 if not unknowncmd:
1874 1876 entry[0](ui)
1875 1877 return
1876 1878
1877 1879 # synopsis
1878 1880 if len(entry) > 2:
1879 1881 if entry[2].startswith('hg'):
1880 1882 ui.write("%s\n" % entry[2])
1881 1883 else:
1882 1884 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1883 1885 else:
1884 1886 ui.write('hg %s\n' % aliases[0])
1885 1887
1886 1888 # aliases
1887 1889 if not ui.quiet and len(aliases) > 1:
1888 1890 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1889 1891
1890 1892 # description
1891 1893 doc = gettext(entry[0].__doc__)
1892 1894 if not doc:
1893 1895 doc = _("(no help text available)")
1894 1896 if hasattr(entry[0], 'definition'): # aliased command
1895 1897 if entry[0].definition.startswith('!'): # shell alias
1896 1898 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1897 1899 else:
1898 1900 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1899 1901 if ui.quiet:
1900 1902 doc = doc.splitlines()[0]
1901 1903 keep = ui.verbose and ['verbose'] or []
1902 1904 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1903 1905 ui.write("\n%s\n" % formatted)
1904 1906 if pruned:
1905 1907 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1906 1908
1907 1909 if not ui.quiet:
1908 1910 # options
1909 1911 if entry[1]:
1910 1912 option_lists.append((_("options:\n"), entry[1]))
1911 1913
1912 1914 addglobalopts(False)
1913 1915
1914 1916 def helplist(header, select=None):
1915 1917 h = {}
1916 1918 cmds = {}
1917 1919 for c, e in table.iteritems():
1918 1920 f = c.split("|", 1)[0]
1919 1921 if select and not select(f):
1920 1922 continue
1921 1923 if (not select and name != 'shortlist' and
1922 1924 e[0].__module__ != __name__):
1923 1925 continue
1924 1926 if name == "shortlist" and not f.startswith("^"):
1925 1927 continue
1926 1928 f = f.lstrip("^")
1927 1929 if not ui.debugflag and f.startswith("debug"):
1928 1930 continue
1929 1931 doc = e[0].__doc__
1930 1932 if doc and 'DEPRECATED' in doc and not ui.verbose:
1931 1933 continue
1932 1934 doc = gettext(doc)
1933 1935 if not doc:
1934 1936 doc = _("(no help text available)")
1935 1937 h[f] = doc.splitlines()[0].rstrip()
1936 1938 cmds[f] = c.lstrip("^")
1937 1939
1938 1940 if not h:
1939 1941 ui.status(_('no commands defined\n'))
1940 1942 return
1941 1943
1942 1944 ui.status(header)
1943 1945 fns = sorted(h)
1944 1946 m = max(map(len, fns))
1945 1947 for f in fns:
1946 1948 if ui.verbose:
1947 1949 commands = cmds[f].replace("|",", ")
1948 1950 ui.write(" %s:\n %s\n"%(commands, h[f]))
1949 1951 else:
1950 1952 ui.write('%s\n' % (util.wrap(h[f],
1951 1953 initindent=' %-*s ' % (m, f),
1952 1954 hangindent=' ' * (m + 4))))
1953 1955
1954 1956 if not ui.quiet:
1955 1957 addglobalopts(True)
1956 1958
1957 1959 def helptopic(name):
1958 1960 for names, header, doc in help.helptable:
1959 1961 if name in names:
1960 1962 break
1961 1963 else:
1962 1964 raise error.UnknownCommand(name)
1963 1965
1964 1966 # description
1965 1967 if not doc:
1966 1968 doc = _("(no help text available)")
1967 1969 if hasattr(doc, '__call__'):
1968 1970 doc = doc()
1969 1971
1970 1972 ui.write("%s\n\n" % header)
1971 1973 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1972 1974
1973 1975 def helpext(name):
1974 1976 try:
1975 1977 mod = extensions.find(name)
1976 1978 doc = gettext(mod.__doc__) or _('no help text available')
1977 1979 except KeyError:
1978 1980 mod = None
1979 1981 doc = extensions.disabledext(name)
1980 1982 if not doc:
1981 1983 raise error.UnknownCommand(name)
1982 1984
1983 1985 if '\n' not in doc:
1984 1986 head, tail = doc, ""
1985 1987 else:
1986 1988 head, tail = doc.split('\n', 1)
1987 1989 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1988 1990 if tail:
1989 1991 ui.write(minirst.format(tail, textwidth))
1990 1992 ui.status('\n\n')
1991 1993
1992 1994 if mod:
1993 1995 try:
1994 1996 ct = mod.cmdtable
1995 1997 except AttributeError:
1996 1998 ct = {}
1997 1999 modcmds = set([c.split('|', 1)[0] for c in ct])
1998 2000 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1999 2001 else:
2000 2002 ui.write(_('use "hg help extensions" for information on enabling '
2001 2003 'extensions\n'))
2002 2004
2003 2005 def helpextcmd(name):
2004 2006 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2005 2007 doc = gettext(mod.__doc__).splitlines()[0]
2006 2008
2007 2009 msg = help.listexts(_("'%s' is provided by the following "
2008 2010 "extension:") % cmd, {ext: doc}, len(ext),
2009 2011 indent=4)
2010 2012 ui.write(minirst.format(msg, textwidth))
2011 2013 ui.write('\n\n')
2012 2014 ui.write(_('use "hg help extensions" for information on enabling '
2013 2015 'extensions\n'))
2014 2016
2015 2017 if name and name != 'shortlist':
2016 2018 i = None
2017 2019 if unknowncmd:
2018 2020 queries = (helpextcmd,)
2019 2021 else:
2020 2022 queries = (helptopic, helpcmd, helpext, helpextcmd)
2021 2023 for f in queries:
2022 2024 try:
2023 2025 f(name)
2024 2026 i = None
2025 2027 break
2026 2028 except error.UnknownCommand, inst:
2027 2029 i = inst
2028 2030 if i:
2029 2031 raise i
2030 2032
2031 2033 else:
2032 2034 # program name
2033 2035 if ui.verbose or with_version:
2034 2036 version_(ui)
2035 2037 else:
2036 2038 ui.status(_("Mercurial Distributed SCM\n"))
2037 2039 ui.status('\n')
2038 2040
2039 2041 # list of commands
2040 2042 if name == "shortlist":
2041 2043 header = _('basic commands:\n\n')
2042 2044 else:
2043 2045 header = _('list of commands:\n\n')
2044 2046
2045 2047 helplist(header)
2046 2048 if name != 'shortlist':
2047 2049 exts, maxlength = extensions.enabled()
2048 2050 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2049 2051 if text:
2050 2052 ui.write("\n%s\n" % minirst.format(text, textwidth))
2051 2053
2052 2054 # list all option lists
2053 2055 opt_output = []
2054 2056 multioccur = False
2055 2057 for title, options in option_lists:
2056 2058 opt_output.append(("\n%s" % title, None))
2057 2059 for option in options:
2058 2060 if len(option) == 5:
2059 2061 shortopt, longopt, default, desc, optlabel = option
2060 2062 else:
2061 2063 shortopt, longopt, default, desc = option
2062 2064 optlabel = _("VALUE") # default label
2063 2065
2064 2066 if _("DEPRECATED") in desc and not ui.verbose:
2065 2067 continue
2066 2068 if isinstance(default, list):
2067 2069 numqualifier = " %s [+]" % optlabel
2068 2070 multioccur = True
2069 2071 elif (default is not None) and not isinstance(default, bool):
2070 2072 numqualifier = " %s" % optlabel
2071 2073 else:
2072 2074 numqualifier = ""
2073 2075 opt_output.append(("%2s%s" %
2074 2076 (shortopt and "-%s" % shortopt,
2075 2077 longopt and " --%s%s" %
2076 2078 (longopt, numqualifier)),
2077 2079 "%s%s" % (desc,
2078 2080 default
2079 2081 and _(" (default: %s)") % default
2080 2082 or "")))
2081 2083 if multioccur:
2082 2084 msg = _("\n[+] marked option can be specified multiple times")
2083 2085 if ui.verbose and name != 'shortlist':
2084 2086 opt_output.append((msg, None))
2085 2087 else:
2086 2088 opt_output.insert(-1, (msg, None))
2087 2089
2088 2090 if not name:
2089 2091 ui.write(_("\nadditional help topics:\n\n"))
2090 2092 topics = []
2091 2093 for names, header, doc in help.helptable:
2092 2094 topics.append((sorted(names, key=len, reverse=True)[0], header))
2093 2095 topics_len = max([len(s[0]) for s in topics])
2094 2096 for t, desc in topics:
2095 2097 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2096 2098
2097 2099 if opt_output:
2098 2100 colwidth = encoding.colwidth
2099 2101 # normalize: (opt or message, desc or None, width of opt)
2100 2102 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2101 2103 for opt, desc in opt_output]
2102 2104 hanging = max([e[2] for e in entries])
2103 2105 for opt, desc, width in entries:
2104 2106 if desc:
2105 2107 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2106 2108 hangindent = ' ' * (hanging + 3)
2107 2109 ui.write('%s\n' % (util.wrap(desc,
2108 2110 initindent=initindent,
2109 2111 hangindent=hangindent)))
2110 2112 else:
2111 2113 ui.write("%s\n" % opt)
2112 2114
2113 2115 def identify(ui, repo, source=None,
2114 2116 rev=None, num=None, id=None, branch=None, tags=None):
2115 2117 """identify the working copy or specified revision
2116 2118
2117 2119 With no revision, print a summary of the current state of the
2118 2120 repository.
2119 2121
2120 2122 Specifying a path to a repository root or Mercurial bundle will
2121 2123 cause lookup to operate on that repository/bundle.
2122 2124
2123 2125 This summary identifies the repository state using one or two
2124 2126 parent hash identifiers, followed by a "+" if there are
2125 2127 uncommitted changes in the working directory, a list of tags for
2126 2128 this revision and a branch name for non-default branches.
2127 2129
2128 2130 Returns 0 if successful.
2129 2131 """
2130 2132
2131 2133 if not repo and not source:
2132 2134 raise util.Abort(_("there is no Mercurial repository here "
2133 2135 "(.hg not found)"))
2134 2136
2135 2137 hexfunc = ui.debugflag and hex or short
2136 2138 default = not (num or id or branch or tags)
2137 2139 output = []
2138 2140
2139 2141 revs = []
2140 2142 if source:
2141 2143 source, branches = hg.parseurl(ui.expandpath(source))
2142 2144 repo = hg.repository(ui, source)
2143 2145 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2144 2146
2145 2147 if not repo.local():
2146 2148 if not rev and revs:
2147 2149 rev = revs[0]
2148 2150 if not rev:
2149 2151 rev = "tip"
2150 2152 if num or branch or tags:
2151 2153 raise util.Abort(
2152 2154 "can't query remote revision number, branch, or tags")
2153 2155 output = [hexfunc(repo.lookup(rev))]
2154 2156 elif not rev:
2155 2157 ctx = repo[None]
2156 2158 parents = ctx.parents()
2157 2159 changed = False
2158 2160 if default or id or num:
2159 2161 changed = util.any(repo.status())
2160 2162 if default or id:
2161 2163 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2162 2164 (changed) and "+" or "")]
2163 2165 if num:
2164 2166 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2165 2167 (changed) and "+" or ""))
2166 2168 else:
2167 2169 ctx = repo[rev]
2168 2170 if default or id:
2169 2171 output = [hexfunc(ctx.node())]
2170 2172 if num:
2171 2173 output.append(str(ctx.rev()))
2172 2174
2173 2175 if repo.local() and default and not ui.quiet:
2174 2176 b = encoding.tolocal(ctx.branch())
2175 2177 if b != 'default':
2176 2178 output.append("(%s)" % b)
2177 2179
2178 2180 # multiple tags for a single parent separated by '/'
2179 2181 t = "/".join(ctx.tags())
2180 2182 if t:
2181 2183 output.append(t)
2182 2184
2183 2185 if branch:
2184 2186 output.append(encoding.tolocal(ctx.branch()))
2185 2187
2186 2188 if tags:
2187 2189 output.extend(ctx.tags())
2188 2190
2189 2191 ui.write("%s\n" % ' '.join(output))
2190 2192
2191 2193 def import_(ui, repo, patch1, *patches, **opts):
2192 2194 """import an ordered set of patches
2193 2195
2194 2196 Import a list of patches and commit them individually (unless
2195 2197 --no-commit is specified).
2196 2198
2197 2199 If there are outstanding changes in the working directory, import
2198 2200 will abort unless given the -f/--force flag.
2199 2201
2200 2202 You can import a patch straight from a mail message. Even patches
2201 2203 as attachments work (to use the body part, it must have type
2202 2204 text/plain or text/x-patch). From and Subject headers of email
2203 2205 message are used as default committer and commit message. All
2204 2206 text/plain body parts before first diff are added to commit
2205 2207 message.
2206 2208
2207 2209 If the imported patch was generated by :hg:`export`, user and
2208 2210 description from patch override values from message headers and
2209 2211 body. Values given on command line with -m/--message and -u/--user
2210 2212 override these.
2211 2213
2212 2214 If --exact is specified, import will set the working directory to
2213 2215 the parent of each patch before applying it, and will abort if the
2214 2216 resulting changeset has a different ID than the one recorded in
2215 2217 the patch. This may happen due to character set problems or other
2216 2218 deficiencies in the text patch format.
2217 2219
2218 2220 With -s/--similarity, hg will attempt to discover renames and
2219 2221 copies in the patch in the same way as 'addremove'.
2220 2222
2221 2223 To read a patch from standard input, use "-" as the patch name. If
2222 2224 a URL is specified, the patch will be downloaded from it.
2223 2225 See :hg:`help dates` for a list of formats valid for -d/--date.
2224 2226
2225 2227 Returns 0 on success.
2226 2228 """
2227 2229 patches = (patch1,) + patches
2228 2230
2229 2231 date = opts.get('date')
2230 2232 if date:
2231 2233 opts['date'] = util.parsedate(date)
2232 2234
2233 2235 try:
2234 2236 sim = float(opts.get('similarity') or 0)
2235 2237 except ValueError:
2236 2238 raise util.Abort(_('similarity must be a number'))
2237 2239 if sim < 0 or sim > 100:
2238 2240 raise util.Abort(_('similarity must be between 0 and 100'))
2239 2241
2240 2242 if opts.get('exact') or not opts.get('force'):
2241 2243 cmdutil.bail_if_changed(repo)
2242 2244
2243 2245 d = opts["base"]
2244 2246 strip = opts["strip"]
2245 2247 wlock = lock = None
2246 2248
2247 2249 def tryone(ui, hunk):
2248 2250 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2249 2251 patch.extract(ui, hunk)
2250 2252
2251 2253 if not tmpname:
2252 2254 return None
2253 2255 commitid = _('to working directory')
2254 2256
2255 2257 try:
2256 2258 cmdline_message = cmdutil.logmessage(opts)
2257 2259 if cmdline_message:
2258 2260 # pickup the cmdline msg
2259 2261 message = cmdline_message
2260 2262 elif message:
2261 2263 # pickup the patch msg
2262 2264 message = message.strip()
2263 2265 else:
2264 2266 # launch the editor
2265 2267 message = None
2266 2268 ui.debug('message:\n%s\n' % message)
2267 2269
2268 2270 wp = repo.parents()
2269 2271 if opts.get('exact'):
2270 2272 if not nodeid or not p1:
2271 2273 raise util.Abort(_('not a Mercurial patch'))
2272 2274 p1 = repo.lookup(p1)
2273 2275 p2 = repo.lookup(p2 or hex(nullid))
2274 2276
2275 2277 if p1 != wp[0].node():
2276 2278 hg.clean(repo, p1)
2277 2279 repo.dirstate.setparents(p1, p2)
2278 2280 elif p2:
2279 2281 try:
2280 2282 p1 = repo.lookup(p1)
2281 2283 p2 = repo.lookup(p2)
2282 2284 if p1 == wp[0].node():
2283 2285 repo.dirstate.setparents(p1, p2)
2284 2286 except error.RepoError:
2285 2287 pass
2286 2288 if opts.get('exact') or opts.get('import_branch'):
2287 2289 repo.dirstate.setbranch(branch or 'default')
2288 2290
2289 2291 files = {}
2290 2292 try:
2291 2293 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2292 2294 files=files, eolmode=None)
2293 2295 finally:
2294 2296 files = cmdutil.updatedir(ui, repo, files,
2295 2297 similarity=sim / 100.0)
2296 2298 if not opts.get('no_commit'):
2297 2299 if opts.get('exact'):
2298 2300 m = None
2299 2301 else:
2300 2302 m = cmdutil.matchfiles(repo, files or [])
2301 2303 n = repo.commit(message, opts.get('user') or user,
2302 2304 opts.get('date') or date, match=m,
2303 2305 editor=cmdutil.commiteditor)
2304 2306 if opts.get('exact'):
2305 2307 if hex(n) != nodeid:
2306 2308 repo.rollback()
2307 2309 raise util.Abort(_('patch is damaged'
2308 2310 ' or loses information'))
2309 2311 # Force a dirstate write so that the next transaction
2310 2312 # backups an up-do-date file.
2311 2313 repo.dirstate.write()
2312 2314 if n:
2313 2315 commitid = short(n)
2314 2316
2315 2317 return commitid
2316 2318 finally:
2317 2319 os.unlink(tmpname)
2318 2320
2319 2321 try:
2320 2322 wlock = repo.wlock()
2321 2323 lock = repo.lock()
2322 2324 lastcommit = None
2323 2325 for p in patches:
2324 2326 pf = os.path.join(d, p)
2325 2327
2326 2328 if pf == '-':
2327 2329 ui.status(_("applying patch from stdin\n"))
2328 2330 pf = sys.stdin
2329 2331 else:
2330 2332 ui.status(_("applying %s\n") % p)
2331 2333 pf = url.open(ui, pf)
2332 2334
2333 2335 haspatch = False
2334 2336 for hunk in patch.split(pf):
2335 2337 commitid = tryone(ui, hunk)
2336 2338 if commitid:
2337 2339 haspatch = True
2338 2340 if lastcommit:
2339 2341 ui.status(_('applied %s\n') % lastcommit)
2340 2342 lastcommit = commitid
2341 2343
2342 2344 if not haspatch:
2343 2345 raise util.Abort(_('no diffs found'))
2344 2346
2345 2347 finally:
2346 2348 release(lock, wlock)
2347 2349
2348 2350 def incoming(ui, repo, source="default", **opts):
2349 2351 """show new changesets found in source
2350 2352
2351 2353 Show new changesets found in the specified path/URL or the default
2352 2354 pull location. These are the changesets that would have been pulled
2353 2355 if a pull at the time you issued this command.
2354 2356
2355 2357 For remote repository, using --bundle avoids downloading the
2356 2358 changesets twice if the incoming is followed by a pull.
2357 2359
2358 2360 See pull for valid source format details.
2359 2361
2360 2362 Returns 0 if there are incoming changes, 1 otherwise.
2361 2363 """
2362 2364 if opts.get('bundle') and opts.get('subrepos'):
2363 2365 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2364 2366
2365 2367 ret = hg.incoming(ui, repo, source, opts)
2366 2368 return ret
2367 2369
2368 2370 def init(ui, dest=".", **opts):
2369 2371 """create a new repository in the given directory
2370 2372
2371 2373 Initialize a new repository in the given directory. If the given
2372 2374 directory does not exist, it will be created.
2373 2375
2374 2376 If no directory is given, the current directory is used.
2375 2377
2376 2378 It is possible to specify an ``ssh://`` URL as the destination.
2377 2379 See :hg:`help urls` for more information.
2378 2380
2379 2381 Returns 0 on success.
2380 2382 """
2381 2383 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2382 2384
2383 2385 def locate(ui, repo, *pats, **opts):
2384 2386 """locate files matching specific patterns
2385 2387
2386 2388 Print files under Mercurial control in the working directory whose
2387 2389 names match the given patterns.
2388 2390
2389 2391 By default, this command searches all directories in the working
2390 2392 directory. To search just the current directory and its
2391 2393 subdirectories, use "--include .".
2392 2394
2393 2395 If no patterns are given to match, this command prints the names
2394 2396 of all files under Mercurial control in the working directory.
2395 2397
2396 2398 If you want to feed the output of this command into the "xargs"
2397 2399 command, use the -0 option to both this command and "xargs". This
2398 2400 will avoid the problem of "xargs" treating single filenames that
2399 2401 contain whitespace as multiple filenames.
2400 2402
2401 2403 Returns 0 if a match is found, 1 otherwise.
2402 2404 """
2403 2405 end = opts.get('print0') and '\0' or '\n'
2404 2406 rev = opts.get('rev') or None
2405 2407
2406 2408 ret = 1
2407 2409 m = cmdutil.match(repo, pats, opts, default='relglob')
2408 2410 m.bad = lambda x, y: False
2409 2411 for abs in repo[rev].walk(m):
2410 2412 if not rev and abs not in repo.dirstate:
2411 2413 continue
2412 2414 if opts.get('fullpath'):
2413 2415 ui.write(repo.wjoin(abs), end)
2414 2416 else:
2415 2417 ui.write(((pats and m.rel(abs)) or abs), end)
2416 2418 ret = 0
2417 2419
2418 2420 return ret
2419 2421
2420 2422 def log(ui, repo, *pats, **opts):
2421 2423 """show revision history of entire repository or files
2422 2424
2423 2425 Print the revision history of the specified files or the entire
2424 2426 project.
2425 2427
2426 2428 File history is shown without following rename or copy history of
2427 2429 files. Use -f/--follow with a filename to follow history across
2428 2430 renames and copies. --follow without a filename will only show
2429 2431 ancestors or descendants of the starting revision. --follow-first
2430 2432 only follows the first parent of merge revisions.
2431 2433
2432 2434 If no revision range is specified, the default is tip:0 unless
2433 2435 --follow is set, in which case the working directory parent is
2434 2436 used as the starting revision. You can specify a revision set for
2435 2437 log, see :hg:`help revsets` for more information.
2436 2438
2437 2439 See :hg:`help dates` for a list of formats valid for -d/--date.
2438 2440
2439 2441 By default this command prints revision number and changeset id,
2440 2442 tags, non-trivial parents, user, date and time, and a summary for
2441 2443 each commit. When the -v/--verbose switch is used, the list of
2442 2444 changed files and full commit message are shown.
2443 2445
2444 2446 .. note::
2445 2447 log -p/--patch may generate unexpected diff output for merge
2446 2448 changesets, as it will only compare the merge changeset against
2447 2449 its first parent. Also, only files different from BOTH parents
2448 2450 will appear in files:.
2449 2451
2450 2452 Returns 0 on success.
2451 2453 """
2452 2454
2453 2455 matchfn = cmdutil.match(repo, pats, opts)
2454 2456 limit = cmdutil.loglimit(opts)
2455 2457 count = 0
2456 2458
2457 2459 endrev = None
2458 2460 if opts.get('copies') and opts.get('rev'):
2459 2461 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2460 2462
2461 2463 df = False
2462 2464 if opts["date"]:
2463 2465 df = util.matchdate(opts["date"])
2464 2466
2465 2467 branches = opts.get('branch', []) + opts.get('only_branch', [])
2466 2468 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2467 2469
2468 2470 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2469 2471 def prep(ctx, fns):
2470 2472 rev = ctx.rev()
2471 2473 parents = [p for p in repo.changelog.parentrevs(rev)
2472 2474 if p != nullrev]
2473 2475 if opts.get('no_merges') and len(parents) == 2:
2474 2476 return
2475 2477 if opts.get('only_merges') and len(parents) != 2:
2476 2478 return
2477 2479 if opts.get('branch') and ctx.branch() not in opts['branch']:
2478 2480 return
2479 2481 if df and not df(ctx.date()[0]):
2480 2482 return
2481 2483 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2482 2484 return
2483 2485 if opts.get('keyword'):
2484 2486 for k in [kw.lower() for kw in opts['keyword']]:
2485 2487 if (k in ctx.user().lower() or
2486 2488 k in ctx.description().lower() or
2487 2489 k in " ".join(ctx.files()).lower()):
2488 2490 break
2489 2491 else:
2490 2492 return
2491 2493
2492 2494 copies = None
2493 2495 if opts.get('copies') and rev:
2494 2496 copies = []
2495 2497 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2496 2498 for fn in ctx.files():
2497 2499 rename = getrenamed(fn, rev)
2498 2500 if rename:
2499 2501 copies.append((fn, rename[0]))
2500 2502
2501 2503 revmatchfn = None
2502 2504 if opts.get('patch') or opts.get('stat'):
2503 2505 if opts.get('follow') or opts.get('follow_first'):
2504 2506 # note: this might be wrong when following through merges
2505 2507 revmatchfn = cmdutil.match(repo, fns, default='path')
2506 2508 else:
2507 2509 revmatchfn = matchfn
2508 2510
2509 2511 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2510 2512
2511 2513 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2512 2514 if count == limit:
2513 2515 break
2514 2516 if displayer.flush(ctx.rev()):
2515 2517 count += 1
2516 2518 displayer.close()
2517 2519
2518 2520 def manifest(ui, repo, node=None, rev=None):
2519 2521 """output the current or given revision of the project manifest
2520 2522
2521 2523 Print a list of version controlled files for the given revision.
2522 2524 If no revision is given, the first parent of the working directory
2523 2525 is used, or the null revision if no revision is checked out.
2524 2526
2525 2527 With -v, print file permissions, symlink and executable bits.
2526 2528 With --debug, print file revision hashes.
2527 2529
2528 2530 Returns 0 on success.
2529 2531 """
2530 2532
2531 2533 if rev and node:
2532 2534 raise util.Abort(_("please specify just one revision"))
2533 2535
2534 2536 if not node:
2535 2537 node = rev
2536 2538
2537 2539 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2538 2540 ctx = repo[node]
2539 2541 for f in ctx:
2540 2542 if ui.debugflag:
2541 2543 ui.write("%40s " % hex(ctx.manifest()[f]))
2542 2544 if ui.verbose:
2543 2545 ui.write(decor[ctx.flags(f)])
2544 2546 ui.write("%s\n" % f)
2545 2547
2546 2548 def merge(ui, repo, node=None, **opts):
2547 2549 """merge working directory with another revision
2548 2550
2549 2551 The current working directory is updated with all changes made in
2550 2552 the requested revision since the last common predecessor revision.
2551 2553
2552 2554 Files that changed between either parent are marked as changed for
2553 2555 the next commit and a commit must be performed before any further
2554 2556 updates to the repository are allowed. The next commit will have
2555 2557 two parents.
2556 2558
2557 2559 If no revision is specified, the working directory's parent is a
2558 2560 head revision, and the current branch contains exactly one other
2559 2561 head, the other head is merged with by default. Otherwise, an
2560 2562 explicit revision with which to merge with must be provided.
2561 2563
2562 2564 To undo an uncommitted merge, use :hg:`update --clean .` which
2563 2565 will check out a clean copy of the original merge parent, losing
2564 2566 all changes.
2565 2567
2566 2568 Returns 0 on success, 1 if there are unresolved files.
2567 2569 """
2568 2570
2569 2571 if opts.get('rev') and node:
2570 2572 raise util.Abort(_("please specify just one revision"))
2571 2573 if not node:
2572 2574 node = opts.get('rev')
2573 2575
2574 2576 if not node:
2575 2577 branch = repo.changectx(None).branch()
2576 2578 bheads = repo.branchheads(branch)
2577 2579 if len(bheads) > 2:
2578 2580 raise util.Abort(_(
2579 2581 'branch \'%s\' has %d heads - '
2580 2582 'please merge with an explicit rev\n'
2581 2583 '(run \'hg heads .\' to see heads)')
2582 2584 % (branch, len(bheads)))
2583 2585
2584 2586 parent = repo.dirstate.parents()[0]
2585 2587 if len(bheads) == 1:
2586 2588 if len(repo.heads()) > 1:
2587 2589 raise util.Abort(_(
2588 2590 'branch \'%s\' has one head - '
2589 2591 'please merge with an explicit rev\n'
2590 2592 '(run \'hg heads\' to see all heads)')
2591 2593 % branch)
2592 2594 msg = _('there is nothing to merge')
2593 2595 if parent != repo.lookup(repo[None].branch()):
2594 2596 msg = _('%s - use "hg update" instead') % msg
2595 2597 raise util.Abort(msg)
2596 2598
2597 2599 if parent not in bheads:
2598 2600 raise util.Abort(_('working dir not at a head rev - '
2599 2601 'use "hg update" or merge with an explicit rev'))
2600 2602 node = parent == bheads[0] and bheads[-1] or bheads[0]
2601 2603
2602 2604 if opts.get('preview'):
2603 2605 # find nodes that are ancestors of p2 but not of p1
2604 2606 p1 = repo.lookup('.')
2605 2607 p2 = repo.lookup(node)
2606 2608 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2607 2609
2608 2610 displayer = cmdutil.show_changeset(ui, repo, opts)
2609 2611 for node in nodes:
2610 2612 displayer.show(repo[node])
2611 2613 displayer.close()
2612 2614 return 0
2613 2615
2614 2616 return hg.merge(repo, node, force=opts.get('force'))
2615 2617
2616 2618 def outgoing(ui, repo, dest=None, **opts):
2617 2619 """show changesets not found in the destination
2618 2620
2619 2621 Show changesets not found in the specified destination repository
2620 2622 or the default push location. These are the changesets that would
2621 2623 be pushed if a push was requested.
2622 2624
2623 2625 See pull for details of valid destination formats.
2624 2626
2625 2627 Returns 0 if there are outgoing changes, 1 otherwise.
2626 2628 """
2627 2629 ret = hg.outgoing(ui, repo, dest, opts)
2628 2630 return ret
2629 2631
2630 2632 def parents(ui, repo, file_=None, **opts):
2631 2633 """show the parents of the working directory or revision
2632 2634
2633 2635 Print the working directory's parent revisions. If a revision is
2634 2636 given via -r/--rev, the parent of that revision will be printed.
2635 2637 If a file argument is given, the revision in which the file was
2636 2638 last changed (before the working directory revision or the
2637 2639 argument to --rev if given) is printed.
2638 2640
2639 2641 Returns 0 on success.
2640 2642 """
2641 2643 rev = opts.get('rev')
2642 2644 if rev:
2643 2645 ctx = repo[rev]
2644 2646 else:
2645 2647 ctx = repo[None]
2646 2648
2647 2649 if file_:
2648 2650 m = cmdutil.match(repo, (file_,), opts)
2649 2651 if m.anypats() or len(m.files()) != 1:
2650 2652 raise util.Abort(_('can only specify an explicit filename'))
2651 2653 file_ = m.files()[0]
2652 2654 filenodes = []
2653 2655 for cp in ctx.parents():
2654 2656 if not cp:
2655 2657 continue
2656 2658 try:
2657 2659 filenodes.append(cp.filenode(file_))
2658 2660 except error.LookupError:
2659 2661 pass
2660 2662 if not filenodes:
2661 2663 raise util.Abort(_("'%s' not found in manifest!") % file_)
2662 2664 fl = repo.file(file_)
2663 2665 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2664 2666 else:
2665 2667 p = [cp.node() for cp in ctx.parents()]
2666 2668
2667 2669 displayer = cmdutil.show_changeset(ui, repo, opts)
2668 2670 for n in p:
2669 2671 if n != nullid:
2670 2672 displayer.show(repo[n])
2671 2673 displayer.close()
2672 2674
2673 2675 def paths(ui, repo, search=None):
2674 2676 """show aliases for remote repositories
2675 2677
2676 2678 Show definition of symbolic path name NAME. If no name is given,
2677 2679 show definition of all available names.
2678 2680
2679 2681 Path names are defined in the [paths] section of your
2680 2682 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2681 2683 repository, ``.hg/hgrc`` is used, too.
2682 2684
2683 2685 The path names ``default`` and ``default-push`` have a special
2684 2686 meaning. When performing a push or pull operation, they are used
2685 2687 as fallbacks if no location is specified on the command-line.
2686 2688 When ``default-push`` is set, it will be used for push and
2687 2689 ``default`` will be used for pull; otherwise ``default`` is used
2688 2690 as the fallback for both. When cloning a repository, the clone
2689 2691 source is written as ``default`` in ``.hg/hgrc``. Note that
2690 2692 ``default`` and ``default-push`` apply to all inbound (e.g.
2691 2693 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2692 2694 :hg:`bundle`) operations.
2693 2695
2694 2696 See :hg:`help urls` for more information.
2695 2697
2696 2698 Returns 0 on success.
2697 2699 """
2698 2700 if search:
2699 2701 for name, path in ui.configitems("paths"):
2700 2702 if name == search:
2701 2703 ui.write("%s\n" % url.hidepassword(path))
2702 2704 return
2703 2705 ui.warn(_("not found!\n"))
2704 2706 return 1
2705 2707 else:
2706 2708 for name, path in ui.configitems("paths"):
2707 2709 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2708 2710
2709 2711 def postincoming(ui, repo, modheads, optupdate, checkout):
2710 2712 if modheads == 0:
2711 2713 return
2712 2714 if optupdate:
2713 2715 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2714 2716 return hg.update(repo, checkout)
2715 2717 else:
2716 2718 ui.status(_("not updating, since new heads added\n"))
2717 2719 if modheads > 1:
2718 2720 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2719 2721 else:
2720 2722 ui.status(_("(run 'hg update' to get a working copy)\n"))
2721 2723
2722 2724 def pull(ui, repo, source="default", **opts):
2723 2725 """pull changes from the specified source
2724 2726
2725 2727 Pull changes from a remote repository to a local one.
2726 2728
2727 2729 This finds all changes from the repository at the specified path
2728 2730 or URL and adds them to a local repository (the current one unless
2729 2731 -R is specified). By default, this does not update the copy of the
2730 2732 project in the working directory.
2731 2733
2732 2734 Use :hg:`incoming` if you want to see what would have been added
2733 2735 by a pull at the time you issued this command. If you then decide
2734 2736 to add those changes to the repository, you should use :hg:`pull
2735 2737 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2736 2738
2737 2739 If SOURCE is omitted, the 'default' path will be used.
2738 2740 See :hg:`help urls` for more information.
2739 2741
2740 2742 Returns 0 on success, 1 if an update had unresolved files.
2741 2743 """
2742 2744 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2743 2745 other = hg.repository(hg.remoteui(repo, opts), source)
2744 2746 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2745 2747 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2746 2748 if revs:
2747 2749 try:
2748 2750 revs = [other.lookup(rev) for rev in revs]
2749 2751 except error.CapabilityError:
2750 2752 err = _("other repository doesn't support revision lookup, "
2751 2753 "so a rev cannot be specified.")
2752 2754 raise util.Abort(err)
2753 2755
2754 2756 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2755 2757 if checkout:
2756 2758 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2757 2759 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2758 2760
2759 2761 def push(ui, repo, dest=None, **opts):
2760 2762 """push changes to the specified destination
2761 2763
2762 2764 Push changesets from the local repository to the specified
2763 2765 destination.
2764 2766
2765 2767 This operation is symmetrical to pull: it is identical to a pull
2766 2768 in the destination repository from the current one.
2767 2769
2768 2770 By default, push will not allow creation of new heads at the
2769 2771 destination, since multiple heads would make it unclear which head
2770 2772 to use. In this situation, it is recommended to pull and merge
2771 2773 before pushing.
2772 2774
2773 2775 Use --new-branch if you want to allow push to create a new named
2774 2776 branch that is not present at the destination. This allows you to
2775 2777 only create a new branch without forcing other changes.
2776 2778
2777 2779 Use -f/--force to override the default behavior and push all
2778 2780 changesets on all branches.
2779 2781
2780 2782 If -r/--rev is used, the specified revision and all its ancestors
2781 2783 will be pushed to the remote repository.
2782 2784
2783 2785 Please see :hg:`help urls` for important details about ``ssh://``
2784 2786 URLs. If DESTINATION is omitted, a default path will be used.
2785 2787
2786 2788 Returns 0 if push was successful, 1 if nothing to push.
2787 2789 """
2788 2790 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2789 2791 dest, branches = hg.parseurl(dest, opts.get('branch'))
2790 2792 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2791 2793 other = hg.repository(hg.remoteui(repo, opts), dest)
2792 2794 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2793 2795 if revs:
2794 2796 revs = [repo.lookup(rev) for rev in revs]
2795 2797
2796 2798 # push subrepos depth-first for coherent ordering
2797 2799 c = repo['']
2798 2800 subs = c.substate # only repos that are committed
2799 2801 for s in sorted(subs):
2800 2802 if not c.sub(s).push(opts.get('force')):
2801 2803 return False
2802 2804
2803 2805 r = repo.push(other, opts.get('force'), revs=revs,
2804 2806 newbranch=opts.get('new_branch'))
2805 2807 return r == 0
2806 2808
2807 2809 def recover(ui, repo):
2808 2810 """roll back an interrupted transaction
2809 2811
2810 2812 Recover from an interrupted commit or pull.
2811 2813
2812 2814 This command tries to fix the repository status after an
2813 2815 interrupted operation. It should only be necessary when Mercurial
2814 2816 suggests it.
2815 2817
2816 2818 Returns 0 if successful, 1 if nothing to recover or verify fails.
2817 2819 """
2818 2820 if repo.recover():
2819 2821 return hg.verify(repo)
2820 2822 return 1
2821 2823
2822 2824 def remove(ui, repo, *pats, **opts):
2823 2825 """remove the specified files on the next commit
2824 2826
2825 2827 Schedule the indicated files for removal from the repository.
2826 2828
2827 2829 This only removes files from the current branch, not from the
2828 2830 entire project history. -A/--after can be used to remove only
2829 2831 files that have already been deleted, -f/--force can be used to
2830 2832 force deletion, and -Af can be used to remove files from the next
2831 2833 revision without deleting them from the working directory.
2832 2834
2833 2835 The following table details the behavior of remove for different
2834 2836 file states (columns) and option combinations (rows). The file
2835 2837 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2836 2838 reported by :hg:`status`). The actions are Warn, Remove (from
2837 2839 branch) and Delete (from disk)::
2838 2840
2839 2841 A C M !
2840 2842 none W RD W R
2841 2843 -f R RD RD R
2842 2844 -A W W W R
2843 2845 -Af R R R R
2844 2846
2845 2847 This command schedules the files to be removed at the next commit.
2846 2848 To undo a remove before that, see :hg:`revert`.
2847 2849
2848 2850 Returns 0 on success, 1 if any warnings encountered.
2849 2851 """
2850 2852
2851 2853 ret = 0
2852 2854 after, force = opts.get('after'), opts.get('force')
2853 2855 if not pats and not after:
2854 2856 raise util.Abort(_('no files specified'))
2855 2857
2856 2858 m = cmdutil.match(repo, pats, opts)
2857 2859 s = repo.status(match=m, clean=True)
2858 2860 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2859 2861
2860 2862 for f in m.files():
2861 2863 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2862 2864 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2863 2865 ret = 1
2864 2866
2865 2867 if force:
2866 2868 remove, forget = modified + deleted + clean, added
2867 2869 elif after:
2868 2870 remove, forget = deleted, []
2869 2871 for f in modified + added + clean:
2870 2872 ui.warn(_('not removing %s: file still exists (use -f'
2871 2873 ' to force removal)\n') % m.rel(f))
2872 2874 ret = 1
2873 2875 else:
2874 2876 remove, forget = deleted + clean, []
2875 2877 for f in modified:
2876 2878 ui.warn(_('not removing %s: file is modified (use -f'
2877 2879 ' to force removal)\n') % m.rel(f))
2878 2880 ret = 1
2879 2881 for f in added:
2880 2882 ui.warn(_('not removing %s: file has been marked for add (use -f'
2881 2883 ' to force removal)\n') % m.rel(f))
2882 2884 ret = 1
2883 2885
2884 2886 for f in sorted(remove + forget):
2885 2887 if ui.verbose or not m.exact(f):
2886 2888 ui.status(_('removing %s\n') % m.rel(f))
2887 2889
2888 2890 repo[None].forget(forget)
2889 2891 repo[None].remove(remove, unlink=not after)
2890 2892 return ret
2891 2893
2892 2894 def rename(ui, repo, *pats, **opts):
2893 2895 """rename files; equivalent of copy + remove
2894 2896
2895 2897 Mark dest as copies of sources; mark sources for deletion. If dest
2896 2898 is a directory, copies are put in that directory. If dest is a
2897 2899 file, there can only be one source.
2898 2900
2899 2901 By default, this command copies the contents of files as they
2900 2902 exist in the working directory. If invoked with -A/--after, the
2901 2903 operation is recorded, but no copying is performed.
2902 2904
2903 2905 This command takes effect at the next commit. To undo a rename
2904 2906 before that, see :hg:`revert`.
2905 2907
2906 2908 Returns 0 on success, 1 if errors are encountered.
2907 2909 """
2908 2910 wlock = repo.wlock(False)
2909 2911 try:
2910 2912 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2911 2913 finally:
2912 2914 wlock.release()
2913 2915
2914 2916 def resolve(ui, repo, *pats, **opts):
2915 2917 """redo merges or set/view the merge status of files
2916 2918
2917 2919 Merges with unresolved conflicts are often the result of
2918 2920 non-interactive merging using the ``internal:merge`` configuration
2919 2921 setting, or a command-line merge tool like ``diff3``. The resolve
2920 2922 command is used to manage the files involved in a merge, after
2921 2923 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2922 2924 working directory must have two parents).
2923 2925
2924 2926 The resolve command can be used in the following ways:
2925 2927
2926 2928 - :hg:`resolve FILE...`: attempt to re-merge the specified files,
2927 2929 discarding any previous merge attempts. Re-merging is not
2928 2930 performed for files already marked as resolved. Use ``--all/-a``
2929 2931 to selects all unresolved files.
2930 2932
2931 2933 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2932 2934 (e.g. after having manually fixed-up the files). The default is
2933 2935 to mark all unresolved files.
2934 2936
2935 2937 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2936 2938 default is to mark all resolved files.
2937 2939
2938 2940 - :hg:`resolve -l`: list files which had or still have conflicts.
2939 2941 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2940 2942
2941 2943 Note that Mercurial will not let you commit files with unresolved
2942 2944 merge conflicts. You must use :hg:`resolve -m ...` before you can
2943 2945 commit after a conflicting merge.
2944 2946
2945 2947 Returns 0 on success, 1 if any files fail a resolve attempt.
2946 2948 """
2947 2949
2948 2950 all, mark, unmark, show, nostatus = \
2949 2951 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2950 2952
2951 2953 if (show and (mark or unmark)) or (mark and unmark):
2952 2954 raise util.Abort(_("too many options specified"))
2953 2955 if pats and all:
2954 2956 raise util.Abort(_("can't specify --all and patterns"))
2955 2957 if not (all or pats or show or mark or unmark):
2956 2958 raise util.Abort(_('no files or directories specified; '
2957 2959 'use --all to remerge all files'))
2958 2960
2959 2961 ms = mergemod.mergestate(repo)
2960 2962 m = cmdutil.match(repo, pats, opts)
2961 2963 ret = 0
2962 2964
2963 2965 for f in ms:
2964 2966 if m(f):
2965 2967 if show:
2966 2968 if nostatus:
2967 2969 ui.write("%s\n" % f)
2968 2970 else:
2969 2971 ui.write("%s %s\n" % (ms[f].upper(), f),
2970 2972 label='resolve.' +
2971 2973 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2972 2974 elif mark:
2973 2975 ms.mark(f, "r")
2974 2976 elif unmark:
2975 2977 ms.mark(f, "u")
2976 2978 else:
2977 2979 wctx = repo[None]
2978 2980 mctx = wctx.parents()[-1]
2979 2981
2980 2982 # backup pre-resolve (merge uses .orig for its own purposes)
2981 2983 a = repo.wjoin(f)
2982 2984 util.copyfile(a, a + ".resolve")
2983 2985
2984 2986 # resolve file
2985 2987 if ms.resolve(f, wctx, mctx):
2986 2988 ret = 1
2987 2989
2988 2990 # replace filemerge's .orig file with our resolve file
2989 2991 util.rename(a + ".resolve", a + ".orig")
2990 2992
2991 2993 ms.commit()
2992 2994 return ret
2993 2995
2994 2996 def revert(ui, repo, *pats, **opts):
2995 2997 """restore individual files or directories to an earlier state
2996 2998
2997 2999 .. note::
2998 3000 This command is most likely not what you are looking for.
2999 3001 revert will partially overwrite content in the working
3000 3002 directory without changing the working directory parents. Use
3001 3003 :hg:`update -r rev` to check out earlier revisions, or
3002 3004 :hg:`update --clean .` to undo a merge which has added another
3003 3005 parent.
3004 3006
3005 3007 With no revision specified, revert the named files or directories
3006 3008 to the contents they had in the parent of the working directory.
3007 3009 This restores the contents of the affected files to an unmodified
3008 3010 state and unschedules adds, removes, copies, and renames. If the
3009 3011 working directory has two parents, you must explicitly specify a
3010 3012 revision.
3011 3013
3012 3014 Using the -r/--rev option, revert the given files or directories
3013 3015 to their contents as of a specific revision. This can be helpful
3014 3016 to "roll back" some or all of an earlier change. See :hg:`help
3015 3017 dates` for a list of formats valid for -d/--date.
3016 3018
3017 3019 Revert modifies the working directory. It does not commit any
3018 3020 changes, or change the parent of the working directory. If you
3019 3021 revert to a revision other than the parent of the working
3020 3022 directory, the reverted files will thus appear modified
3021 3023 afterwards.
3022 3024
3023 3025 If a file has been deleted, it is restored. If the executable mode
3024 3026 of a file was changed, it is reset.
3025 3027
3026 3028 If names are given, all files matching the names are reverted.
3027 3029 If no arguments are given, no files are reverted.
3028 3030
3029 3031 Modified files are saved with a .orig suffix before reverting.
3030 3032 To disable these backups, use --no-backup.
3031 3033
3032 3034 Returns 0 on success.
3033 3035 """
3034 3036
3035 3037 if opts.get("date"):
3036 3038 if opts.get("rev"):
3037 3039 raise util.Abort(_("you can't specify a revision and a date"))
3038 3040 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3039 3041
3040 3042 if not pats and not opts.get('all'):
3041 3043 raise util.Abort(_('no files or directories specified; '
3042 3044 'use --all to revert the whole repo'))
3043 3045
3044 3046 parent, p2 = repo.dirstate.parents()
3045 3047 if not opts.get('rev') and p2 != nullid:
3046 3048 raise util.Abort(_('uncommitted merge - please provide a '
3047 3049 'specific revision'))
3048 3050 ctx = repo[opts.get('rev')]
3049 3051 node = ctx.node()
3050 3052 mf = ctx.manifest()
3051 3053 if node == parent:
3052 3054 pmf = mf
3053 3055 else:
3054 3056 pmf = None
3055 3057
3056 3058 # need all matching names in dirstate and manifest of target rev,
3057 3059 # so have to walk both. do not print errors if files exist in one
3058 3060 # but not other.
3059 3061
3060 3062 names = {}
3061 3063
3062 3064 wlock = repo.wlock()
3063 3065 try:
3064 3066 # walk dirstate.
3065 3067
3066 3068 m = cmdutil.match(repo, pats, opts)
3067 3069 m.bad = lambda x, y: False
3068 3070 for abs in repo.walk(m):
3069 3071 names[abs] = m.rel(abs), m.exact(abs)
3070 3072
3071 3073 # walk target manifest.
3072 3074
3073 3075 def badfn(path, msg):
3074 3076 if path in names:
3075 3077 return
3076 3078 path_ = path + '/'
3077 3079 for f in names:
3078 3080 if f.startswith(path_):
3079 3081 return
3080 3082 ui.warn("%s: %s\n" % (m.rel(path), msg))
3081 3083
3082 3084 m = cmdutil.match(repo, pats, opts)
3083 3085 m.bad = badfn
3084 3086 for abs in repo[node].walk(m):
3085 3087 if abs not in names:
3086 3088 names[abs] = m.rel(abs), m.exact(abs)
3087 3089
3088 3090 m = cmdutil.matchfiles(repo, names)
3089 3091 changes = repo.status(match=m)[:4]
3090 3092 modified, added, removed, deleted = map(set, changes)
3091 3093
3092 3094 # if f is a rename, also revert the source
3093 3095 cwd = repo.getcwd()
3094 3096 for f in added:
3095 3097 src = repo.dirstate.copied(f)
3096 3098 if src and src not in names and repo.dirstate[src] == 'r':
3097 3099 removed.add(src)
3098 3100 names[src] = (repo.pathto(src, cwd), True)
3099 3101
3100 3102 def removeforget(abs):
3101 3103 if repo.dirstate[abs] == 'a':
3102 3104 return _('forgetting %s\n')
3103 3105 return _('removing %s\n')
3104 3106
3105 3107 revert = ([], _('reverting %s\n'))
3106 3108 add = ([], _('adding %s\n'))
3107 3109 remove = ([], removeforget)
3108 3110 undelete = ([], _('undeleting %s\n'))
3109 3111
3110 3112 disptable = (
3111 3113 # dispatch table:
3112 3114 # file state
3113 3115 # action if in target manifest
3114 3116 # action if not in target manifest
3115 3117 # make backup if in target manifest
3116 3118 # make backup if not in target manifest
3117 3119 (modified, revert, remove, True, True),
3118 3120 (added, revert, remove, True, False),
3119 3121 (removed, undelete, None, False, False),
3120 3122 (deleted, revert, remove, False, False),
3121 3123 )
3122 3124
3123 3125 for abs, (rel, exact) in sorted(names.items()):
3124 3126 mfentry = mf.get(abs)
3125 3127 target = repo.wjoin(abs)
3126 3128 def handle(xlist, dobackup):
3127 3129 xlist[0].append(abs)
3128 3130 if (dobackup and not opts.get('no_backup') and
3129 3131 os.path.lexists(target)):
3130 3132 bakname = "%s.orig" % rel
3131 3133 ui.note(_('saving current version of %s as %s\n') %
3132 3134 (rel, bakname))
3133 3135 if not opts.get('dry_run'):
3134 3136 util.rename(target, bakname)
3135 3137 if ui.verbose or not exact:
3136 3138 msg = xlist[1]
3137 3139 if not isinstance(msg, basestring):
3138 3140 msg = msg(abs)
3139 3141 ui.status(msg % rel)
3140 3142 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3141 3143 if abs not in table:
3142 3144 continue
3143 3145 # file has changed in dirstate
3144 3146 if mfentry:
3145 3147 handle(hitlist, backuphit)
3146 3148 elif misslist is not None:
3147 3149 handle(misslist, backupmiss)
3148 3150 break
3149 3151 else:
3150 3152 if abs not in repo.dirstate:
3151 3153 if mfentry:
3152 3154 handle(add, True)
3153 3155 elif exact:
3154 3156 ui.warn(_('file not managed: %s\n') % rel)
3155 3157 continue
3156 3158 # file has not changed in dirstate
3157 3159 if node == parent:
3158 3160 if exact:
3159 3161 ui.warn(_('no changes needed to %s\n') % rel)
3160 3162 continue
3161 3163 if pmf is None:
3162 3164 # only need parent manifest in this unlikely case,
3163 3165 # so do not read by default
3164 3166 pmf = repo[parent].manifest()
3165 3167 if abs in pmf:
3166 3168 if mfentry:
3167 3169 # if version of file is same in parent and target
3168 3170 # manifests, do nothing
3169 3171 if (pmf[abs] != mfentry or
3170 3172 pmf.flags(abs) != mf.flags(abs)):
3171 3173 handle(revert, False)
3172 3174 else:
3173 3175 handle(remove, False)
3174 3176
3175 3177 if not opts.get('dry_run'):
3176 3178 def checkout(f):
3177 3179 fc = ctx[f]
3178 3180 repo.wwrite(f, fc.data(), fc.flags())
3179 3181
3180 3182 audit_path = util.path_auditor(repo.root)
3181 3183 for f in remove[0]:
3182 3184 if repo.dirstate[f] == 'a':
3183 3185 repo.dirstate.forget(f)
3184 3186 continue
3185 3187 audit_path(f)
3186 3188 try:
3187 3189 util.unlink(repo.wjoin(f))
3188 3190 except OSError:
3189 3191 pass
3190 3192 repo.dirstate.remove(f)
3191 3193
3192 3194 normal = None
3193 3195 if node == parent:
3194 3196 # We're reverting to our parent. If possible, we'd like status
3195 3197 # to report the file as clean. We have to use normallookup for
3196 3198 # merges to avoid losing information about merged/dirty files.
3197 3199 if p2 != nullid:
3198 3200 normal = repo.dirstate.normallookup
3199 3201 else:
3200 3202 normal = repo.dirstate.normal
3201 3203 for f in revert[0]:
3202 3204 checkout(f)
3203 3205 if normal:
3204 3206 normal(f)
3205 3207
3206 3208 for f in add[0]:
3207 3209 checkout(f)
3208 3210 repo.dirstate.add(f)
3209 3211
3210 3212 normal = repo.dirstate.normallookup
3211 3213 if node == parent and p2 == nullid:
3212 3214 normal = repo.dirstate.normal
3213 3215 for f in undelete[0]:
3214 3216 checkout(f)
3215 3217 normal(f)
3216 3218
3217 3219 finally:
3218 3220 wlock.release()
3219 3221
3220 3222 def rollback(ui, repo, **opts):
3221 3223 """roll back the last transaction (dangerous)
3222 3224
3223 3225 This command should be used with care. There is only one level of
3224 3226 rollback, and there is no way to undo a rollback. It will also
3225 3227 restore the dirstate at the time of the last transaction, losing
3226 3228 any dirstate changes since that time. This command does not alter
3227 3229 the working directory.
3228 3230
3229 3231 Transactions are used to encapsulate the effects of all commands
3230 3232 that create new changesets or propagate existing changesets into a
3231 3233 repository. For example, the following commands are transactional,
3232 3234 and their effects can be rolled back:
3233 3235
3234 3236 - commit
3235 3237 - import
3236 3238 - pull
3237 3239 - push (with this repository as the destination)
3238 3240 - unbundle
3239 3241
3240 3242 This command is not intended for use on public repositories. Once
3241 3243 changes are visible for pull by other users, rolling a transaction
3242 3244 back locally is ineffective (someone else may already have pulled
3243 3245 the changes). Furthermore, a race is possible with readers of the
3244 3246 repository; for example an in-progress pull from the repository
3245 3247 may fail if a rollback is performed.
3246 3248
3247 3249 Returns 0 on success, 1 if no rollback data is available.
3248 3250 """
3249 3251 return repo.rollback(opts.get('dry_run'))
3250 3252
3251 3253 def root(ui, repo):
3252 3254 """print the root (top) of the current working directory
3253 3255
3254 3256 Print the root directory of the current repository.
3255 3257
3256 3258 Returns 0 on success.
3257 3259 """
3258 3260 ui.write(repo.root + "\n")
3259 3261
3260 3262 def serve(ui, repo, **opts):
3261 3263 """start stand-alone webserver
3262 3264
3263 3265 Start a local HTTP repository browser and pull server. You can use
3264 3266 this for ad-hoc sharing and browing of repositories. It is
3265 3267 recommended to use a real web server to serve a repository for
3266 3268 longer periods of time.
3267 3269
3268 3270 Please note that the server does not implement access control.
3269 3271 This means that, by default, anybody can read from the server and
3270 3272 nobody can write to it by default. Set the ``web.allow_push``
3271 3273 option to ``*`` to allow everybody to push to the server. You
3272 3274 should use a real web server if you need to authenticate users.
3273 3275
3274 3276 By default, the server logs accesses to stdout and errors to
3275 3277 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3276 3278 files.
3277 3279
3278 3280 To have the server choose a free port number to listen on, specify
3279 3281 a port number of 0; in this case, the server will print the port
3280 3282 number it uses.
3281 3283
3282 3284 Returns 0 on success.
3283 3285 """
3284 3286
3285 3287 if opts["stdio"]:
3286 3288 if repo is None:
3287 3289 raise error.RepoError(_("There is no Mercurial repository here"
3288 3290 " (.hg not found)"))
3289 3291 s = sshserver.sshserver(ui, repo)
3290 3292 s.serve_forever()
3291 3293
3292 3294 # this way we can check if something was given in the command-line
3293 3295 if opts.get('port'):
3294 3296 opts['port'] = util.getport(opts.get('port'))
3295 3297
3296 3298 baseui = repo and repo.baseui or ui
3297 3299 optlist = ("name templates style address port prefix ipv6"
3298 3300 " accesslog errorlog certificate encoding")
3299 3301 for o in optlist.split():
3300 3302 val = opts.get(o, '')
3301 3303 if val in (None, ''): # should check against default options instead
3302 3304 continue
3303 3305 baseui.setconfig("web", o, val)
3304 3306 if repo and repo.ui != baseui:
3305 3307 repo.ui.setconfig("web", o, val)
3306 3308
3307 3309 o = opts.get('web_conf') or opts.get('webdir_conf')
3308 3310 if not o:
3309 3311 if not repo:
3310 3312 raise error.RepoError(_("There is no Mercurial repository"
3311 3313 " here (.hg not found)"))
3312 3314 o = repo.root
3313 3315
3314 3316 app = hgweb.hgweb(o, baseui=ui)
3315 3317
3316 3318 class service(object):
3317 3319 def init(self):
3318 3320 util.set_signal_handler()
3319 3321 self.httpd = hgweb.server.create_server(ui, app)
3320 3322
3321 3323 if opts['port'] and not ui.verbose:
3322 3324 return
3323 3325
3324 3326 if self.httpd.prefix:
3325 3327 prefix = self.httpd.prefix.strip('/') + '/'
3326 3328 else:
3327 3329 prefix = ''
3328 3330
3329 3331 port = ':%d' % self.httpd.port
3330 3332 if port == ':80':
3331 3333 port = ''
3332 3334
3333 3335 bindaddr = self.httpd.addr
3334 3336 if bindaddr == '0.0.0.0':
3335 3337 bindaddr = '*'
3336 3338 elif ':' in bindaddr: # IPv6
3337 3339 bindaddr = '[%s]' % bindaddr
3338 3340
3339 3341 fqaddr = self.httpd.fqaddr
3340 3342 if ':' in fqaddr:
3341 3343 fqaddr = '[%s]' % fqaddr
3342 3344 if opts['port']:
3343 3345 write = ui.status
3344 3346 else:
3345 3347 write = ui.write
3346 3348 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3347 3349 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3348 3350
3349 3351 def run(self):
3350 3352 self.httpd.serve_forever()
3351 3353
3352 3354 service = service()
3353 3355
3354 3356 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3355 3357
3356 3358 def status(ui, repo, *pats, **opts):
3357 3359 """show changed files in the working directory
3358 3360
3359 3361 Show status of files in the repository. If names are given, only
3360 3362 files that match are shown. Files that are clean or ignored or
3361 3363 the source of a copy/move operation, are not listed unless
3362 3364 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3363 3365 Unless options described with "show only ..." are given, the
3364 3366 options -mardu are used.
3365 3367
3366 3368 Option -q/--quiet hides untracked (unknown and ignored) files
3367 3369 unless explicitly requested with -u/--unknown or -i/--ignored.
3368 3370
3369 3371 .. note::
3370 3372 status may appear to disagree with diff if permissions have
3371 3373 changed or a merge has occurred. The standard diff format does
3372 3374 not report permission changes and diff only reports changes
3373 3375 relative to one merge parent.
3374 3376
3375 3377 If one revision is given, it is used as the base revision.
3376 3378 If two revisions are given, the differences between them are
3377 3379 shown. The --change option can also be used as a shortcut to list
3378 3380 the changed files of a revision from its first parent.
3379 3381
3380 3382 The codes used to show the status of files are::
3381 3383
3382 3384 M = modified
3383 3385 A = added
3384 3386 R = removed
3385 3387 C = clean
3386 3388 ! = missing (deleted by non-hg command, but still tracked)
3387 3389 ? = not tracked
3388 3390 I = ignored
3389 3391 = origin of the previous file listed as A (added)
3390 3392
3391 3393 Returns 0 on success.
3392 3394 """
3393 3395
3394 3396 revs = opts.get('rev')
3395 3397 change = opts.get('change')
3396 3398
3397 3399 if revs and change:
3398 3400 msg = _('cannot specify --rev and --change at the same time')
3399 3401 raise util.Abort(msg)
3400 3402 elif change:
3401 3403 node2 = repo.lookup(change)
3402 3404 node1 = repo[node2].parents()[0].node()
3403 3405 else:
3404 3406 node1, node2 = cmdutil.revpair(repo, revs)
3405 3407
3406 3408 cwd = (pats and repo.getcwd()) or ''
3407 3409 end = opts.get('print0') and '\0' or '\n'
3408 3410 copy = {}
3409 3411 states = 'modified added removed deleted unknown ignored clean'.split()
3410 3412 show = [k for k in states if opts.get(k)]
3411 3413 if opts.get('all'):
3412 3414 show += ui.quiet and (states[:4] + ['clean']) or states
3413 3415 if not show:
3414 3416 show = ui.quiet and states[:4] or states[:5]
3415 3417
3416 3418 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3417 3419 'ignored' in show, 'clean' in show, 'unknown' in show,
3418 3420 opts.get('subrepos'))
3419 3421 changestates = zip(states, 'MAR!?IC', stat)
3420 3422
3421 3423 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3422 3424 ctxn = repo[nullid]
3423 3425 ctx1 = repo[node1]
3424 3426 ctx2 = repo[node2]
3425 3427 added = stat[1]
3426 3428 if node2 is None:
3427 3429 added = stat[0] + stat[1] # merged?
3428 3430
3429 3431 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3430 3432 if k in added:
3431 3433 copy[k] = v
3432 3434 elif v in added:
3433 3435 copy[v] = k
3434 3436
3435 3437 for state, char, files in changestates:
3436 3438 if state in show:
3437 3439 format = "%s %%s%s" % (char, end)
3438 3440 if opts.get('no_status'):
3439 3441 format = "%%s%s" % end
3440 3442
3441 3443 for f in files:
3442 3444 ui.write(format % repo.pathto(f, cwd),
3443 3445 label='status.' + state)
3444 3446 if f in copy:
3445 3447 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3446 3448 label='status.copied')
3447 3449
3448 3450 def summary(ui, repo, **opts):
3449 3451 """summarize working directory state
3450 3452
3451 3453 This generates a brief summary of the working directory state,
3452 3454 including parents, branch, commit status, and available updates.
3453 3455
3454 3456 With the --remote option, this will check the default paths for
3455 3457 incoming and outgoing changes. This can be time-consuming.
3456 3458
3457 3459 Returns 0 on success.
3458 3460 """
3459 3461
3460 3462 ctx = repo[None]
3461 3463 parents = ctx.parents()
3462 3464 pnode = parents[0].node()
3463 3465
3464 3466 for p in parents:
3465 3467 # label with log.changeset (instead of log.parent) since this
3466 3468 # shows a working directory parent *changeset*:
3467 3469 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3468 3470 label='log.changeset')
3469 3471 ui.write(' '.join(p.tags()), label='log.tag')
3470 3472 if p.rev() == -1:
3471 3473 if not len(repo):
3472 3474 ui.write(_(' (empty repository)'))
3473 3475 else:
3474 3476 ui.write(_(' (no revision checked out)'))
3475 3477 ui.write('\n')
3476 3478 if p.description():
3477 3479 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3478 3480 label='log.summary')
3479 3481
3480 3482 branch = ctx.branch()
3481 3483 bheads = repo.branchheads(branch)
3482 3484 m = _('branch: %s\n') % branch
3483 3485 if branch != 'default':
3484 3486 ui.write(m, label='log.branch')
3485 3487 else:
3486 3488 ui.status(m, label='log.branch')
3487 3489
3488 3490 st = list(repo.status(unknown=True))[:6]
3489 3491
3490 3492 c = repo.dirstate.copies()
3491 3493 copied, renamed = [], []
3492 3494 for d, s in c.iteritems():
3493 3495 if s in st[2]:
3494 3496 st[2].remove(s)
3495 3497 renamed.append(d)
3496 3498 else:
3497 3499 copied.append(d)
3498 3500 if d in st[1]:
3499 3501 st[1].remove(d)
3500 3502 st.insert(3, renamed)
3501 3503 st.insert(4, copied)
3502 3504
3503 3505 ms = mergemod.mergestate(repo)
3504 3506 st.append([f for f in ms if ms[f] == 'u'])
3505 3507
3506 3508 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3507 3509 st.append(subs)
3508 3510
3509 3511 labels = [ui.label(_('%d modified'), 'status.modified'),
3510 3512 ui.label(_('%d added'), 'status.added'),
3511 3513 ui.label(_('%d removed'), 'status.removed'),
3512 3514 ui.label(_('%d renamed'), 'status.copied'),
3513 3515 ui.label(_('%d copied'), 'status.copied'),
3514 3516 ui.label(_('%d deleted'), 'status.deleted'),
3515 3517 ui.label(_('%d unknown'), 'status.unknown'),
3516 3518 ui.label(_('%d ignored'), 'status.ignored'),
3517 3519 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3518 3520 ui.label(_('%d subrepos'), 'status.modified')]
3519 3521 t = []
3520 3522 for s, l in zip(st, labels):
3521 3523 if s:
3522 3524 t.append(l % len(s))
3523 3525
3524 3526 t = ', '.join(t)
3525 3527 cleanworkdir = False
3526 3528
3527 3529 if len(parents) > 1:
3528 3530 t += _(' (merge)')
3529 3531 elif branch != parents[0].branch():
3530 3532 t += _(' (new branch)')
3531 3533 elif (parents[0].extra().get('close') and
3532 3534 pnode in repo.branchheads(branch, closed=True)):
3533 3535 t += _(' (head closed)')
3534 3536 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3535 3537 t += _(' (clean)')
3536 3538 cleanworkdir = True
3537 3539 elif pnode not in bheads:
3538 3540 t += _(' (new branch head)')
3539 3541
3540 3542 if cleanworkdir:
3541 3543 ui.status(_('commit: %s\n') % t.strip())
3542 3544 else:
3543 3545 ui.write(_('commit: %s\n') % t.strip())
3544 3546
3545 3547 # all ancestors of branch heads - all ancestors of parent = new csets
3546 3548 new = [0] * len(repo)
3547 3549 cl = repo.changelog
3548 3550 for a in [cl.rev(n) for n in bheads]:
3549 3551 new[a] = 1
3550 3552 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3551 3553 new[a] = 1
3552 3554 for a in [p.rev() for p in parents]:
3553 3555 if a >= 0:
3554 3556 new[a] = 0
3555 3557 for a in cl.ancestors(*[p.rev() for p in parents]):
3556 3558 new[a] = 0
3557 3559 new = sum(new)
3558 3560
3559 3561 if new == 0:
3560 3562 ui.status(_('update: (current)\n'))
3561 3563 elif pnode not in bheads:
3562 3564 ui.write(_('update: %d new changesets (update)\n') % new)
3563 3565 else:
3564 3566 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3565 3567 (new, len(bheads)))
3566 3568
3567 3569 if opts.get('remote'):
3568 3570 t = []
3569 3571 source, branches = hg.parseurl(ui.expandpath('default'))
3570 3572 other = hg.repository(hg.remoteui(repo, {}), source)
3571 3573 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3572 3574 ui.debug('comparing with %s\n' % url.hidepassword(source))
3573 3575 repo.ui.pushbuffer()
3574 3576 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3575 3577 repo.ui.popbuffer()
3576 3578 if incoming:
3577 3579 t.append(_('1 or more incoming'))
3578 3580
3579 3581 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3580 3582 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3581 3583 other = hg.repository(hg.remoteui(repo, {}), dest)
3582 3584 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3583 3585 repo.ui.pushbuffer()
3584 3586 o = discovery.findoutgoing(repo, other)
3585 3587 repo.ui.popbuffer()
3586 3588 o = repo.changelog.nodesbetween(o, None)[0]
3587 3589 if o:
3588 3590 t.append(_('%d outgoing') % len(o))
3589 3591
3590 3592 if t:
3591 3593 ui.write(_('remote: %s\n') % (', '.join(t)))
3592 3594 else:
3593 3595 ui.status(_('remote: (synced)\n'))
3594 3596
3595 3597 def tag(ui, repo, name1, *names, **opts):
3596 3598 """add one or more tags for the current or given revision
3597 3599
3598 3600 Name a particular revision using <name>.
3599 3601
3600 3602 Tags are used to name particular revisions of the repository and are
3601 3603 very useful to compare different revisions, to go back to significant
3602 3604 earlier versions or to mark branch points as releases, etc.
3603 3605
3604 3606 If no revision is given, the parent of the working directory is
3605 3607 used, or tip if no revision is checked out.
3606 3608
3607 3609 To facilitate version control, distribution, and merging of tags,
3608 3610 they are stored as a file named ".hgtags" which is managed
3609 3611 similarly to other project files and can be hand-edited if
3610 3612 necessary. The file '.hg/localtags' is used for local tags (not
3611 3613 shared among repositories).
3612 3614
3613 3615 See :hg:`help dates` for a list of formats valid for -d/--date.
3614 3616
3615 3617 Since tag names have priority over branch names during revision
3616 3618 lookup, using an existing branch name as a tag name is discouraged.
3617 3619
3618 3620 Returns 0 on success.
3619 3621 """
3620 3622
3621 3623 rev_ = "."
3622 3624 names = [t.strip() for t in (name1,) + names]
3623 3625 if len(names) != len(set(names)):
3624 3626 raise util.Abort(_('tag names must be unique'))
3625 3627 for n in names:
3626 3628 if n in ['tip', '.', 'null']:
3627 3629 raise util.Abort(_('the name \'%s\' is reserved') % n)
3628 3630 if not n:
3629 3631 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3630 3632 if opts.get('rev') and opts.get('remove'):
3631 3633 raise util.Abort(_("--rev and --remove are incompatible"))
3632 3634 if opts.get('rev'):
3633 3635 rev_ = opts['rev']
3634 3636 message = opts.get('message')
3635 3637 if opts.get('remove'):
3636 3638 expectedtype = opts.get('local') and 'local' or 'global'
3637 3639 for n in names:
3638 3640 if not repo.tagtype(n):
3639 3641 raise util.Abort(_('tag \'%s\' does not exist') % n)
3640 3642 if repo.tagtype(n) != expectedtype:
3641 3643 if expectedtype == 'global':
3642 3644 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3643 3645 else:
3644 3646 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3645 3647 rev_ = nullid
3646 3648 if not message:
3647 3649 # we don't translate commit messages
3648 3650 message = 'Removed tag %s' % ', '.join(names)
3649 3651 elif not opts.get('force'):
3650 3652 for n in names:
3651 3653 if n in repo.tags():
3652 3654 raise util.Abort(_('tag \'%s\' already exists '
3653 3655 '(use -f to force)') % n)
3654 3656 if not rev_ and repo.dirstate.parents()[1] != nullid:
3655 3657 raise util.Abort(_('uncommitted merge - please provide a '
3656 3658 'specific revision'))
3657 3659 r = repo[rev_].node()
3658 3660
3659 3661 if not message:
3660 3662 # we don't translate commit messages
3661 3663 message = ('Added tag %s for changeset %s' %
3662 3664 (', '.join(names), short(r)))
3663 3665
3664 3666 date = opts.get('date')
3665 3667 if date:
3666 3668 date = util.parsedate(date)
3667 3669
3668 3670 if opts.get('edit'):
3669 3671 message = ui.edit(message, ui.username())
3670 3672
3671 3673 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3672 3674
3673 3675 def tags(ui, repo):
3674 3676 """list repository tags
3675 3677
3676 3678 This lists both regular and local tags. When the -v/--verbose
3677 3679 switch is used, a third column "local" is printed for local tags.
3678 3680
3679 3681 Returns 0 on success.
3680 3682 """
3681 3683
3682 3684 hexfunc = ui.debugflag and hex or short
3683 3685 tagtype = ""
3684 3686
3685 3687 for t, n in reversed(repo.tagslist()):
3686 3688 if ui.quiet:
3687 3689 ui.write("%s\n" % t)
3688 3690 continue
3689 3691
3690 3692 try:
3691 3693 hn = hexfunc(n)
3692 3694 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3693 3695 except error.LookupError:
3694 3696 r = " ?:%s" % hn
3695 3697 else:
3696 3698 spaces = " " * (30 - encoding.colwidth(t))
3697 3699 if ui.verbose:
3698 3700 if repo.tagtype(t) == 'local':
3699 3701 tagtype = " local"
3700 3702 else:
3701 3703 tagtype = ""
3702 3704 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3703 3705
3704 3706 def tip(ui, repo, **opts):
3705 3707 """show the tip revision
3706 3708
3707 3709 The tip revision (usually just called the tip) is the changeset
3708 3710 most recently added to the repository (and therefore the most
3709 3711 recently changed head).
3710 3712
3711 3713 If you have just made a commit, that commit will be the tip. If
3712 3714 you have just pulled changes from another repository, the tip of
3713 3715 that repository becomes the current tip. The "tip" tag is special
3714 3716 and cannot be renamed or assigned to a different changeset.
3715 3717
3716 3718 Returns 0 on success.
3717 3719 """
3718 3720 displayer = cmdutil.show_changeset(ui, repo, opts)
3719 3721 displayer.show(repo[len(repo) - 1])
3720 3722 displayer.close()
3721 3723
3722 3724 def unbundle(ui, repo, fname1, *fnames, **opts):
3723 3725 """apply one or more changegroup files
3724 3726
3725 3727 Apply one or more compressed changegroup files generated by the
3726 3728 bundle command.
3727 3729
3728 3730 Returns 0 on success, 1 if an update has unresolved files.
3729 3731 """
3730 3732 fnames = (fname1,) + fnames
3731 3733
3732 3734 lock = repo.lock()
3733 3735 try:
3734 3736 for fname in fnames:
3735 3737 f = url.open(ui, fname)
3736 3738 gen = changegroup.readbundle(f, fname)
3737 3739 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3738 3740 lock=lock)
3739 3741 finally:
3740 3742 lock.release()
3741 3743
3742 3744 return postincoming(ui, repo, modheads, opts.get('update'), None)
3743 3745
3744 3746 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3745 3747 """update working directory (or switch revisions)
3746 3748
3747 3749 Update the repository's working directory to the specified
3748 3750 changeset. If no changeset is specified, update to the tip of the
3749 3751 current named branch.
3750 3752
3751 3753 If the changeset is not a descendant of the working directory's
3752 3754 parent, the update is aborted. With the -c/--check option, the
3753 3755 working directory is checked for uncommitted changes; if none are
3754 3756 found, the working directory is updated to the specified
3755 3757 changeset.
3756 3758
3757 3759 The following rules apply when the working directory contains
3758 3760 uncommitted changes:
3759 3761
3760 3762 1. If neither -c/--check nor -C/--clean is specified, and if
3761 3763 the requested changeset is an ancestor or descendant of
3762 3764 the working directory's parent, the uncommitted changes
3763 3765 are merged into the requested changeset and the merged
3764 3766 result is left uncommitted. If the requested changeset is
3765 3767 not an ancestor or descendant (that is, it is on another
3766 3768 branch), the update is aborted and the uncommitted changes
3767 3769 are preserved.
3768 3770
3769 3771 2. With the -c/--check option, the update is aborted and the
3770 3772 uncommitted changes are preserved.
3771 3773
3772 3774 3. With the -C/--clean option, uncommitted changes are discarded and
3773 3775 the working directory is updated to the requested changeset.
3774 3776
3775 3777 Use null as the changeset to remove the working directory (like
3776 3778 :hg:`clone -U`).
3777 3779
3778 3780 If you want to update just one file to an older changeset, use
3779 3781 :hg:`revert`.
3780 3782
3781 3783 See :hg:`help dates` for a list of formats valid for -d/--date.
3782 3784
3783 3785 Returns 0 on success, 1 if there are unresolved files.
3784 3786 """
3785 3787 if rev and node:
3786 3788 raise util.Abort(_("please specify just one revision"))
3787 3789
3788 3790 if not rev:
3789 3791 rev = node
3790 3792
3791 3793 if check and clean:
3792 3794 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3793 3795
3794 3796 if check:
3795 3797 # we could use dirty() but we can ignore merge and branch trivia
3796 3798 c = repo[None]
3797 3799 if c.modified() or c.added() or c.removed():
3798 3800 raise util.Abort(_("uncommitted local changes"))
3799 3801
3800 3802 if date:
3801 3803 if rev:
3802 3804 raise util.Abort(_("you can't specify a revision and a date"))
3803 3805 rev = cmdutil.finddate(ui, repo, date)
3804 3806
3805 3807 if clean or check:
3806 3808 return hg.clean(repo, rev)
3807 3809 else:
3808 3810 return hg.update(repo, rev)
3809 3811
3810 3812 def verify(ui, repo):
3811 3813 """verify the integrity of the repository
3812 3814
3813 3815 Verify the integrity of the current repository.
3814 3816
3815 3817 This will perform an extensive check of the repository's
3816 3818 integrity, validating the hashes and checksums of each entry in
3817 3819 the changelog, manifest, and tracked files, as well as the
3818 3820 integrity of their crosslinks and indices.
3819 3821
3820 3822 Returns 0 on success, 1 if errors are encountered.
3821 3823 """
3822 3824 return hg.verify(repo)
3823 3825
3824 3826 def version_(ui):
3825 3827 """output version and copyright information"""
3826 3828 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3827 3829 % util.version())
3828 3830 ui.status(_(
3829 3831 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3830 3832 "This is free software; see the source for copying conditions. "
3831 3833 "There is NO\nwarranty; "
3832 3834 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3833 3835 ))
3834 3836
3835 3837 # Command options and aliases are listed here, alphabetically
3836 3838
3837 3839 globalopts = [
3838 3840 ('R', 'repository', '',
3839 3841 _('repository root directory or name of overlay bundle file'),
3840 3842 _('REPO')),
3841 3843 ('', 'cwd', '',
3842 3844 _('change working directory'), _('DIR')),
3843 3845 ('y', 'noninteractive', None,
3844 3846 _('do not prompt, assume \'yes\' for any required answers')),
3845 3847 ('q', 'quiet', None, _('suppress output')),
3846 3848 ('v', 'verbose', None, _('enable additional output')),
3847 3849 ('', 'config', [],
3848 3850 _('set/override config option (use \'section.name=value\')'),
3849 3851 _('CONFIG')),
3850 3852 ('', 'debug', None, _('enable debugging output')),
3851 3853 ('', 'debugger', None, _('start debugger')),
3852 3854 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3853 3855 _('ENCODE')),
3854 3856 ('', 'encodingmode', encoding.encodingmode,
3855 3857 _('set the charset encoding mode'), _('MODE')),
3856 3858 ('', 'traceback', None, _('always print a traceback on exception')),
3857 3859 ('', 'time', None, _('time how long the command takes')),
3858 3860 ('', 'profile', None, _('print command execution profile')),
3859 3861 ('', 'version', None, _('output version information and exit')),
3860 3862 ('h', 'help', None, _('display help and exit')),
3861 3863 ]
3862 3864
3863 3865 dryrunopts = [('n', 'dry-run', None,
3864 3866 _('do not perform actions, just print output'))]
3865 3867
3866 3868 remoteopts = [
3867 3869 ('e', 'ssh', '',
3868 3870 _('specify ssh command to use'), _('CMD')),
3869 3871 ('', 'remotecmd', '',
3870 3872 _('specify hg command to run on the remote side'), _('CMD')),
3871 3873 ]
3872 3874
3873 3875 walkopts = [
3874 3876 ('I', 'include', [],
3875 3877 _('include names matching the given patterns'), _('PATTERN')),
3876 3878 ('X', 'exclude', [],
3877 3879 _('exclude names matching the given patterns'), _('PATTERN')),
3878 3880 ]
3879 3881
3880 3882 commitopts = [
3881 3883 ('m', 'message', '',
3882 3884 _('use text as commit message'), _('TEXT')),
3883 3885 ('l', 'logfile', '',
3884 3886 _('read commit message from file'), _('FILE')),
3885 3887 ]
3886 3888
3887 3889 commitopts2 = [
3888 3890 ('d', 'date', '',
3889 3891 _('record datecode as commit date'), _('DATE')),
3890 3892 ('u', 'user', '',
3891 3893 _('record the specified user as committer'), _('USER')),
3892 3894 ]
3893 3895
3894 3896 templateopts = [
3895 3897 ('', 'style', '',
3896 3898 _('display using template map file'), _('STYLE')),
3897 3899 ('', 'template', '',
3898 3900 _('display with template'), _('TEMPLATE')),
3899 3901 ]
3900 3902
3901 3903 logopts = [
3902 3904 ('p', 'patch', None, _('show patch')),
3903 3905 ('g', 'git', None, _('use git extended diff format')),
3904 3906 ('l', 'limit', '',
3905 3907 _('limit number of changes displayed'), _('NUM')),
3906 3908 ('M', 'no-merges', None, _('do not show merges')),
3907 3909 ('', 'stat', None, _('output diffstat-style summary of changes')),
3908 3910 ] + templateopts
3909 3911
3910 3912 diffopts = [
3911 3913 ('a', 'text', None, _('treat all files as text')),
3912 3914 ('g', 'git', None, _('use git extended diff format')),
3913 3915 ('', 'nodates', None, _('omit dates from diff headers'))
3914 3916 ]
3915 3917
3916 3918 diffopts2 = [
3917 3919 ('p', 'show-function', None, _('show which function each change is in')),
3918 3920 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3919 3921 ('w', 'ignore-all-space', None,
3920 3922 _('ignore white space when comparing lines')),
3921 3923 ('b', 'ignore-space-change', None,
3922 3924 _('ignore changes in the amount of white space')),
3923 3925 ('B', 'ignore-blank-lines', None,
3924 3926 _('ignore changes whose lines are all blank')),
3925 3927 ('U', 'unified', '',
3926 3928 _('number of lines of context to show'), _('NUM')),
3927 3929 ('', 'stat', None, _('output diffstat-style summary of changes')),
3928 3930 ]
3929 3931
3930 3932 similarityopts = [
3931 3933 ('s', 'similarity', '',
3932 3934 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3933 3935 ]
3934 3936
3935 3937 subrepoopts = [
3936 3938 ('S', 'subrepos', None,
3937 3939 _('recurse into subrepositories'))
3938 3940 ]
3939 3941
3940 3942 table = {
3941 3943 "^add": (add, walkopts + subrepoopts + dryrunopts,
3942 3944 _('[OPTION]... [FILE]...')),
3943 3945 "addremove":
3944 3946 (addremove, similarityopts + walkopts + dryrunopts,
3945 3947 _('[OPTION]... [FILE]...')),
3946 3948 "^annotate|blame":
3947 3949 (annotate,
3948 3950 [('r', 'rev', '',
3949 3951 _('annotate the specified revision'), _('REV')),
3950 3952 ('', 'follow', None,
3951 3953 _('follow copies/renames and list the filename (DEPRECATED)')),
3952 3954 ('', 'no-follow', None, _("don't follow copies and renames")),
3953 3955 ('a', 'text', None, _('treat all files as text')),
3954 3956 ('u', 'user', None, _('list the author (long with -v)')),
3955 3957 ('f', 'file', None, _('list the filename')),
3956 3958 ('d', 'date', None, _('list the date (short with -q)')),
3957 3959 ('n', 'number', None, _('list the revision number (default)')),
3958 3960 ('c', 'changeset', None, _('list the changeset')),
3959 3961 ('l', 'line-number', None,
3960 3962 _('show line number at the first appearance'))
3961 3963 ] + walkopts,
3962 3964 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3963 3965 "archive":
3964 3966 (archive,
3965 3967 [('', 'no-decode', None, _('do not pass files through decoders')),
3966 3968 ('p', 'prefix', '',
3967 3969 _('directory prefix for files in archive'), _('PREFIX')),
3968 3970 ('r', 'rev', '',
3969 3971 _('revision to distribute'), _('REV')),
3970 3972 ('t', 'type', '',
3971 3973 _('type of distribution to create'), _('TYPE')),
3972 3974 ] + subrepoopts + walkopts,
3973 3975 _('[OPTION]... DEST')),
3974 3976 "backout":
3975 3977 (backout,
3976 3978 [('', 'merge', None,
3977 3979 _('merge with old dirstate parent after backout')),
3978 3980 ('', 'parent', '',
3979 3981 _('parent to choose when backing out merge'), _('REV')),
3980 3982 ('r', 'rev', '',
3981 3983 _('revision to backout'), _('REV')),
3982 3984 ] + walkopts + commitopts + commitopts2,
3983 3985 _('[OPTION]... [-r] REV')),
3984 3986 "bisect":
3985 3987 (bisect,
3986 3988 [('r', 'reset', False, _('reset bisect state')),
3987 3989 ('g', 'good', False, _('mark changeset good')),
3988 3990 ('b', 'bad', False, _('mark changeset bad')),
3989 3991 ('s', 'skip', False, _('skip testing changeset')),
3990 3992 ('c', 'command', '',
3991 3993 _('use command to check changeset state'), _('CMD')),
3992 3994 ('U', 'noupdate', False, _('do not update to target'))],
3993 3995 _("[-gbsr] [-U] [-c CMD] [REV]")),
3994 3996 "branch":
3995 3997 (branch,
3996 3998 [('f', 'force', None,
3997 3999 _('set branch name even if it shadows an existing branch')),
3998 4000 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3999 4001 _('[-fC] [NAME]')),
4000 4002 "branches":
4001 4003 (branches,
4002 4004 [('a', 'active', False,
4003 4005 _('show only branches that have unmerged heads')),
4004 4006 ('c', 'closed', False,
4005 4007 _('show normal and closed branches'))],
4006 4008 _('[-ac]')),
4007 4009 "bundle":
4008 4010 (bundle,
4009 4011 [('f', 'force', None,
4010 4012 _('run even when the destination is unrelated')),
4011 4013 ('r', 'rev', [],
4012 4014 _('a changeset intended to be added to the destination'),
4013 4015 _('REV')),
4014 4016 ('b', 'branch', [],
4015 4017 _('a specific branch you would like to bundle'),
4016 4018 _('BRANCH')),
4017 4019 ('', 'base', [],
4018 4020 _('a base changeset assumed to be available at the destination'),
4019 4021 _('REV')),
4020 4022 ('a', 'all', None, _('bundle all changesets in the repository')),
4021 4023 ('t', 'type', 'bzip2',
4022 4024 _('bundle compression type to use'), _('TYPE')),
4023 4025 ] + remoteopts,
4024 4026 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4025 4027 "cat":
4026 4028 (cat,
4027 4029 [('o', 'output', '',
4028 4030 _('print output to file with formatted name'), _('FORMAT')),
4029 4031 ('r', 'rev', '',
4030 4032 _('print the given revision'), _('REV')),
4031 4033 ('', 'decode', None, _('apply any matching decode filter')),
4032 4034 ] + walkopts,
4033 4035 _('[OPTION]... FILE...')),
4034 4036 "^clone":
4035 4037 (clone,
4036 4038 [('U', 'noupdate', None,
4037 4039 _('the clone will include an empty working copy (only a repository)')),
4038 4040 ('u', 'updaterev', '',
4039 4041 _('revision, tag or branch to check out'), _('REV')),
4040 4042 ('r', 'rev', [],
4041 4043 _('include the specified changeset'), _('REV')),
4042 4044 ('b', 'branch', [],
4043 4045 _('clone only the specified branch'), _('BRANCH')),
4044 4046 ('', 'pull', None, _('use pull protocol to copy metadata')),
4045 4047 ('', 'uncompressed', None,
4046 4048 _('use uncompressed transfer (fast over LAN)')),
4047 4049 ] + remoteopts,
4048 4050 _('[OPTION]... SOURCE [DEST]')),
4049 4051 "^commit|ci":
4050 4052 (commit,
4051 4053 [('A', 'addremove', None,
4052 4054 _('mark new/missing files as added/removed before committing')),
4053 4055 ('', 'close-branch', None,
4054 4056 _('mark a branch as closed, hiding it from the branch list')),
4055 4057 ] + walkopts + commitopts + commitopts2,
4056 4058 _('[OPTION]... [FILE]...')),
4057 4059 "copy|cp":
4058 4060 (copy,
4059 4061 [('A', 'after', None, _('record a copy that has already occurred')),
4060 4062 ('f', 'force', None,
4061 4063 _('forcibly copy over an existing managed file')),
4062 4064 ] + walkopts + dryrunopts,
4063 4065 _('[OPTION]... [SOURCE]... DEST')),
4064 4066 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4065 4067 "debugbuilddag":
4066 4068 (debugbuilddag,
4067 4069 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4068 4070 ('a', 'appended-file', None, _('add single file all revs append to')),
4069 4071 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4070 4072 ('n', 'new-file', None, _('add new file at each rev')),
4071 4073 ],
4072 4074 _('[OPTION]... TEXT')),
4073 4075 "debugcheckstate": (debugcheckstate, [], ''),
4074 4076 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4075 4077 "debugcomplete":
4076 4078 (debugcomplete,
4077 4079 [('o', 'options', None, _('show the command options'))],
4078 4080 _('[-o] CMD')),
4079 4081 "debugdag":
4080 4082 (debugdag,
4081 4083 [('t', 'tags', None, _('use tags as labels')),
4082 4084 ('b', 'branches', None, _('annotate with branch names')),
4083 4085 ('', 'dots', None, _('use dots for runs')),
4084 4086 ('s', 'spaces', None, _('separate elements by spaces')),
4085 4087 ],
4086 4088 _('[OPTION]... [FILE [REV]...]')),
4087 4089 "debugdate":
4088 4090 (debugdate,
4089 4091 [('e', 'extended', None, _('try extended date formats'))],
4090 4092 _('[-e] DATE [RANGE]')),
4091 4093 "debugdata": (debugdata, [], _('FILE REV')),
4092 4094 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4093 4095 "debugindex": (debugindex, [], _('FILE')),
4094 4096 "debugindexdot": (debugindexdot, [], _('FILE')),
4095 4097 "debuginstall": (debuginstall, [], ''),
4096 4098 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4097 4099 "debugrebuildstate":
4098 4100 (debugrebuildstate,
4099 4101 [('r', 'rev', '',
4100 4102 _('revision to rebuild to'), _('REV'))],
4101 4103 _('[-r REV] [REV]')),
4102 4104 "debugrename":
4103 4105 (debugrename,
4104 4106 [('r', 'rev', '',
4105 4107 _('revision to debug'), _('REV'))],
4106 4108 _('[-r REV] FILE')),
4107 4109 "debugrevspec":
4108 4110 (debugrevspec, [], ('REVSPEC')),
4109 4111 "debugsetparents":
4110 4112 (debugsetparents, [], _('REV1 [REV2]')),
4111 4113 "debugstate":
4112 4114 (debugstate,
4113 4115 [('', 'nodates', None, _('do not display the saved mtime'))],
4114 4116 _('[OPTION]...')),
4115 4117 "debugsub":
4116 4118 (debugsub,
4117 4119 [('r', 'rev', '',
4118 4120 _('revision to check'), _('REV'))],
4119 4121 _('[-r REV] [REV]')),
4120 4122 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4121 4123 "^diff":
4122 4124 (diff,
4123 4125 [('r', 'rev', [],
4124 4126 _('revision'), _('REV')),
4125 4127 ('c', 'change', '',
4126 4128 _('change made by revision'), _('REV'))
4127 4129 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4128 4130 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4129 4131 "^export":
4130 4132 (export,
4131 4133 [('o', 'output', '',
4132 4134 _('print output to file with formatted name'), _('FORMAT')),
4133 4135 ('', 'switch-parent', None, _('diff against the second parent')),
4134 4136 ('r', 'rev', [],
4135 4137 _('revisions to export'), _('REV')),
4136 4138 ] + diffopts,
4137 4139 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4138 4140 "^forget":
4139 4141 (forget,
4140 4142 [] + walkopts,
4141 4143 _('[OPTION]... FILE...')),
4142 4144 "grep":
4143 4145 (grep,
4144 4146 [('0', 'print0', None, _('end fields with NUL')),
4145 4147 ('', 'all', None, _('print all revisions that match')),
4146 4148 ('f', 'follow', None,
4147 4149 _('follow changeset history,'
4148 4150 ' or file history across copies and renames')),
4149 4151 ('i', 'ignore-case', None, _('ignore case when matching')),
4150 4152 ('l', 'files-with-matches', None,
4151 4153 _('print only filenames and revisions that match')),
4152 4154 ('n', 'line-number', None, _('print matching line numbers')),
4153 4155 ('r', 'rev', [],
4154 4156 _('only search files changed within revision range'), _('REV')),
4155 4157 ('u', 'user', None, _('list the author (long with -v)')),
4156 4158 ('d', 'date', None, _('list the date (short with -q)')),
4157 4159 ] + walkopts,
4158 4160 _('[OPTION]... PATTERN [FILE]...')),
4159 4161 "heads":
4160 4162 (heads,
4161 4163 [('r', 'rev', '',
4162 4164 _('show only heads which are descendants of STARTREV'),
4163 4165 _('STARTREV')),
4164 4166 ('t', 'topo', False, _('show topological heads only')),
4165 4167 ('a', 'active', False,
4166 4168 _('show active branchheads only (DEPRECATED)')),
4167 4169 ('c', 'closed', False,
4168 4170 _('show normal and closed branch heads')),
4169 4171 ] + templateopts,
4170 4172 _('[-ac] [-r STARTREV] [REV]...')),
4171 4173 "help": (help_, [], _('[TOPIC]')),
4172 4174 "identify|id":
4173 4175 (identify,
4174 4176 [('r', 'rev', '',
4175 4177 _('identify the specified revision'), _('REV')),
4176 4178 ('n', 'num', None, _('show local revision number')),
4177 4179 ('i', 'id', None, _('show global revision id')),
4178 4180 ('b', 'branch', None, _('show branch')),
4179 4181 ('t', 'tags', None, _('show tags'))],
4180 4182 _('[-nibt] [-r REV] [SOURCE]')),
4181 4183 "import|patch":
4182 4184 (import_,
4183 4185 [('p', 'strip', 1,
4184 4186 _('directory strip option for patch. This has the same '
4185 4187 'meaning as the corresponding patch option'),
4186 4188 _('NUM')),
4187 4189 ('b', 'base', '',
4188 4190 _('base path'), _('PATH')),
4189 4191 ('f', 'force', None,
4190 4192 _('skip check for outstanding uncommitted changes')),
4191 4193 ('', 'no-commit', None,
4192 4194 _("don't commit, just update the working directory")),
4193 4195 ('', 'exact', None,
4194 4196 _('apply patch to the nodes from which it was generated')),
4195 4197 ('', 'import-branch', None,
4196 4198 _('use any branch information in patch (implied by --exact)'))] +
4197 4199 commitopts + commitopts2 + similarityopts,
4198 4200 _('[OPTION]... PATCH...')),
4199 4201 "incoming|in":
4200 4202 (incoming,
4201 4203 [('f', 'force', None,
4202 4204 _('run even if remote repository is unrelated')),
4203 4205 ('n', 'newest-first', None, _('show newest record first')),
4204 4206 ('', 'bundle', '',
4205 4207 _('file to store the bundles into'), _('FILE')),
4206 4208 ('r', 'rev', [],
4207 4209 _('a remote changeset intended to be added'), _('REV')),
4208 4210 ('b', 'branch', [],
4209 4211 _('a specific branch you would like to pull'), _('BRANCH')),
4210 4212 ] + logopts + remoteopts + subrepoopts,
4211 4213 _('[-p] [-n] [-M] [-f] [-r REV]...'
4212 4214 ' [--bundle FILENAME] [SOURCE]')),
4213 4215 "^init":
4214 4216 (init,
4215 4217 remoteopts,
4216 4218 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4217 4219 "locate":
4218 4220 (locate,
4219 4221 [('r', 'rev', '',
4220 4222 _('search the repository as it is in REV'), _('REV')),
4221 4223 ('0', 'print0', None,
4222 4224 _('end filenames with NUL, for use with xargs')),
4223 4225 ('f', 'fullpath', None,
4224 4226 _('print complete paths from the filesystem root')),
4225 4227 ] + walkopts,
4226 4228 _('[OPTION]... [PATTERN]...')),
4227 4229 "^log|history":
4228 4230 (log,
4229 4231 [('f', 'follow', None,
4230 4232 _('follow changeset history,'
4231 4233 ' or file history across copies and renames')),
4232 4234 ('', 'follow-first', None,
4233 4235 _('only follow the first parent of merge changesets')),
4234 4236 ('d', 'date', '',
4235 4237 _('show revisions matching date spec'), _('DATE')),
4236 4238 ('C', 'copies', None, _('show copied files')),
4237 4239 ('k', 'keyword', [],
4238 4240 _('do case-insensitive search for a given text'), _('TEXT')),
4239 4241 ('r', 'rev', [],
4240 4242 _('show the specified revision or range'), _('REV')),
4241 4243 ('', 'removed', None, _('include revisions where files were removed')),
4242 4244 ('m', 'only-merges', None, _('show only merges')),
4243 4245 ('u', 'user', [],
4244 4246 _('revisions committed by user'), _('USER')),
4245 4247 ('', 'only-branch', [],
4246 4248 _('show only changesets within the given named branch (DEPRECATED)'),
4247 4249 _('BRANCH')),
4248 4250 ('b', 'branch', [],
4249 4251 _('show changesets within the given named branch'), _('BRANCH')),
4250 4252 ('P', 'prune', [],
4251 4253 _('do not display revision or any of its ancestors'), _('REV')),
4252 4254 ] + logopts + walkopts,
4253 4255 _('[OPTION]... [FILE]')),
4254 4256 "manifest":
4255 4257 (manifest,
4256 4258 [('r', 'rev', '',
4257 4259 _('revision to display'), _('REV'))],
4258 4260 _('[-r REV]')),
4259 4261 "^merge":
4260 4262 (merge,
4261 4263 [('f', 'force', None, _('force a merge with outstanding changes')),
4262 4264 ('r', 'rev', '',
4263 4265 _('revision to merge'), _('REV')),
4264 4266 ('P', 'preview', None,
4265 4267 _('review revisions to merge (no merge is performed)'))],
4266 4268 _('[-P] [-f] [[-r] REV]')),
4267 4269 "outgoing|out":
4268 4270 (outgoing,
4269 4271 [('f', 'force', None,
4270 4272 _('run even when the destination is unrelated')),
4271 4273 ('r', 'rev', [],
4272 4274 _('a changeset intended to be included in the destination'),
4273 4275 _('REV')),
4274 4276 ('n', 'newest-first', None, _('show newest record first')),
4275 4277 ('b', 'branch', [],
4276 4278 _('a specific branch you would like to push'), _('BRANCH')),
4277 4279 ] + logopts + remoteopts + subrepoopts,
4278 4280 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4279 4281 "parents":
4280 4282 (parents,
4281 4283 [('r', 'rev', '',
4282 4284 _('show parents of the specified revision'), _('REV')),
4283 4285 ] + templateopts,
4284 4286 _('[-r REV] [FILE]')),
4285 4287 "paths": (paths, [], _('[NAME]')),
4286 4288 "^pull":
4287 4289 (pull,
4288 4290 [('u', 'update', None,
4289 4291 _('update to new branch head if changesets were pulled')),
4290 4292 ('f', 'force', None,
4291 4293 _('run even when remote repository is unrelated')),
4292 4294 ('r', 'rev', [],
4293 4295 _('a remote changeset intended to be added'), _('REV')),
4294 4296 ('b', 'branch', [],
4295 4297 _('a specific branch you would like to pull'), _('BRANCH')),
4296 4298 ] + remoteopts,
4297 4299 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4298 4300 "^push":
4299 4301 (push,
4300 4302 [('f', 'force', None, _('force push')),
4301 4303 ('r', 'rev', [],
4302 4304 _('a changeset intended to be included in the destination'),
4303 4305 _('REV')),
4304 4306 ('b', 'branch', [],
4305 4307 _('a specific branch you would like to push'), _('BRANCH')),
4306 4308 ('', 'new-branch', False, _('allow pushing a new branch')),
4307 4309 ] + remoteopts,
4308 4310 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4309 4311 "recover": (recover, []),
4310 4312 "^remove|rm":
4311 4313 (remove,
4312 4314 [('A', 'after', None, _('record delete for missing files')),
4313 4315 ('f', 'force', None,
4314 4316 _('remove (and delete) file even if added or modified')),
4315 4317 ] + walkopts,
4316 4318 _('[OPTION]... FILE...')),
4317 4319 "rename|mv":
4318 4320 (rename,
4319 4321 [('A', 'after', None, _('record a rename that has already occurred')),
4320 4322 ('f', 'force', None,
4321 4323 _('forcibly copy over an existing managed file')),
4322 4324 ] + walkopts + dryrunopts,
4323 4325 _('[OPTION]... SOURCE... DEST')),
4324 4326 "resolve":
4325 4327 (resolve,
4326 4328 [('a', 'all', None, _('select all unresolved files')),
4327 4329 ('l', 'list', None, _('list state of files needing merge')),
4328 4330 ('m', 'mark', None, _('mark files as resolved')),
4329 4331 ('u', 'unmark', None, _('mark files as unresolved')),
4330 4332 ('n', 'no-status', None, _('hide status prefix'))]
4331 4333 + walkopts,
4332 4334 _('[OPTION]... [FILE]...')),
4333 4335 "revert":
4334 4336 (revert,
4335 4337 [('a', 'all', None, _('revert all changes when no arguments given')),
4336 4338 ('d', 'date', '',
4337 4339 _('tipmost revision matching date'), _('DATE')),
4338 4340 ('r', 'rev', '',
4339 4341 _('revert to the specified revision'), _('REV')),
4340 4342 ('', 'no-backup', None, _('do not save backup copies of files')),
4341 4343 ] + walkopts + dryrunopts,
4342 4344 _('[OPTION]... [-r REV] [NAME]...')),
4343 4345 "rollback": (rollback, dryrunopts),
4344 4346 "root": (root, []),
4345 4347 "^serve":
4346 4348 (serve,
4347 4349 [('A', 'accesslog', '',
4348 4350 _('name of access log file to write to'), _('FILE')),
4349 4351 ('d', 'daemon', None, _('run server in background')),
4350 4352 ('', 'daemon-pipefds', '',
4351 4353 _('used internally by daemon mode'), _('NUM')),
4352 4354 ('E', 'errorlog', '',
4353 4355 _('name of error log file to write to'), _('FILE')),
4354 4356 # use string type, then we can check if something was passed
4355 4357 ('p', 'port', '',
4356 4358 _('port to listen on (default: 8000)'), _('PORT')),
4357 4359 ('a', 'address', '',
4358 4360 _('address to listen on (default: all interfaces)'), _('ADDR')),
4359 4361 ('', 'prefix', '',
4360 4362 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4361 4363 ('n', 'name', '',
4362 4364 _('name to show in web pages (default: working directory)'),
4363 4365 _('NAME')),
4364 4366 ('', 'web-conf', '',
4365 4367 _('name of the hgweb config file (see "hg help hgweb")'),
4366 4368 _('FILE')),
4367 4369 ('', 'webdir-conf', '',
4368 4370 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4369 4371 ('', 'pid-file', '',
4370 4372 _('name of file to write process ID to'), _('FILE')),
4371 4373 ('', 'stdio', None, _('for remote clients')),
4372 4374 ('t', 'templates', '',
4373 4375 _('web templates to use'), _('TEMPLATE')),
4374 4376 ('', 'style', '',
4375 4377 _('template style to use'), _('STYLE')),
4376 4378 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4377 4379 ('', 'certificate', '',
4378 4380 _('SSL certificate file'), _('FILE'))],
4379 4381 _('[OPTION]...')),
4380 4382 "showconfig|debugconfig":
4381 4383 (showconfig,
4382 4384 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4383 4385 _('[-u] [NAME]...')),
4384 4386 "^summary|sum":
4385 4387 (summary,
4386 4388 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4387 4389 "^status|st":
4388 4390 (status,
4389 4391 [('A', 'all', None, _('show status of all files')),
4390 4392 ('m', 'modified', None, _('show only modified files')),
4391 4393 ('a', 'added', None, _('show only added files')),
4392 4394 ('r', 'removed', None, _('show only removed files')),
4393 4395 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4394 4396 ('c', 'clean', None, _('show only files without changes')),
4395 4397 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4396 4398 ('i', 'ignored', None, _('show only ignored files')),
4397 4399 ('n', 'no-status', None, _('hide status prefix')),
4398 4400 ('C', 'copies', None, _('show source of copied files')),
4399 4401 ('0', 'print0', None,
4400 4402 _('end filenames with NUL, for use with xargs')),
4401 4403 ('', 'rev', [],
4402 4404 _('show difference from revision'), _('REV')),
4403 4405 ('', 'change', '',
4404 4406 _('list the changed files of a revision'), _('REV')),
4405 4407 ] + walkopts + subrepoopts,
4406 4408 _('[OPTION]... [FILE]...')),
4407 4409 "tag":
4408 4410 (tag,
4409 4411 [('f', 'force', None, _('replace existing tag')),
4410 4412 ('l', 'local', None, _('make the tag local')),
4411 4413 ('r', 'rev', '',
4412 4414 _('revision to tag'), _('REV')),
4413 4415 ('', 'remove', None, _('remove a tag')),
4414 4416 # -l/--local is already there, commitopts cannot be used
4415 4417 ('e', 'edit', None, _('edit commit message')),
4416 4418 ('m', 'message', '',
4417 4419 _('use <text> as commit message'), _('TEXT')),
4418 4420 ] + commitopts2,
4419 4421 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4420 4422 "tags": (tags, [], ''),
4421 4423 "tip":
4422 4424 (tip,
4423 4425 [('p', 'patch', None, _('show patch')),
4424 4426 ('g', 'git', None, _('use git extended diff format')),
4425 4427 ] + templateopts,
4426 4428 _('[-p] [-g]')),
4427 4429 "unbundle":
4428 4430 (unbundle,
4429 4431 [('u', 'update', None,
4430 4432 _('update to new branch head if changesets were unbundled'))],
4431 4433 _('[-u] FILE...')),
4432 4434 "^update|up|checkout|co":
4433 4435 (update,
4434 4436 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4435 4437 ('c', 'check', None,
4436 4438 _('update across branches if no uncommitted changes')),
4437 4439 ('d', 'date', '',
4438 4440 _('tipmost revision matching date'), _('DATE')),
4439 4441 ('r', 'rev', '',
4440 4442 _('revision'), _('REV'))],
4441 4443 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4442 4444 "verify": (verify, []),
4443 4445 "version": (version_, []),
4444 4446 }
4445 4447
4446 4448 norepo = ("clone init version help debugcommands debugcomplete"
4447 4449 " debugdate debuginstall debugfsinfo debugpushkey")
4448 4450 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4449 4451 " debugdata debugindex debugindexdot")
@@ -1,119 +1,135 b''
1 1 Use hgrc within $TESTTMP
2 2
3 3 $ HGRCPATH=`pwd`/hgrc
4 4 $ export HGRCPATH
5 5
6 6 Basic syntax error
7 7
8 8 $ echo "invalid" > $HGRCPATH
9 9 $ hg version
10 10 hg: parse error at $TESTTMP/hgrc:1: invalid
11 11 [255]
12 12 $ echo "" > $HGRCPATH
13 13
14 14 Issue1199: Can't use '%' in hgrc (eg url encoded username)
15 15
16 16 $ hg init "foo%bar"
17 17 $ hg clone "foo%bar" foobar
18 18 updating to branch default
19 19 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 20 $ cd foobar
21 21 $ cat .hg/hgrc
22 22 [paths]
23 23 default = */foo%bar (glob)
24 24 $ hg paths
25 25 default = */foo%bar (glob)
26 26 $ hg showconfig
27 27 bundle.mainreporoot=*/foobar (glob)
28 28 paths.default=*/foo%bar (glob)
29 29 $ cd ..
30 30
31 31 issue1829: wrong indentation
32 32
33 33 $ echo '[foo]' > $HGRCPATH
34 34 $ echo ' x = y' >> $HGRCPATH
35 35 $ hg version
36 36 hg: parse error at $TESTTMP/hgrc:2: x = y
37 37 [255]
38 38
39 39 $ python -c "print '[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n'" \
40 40 > > $HGRCPATH
41 41 $ hg showconfig foo
42 42 foo.bar=a\nb\nc\nde\nfg
43 43 foo.baz=bif cb
44 44
45 45 $ FAKEPATH=/path/to/nowhere
46 46 $ export FAKEPATH
47 47 $ echo '%include $FAKEPATH/no-such-file' > $HGRCPATH
48 48 $ hg version
49 49 hg: parse error at $TESTTMP/hgrc:1: cannot include /path/to/nowhere/no-such-file (No such file or directory)
50 50 [255]
51 51 $ unset FAKEPATH
52 52
53 53 username expansion
54 54
55 55 $ olduser=$HGUSER
56 56 $ unset HGUSER
57 57
58 58 $ FAKEUSER='John Doe'
59 59 $ export FAKEUSER
60 60 $ echo '[ui]' > $HGRCPATH
61 61 $ echo 'username = $FAKEUSER' >> $HGRCPATH
62 62
63 63 $ hg init usertest
64 64 $ cd usertest
65 65 $ touch bar
66 66 $ hg commit --addremove --quiet -m "added bar"
67 67 $ hg log --template "{author}\n"
68 68 John Doe
69 69 $ cd ..
70 70
71 71 $ hg showconfig
72 72 ui.username=$FAKEUSER
73 73
74 74 $ unset FAKEUSER
75 75 $ HGUSER=$olduser
76 76 $ export HGUSER
77 77
78 showconfig with multiple arguments
79
80 $ echo "[alias]" > $HGRCPATH
81 $ echo "log = log -g" >> $HGRCPATH
82 $ echo "[defaults]" >> $HGRCPATH
83 $ echo "identify = -n" >> $HGRCPATH
84 $ hg showconfig alias defaults
85 alias.log=log -g
86 defaults.identify=-n
87 $ hg showconfig alias defaults.identify
88 abort: only one config item permitted
89 [255]
90 $ hg showconfig alias.log defaults.identify
91 abort: only one config item permitted
92 [255]
93
78 94 HGPLAIN
79 95
80 96 $ cd ..
81 97 $ p=`pwd`
82 98 $ echo "[ui]" > $HGRCPATH
83 99 $ echo "debug=true" >> $HGRCPATH
84 100 $ echo "fallbackencoding=ASCII" >> $HGRCPATH
85 101 $ echo "quiet=true" >> $HGRCPATH
86 102 $ echo "slash=true" >> $HGRCPATH
87 103 $ echo "traceback=true" >> $HGRCPATH
88 104 $ echo "verbose=true" >> $HGRCPATH
89 105 $ echo "style=~/.hgstyle" >> $HGRCPATH
90 106 $ echo "logtemplate={node}" >> $HGRCPATH
91 107 $ echo "[defaults]" >> $HGRCPATH
92 108 $ echo "identify=-n" >> $HGRCPATH
93 109 $ echo "[alias]" >> $HGRCPATH
94 110 $ echo "log=log -g" >> $HGRCPATH
95 111
96 112 customized hgrc
97 113
98 114 $ hg showconfig
99 115 read config from: $TESTTMP/hgrc
100 116 $TESTTMP/hgrc:13: alias.log=log -g
101 117 $TESTTMP/hgrc:11: defaults.identify=-n
102 118 $TESTTMP/hgrc:2: ui.debug=true
103 119 $TESTTMP/hgrc:3: ui.fallbackencoding=ASCII
104 120 $TESTTMP/hgrc:4: ui.quiet=true
105 121 $TESTTMP/hgrc:5: ui.slash=true
106 122 $TESTTMP/hgrc:6: ui.traceback=true
107 123 $TESTTMP/hgrc:7: ui.verbose=true
108 124 $TESTTMP/hgrc:8: ui.style=~/.hgstyle
109 125 $TESTTMP/hgrc:9: ui.logtemplate={node}
110 126
111 127 plain hgrc
112 128
113 129 $ HGPLAIN=; export HGPLAIN
114 130 $ hg showconfig --config ui.traceback=True --debug
115 131 read config from: $TESTTMP/hgrc
116 132 none: ui.traceback=True
117 133 none: ui.verbose=False
118 134 none: ui.debug=True
119 135 none: ui.quiet=False
General Comments 0
You need to be logged in to leave comments. Login now