[PATCH 3 of 3 v2] repos: introduce '-R readonly:PATH' for doing local operations "read only"
Mads Kiilerich
mads at kiilerich.com
Fri Oct 14 01:17:30 UTC 2016
# HG changeset patch
# User Mads Kiilerich <madski at unity3d.com>
# Date 1476402795 -7200
# Fri Oct 14 01:53:15 2016 +0200
# Node ID 491da143c2f310da732c2e1005e7f8394134a51d
# Parent 24a7ccfb932b134da24e58817991943c8bbd63fa
repos: introduce '-R readonly:PATH' for doing local operations "read only"
When used as 'readonly:.', this is pretty much like if the repository was owned
by another user and the current user didn't have write access to anything in
.hg .
Using this feature will for example allow multiple simultaneous pushes,
pushes without phase changes, and will provide a "safe" way to run commands ...
assuming this and our use of VFS is complete and correct.
The existing "API" for repository types could use some cleanup - it requires
modules with special undefined duck typing. This patch seems to do what is
needed.
The existing VFS class hierarchy has a "readonlyvfs" class, but whatever it is,
it doesn't seem suitable for this use; it doesn't seem to be a reusable class
or mixin.
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -31,6 +31,7 @@ from . import (
merge as mergemod,
node,
phases,
+ readonlyrepo,
repoview,
scmutil,
sshpeer,
@@ -112,6 +113,7 @@ schemes = {
'https': httppeer,
'ssh': sshpeer,
'static-http': statichttprepo,
+ 'readonly': lambda path: readonlyrepo,
}
def _peerlookup(path):
diff --git a/mercurial/readonlyrepo.py b/mercurial/readonlyrepo.py
new file mode 100644
--- /dev/null
+++ b/mercurial/readonlyrepo.py
@@ -0,0 +1,57 @@
+# readonlyrepo.py - a local repository class for mercurial that can't write
+# or lock the repository
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+import errno
+
+from .i18n import _
+from . import (
+ localrepo,
+ scmutil,
+ util,
+)
+
+# created, not thrown yet
+readonlyexception = IOError(errno.EACCES, _('this is a "readonly" repository'))
+
+# this seems to be a necessary part of the repository type API
+islocal = localrepo.islocal
+
+class readonlyvfs(scmutil.vfs):
+ """A VFS that only can be called with read modes - writing will fail with
+ an IO error as if the user didn't have write access"""
+
+ def __call__(self, path, mode='r', *args, **kw):
+ if mode not in ('r', 'rb'):
+ raise readonlyexception
+ return super(readonlyvfs, self).__call__(path, mode, *args, **kw)
+
+class readonlyrepo(localrepo.localrepository):
+ """A repository that is local but read only, as if the user didn't have
+ file system write access."""
+
+ def __init__(self, baseui, path=None, create=False):
+ # we know the "scheme" for path is "readonly" but do not want to extend
+ # the file/bundle hack in the "url" parser - just strip it here
+ assert path.startswith('readonly:'), path
+ path = path[len('readonly:'):]
+
+ super(readonlyrepo, self).__init__(baseui, path=path, create=False)
+
+ assert self.vfs.__class__ is scmutil.vfs
+ self.vfs.__class__ = readonlyvfs
+ assert self.wvfs.__class__ is scmutil.vfs
+ self.wvfs.__class__ = readonlyvfs
+
+ def lock(self, wait=True):
+ raise readonlyexception
+
+ def wlock(self, wait=True):
+ raise readonlyexception
+
+def instance(ui, path, create):
+ return readonlyrepo(ui, util.urllocalpath(path), create=False)
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
@@ -1197,25 +1197,27 @@ publish changesets as plain push does
|
~
- $ hg -R Upsilon push Pi -r 7
+ $ hg -R readonly:Upsilon push Pi -r 7
pushing to Pi
searching for changes
no changes found
+ cannot lock source repo, skipping local public phase update
[1]
$ hgph Upsilon -r 'min(draft())'
- o 8 draft a-F - b740e3e5c05d
+ o 2 draft a-C - 54acac6f23ab
|
~
- $ hg -R Upsilon push Pi -r 8
+ $ hg -R readonly:Upsilon push Pi -r 8
pushing to Pi
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
+ cannot lock source repo, skipping local public phase update
$ hgph Upsilon -r 'min(draft())'
- o 9 draft a-G - 3e27b6f1eee1
+ o 2 draft a-C - 54acac6f23ab
|
~
More information about the Mercurial-devel
mailing list