[PATCH 3 of 4 STABLE] localrepo: make supported features manageable in each repositories individually

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Mon Jul 16 10:15:06 CDT 2012


# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1342451578 -32400
# Branch stable
# Node ID 2792d09973cff9d5c0f922af9b39b2326105e823
# Parent  325d68bcd883c7db3348bbd4035d481e458de55b
localrepo: make supported features manageable in each repositories individually

Before this patch, all localrepositories support same features,
because supported features are managed by the class variable
"supported" of "localrepository".

For example, "largefiles" feature provided by largefiles extension is
recognized as supported, by adding the feature name to "supported" of
"localrepository".

So, commands handling multiple repositories at a time like below
mis-recognize that such features are supported also in repositories
not enabling corresponded extensions:

  - clone or pull from localhost
  - push to localhost
  - recursive execution in subrepo tree

"reposetup()" can't be used to fix this problem, because it is invoked
after checking whether supported features satisfy ones required in the
target repository.

So, this patch adds "supportsetups" set to "localrepository" to manage
hook functions to setup supported features of each repositories.

If any functions are added to "supportsetups", they are invoked, and
information about supported features is managed in each repositories
individually.

This patch also adds checking below:

  - pull from localhost: whether features supported in the local(= dst)
    repository satisfies ones required in the remote(= src)

  - push to localhost: whether features supported in the remote(= dst)
    repository satisfies ones required in the local(= src)

Managing supported features by the class variable means that there is
no difference of supported features between each instances of
"localrepository" in the same Python process, so such checking is not
needed before this patch.

Even with this patch, if intermediate bundlefile is used as pulling
source, pulling indirectly from the remote repository, which requires
features more than ones supported in the local, can't be prevented,
because bundlefile has no information about "required features" in it.

diff -r 325d68bcd883 -r 2792d09973cf mercurial/localrepo.py
--- a/mercurial/localrepo.py	Tue Jul 17 00:12:58 2012 +0900
+++ b/mercurial/localrepo.py	Tue Jul 17 00:12:58 2012 +0900
@@ -30,6 +30,7 @@
     supportedformats = set(('revlogv1', 'generaldelta'))
     supported = supportedformats | set(('store', 'fncache', 'shared',
                                         'dotencode'))
+    supportsetups = set()
 
     def __init__(self, baseui, path=None, create=False):
         repo.repository.__init__(self)
@@ -53,6 +54,11 @@
         except IOError:
             pass
 
+        if self.supportsetups:
+            self.supported = set(self.supported) # use private copy
+            for supportsetup in self.supportsetups:
+                supportsetup(self.ui, self.supported)
+
         if not os.path.isdir(self.path):
             if create:
                 if not os.path.exists(path):
@@ -1539,6 +1545,14 @@
         return r
 
     def pull(self, remote, heads=None, force=False):
+        if remote.local():
+            missing = set(remote.requirements) - self.supported
+            if missing:
+                msg = _("any of required features are not"
+                        " supported in the destination:"
+                        " %s") % (', '.join(sorted(missing)))
+                raise util.Abort(msg)
+
         lock = self.lock()
         try:
             tmp = discovery.findcommonincoming(self, remote, heads=heads,
@@ -1615,6 +1629,14 @@
             we have outgoing changesets but refused to push
           - other values as described by addchangegroup()
         '''
+        if remote.local():
+            missing = set(self.requirements) - remote.supported
+            if missing:
+                msg = _("any of required features are not"
+                        " supported in the destination:"
+                        " %s") % (', '.join(sorted(missing)))
+                raise util.Abort(msg)
+
         # there are two ways to push to remote repo:
         #
         # addchangegroup assumes local user can lock remote
diff -r 325d68bcd883 -r 2792d09973cf tests/test-requires.t
--- a/tests/test-requires.t	Tue Jul 17 00:12:58 2012 +0900
+++ b/tests/test-requires.t	Tue Jul 17 00:12:58 2012 +0900
@@ -15,3 +15,54 @@
   $ hg tip
   abort: unknown repository format: requires features 'indoor-pool', 'outdoor-pool' (upgrade Mercurial)!
   [255]
+  $ cd ..
+
+Test checking between features supported locally and ones required in
+another repository of push/pull/clone on localhost:
+
+  $ mkdir supported-locally
+  $ cd supported-locally
+
+  $ hg init supported
+  $ echo a > supported/a
+  $ hg -R supported commit -Am '#0 at supported'
+  adding a
+
+  $ echo 'supporsetup-test' >> supported/.hg/requires
+  $ cat > $TESTTMP/supportlocally.py <<EOF
+  > from mercurial import localrepo, extensions
+  > def supportsetup(ui, supported):
+  >     for name, module in extensions.extensions(ui):
+  >         if __name__ == module.__name__:
+  >             # support specific feature locally
+  >             supported |= set(['supporsetup-test'])
+  >             return
+  > def uisetup(ui):
+  >     localrepo.localrepository.supportsetups.add(supportsetup)
+  > EOF
+  $ cat > supported/.hg/hgrc <<EOF
+  > [extensions]
+  > # enable extension locally
+  > supportlocally = $TESTTMP/supportlocally.py
+  > EOF
+
+  $ hg init push-dst
+  $ hg -R supported push push-dst
+  pushing to push-dst
+  abort: any of required features are not supported in the destination: supporsetup-test
+  [255]
+
+  $ hg init pull-src
+  $ hg -R pull-src pull supported
+  pulling from supported
+  abort: any of required features are not supported in the destination: supporsetup-test
+  [255]
+
+  $ hg clone supported clone-dst
+  abort: unknown repository format: requires features 'supporsetup-test' (upgrade Mercurial)!
+  [255]
+  $ hg clone --pull supported clone-dst
+  abort: any of required features are not supported in the destination: supporsetup-test
+  [255]
+
+  $ cd ..


More information about the Mercurial-devel mailing list