# HG changeset patch # User Gregory Szorc # Date 2015-10-14 18:05:53 # Node ID 23c0da28c0348a8d5bd4529d5dad2c7f5d2c3a30 # Parent 704818fb170de3ff1e1ab1bc7cda4c4fe5b75bab clonebundles: advertise clone bundles feature to clients Server operators that have enabled clone bundles probably want clients to use it. This patch introduces a feature that will insert a bundle2 "output" part that advertises the existence of the clone bundles feature to clients that aren't using it. The server uses the "cbattempted" argument to "getbundle" to determine whether a client supports clone bundles and to avoid sending the message to clients that failed the clone bundle for whatever reason. diff --git a/hgext/clonebundles.py b/hgext/clonebundles.py --- a/hgext/clonebundles.py +++ b/hgext/clonebundles.py @@ -64,7 +64,10 @@ REQUIRESNI Value should be "true". """ +from mercurial.i18n import _ +from mercurial.node import nullid from mercurial import ( + exchange, extensions, wireproto, ) @@ -94,5 +97,44 @@ def bundles(repo, proto): """ return repo.opener.tryread('clonebundles.manifest') +@exchange.getbundle2partsgenerator('clonebundlesadvertise', 0) +def advertiseclonebundlespart(bundler, repo, source, bundlecaps=None, + b2caps=None, heads=None, common=None, + cbattempted=None, **kwargs): + """Inserts an output part to advertise clone bundles availability.""" + # Allow server operators to disable this behavior. + # # experimental config: ui.clonebundleadvertise + if not repo.ui.configbool('ui', 'clonebundleadvertise', True): + return + + # Only advertise if a manifest is present. + if not repo.opener.exists('clonebundles.manifest'): + return + + # And when changegroup data is requested. + if not kwargs.get('cg', True): + return + + # And when the client supports clone bundles. + if cbattempted is None: + return + + # And when the client didn't attempt a clone bundle as part of this pull. + if cbattempted: + return + + # And when a full clone is requested. + # Note: client should not send "cbattempted" for regular pulls. This check + # is defense in depth. + if common and common != [nullid]: + return + + msg = _('this server supports the experimental "clone bundles" feature ' + 'that should enable faster and more reliable cloning\n' + 'help test it by setting the "experimental.clonebundles" config ' + 'flag to "true"') + + bundler.newpart('output', data=msg) + def extsetup(ui): extensions.wrapfunction(wireproto, '_capabilities', capabilities) diff --git a/tests/test-clonebundles.t b/tests/test-clonebundles.t --- a/tests/test-clonebundles.t +++ b/tests/test-clonebundles.t @@ -64,6 +64,17 @@ Empty manifest file results in retrieval adding file changes added 2 changesets with 2 changes to 2 files +Server advertises presence of feature to client requesting full clone + + $ hg --config experimental.clonebundles=false clone -U http://localhost:$HGPORT advertise-on-clone + requesting all changes + remote: this server supports the experimental "clone bundles" feature that should enable faster and more reliable cloning + remote: help test it by setting the "experimental.clonebundles" config flag to "true" + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + Manifest file with invalid URL aborts $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest