[PATCH 2 of 5] clonebundles: filter on bundle type
Gregory Szorc
gregory.szorc at gmail.com
Wed Sep 30 00:48:45 UTC 2015
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1443573277 25200
# Tue Sep 29 17:34:37 2015 -0700
# Node ID faf364dfab7c2861b712b7e9548b832f3c222bba
# Parent f2353a7a0ac6388085300648ce34325c4b7d9030
clonebundles: filter on bundle type
Not all clients support all bundle types. This patch provides a
mechanism to advertise the type of a bundle at a URL. If the type
is unknown to the client, it ignores it.
There is necessary follow-up work to advertise bundle2 requirements as
well, since bundle2 bundles may contain parts that clients don't know
how to process.
diff --git a/hgext/clonebundles.py b/hgext/clonebundles.py
--- a/hgext/clonebundles.py
+++ b/hgext/clonebundles.py
@@ -31,9 +31,19 @@ can be used by site installations.
The server operator is responsible for generating the bundle manifest file.
Metadata Attributes:
-TBD
+TYPE
+ The type of the bundle. This is one of the strings from
+ mercurial.changegroup.py:bundletypes, which are also the headers of
+ bundle files. Example values include "HG20" and "HG10GZ".
+
+ Clients will automatically filter out bundle types they do not
+ know how to consume.
+
+ The actual value doesn't impact client behavior beyond filtering:
+ clients will still sniff the bundle type from downloaded content.
+ We reuse the file header values for consistency.
"""
from mercurial import (
extensions,
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -1578,17 +1578,28 @@ def maybeapplyclonebundle(repo, remote):
"""Apply a clone bundle from a remote, if possible."""
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 advertised on server; '
'falling back to regular clone\n'))
return
+ entries = filterclonebundleentries(repo.ui, 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):
repo.ui.status(_('finished applying clone bundle\n'))
@@ -1623,8 +1634,20 @@ def parseclonebundlesmanifest(s):
m.append(attrs)
return m
+def filterclonebundleentries(ui, entries):
+ newentries = []
+ for e in entries:
+ if 'TYPE' in e and e['TYPE'] not in changegroup.bundletypes:
+ ui.debug('filtering %s because unknown bundle type %s\n' %
+ (e['URL'], e['TYPE']))
+ continue
+
+ newentries.append(e)
+
+ return newentries
+
def trypullbundlefromurl(ui, repo, url):
"""Attempt to apply a bundle from a URL."""
lock = repo.lock()
try:
diff --git a/tests/test-clonebundles.t b/tests/test-clonebundles.t
--- a/tests/test-clonebundles.t
+++ b/tests/test-clonebundles.t
@@ -113,4 +113,36 @@ Bundle with full content works
added 2 changesets with 2 changes to 2 files
finished applying clone bundle
searching for changes
no changes found
+
+Entry with unknown TYPE is filtered and not used
+
+ $ cat > server/.hg/clonebundles.manifest << EOF
+ > http://bad.entry TYPE=UNKNOWN
+ > http://localhost:$HGPORT1/full.hg TYPE=HG10GZ
+ > EOF
+
+ $ hg clone -U http://localhost:$HGPORT filter-unknown-type
+ applying clone bundle from http://localhost:$HGPORT1/full.hg
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files
+ finished applying clone bundle
+ searching for changes
+ no changes found
+
+Automatic fallback when all entries are filtered
+
+ $ cat > server/.hg/clonebundles.manifest << EOF
+ > http://bad.entry TYPE=UNKNOWN
+ > EOF
+
+ $ hg clone -U http://localhost:$HGPORT filter-all
+ no compatible clone bundles available on server; falling back to regular clone
+ (you may want to report this to the server operator)
+ requesting all changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files
More information about the Mercurial-devel
mailing list