Patchwork [2,of,2,STABLE,V2] push: make locking of source optional (issue3684)

login
register
mail settings
Submitter Pierre-Yves David
Date April 30, 2013, 7:27 p.m.
Message ID <5796eb2d2bfb055b2b9a.1367350051@yamac.lan>
Download mbox | patch
Permalink /patch/1515/
State Accepted
Commit 3f5e75c22585975eaf4ea1c8da71676a88637eec
Headers show

Comments

Pierre-Yves David - April 30, 2013, 7:27 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@logilab.fr>
# Date 1367349596 -7200
#      Tue Apr 30 21:19:56 2013 +0200
# Branch stable
# Node ID 5796eb2d2bfb055b2b9a392884326844aea97bc6
# Parent  efad78b96b8ec2c85bc76996ebbcc8e059356796
push: make locking of source optional (issue3684)

Having the permission to lock the source repo on push is now optional. When the
repo cannot be locked, phase are not changed locally. A status message is issue
when some actual phase movement are skipped:

    cannot lock source repo, skipping local public phase update

A debug message with the exact reason of the locking failure is issued in all
case.
Matt Mackall - April 30, 2013, 7:48 p.m.
On Tue, 2013-04-30 at 21:27 +0200, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@logilab.fr>
> # Date 1367349596 -7200
> #      Tue Apr 30 21:19:56 2013 +0200
> # Branch stable
> # Node ID 5796eb2d2bfb055b2b9a392884326844aea97bc6
> # Parent  efad78b96b8ec2c85bc76996ebbcc8e059356796
> push: make locking of source optional (issue3684)

These are queued for stable, thanks.

Patch

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1762,13 +1762,33 @@  class localrepository(object):
         if not remote.canpush():
             raise util.Abort(_("destination does not support push"))
         unfi = self.unfiltered()
         def localphasemove(nodes, phase=phases.public):
             """move <nodes> to <phase> in the local source repo"""
-            phases.advanceboundary(self, phase, nodes)
+            if locallock is not None:
+                phases.advanceboundary(self, phase, nodes)
+            else:
+                # repo is not locked, do not change any phases!
+                # Informs the user that phases should have been moved when
+                # applicable.
+                actualmoves = [n for n in nodes if phase < self[n].phase()]
+                phasestr = phases.phasenames[phase]
+                if actualmoves:
+                    self.ui.status(_('cannot lock source repo, skipping local'
+                                     ' %s phase update\n') % phasestr)
         # get local lock as we might write phase data
-        locallock = self.lock()
+        locallock = None
+        try:
+            locallock = self.lock()
+        except IOError, err:
+            if err.errno != errno.EACCES:
+                raise
+            # source repo cannot be locked.
+            # We do not abort the push, but just disable the local phase
+            # synchronisation.
+            msg = 'cannot lock source repository: %s\n' % err
+            self.ui.debug(msg)
         try:
             self.checkpush(force, revs)
             lock = None
             unbundle = remote.capable('unbundle')
             if not unbundle:
@@ -1916,11 +1936,12 @@  class localrepository(object):
                 obsolete.syncpush(self, remote)
             finally:
                 if lock is not None:
                     lock.release()
         finally:
-            locallock.release()
+            if locallock is not None:
+                locallock.release()
 
         self.ui.debug("checking for updated bookmarks\n")
         rb = remote.listkeys('bookmarks')
         for k in rb.keys():
             if k in unfi._bookmarks:
diff --git a/tests/test-phases-exchange.t b/tests/test-phases-exchange.t
--- a/tests/test-phases-exchange.t
+++ b/tests/test-phases-exchange.t
@@ -1060,7 +1060,45 @@  2. cloning publishing repository
   |/
   o  1 public a-B - 548a3d25dbf0
   |
   o  0 public a-A - 054250a37db4
   
+
+Pushing From an unlockable repo
+--------------------------------
+(issue3684)
+
+Unability to lock the source repo should not prevent the push. It will prevent
+the retrieval of remote phase during push. For example, pushing to a publishing
+server won't turn changeset public.
+
+1. Test that push is not prevented
+
+  $ hg init Phi
+  $ cd Upsilon
+  $ chmod -R -w .hg
+  $ hg push ../Phi
+  pushing to ../Phi
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 14 changesets with 14 changes to 14 files (+3 heads)
+  $ chmod -R +w .hg
+
+2. Test that failed phases movement are reported
+
+  $ hg phase --force --draft 3
+  $ chmod -R -w .hg
+  $ hg push ../Phi
+  pushing to ../Phi
+  searching for changes
+  no changes found
+  cannot lock source repo, skipping local public phase update
+  [1]
+  $ chmod -R +w .hg
+  $ hgph Upsilon
+
+  $ cd ..
+
   $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS