# HG changeset patch # User Bryan O'Sullivan # Date 1188251288 25200 # Node ID 65dc707606ed5f4e5882f1a06e11a03f13f0220d # Parent b534c502bfb3bd42adbe0a020c1167a1946c1dd0 Push capability checking into protocol-level code. diff --git a/mercurial/commands.py b/mercurial/commands.py --- 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']) diff --git a/mercurial/httprepo.py b/mercurial/httprepo.py --- 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) diff --git a/mercurial/repo.py b/mercurial/repo.py --- 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)) diff --git a/mercurial/sshrepo.py b/mercurial/sshrepo.py --- 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)