[PATCH] bookmarks: allow bookmark command to take multiple arguments

Kevin Bullock kbullock+mercurial at ringworld.org
Thu May 2 21:28:36 CDT 2013


# HG changeset patch
# User Kevin Bullock <kbullock at ringworld.org>
# Date 1367548098 18000
#      Thu May 02 21:28:18 2013 -0500
# Node ID 06c418fa0d575fb24453dd708e3cf79b6d2f2977
# Parent  4cdec37f0018e361e8159632ec5afeb705c433b1
bookmarks: allow bookmark command to take multiple arguments

This change allows setting or deleting multiple bookmarks at once. If more than
one is being set and --inactive is not given, the first one is made active.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -767,9 +767,8 @@ def bisect(ui, repo, rev=None, extra=Non
     ('d', 'delete', False, _('delete a given bookmark')),
     ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
     ('i', 'inactive', False, _('mark a bookmark inactive'))],
-    _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
-def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
-             rename=None, inactive=False):
+    _('hg bookmarks [OPTIONS]... [NAME]...'))
+def bookmark(ui, repo, *names, **opts):
     '''track a line of development with movable markers
 
     Bookmarks are pointers to certain commits that move when committing.
@@ -796,6 +795,12 @@ def bookmark(ui, repo, mark=None, rev=No
     active even if -i/--inactive is not given. If no NAME is given, the
     current active bookmark will be marked inactive.
     '''
+    force = opts.get('force')
+    rev = opts.get('rev')
+    delete = opts.get('delete')
+    rename = opts.get('rename')
+    inactive = opts.get('inactive')
+
     hexfn = ui.debugflag and hex or short
     marks = repo._bookmarks
     cur   = repo.changectx('.').node()
@@ -846,21 +851,24 @@ def bookmark(ui, repo, mark=None, rev=No
         raise util.Abort(_("--rev is incompatible with --delete"))
     if rename and rev:
         raise util.Abort(_("--rev is incompatible with --rename"))
-    if mark is None and (delete or rev):
+    if not names and (delete or rev):
         raise util.Abort(_("bookmark name required"))
 
     if delete:
-        if mark not in marks:
-            raise util.Abort(_("bookmark '%s' does not exist") % mark)
-        if mark == repo._bookmarkcurrent:
-            bookmarks.setcurrent(repo, None)
-        del marks[mark]
+        for mark in names:
+            if mark not in marks:
+                raise util.Abort(_("bookmark '%s' does not exist") % mark)
+            if mark == repo._bookmarkcurrent:
+                bookmarks.setcurrent(repo, None)
+            del marks[mark]
         marks.write()
 
     elif rename:
-        if mark is None:
+        if not names:
             raise util.Abort(_("new bookmark name required"))
-        mark = checkformat(mark)
+        elif len(names) > 1:
+            raise util.Abort(_("only one new bookmark name allowed"))
+        mark = checkformat(names[0])
         if rename not in marks:
             raise util.Abort(_("bookmark '%s' does not exist") % rename)
         checkconflict(repo, mark, force)
@@ -870,19 +878,23 @@ def bookmark(ui, repo, mark=None, rev=No
         del marks[rename]
         marks.write()
 
-    elif mark is not None:
-        mark = checkformat(mark)
-        if inactive and mark == repo._bookmarkcurrent:
-            bookmarks.setcurrent(repo, None)
-            return
-        tgt = cur
-        if rev:
-            tgt = scmutil.revsingle(repo, rev).node()
-        checkconflict(repo, mark, force, tgt)
-        marks[mark] = tgt
-        if not inactive and cur == marks[mark] and not rev:
-            bookmarks.setcurrent(repo, mark)
-        elif cur != tgt and mark == repo._bookmarkcurrent:
+    elif names:
+        newact = None
+        for mark in names:
+            mark = checkformat(mark)
+            if newact is None:
+                newact = mark
+            if inactive and mark == repo._bookmarkcurrent:
+                bookmarks.setcurrent(repo, None)
+                return
+            tgt = cur
+            if rev:
+                tgt = scmutil.revsingle(repo, rev).node()
+            checkconflict(repo, mark, force, tgt)
+            marks[mark] = tgt
+        if not inactive and cur == marks[newact] and not rev:
+            bookmarks.setcurrent(repo, newact)
+        elif cur != tgt and newact == repo._bookmarkcurrent:
             bookmarks.setcurrent(repo, None)
         marks.write()
 
diff --git a/tests/test-bookmarks-current.t b/tests/test-bookmarks-current.t
--- a/tests/test-bookmarks-current.t
+++ b/tests/test-bookmarks-current.t
@@ -43,16 +43,19 @@ list bookmarks
   $ hg bookmarks
    * Z                         -1:000000000000
 
-new bookmark Y
+new bookmarks X and Y, first one made active
 
-  $ hg bookmark Y
+  $ hg bookmark Y X
 
 list bookmarks
 
   $ hg bookmark
+     X                         -1:000000000000
    * Y                         -1:000000000000
      Z                         -1:000000000000
 
+  $ hg bookmark -d X
+
 commit
 
   $ echo 'b' > b
diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t
--- a/tests/test-bookmarks.t
+++ b/tests/test-bookmarks.t
@@ -168,11 +168,14 @@ bookmarks from a revset
   $ hg bookmark -d REVSET
   $ hg bookmark -d TIP
 
-rename without new name
+rename without new name or multiple names
 
   $ hg bookmark -m Y
   abort: new bookmark name required
   [255]
+  $ hg bookmark -m Y Y2 Y3
+  abort: only one new bookmark name allowed
+  [255]
 
 delete without name
 
@@ -417,8 +420,9 @@ test clone with pull protocol
      a@                        2:db815d6d32e6
      x  y                      2:db815d6d32e6
 
-  $ hg bookmark -d @
-  $ hg bookmark -d a@
+delete multiple bookmarks at once
+
+  $ hg bookmark -d @ a@
 
 test clone with a bookmark named "default" (issue3677)
 


More information about the Mercurial-devel mailing list