Patchwork [2,of,5] commands.bookmarks: hold wlock for write operations

login
register
mail settings
Submitter Siddharth Agarwal
Date Nov. 22, 2013, 1:13 a.m.
Message ID <a74d0c24dea02ccea815.1385082790@dev1091.prn1.facebook.com>
Download mbox | patch
Permalink /patch/3090/
State Superseded
Commit 5fe4c1a9dc34c4b4ef85366a32efae9bc7e8c1a1
Headers show

Comments

Siddharth Agarwal - Nov. 22, 2013, 1:13 a.m.
# HG changeset patch
# User Siddharth Agarwal <sid0@fb.com>
# Date 1384893194 28800
#      Tue Nov 19 12:33:14 2013 -0800
# Node ID a74d0c24dea02ccea815a49bdf3d37a86258d152
# Parent  2472f2dcf8fb9b691c03bb9e404b55da90b8d672
commands.bookmarks: hold wlock for write operations

Any invocations of bookmarks other than a plain 'hg bookmarks' will likely
cause a write to the bookmark store. These should be guarded by the wlock.

The repo._bookmarks read should be similarly guarded by the wlock if we're
going to be subsequently writing to it.

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -808,7 +808,6 @@ 
     inactive = opts.get('inactive')
 
     hexfn = ui.debugflag and hex or short
-    marks = repo._bookmarks
     cur   = repo.changectx('.').node()
 
     def checkformat(mark):
@@ -860,59 +859,66 @@ 
     if not names and (delete or rev):
         raise util.Abort(_("bookmark name required"))
 
-    if delete:
-        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 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])
-        if rename not in marks:
-            raise util.Abort(_("bookmark '%s' does not exist") % rename)
-        checkconflict(repo, mark, force)
-        marks[mark] = marks[rename]
-        if repo._bookmarkcurrent == rename and not inactive:
-            bookmarks.setcurrent(repo, mark)
-        del marks[rename]
-        marks.write()
-
-    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()
-
-    elif inactive:
-        if len(marks) == 0:
-            ui.status(_("no bookmarks set\n"))
-        elif not repo._bookmarkcurrent:
-            ui.status(_("no active bookmark\n"))
-        else:
-            bookmarks.setcurrent(repo, None)
-
+    if delete or rename or names or inactive:
+        wlock = repo.wlock()
+        try:
+            marks = repo._bookmarks
+            if delete:
+                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 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])
+                if rename not in marks:
+                    raise util.Abort(_("bookmark '%s' does not exist") % rename)
+                checkconflict(repo, mark, force)
+                marks[mark] = marks[rename]
+                if repo._bookmarkcurrent == rename and not inactive:
+                    bookmarks.setcurrent(repo, mark)
+                del marks[rename]
+                marks.write()
+
+            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()
+
+            elif inactive:
+                if len(marks) == 0:
+                    ui.status(_("no bookmarks set\n"))
+                elif not repo._bookmarkcurrent:
+                    ui.status(_("no active bookmark\n"))
+                else:
+                    bookmarks.setcurrent(repo, None)
+        finally:
+            wlock.release()
     else: # show bookmarks
+        marks = repo._bookmarks
         if len(marks) == 0:
             ui.status(_("no bookmarks set\n"))
         else: