changeset 35606:4b68ca118d8d

pull: hold wlock for the full operation when --update is used With now, the wlock is not held between the pull and the update. This can lead to race condition and make logic checking to post pull results more complicated (eg: with _afterlock).
author Boris Feld <boris.feld@octobus.net>
date Thu, 11 Jan 2018 11:57:59 +0000
parents 45a816361926
children 24b5106e3e1e
files mercurial/commands.py tests/test-keyword.t
diffstat 2 files changed, 35 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py	Thu Jan 11 18:20:08 2018 +0800
+++ b/mercurial/commands.py	Thu Jan 11 11:57:59 2018 +0000
@@ -4007,36 +4007,40 @@
                         "so a rev cannot be specified.")
                 raise error.Abort(err)
 
-        pullopargs.update(opts.get('opargs', {}))
-        modheads = exchange.pull(repo, other, heads=revs,
-                                 force=opts.get('force'),
-                                 bookmarks=opts.get('bookmark', ()),
-                                 opargs=pullopargs).cgresult
-
-        # brev is a name, which might be a bookmark to be activated at
-        # the end of the update. In other words, it is an explicit
-        # destination of the update
-        brev = None
-
-        if checkout:
-            checkout = str(repo.changelog.rev(checkout))
-
-            # order below depends on implementation of
-            # hg.addbranchrevs(). opts['bookmark'] is ignored,
-            # because 'checkout' is determined without it.
-            if opts.get('rev'):
-                brev = opts['rev'][0]
-            elif opts.get('branch'):
-                brev = opts['branch'][0]
-            else:
-                brev = branches[0]
-        repo._subtoppath = source
-        try:
-            ret = postincoming(ui, repo, modheads, opts.get('update'),
-                               checkout, brev)
-
-        finally:
-            del repo._subtoppath
+        wlock = util.nullcontextmanager()
+        if opts.get('update'):
+            wlock = repo.wlock()
+        with wlock:
+            pullopargs.update(opts.get('opargs', {}))
+            modheads = exchange.pull(repo, other, heads=revs,
+                                     force=opts.get('force'),
+                                     bookmarks=opts.get('bookmark', ()),
+                                     opargs=pullopargs).cgresult
+
+            # brev is a name, which might be a bookmark to be activated at
+            # the end of the update. In other words, it is an explicit
+            # destination of the update
+            brev = None
+
+            if checkout:
+                checkout = str(repo.changelog.rev(checkout))
+
+                # order below depends on implementation of
+                # hg.addbranchrevs(). opts['bookmark'] is ignored,
+                # because 'checkout' is determined without it.
+                if opts.get('rev'):
+                    brev = opts['rev'][0]
+                elif opts.get('branch'):
+                    brev = opts['branch'][0]
+                else:
+                    brev = branches[0]
+            repo._subtoppath = source
+            try:
+                ret = postincoming(ui, repo, modheads, opts.get('update'),
+                                   checkout, brev)
+
+            finally:
+                del repo._subtoppath
 
     finally:
         other.close()
--- a/tests/test-keyword.t	Thu Jan 11 18:20:08 2018 +0800
+++ b/tests/test-keyword.t	Thu Jan 11 11:57:59 2018 +0000
@@ -262,6 +262,7 @@
   adding file changes
   added 2 changesets with 3 changes to 3 files
   new changesets a2392c293916:ef63ca68695b
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
@@ -314,7 +315,6 @@
   +++ b/b	Thu Jan 01 00:00:00 1970 +0000
   @@ -0,0 +1,1 @@
   +ignore $Id$
-  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ cp $HGRCPATH.nohooks $HGRCPATH