diff mercurial/commands.py @ 26028:6fbe35588433 stable

update: wlock the repo for the whole 'hg update' command The update command is touching the repository and should lock it for the length of its operations. Equally importantly, it should lock the repository when it is writing bookmarks. It wasn't doing so until now, leaving doors open for all kinds of drunk beaver parties. This results in some minor tests changes, and the fixing of a couple of bugs from race conditions. Code does not receive any changes beside extra indentation.
author Pierre-Yves David <pierre-yves.david@fb.com>
date Tue, 11 Aug 2015 16:26:12 -0700
parents 4eb8d8a44bf1
children 5243890224ff f31ddc9bfa5f
line wrap: on
line diff
--- a/mercurial/commands.py	Thu Aug 13 11:09:36 2015 -0300
+++ b/mercurial/commands.py	Tue Aug 11 16:26:12 2015 -0700
@@ -6451,51 +6451,55 @@
     if rev is None or rev == '':
         rev = node
 
-    cmdutil.clearunfinished(repo)
-
-    # with no argument, we also move the active bookmark, if any
-    rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
-
-    # if we defined a bookmark, we have to remember the original bookmark name
-    brev = rev
-    rev = scmutil.revsingle(repo, rev, rev).rev()
-
-    if check and clean:
-        raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
-
-    if date:
-        if rev is not None:
-            raise util.Abort(_("you can't specify a revision and a date"))
-        rev = cmdutil.finddate(ui, repo, date)
-
-    if check:
-        cmdutil.bailifchanged(repo, merge=False)
-        if rev is None:
-            rev = repo[repo[None].branch()].rev()
-
-    repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
-
-    if clean:
-        ret = hg.clean(repo, rev)
-    else:
-        ret = hg.update(repo, rev)
-
-    if not ret and movemarkfrom:
-        if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
-            ui.status(_("updating bookmark %s\n") % repo._activebookmark)
+    wlock = repo.wlock()
+    try:
+        cmdutil.clearunfinished(repo)
+
+        # with no argument, we also move the active bookmark, if any
+        rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
+
+        # if we defined a bookmark, we have to remember the original name
+        brev = rev
+        rev = scmutil.revsingle(repo, rev, rev).rev()
+
+        if check and clean:
+            raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
+
+        if date:
+            if rev is not None:
+                raise util.Abort(_("you can't specify a revision and a date"))
+            rev = cmdutil.finddate(ui, repo, date)
+
+        if check:
+            cmdutil.bailifchanged(repo, merge=False)
+            if rev is None:
+                rev = repo[repo[None].branch()].rev()
+
+        repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
+
+        if clean:
+            ret = hg.clean(repo, rev)
         else:
-            # this can happen with a non-linear update
-            ui.status(_("(leaving bookmark %s)\n") %
-                      repo._activebookmark)
+            ret = hg.update(repo, rev)
+
+        if not ret and movemarkfrom:
+            if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
+                ui.status(_("updating bookmark %s\n") % repo._activebookmark)
+            else:
+                # this can happen with a non-linear update
+                ui.status(_("(leaving bookmark %s)\n") %
+                          repo._activebookmark)
+                bookmarks.deactivate(repo)
+        elif brev in repo._bookmarks:
+            bookmarks.activate(repo, brev)
+            ui.status(_("(activating bookmark %s)\n") % brev)
+        elif brev:
+            if repo._activebookmark:
+                ui.status(_("(leaving bookmark %s)\n") %
+                          repo._activebookmark)
             bookmarks.deactivate(repo)
-    elif brev in repo._bookmarks:
-        bookmarks.activate(repo, brev)
-        ui.status(_("(activating bookmark %s)\n") % brev)
-    elif brev:
-        if repo._activebookmark:
-            ui.status(_("(leaving bookmark %s)\n") %
-                      repo._activebookmark)
-        bookmarks.deactivate(repo)
+    finally:
+        wlock.release()
 
     return ret