[PATCH 3 of 8] commands: add bookmark command and bookmark related options to core commands

dsp at php.net dsp at php.net
Sun Jan 16 16:57:39 CST 2011


# HG changeset patch
# User David Soria Parra <dsp at php.net>
# Date 1295218242 -3600
# Node ID b53822f164c46165cb92dfdae601832431f2225a
# Parent  1875d111f3bffa7a967bbe553ac5d774dd7fe4e2
commands: add bookmark command and bookmark related options to core commands

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -14,7 +14,7 @@
 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
 import merge as mergemod
 import minirst, revset
-import dagparser
+import dagparser, bookmarks
 
 # Commands start here, listed alphabetically
 
@@ -461,6 +461,92 @@
             cmdutil.bail_if_changed(repo)
             return hg.clean(repo, node)
 
+def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
+    '''track a line of development with movable markers
+
+    Bookmarks are pointers to certain commits that move when
+    committing. Bookmarks are local. They can be renamed, copied and
+    deleted. It is possible to use bookmark names in :hg:`merge` and
+    :hg:`update` to merge and update respectively to a given bookmark.
+
+    You can use :hg:`bookmark NAME` to set a bookmark on the working
+    directory's parent revision with the given name. If you specify
+    a revision using -r REV (where REV may be an existing bookmark),
+    the bookmark is assigned to that revision.
+
+    Bookmarks can be pushed and pulled between repositories (see :hg:`help
+    push` and :hg:`help pull`).
+    '''
+    hexfn = ui.debugflag and hex or short
+    cur   = repo.changectx('.').node()
+
+    if rename:
+        if rename not in repo.bookmarks:
+            raise util.Abort(_("a bookmark of this name does not exist"))
+        if mark in repo.bookmarks and not force:
+            raise util.Abort(_("a bookmark of the same name already exists"))
+        if mark is None:
+            raise util.Abort(_("new bookmark name required"))
+        repo.bookmarks[mark] = repo.bookmarks[rename]
+        del repo.bookmarks[rename]
+        if repo.bookmarkcurrent == rename:
+            repo.bookmarkcurrent = mark
+        repo.writebookmarks()
+        return
+
+    if delete:
+        if mark is None:
+            raise util.Abort(_("bookmark name required"))
+        if mark not in repo.bookmarks:
+            raise util.Abort(_("a bookmark of this name does not exist"))
+        if mark == repo.bookmarkcurrent:
+            repo.bookmarkcurrent = None
+        del repo.bookmarks[mark]
+        repo.writebookmarks()
+        return
+
+    if mark is not None:
+        if "\n" in mark:
+            raise util.Abort(_("bookmark name cannot contain newlines"))
+        mark = mark.strip()
+        if not mark:
+            raise util.Abort(_("bookmark names cannot consist entirely of "
+                               "whitespace"))
+        if mark in repo.bookmarks and not force:
+            raise util.Abort(_("a bookmark of the same name already exists"))
+        if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
+            and not force):
+            raise util.Abort(
+                _("a bookmark cannot have the name of an existing branch"))
+        if rev:
+            repo.bookmarks[mark] = repo.lookup(rev)
+        else:
+            repo.bookmarks[mark] = repo.changectx('.').node()
+        repo.bookmarkcurrent = mark
+        repo.writebookmarks()
+        return
+
+    if mark is None:
+        if rev:
+            raise util.Abort(_("bookmark name required"))
+        if len(repo.bookmarks) == 0:
+            ui.status(_("no bookmarks set\n"))
+        else:
+            for bmark, n in sorted(repo.bookmarks.iteritems()):
+                current = repo.bookmarkcurrent
+                if bmark == current and n == cur:
+                    prefix, label = '*', 'bookmarks.current'
+                else:
+                    prefix, label = ' ', ''
+
+                if ui.quiet:
+                    ui.write("%s\n" % bmark, label=label)
+                else:
+                    ui.write(" %s %-25s %d:%s\n" % (
+                        prefix, bmark, repo.changelog.rev(n), hexfn(n)),
+                        label=label)
+        return
+
 def branch(ui, repo, label=None, **opts):
     """set or show the current branch name
 
@@ -2403,7 +2489,13 @@
     if opts.get('bundle') and opts.get('subrepos'):
         raise util.Abort(_('cannot combine --bundle and --subrepos'))
 
-    ret = hg.incoming(ui, repo, source, opts)
+    if opts.get("bookmarks"):
+        source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
+        other = hg.repository(hg.remoteui(repo, opts), source)
+        ui.status(_('comparing with %s\n') % url.hidepassword(source))
+        return bookmarks.diffbookmarks(ui, repo, other)
+    else:
+        ret = hg.incoming(ui, repo, source, opts)
     return ret
 
 def init(ui, dest=".", **opts):
@@ -2679,7 +2771,14 @@
 
     Returns 0 if there are outgoing changes, 1 otherwise.
     """
