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