Mercurial > public > mercurial-scm > hg
comparison mercurial/commands.py @ 13368:d4ab9486e514
bookmarks: move push/pull command features to core
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 10 Feb 2011 13:46:28 -0600 |
parents | cef73cd9c268 |
children | a184dbd9b2c5 |
comparison
equal
deleted
inserted
replaced
13367:cef73cd9c268 | 13368:d4ab9486e514 |
---|---|
454 "(%d changesets remaining, ~%d tests)\n") | 454 "(%d changesets remaining, ~%d tests)\n") |
455 % (rev, short(node), changesets, tests)) | 455 % (rev, short(node), changesets, tests)) |
456 if not noupdate: | 456 if not noupdate: |
457 cmdutil.bail_if_changed(repo) | 457 cmdutil.bail_if_changed(repo) |
458 return hg.clean(repo, node) | 458 return hg.clean(repo, node) |
459 | |
460 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None): | |
461 '''track a line of development with movable markers | |
462 | |
463 Bookmarks are pointers to certain commits that move when | |
464 committing. Bookmarks are local. They can be renamed, copied and | |
465 deleted. It is possible to use bookmark names in :hg:`merge` and | |
466 :hg:`update` to merge and update respectively to a given bookmark. | |
467 | |
468 You can use :hg:`bookmark NAME` to set a bookmark on the working | |
469 directory's parent revision with the given name. If you specify | |
470 a revision using -r REV (where REV may be an existing bookmark), | |
471 the bookmark is assigned to that revision. | |
472 | |
473 Bookmarks can be pushed and pulled between repositories (see :hg:`help | |
474 push` and :hg:`help pull`). This requires the bookmark extension to be | |
475 enabled for both the local and remote repositories. | |
476 ''' | |
477 hexfn = ui.debugflag and hex or short | |
478 marks = repo._bookmarks | |
479 cur = repo.changectx('.').node() | |
480 | |
481 if rename: | |
482 if rename not in marks: | |
483 raise util.Abort(_("a bookmark of this name does not exist")) | |
484 if mark in marks and not force: | |
485 raise util.Abort(_("a bookmark of the same name already exists")) | |
486 if mark is None: | |
487 raise util.Abort(_("new bookmark name required")) | |
488 marks[mark] = marks[rename] | |
489 del marks[rename] | |
490 if repo._bookmarkcurrent == rename: | |
491 bookmarks.setcurrent(repo, mark) | |
492 bookmarks.write(repo) | |
493 return | |
494 | |
495 if delete: | |
496 if mark is None: | |
497 raise util.Abort(_("bookmark name required")) | |
498 if mark not in marks: | |
499 raise util.Abort(_("a bookmark of this name does not exist")) | |
500 if mark == repo._bookmarkcurrent: | |
501 bookmarks.setcurrent(repo, None) | |
502 del marks[mark] | |
503 bookmarks.write(repo) | |
504 return | |
505 | |
506 if mark is not None: | |
507 if "\n" in mark: | |
508 raise util.Abort(_("bookmark name cannot contain newlines")) | |
509 mark = mark.strip() | |
510 if not mark: | |
511 raise util.Abort(_("bookmark names cannot consist entirely of " | |
512 "whitespace")) | |
513 if mark in marks and not force: | |
514 raise util.Abort(_("a bookmark of the same name already exists")) | |
515 if ((mark in repo.branchtags() or mark == repo.dirstate.branch()) | |
516 and not force): | |
517 raise util.Abort( | |
518 _("a bookmark cannot have the name of an existing branch")) | |
519 if rev: | |
520 marks[mark] = repo.lookup(rev) | |
521 else: | |
522 marks[mark] = repo.changectx('.').node() | |
523 bookmarks.setcurrent(repo, mark) | |
524 bookmarks.write(repo) | |
525 return | |
526 | |
527 if mark is None: | |
528 if rev: | |
529 raise util.Abort(_("bookmark name required")) | |
530 if len(marks) == 0: | |
531 ui.status(_("no bookmarks set\n")) | |
532 else: | |
533 for bmark, n in marks.iteritems(): | |
534 if ui.configbool('bookmarks', 'track.current'): | |
535 current = repo._bookmarkcurrent | |
536 if bmark == current and n == cur: | |
537 prefix, label = '*', 'bookmarks.current' | |
538 else: | |
539 prefix, label = ' ', '' | |
540 else: | |
541 if n == cur: | |
542 prefix, label = '*', 'bookmarks.current' | |
543 else: | |
544 prefix, label = ' ', '' | |
545 | |
546 if ui.quiet: | |
547 ui.write("%s\n" % bmark, label=label) | |
548 else: | |
549 ui.write(" %s %-25s %d:%s\n" % ( | |
550 prefix, bmark, repo.changelog.rev(n), hexfn(n)), | |
551 label=label) | |
552 return | |
459 | 553 |
460 def branch(ui, repo, label=None, **opts): | 554 def branch(ui, repo, label=None, **opts): |
461 """set or show the current branch name | 555 """set or show the current branch name |
462 | 556 |
463 With no argument, show the current branch name. With one argument, | 557 With no argument, show the current branch name. With one argument, |
2804 """ | 2898 """ |
2805 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) | 2899 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch')) |
2806 other = hg.repository(hg.remoteui(repo, opts), source) | 2900 other = hg.repository(hg.remoteui(repo, opts), source) |
2807 ui.status(_('pulling from %s\n') % url.hidepassword(source)) | 2901 ui.status(_('pulling from %s\n') % url.hidepassword(source)) |
2808 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev')) | 2902 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev')) |
2903 | |
2904 if opts.get('bookmark'): | |
2905 if not revs: | |
2906 revs = [] | |
2907 rb = other.listkeys('bookmarks') | |
2908 for b in opts['bookmark']: | |
2909 if b not in rb: | |
2910 raise util.Abort(_('remote bookmark %s not found!') % b) | |
2911 revs.append(rb[b]) | |
2912 | |
2809 if revs: | 2913 if revs: |
2810 try: | 2914 try: |
2811 revs = [other.lookup(rev) for rev in revs] | 2915 revs = [other.lookup(rev) for rev in revs] |
2812 except error.CapabilityError: | 2916 except error.CapabilityError: |
2813 err = _("other repository doesn't support revision lookup, " | 2917 err = _("other repository doesn't support revision lookup, " |
2817 modheads = repo.pull(other, heads=revs, force=opts.get('force')) | 2921 modheads = repo.pull(other, heads=revs, force=opts.get('force')) |
2818 if checkout: | 2922 if checkout: |
2819 checkout = str(repo.changelog.rev(other.lookup(checkout))) | 2923 checkout = str(repo.changelog.rev(other.lookup(checkout))) |
2820 repo._subtoppath = source | 2924 repo._subtoppath = source |
2821 try: | 2925 try: |
2822 return postincoming(ui, repo, modheads, opts.get('update'), checkout) | 2926 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout) |
2927 | |
2823 finally: | 2928 finally: |
2824 del repo._subtoppath | 2929 del repo._subtoppath |
2930 | |
2931 # update specified bookmarks | |
2932 if opts.get('bookmark'): | |
2933 for b in opts['bookmark']: | |
2934 # explicit pull overrides local bookmark if any | |
2935 ui.status(_("importing bookmark %s\n") % b) | |
2936 repo._bookmarks[b] = repo[rb[b]].node() | |
2937 bookmarks.write(repo) | |
2938 | |
2939 return ret | |
2825 | 2940 |
2826 def push(ui, repo, dest=None, **opts): | 2941 def push(ui, repo, dest=None, **opts): |
2827 """push changes to the specified destination | 2942 """push changes to the specified destination |
2828 | 2943 |
2829 Push changesets from the local repository to the specified | 2944 Push changesets from the local repository to the specified |
2850 Please see :hg:`help urls` for important details about ``ssh://`` | 2965 Please see :hg:`help urls` for important details about ``ssh://`` |
2851 URLs. If DESTINATION is omitted, a default path will be used. | 2966 URLs. If DESTINATION is omitted, a default path will be used. |
2852 | 2967 |
2853 Returns 0 if push was successful, 1 if nothing to push. | 2968 Returns 0 if push was successful, 1 if nothing to push. |
2854 """ | 2969 """ |
2970 | |
2971 if opts.get('bookmark'): | |
2972 for b in opts['bookmark']: | |
2973 # translate -B options to -r so changesets get pushed | |
2974 if b in repo._bookmarks: | |
2975 opts.setdefault('rev', []).append(b) | |
2976 else: | |
2977 # if we try to push a deleted bookmark, translate it to null | |
2978 # this lets simultaneous -r, -b options continue working | |
2979 opts.setdefault('rev', []).append("null") | |
2980 | |
2855 dest = ui.expandpath(dest or 'default-push', dest or 'default') | 2981 dest = ui.expandpath(dest or 'default-push', dest or 'default') |
2856 dest, branches = hg.parseurl(dest, opts.get('branch')) | 2982 dest, branches = hg.parseurl(dest, opts.get('branch')) |
2857 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev')) | 2983 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev')) |
2858 other = hg.repository(hg.remoteui(repo, opts), dest) | 2984 other = hg.repository(hg.remoteui(repo, opts), dest) |
2859 ui.status(_('pushing to %s\n') % url.hidepassword(dest)) | 2985 ui.status(_('pushing to %s\n') % url.hidepassword(dest)) |
2868 for s in sorted(subs): | 2994 for s in sorted(subs): |
2869 if not c.sub(s).push(opts.get('force')): | 2995 if not c.sub(s).push(opts.get('force')): |
2870 return False | 2996 return False |
2871 finally: | 2997 finally: |
2872 del repo._subtoppath | 2998 del repo._subtoppath |
2873 r = repo.push(other, opts.get('force'), revs=revs, | 2999 result = repo.push(other, opts.get('force'), revs=revs, |
2874 newbranch=opts.get('new_branch')) | 3000 newbranch=opts.get('new_branch')) |
2875 return r == 0 | 3001 |
3002 result = (result == 0) | |
3003 | |
3004 if opts.get('bookmark'): | |
3005 rb = other.listkeys('bookmarks') | |
3006 for b in opts['bookmark']: | |
3007 # explicit push overrides remote bookmark if any | |
3008 if b in repo._bookmarks: | |
3009 ui.status(_("exporting bookmark %s\n") % b) | |
3010 new = repo[b].hex() | |
3011 elif b in rb: | |
3012 ui.status(_("deleting remote bookmark %s\n") % b) | |
3013 new = '' # delete | |
3014 else: | |
3015 ui.warn(_('bookmark %s does not exist on the local ' | |
3016 'or remote repository!\n') % b) | |
3017 return 2 | |
3018 old = rb.get(b, '') | |
3019 r = other.pushkey('bookmarks', b, old, new) | |
3020 if not r: | |
3021 ui.warn(_('updating bookmark %s failed!\n') % b) | |
3022 if not result: | |
3023 result = 2 | |
3024 | |
3025 return result | |
2876 | 3026 |
2877 def recover(ui, repo): | 3027 def recover(ui, repo): |
2878 """roll back an interrupted transaction | 3028 """roll back an interrupted transaction |
2879 | 3029 |
2880 Recover from an interrupted commit or pull. | 3030 Recover from an interrupted commit or pull. |
4089 ('s', 'skip', False, _('skip testing changeset')), | 4239 ('s', 'skip', False, _('skip testing changeset')), |
4090 ('c', 'command', '', | 4240 ('c', 'command', '', |
4091 _('use command to check changeset state'), _('CMD')), | 4241 _('use command to check changeset state'), _('CMD')), |
4092 ('U', 'noupdate', False, _('do not update to target'))], | 4242 ('U', 'noupdate', False, _('do not update to target'))], |
4093 _("[-gbsr] [-U] [-c CMD] [REV]")), | 4243 _("[-gbsr] [-U] [-c CMD] [REV]")), |
4244 "bookmarks": | |
4245 (bookmark, | |
4246 [('f', 'force', False, _('force')), | |
4247 ('r', 'rev', '', _('revision'), _('REV')), | |
4248 ('d', 'delete', False, _('delete a given bookmark')), | |
4249 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))], | |
4250 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')), | |
4094 "branch": | 4251 "branch": |
4095 (branch, | 4252 (branch, |
4096 [('f', 'force', None, | 4253 [('f', 'force', None, |
4097 _('set branch name even if it shadows an existing branch')), | 4254 _('set branch name even if it shadows an existing branch')), |
4098 ('C', 'clean', None, _('reset branch name to parent branch name'))], | 4255 ('C', 'clean', None, _('reset branch name to parent branch name'))], |
4394 _('update to new branch head if changesets were pulled')), | 4551 _('update to new branch head if changesets were pulled')), |
4395 ('f', 'force', None, | 4552 ('f', 'force', None, |
4396 _('run even when remote repository is unrelated')), | 4553 _('run even when remote repository is unrelated')), |
4397 ('r', 'rev', [], | 4554 ('r', 'rev', [], |
4398 _('a remote changeset intended to be added'), _('REV')), | 4555 _('a remote changeset intended to be added'), _('REV')), |
4556 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')), | |
4399 ('b', 'branch', [], | 4557 ('b', 'branch', [], |
4400 _('a specific branch you would like to pull'), _('BRANCH')), | 4558 _('a specific branch you would like to pull'), _('BRANCH')), |
4401 ] + remoteopts, | 4559 ] + remoteopts, |
4402 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')), | 4560 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')), |
4403 "^push": | 4561 "^push": |
4404 (push, | 4562 (push, |
4405 [('f', 'force', None, _('force push')), | 4563 [('f', 'force', None, _('force push')), |
4406 ('r', 'rev', [], | 4564 ('r', 'rev', [], |
4407 _('a changeset intended to be included in the destination'), | 4565 _('a changeset intended to be included in the destination'), |
4408 _('REV')), | 4566 _('REV')), |
4567 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')), | |
4409 ('b', 'branch', [], | 4568 ('b', 'branch', [], |
4410 _('a specific branch you would like to push'), _('BRANCH')), | 4569 _('a specific branch you would like to push'), _('BRANCH')), |
4411 ('', 'new-branch', False, _('allow pushing a new branch')), | 4570 ('', 'new-branch', False, _('allow pushing a new branch')), |
4412 ] + remoteopts, | 4571 ] + remoteopts, |
4413 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')), | 4572 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')), |