-    ret = hg.outgoing(ui, repo, dest, opts)
+    if opts.get("bookmarks"):
+        dest = ui.expandpath(dest or 'default-push', dest or 'default')
+        dest, branches = hg.parseurl(dest, opts.get('branch'))
+        other = hg.repository(hg.remoteui(repo, opts), dest)
+        ui.status(_('comparing with %s\n') % url.hidepassword(dest))
+        return bookmarks.diffbookmarks(ui, other, repo)
+    else:
+        ret = hg.outgoing(ui, repo, dest, opts)
     return ret
 
 def parents(ui, repo, file_=None, **opts):
@@ -2859,8 +2958,36 @@
                 return False
     finally:
         del repo._subtoppath
+
+    for b in opts.get('bookmark', []):
+        if revs is None:
+            revs = []
+        if b in repo.bookmarks:
+            revs.append(b)
+
     r = repo.push(other, opts.get('force'), revs=revs,
                   newbranch=opts.get('new_branch'))
+
+    if opts.get("bookmark"):
+        rb = other.listkeys('bookmarks')
+        for b in opts['bookmark']:
+            # explicit push overrides remote bookmark if any
+            if b in repo.bookmarks:
+                ui.status(_("exporting bookmark %s\n") % b)
+                new = repo[b].hex()
+            elif b in rb:
+                ui.status(_("deleting remote bookmark %s\n") % b)
+                new = '' # delete
+            else:
+                ui.warn(_('bookmark %s does not exist on the local '
+                          'or remote repository!\n') % b)
+                return 2
+            old = rb.get(b, '')
+            r = other.pushkey('bookmarks', b, old, new)
+            if not r:
+                ui.warn(_('updating bookmark %s failed!\n') % b)
+                if not result:
+                    return 2
     return r == 0
 
 def recover(ui, repo):
@@ -3865,6 +3992,7 @@
     if not rev:
         rev = node
 
+    mark = rev
     rev = cmdutil.revsingle(repo, rev, rev).rev()
 
     if check and clean:
@@ -3882,9 +4010,13 @@
         rev = cmdutil.finddate(ui, repo, date)
 
     if clean or check:
-        return hg.clean(repo, rev)
+        res = hg.clean(repo, rev)
     else:
-        return hg.update(repo, rev)
+        res = hg.update(repo, rev)
+    if mark in repo.bookmarks:
+        repo.bookmarkcurrent = mark
+        repo.writebookmarks()
+    return res
 
 def verify(ui, repo):
     """verify the integrity of the repository
@@ -4063,6 +4195,13 @@
            _('revision to backout'), _('REV')),
          ] + walkopts + commitopts + commitopts2,
          _('[OPTION]... [-r] REV')),
+    "bookmarks":
+        (bookmark,
+         [('f', 'force', False, _('force')),
+          ('r', 'rev', '', _('revision'), _('REV')),
+          ('d', 'delete', False, _('delete a given bookmark')),
+          ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
+         _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
     "bisect":
         (bisect,
          [('r', 'reset', False, _('reset bisect state')),
@@ -4291,6 +4430,8 @@
            _('a remote changeset intended to be added'), _('REV')),
           ('b', 'branch', [],
            _('a specific branch you would like to pull'), _('BRANCH')),
+          ('B', 'bookmarks', False,
+           _("compare bookmark")),
          ] + logopts + remoteopts + subrepoopts,
          _('[-p] [-n] [-M] [-f] [-r REV]...'
            ' [--bundle FILENAME] [SOURCE]')),
@@ -4359,6 +4500,8 @@
           ('n', 'newest-first', None, _('show newest record first')),
           ('b', 'branch', [],
            _('a specific branch you would like to push'), _('BRANCH')),
+          ('B', 'bookmarks', False,
+           _("compare bookmark")),
          ] + logopts + remoteopts + subrepoopts,
          _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
     "parents":
@@ -4388,6 +4531,9 @@
            _('REV')),
           ('b', 'branch', [],
            _('a specific branch you would like to push'), _('BRANCH')),
+          ('B', 'bookmark', [],
+                     _("bookmark to import"),
+                     _('BOOKMARK')),
           ('', 'new-branch', False, _('allow pushing a new branch')),
          ] + remoteopts,
          _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),


More information about the Mercurial-devel mailing list