diff -r d2e16419d3f4 -r 74de1c59f71c mercurial/exchange.py --- a/mercurial/exchange.py Tue Oct 13 10:41:54 2015 -0700 +++ b/mercurial/exchange.py Tue Oct 13 11:45:30 2015 -0700 @@ -1599,15 +1599,26 @@ res = remote._call('clonebundles') entries = parseclonebundlesmanifest(res) - - # TODO filter entries by supported features. - # TODO sort entries by user preferences. - if not entries: repo.ui.note(_('no clone bundles available on remote; ' 'falling back to regular clone\n')) return + entries = filterclonebundleentries(repo, entries) + if not entries: + # There is a thundering herd concern here. However, if a server + # operator doesn't advertise bundles appropriate for its clients, + # they deserve what's coming. Furthermore, from a client's + # perspective, no automatic fallback would mean not being able to + # clone! + repo.ui.warn(_('no compatible clone bundles available on server; ' + 'falling back to regular clone\n')) + repo.ui.warn(_('(you may want to report this to the server ' + 'operator)\n')) + return + + # TODO sort entries by user preferences. + url = entries[0]['URL'] repo.ui.status(_('applying clone bundle from %s\n') % url) if trypullbundlefromurl(repo.ui, repo, url): @@ -1644,6 +1655,25 @@ return m +def filterclonebundleentries(repo, entries): + newentries = [] + for entry in entries: + spec = entry.get('BUNDLESPEC') + if spec: + try: + parsebundlespec(repo, spec, strict=True) + except error.InvalidBundleSpecification as e: + repo.ui.debug(str(e) + '\n') + continue + except error.UnsupportedBundleSpecification as e: + repo.ui.debug('filtering %s because unsupported bundle ' + 'spec: %s\n' % (entry['URL'], str(e))) + continue + + newentries.append(entry) + + return newentries + def trypullbundlefromurl(ui, repo, url): """Attempt to apply a bundle from a URL.""" lock = repo.lock()