[PATCH 2 of 2 STABLE V2] push: make locking of source optional (issue3684)
Pierre-Yves David
pierre-yves.david at ens-lyon.org
Tue Apr 30 14:27:31 CDT 2013
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at 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.
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
More information about the Mercurial-devel
mailing list