[PATCH 2 of 2] bookmarks-command: change bookmark within a transaction

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Jul 7 20:35:42 CDT 2015


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1411890576 25200
#      Sun Sep 28 00:49:36 2014 -0700
# Node ID e37a2f514739d95ee168d05fe81ebbce5a8791fe
# Parent  a59f61d46778910f1ee25adf6f64667d443285b0
bookmarks-command: change bookmark within a transaction

For some times, bookmark can and should be moved in the transaction. This
changeset migrate the 'hg bookmarks' commands to use a transaction.

Test regarding rollback and transaction hooks are impacted for obvious reasons.
Some have to be sightly updated to keep testing the same things. Some can just
be dropped because they do not make sense anymore.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -19,11 +19,11 @@ from hgweb import server as hgweb_server
 import merge as mergemod
 import minirst, revset, fileset
 import dagparser, context, simplemerge, graphmod, copies
 import random
 import setdiscovery, treediscovery, dagutil, pvec, localrepo
-import phases, obsolete, exchange, bundle2, repair
+import phases, obsolete, exchange, bundle2, repair, lock as lockmod
 import ui as uimod
 
 table = {}
 
 command = cmdutil.command(table)
@@ -974,25 +974,28 @@ def bookmark(ui, repo, *names, **opts):
         raise util.Abort(_("--rev is incompatible with --rename"))
     if not names and (delete or rev):
         raise util.Abort(_("bookmark name required"))
 
     if delete or rename or names or inactive:
-        wlock = repo.wlock()
+        wlock = lock = tr = None
         try:
+            wlock = repo.wlock()
+            lock = repo.lock()
             cur = repo.changectx('.').node()
             marks = repo._bookmarks
             if delete:
+                tr = repo.transaction('bookmark')
                 for mark in names:
                     if mark not in marks:
                         raise util.Abort(_("bookmark '%s' does not exist") %
                                          mark)
                     if mark == repo._activebookmark:
                         bookmarks.deactivate(repo)
                     del marks[mark]
-                marks.write()
 
             elif rename:
+                tr = repo.transaction('bookmark')
                 if not names:
                     raise util.Abort(_("new bookmark name required"))
                 elif len(names) > 1:
                     raise util.Abort(_("only one new bookmark name allowed"))
                 mark = checkformat(names[0])
@@ -1001,13 +1004,12 @@ def bookmark(ui, repo, *names, **opts):
                 checkconflict(repo, mark, cur, force)
                 marks[mark] = marks[rename]
                 if repo._activebookmark == rename and not inactive:
                     bookmarks.activate(repo, mark)
                 del marks[rename]
-                marks.write()
-
             elif names:
+                tr = repo.transaction('bookmark')
                 newact = None
                 for mark in names:
                     mark = checkformat(mark)
                     if newact is None:
                         newact = mark
@@ -1021,21 +1023,22 @@ def bookmark(ui, repo, *names, **opts):
                     marks[mark] = tgt
                 if not inactive and cur == marks[newact] and not rev:
                     bookmarks.activate(repo, newact)
                 elif cur != tgt and newact == repo._activebookmark:
                     bookmarks.deactivate(repo)
-                marks.write()
-
             elif inactive:
                 if len(marks) == 0:
                     ui.status(_("no bookmarks set\n"))
                 elif not repo._activebookmark:
                     ui.status(_("no active bookmark\n"))
                 else:
                     bookmarks.deactivate(repo)
+            if tr is not None:
+                marks.recordchange(tr)
+                tr.close()
         finally:
-            wlock.release()
+            lockmod.release(tr, lock, wlock)
     else: # show bookmarks
         fm = ui.formatter('bookmarks', opts)
         hexfn = fm.hexfunc
         marks = repo._bookmarks
         if len(marks) == 0 and not fm:
diff --git a/tests/test-bookmarks-strip.t b/tests/test-bookmarks-strip.t
--- a/tests/test-bookmarks-strip.t
+++ b/tests/test-bookmarks-strip.t
@@ -61,57 +61,5 @@ strip to revision 1
 list bookmarks
 
   $ hg book
      test                      0:5c9ad3787638
      test2                     0:5c9ad3787638
-
-immediate rollback and reentrancy issue
-
-  $ echo "mq=!" >> $HGRCPATH
-  $ hg init repo
-  $ cd repo
-  $ echo a > a
-  $ hg ci -Am adda
-  adding a
-  $ echo b > b
-  $ hg ci -Am addb
-  adding b
-  $ hg bookmarks markb
-  $ hg rollback
-  repository tip rolled back to revision 0 (undo commit)
-  working directory now based on revision 0
-
-are you there?
-
-  $ hg bookmarks
-  no bookmarks set
-
-can we commit? (issue2692)
-
-  $ echo c > c
-  $ hg ci -Am rockon
-  adding c
-
-can you be added again?
-
-  $ hg bookmarks markb
-  $ hg bookmarks
-   * markb                     1:fdb34407462c
-
-rollback dry run with rollback information
-
-  $ hg rollback -n
-  repository tip rolled back to revision 0 (undo commit)
-  $ hg bookmarks
-   * markb                     1:fdb34407462c
-
-rollback dry run with rollback information and no commit undo
-
-  $ rm .hg/store/undo
-  $ hg rollback -n
-  no rollback information available
-  [1]
-  $ hg bookmarks
-   * markb                     1:fdb34407462c
-
-  $ cd ..
-
diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t
--- a/tests/test-bookmarks.t
+++ b/tests/test-bookmarks.t
@@ -401,22 +401,38 @@ test id
   db815d6d32e6 tip Y/Z/x  y
 
 test rollback
 
   $ echo foo > f1
+  $ hg bookmark tmp-rollback
   $ hg ci -Amr
   adding f1
-  $ hg bookmark -f Y -r 1
-  $ hg bookmark -f Z -r 1
+  $ hg bookmarks
+     X2                        1:925d80f479bb
+     Y                         2:db815d6d32e6
+     Z                         2:db815d6d32e6
+   * tmp-rollback              3:2bf5cfec5864
+     x  y                      2:db815d6d32e6
   $ hg rollback
   repository tip rolled back to revision 2 (undo commit)
   working directory now based on revision 2
   $ hg bookmarks
      X2                        1:925d80f479bb
      Y                         2:db815d6d32e6
      Z                         2:db815d6d32e6
+   * tmp-rollback              2:db815d6d32e6
      x  y                      2:db815d6d32e6
+  $ hg bookmark -f Z -r 1
+  $ hg rollback
+  repository tip rolled back to revision 2 (undo bookmark)
+  $ hg bookmarks
+     X2                        1:925d80f479bb
+     Y                         2:db815d6d32e6
+     Z                         2:db815d6d32e6
+   * tmp-rollback              2:db815d6d32e6
+     x  y                      2:db815d6d32e6
+  $ hg bookmark -d tmp-rollback
 
 activate bookmark on working dir parent without --force
 
   $ hg bookmark --inactive Z
   $ hg bookmark Z
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -171,40 +171,70 @@ pull empty
   2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
 
 add extra data to test their exchange during push
 
   $ hg -R main bookmark --rev eea13746799a book_eea1
+  pre-close-tip:02de42196ebe draft 
+  postclose-tip:02de42196ebe draft 
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
   txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
   $ hg -R main bookmark --rev 02de42196ebe book_02de
+  pre-close-tip:02de42196ebe draft book_02de
+  postclose-tip:02de42196ebe draft book_02de
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
   pre-close-tip:02de42196ebe draft book_02de
   postclose-tip:02de42196ebe draft book_02de
   txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
   $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
+  pre-close-tip:02de42196ebe draft book_02de
+  postclose-tip:02de42196ebe draft book_02de
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
   pre-close-tip:02de42196ebe draft book_02de
   postclose-tip:02de42196ebe draft book_02de
   txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
   $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
+  pre-close-tip:02de42196ebe draft book_02de
+  postclose-tip:02de42196ebe draft book_02de
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
   pre-close-tip:02de42196ebe draft book_02de
   postclose-tip:02de42196ebe draft book_02de
   txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
   $ hg -R main bookmark --rev 32af7686d403 book_32af
+  pre-close-tip:02de42196ebe draft book_02de
+  postclose-tip:02de42196ebe draft book_02de
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
   pre-close-tip:02de42196ebe draft book_02de
   postclose-tip:02de42196ebe draft book_02de
   txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete (glob)
 
   $ hg -R other bookmark --rev cd010b8cd998 book_eea1
+  pre-close-tip:24b6387c8c8c public 
+  postclose-tip:24b6387c8c8c public 
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R other bookmark --rev cd010b8cd998 book_02de
+  pre-close-tip:24b6387c8c8c public 
+  postclose-tip:24b6387c8c8c public 
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R other bookmark --rev cd010b8cd998 book_42cc
+  pre-close-tip:24b6387c8c8c public 
+  postclose-tip:24b6387c8c8c public 
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
+  pre-close-tip:24b6387c8c8c public 
+  postclose-tip:24b6387c8c8c public 
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ hg -R other bookmark --rev cd010b8cd998 book_32af
+  pre-close-tip:24b6387c8c8c public 
+  postclose-tip:24b6387c8c8c public 
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
 
   $ hg -R main phase --public eea13746799a
   pre-close-tip:02de42196ebe draft book_02de
   postclose-tip:02de42196ebe draft book_02de
   txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
diff --git a/tests/test-hook.t b/tests/test-hook.t
--- a/tests/test-hook.t
+++ b/tests/test-hook.t
@@ -245,10 +245,13 @@ pushkey hook
 
 listkeys hook
 
   $ echo "listkeys = printenv.py listkeys" >> .hg/hgrc
   $ hg bookmark -r null bar
+  pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
+  pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ cd ../b
   $ hg pull -B bar ../a
   pulling from ../a
   listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
   no changes found
@@ -277,10 +280,13 @@ test that prepushkey can prevent incomin
 
 test that prelistkeys can prevent listing keys
 
   $ echo "prelistkeys = printenv.py prelistkeys.forbid 1" >> .hg/hgrc
   $ hg bookmark -r null quux
+  pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
+  pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_PENDING=$TESTTMP/a HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
+  txnclose hook: HG_BOOKMARK_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=bookmark (glob)
   $ cd ../b
   $ hg pull -B quux ../a
   pulling from ../a
   prelistkeys.forbid hook: HG_NAMESPACE=bookmarks
   abort: prelistkeys hook exited with status 1
diff --git a/tests/test-rollback.t b/tests/test-rollback.t
--- a/tests/test-rollback.t
+++ b/tests/test-rollback.t
@@ -72,31 +72,31 @@ working dir unaffected by rollback: do n
   $ hg status
   M a
   $ hg bookmark foo
   $ hg commit -m'modify a again'
   $ echo b > b
+  $ hg bookmark bar -r default #making bar active, before the transaction
   $ hg commit -Am'add b'
   adding b
   $ hg log --template '{rev}  {branch}  {desc|firstline}\n'
   2  test  add b
   1  test  modify a again
   0  default  add a again
-  $ hg update default
+  $ hg update bar
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  (leaving bookmark foo)
-  $ hg bookmark bar
+  (activating bookmark bar)
   $ cat .hg/undo.branch ; echo
   test
   $ hg rollback -f
   repository tip rolled back to revision 1 (undo commit)
   $ hg id -n
   0
   $ hg branch
   default
   $ cat .hg/bookmarks.current ; echo
   bar
-  $ hg bookmark --delete foo
+  $ hg bookmark --delete foo bar
 
 rollback by pretxncommit saves commit message (issue1635)
 
   $ echo a >> a
   $ hg --config hooks.pretxncommit=false commit -m"precious commit message"


More information about the Mercurial-devel mailing list