changeset 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 7b7e25a85f63
children 563ea14c62d4
files mercurial/commands.py tests/test-blackbox.t tests/test-hook.t tests/test-lock-badness.t
diffstat 4 files changed, 50 insertions(+), 47 deletions(-) [+]
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
 
--- a/tests/test-blackbox.t	Thu Aug 13 11:09:36 2015 -0300
+++ b/tests/test-blackbox.t	Tue Aug 11 16:26:12 2015 -0700
@@ -119,8 +119,8 @@
   $ echo '[hooks]' >> .hg/hgrc
   $ echo 'update = echo hooked' >> .hg/hgrc
   $ hg update
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   hooked
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg blackbox -l 5
   1970/01/01 00:00:00 bob> update
   1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 0 tags
--- a/tests/test-hook.t	Thu Aug 13 11:09:36 2015 -0300
+++ b/tests/test-hook.t	Tue Aug 11 16:26:12 2015 -0700
@@ -223,8 +223,8 @@
   $ echo "update = printenv.py update" >> .hg/hgrc
   $ hg update
   preupdate hook: HG_PARENT1=539e4b31b6dc
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   update hook: HG_ERROR=0 HG_PARENT1=539e4b31b6dc
-  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 pushkey hook
 
@@ -644,8 +644,8 @@
   $ hg ci -ma
   223eafe2750c tip
   $ hg up 0 --config extensions.largefiles=
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   cb9a9f314b8b
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui
 that is passed to pre/post hooks
--- a/tests/test-lock-badness.t	Thu Aug 13 11:09:36 2015 -0300
+++ b/tests/test-lock-badness.t	Tue Aug 11 16:26:12 2015 -0700
@@ -59,7 +59,6 @@
   $ hg -R b up -q --config hooks.pre-update="python:`pwd`/hooks.py:sleephalf"
   waiting for lock on working directory of b held by '*:*' (glob)
   got lock after ? seconds (glob)
-  warning: ignoring unknown working parent d2ae7f538514!
   $ wait
   $ cat stdout
   adding b