changeset 5255:65dc707606ed

Push capability checking into protocol-level code.
author Bryan O'Sullivan <bos@serpentine.com>
date Mon, 27 Aug 2007 14:48:08 -0700
parents b534c502bfb3
children a4547dfbbf20
files mercurial/commands.py mercurial/httprepo.py mercurial/repo.py mercurial/sshrepo.py
diffstat 4 files changed, 21 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1645,11 +1645,7 @@ def incoming(ui, repo, source="default",
     other = hg.repository(ui, source)
     ui.status(_('comparing with %s\n') % source)
     if revs:
-        if 'lookup' in other.capabilities:
-            revs = [other.lookup(rev) for rev in revs]
-        else:
-            error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
-            raise util.Abort(error)
+        revs = [other.lookup(rev) for rev in revs]
     incoming = repo.findincoming(other, heads=revs, force=opts["force"])
     if not incoming:
         try:
@@ -1667,8 +1663,6 @@ def incoming(ui, repo, source="default",
             if revs is None:
                 cg = other.changegroup(incoming, "incoming")
             else:
-                if 'changegroupsubset' not in other.capabilities:
-                    raise util.Abort(_("Partial incoming cannot be done because other repository doesn't support changegroupsubset."))
                 cg = other.changegroupsubset(incoming, revs, 'incoming')
             bundletype = other.local() and "HG10BZ" or "HG10UN"
             fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
@@ -2078,10 +2072,11 @@ def pull(ui, repo, source="default", **o
     other = hg.repository(ui, source)
     ui.status(_('pulling from %s\n') % (source))
     if revs:
-        if 'lookup' in other.capabilities:
+        try:
             revs = [other.lookup(rev) for rev in revs]
-        else:
-            error = _("Other repository doesn't support revision lookup, so a rev cannot be specified.")
+        except repo.NoCapability:
+            error = _("Other repository doesn't support revision lookup, "
+                      "so a rev cannot be specified.")
             raise util.Abort(error)
 
     modheads = repo.pull(other, heads=revs, force=opts['force'])
--- a/mercurial/httprepo.py
+++ b/mercurial/httprepo.py
@@ -354,6 +354,7 @@ class httprepository(remoterepository):
             fp.close()
 
     def lookup(self, key):
+        self.requirecap('lookup', _('look up remote revision'))
         d = self.do_cmd("lookup", key = key).read()
         success, data = d[:-1].split(' ', 1)
         if int(success):
@@ -391,6 +392,7 @@ class httprepository(remoterepository):
         return util.chunkbuffer(zgenerator(f))
 
     def changegroupsubset(self, bases, heads, source):
+        self.requirecap('changegroupsubset', _('look up remote changes'))
         baselst = " ".join([hex(n) for n in bases])
         headlst = " ".join([hex(n) for n in heads])
         f = self.do_cmd("changegroupsubset", bases=baselst, heads=headlst)
--- a/mercurial/repo.py
+++ b/mercurial/repo.py
@@ -9,16 +9,26 @@
 class RepoError(Exception):
     pass
 
+class NoCapability(RepoError):
+    pass
+
 class repository(object):
     def capable(self, name):
         '''tell whether repo supports named capability.
         return False if not supported.
         if boolean capability, return True.
         if string capability, return string.'''
+        if name in self.capabilities:
+            return True
         name_eq = name + '='
         for cap in self.capabilities:
-            if name == cap:
-                return True
             if cap.startswith(name_eq):
                 return cap[len(name_eq):]
         return False
+
+    def requirecap(self, name, purpose):
+        '''raise an exception if the given capability is not present'''
+        if not self.capable(name):
+            raise NoCapability(_('cannot %s; remote repository does not '
+                                 'support the %r capability') %
+                               (purpose, name))
--- a/mercurial/sshrepo.py
+++ b/mercurial/sshrepo.py
@@ -131,6 +131,7 @@ class sshrepository(remoterepository):
         self.call("unlock")
 
     def lookup(self, key):
+        self.requirecap('lookup', _('look up remote revision'))
         d = self.call("lookup", key=key)
         success, data = d[:-1].split(" ", 1)
         if int(success):
@@ -168,6 +169,7 @@ class sshrepository(remoterepository):
         return self.do_cmd("changegroup", roots=n)
 
     def changegroupsubset(self, bases, heads, kind):
+        self.requirecap('changegroupsubset', _('look up remote changes'))
         bases = " ".join(map(hex, bases))
         heads = " ".join(map(hex, heads))
         return self.do_cmd("changegroupsubset", bases=bases, heads=heads)