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]')),