Patchwork [4,of,4] clonebundle: make it possible to retrieve the initial bundle through largefile

mail settings
Submitter Boris Feld
Date Jan. 2, 2018, 10:40 a.m.
Message ID <2e5d1231c400dea6f663.1514889624@FB>
Download mbox | patch
Permalink /patch/26520/
State Superseded
Headers show


Boris Feld - Jan. 2, 2018, 10:40 a.m.
# HG changeset patch
# User Boris Feld <>
# Date 1513861091 -3600
#      Thu Dec 21 13:58:11 2017 +0100
# Node ID 2e5d1231c400dea6f663ab32733ebbf49f36ae3a
# Parent  b8273301d55368ba740313ce464ab116d6c263dc
# EXP-Topic largefile-url
# Available At
#              hg pull -r 2e5d1231c400
clonebundle: make it possible to retrieve the initial bundle through largefile

By setting the default path early enough, we make it possible to retrieve a
clone bundle as a largefile from the repository we are cloning.

But... why?

Clone bundle is a great feature to speeds up clone of large repository. However
one of the main obstacle for clone bundle deployment is the authentication
scheme. For non public project, just putting a static file on some random CDN is
not an option as we have to make sure people have the proper permission to
retrieves the bundle. On the other hand, 'largefiles' already have all the
necessary logic to serve arbitrary binary files -after- an authentication
checks. So reusing an existing large file infrastructure can be a significant
shortcut to clone bundle in this kind of closed environment.

The idea might seems strange, but the necessary update to the large file
extensions are quite small while the benefits are huge. In addition, since all
the extra logic live in the 'largefiles' extensions, core does not have to know
anything about it.


diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -659,6 +659,9 @@  def clone(ui, peeropts, source, dest=Non
                 checkout = revs[0]
             local = destpeer.local()
             if local:
+                u = util.url(abspath)
+                defaulturl = bytes(u)
+                local.ui.setconfig('paths', 'default', defaulturl, 'clone')
                 if not stream:
                     if pull:
                         stream = False
diff --git a/tests/test-clonebundles.t b/tests/test-clonebundles.t
--- a/tests/test-clonebundles.t
+++ b/tests/test-clonebundles.t
@@ -517,3 +517,30 @@  A manifest with a gzip bundle and a stre
   transferred 613 bytes in * seconds (*) (glob)
   searching for changes
   no changes found
+Test clone bundle retrieved through bundle2
+  $ cat << EOF >> $HGRCPATH
+  > [extensions]
+  > largefiles=
+  > EOF
+  $
+  $ hg -R server serve -d -p $HGPORT --pid-file --accesslog access.log
+  $ cat >> $DAEMON_PIDS
+  $ hg -R server debuglfput gz-a.hg
+  f6eca29e25359f6a92f1ea64527cdcf1b5abe62a
+  $ cat > server/.hg/clonebundles.manifest << EOF
+  > largefile://f6eca29e25359f6a92f1ea64527cdcf1b5abe62a BUNDLESPEC=gzip-v2
+  > EOF
+  $ hg clone -U http://localhost:$HGPORT largefile-provided --traceback
+  applying clone bundle from largefile://f6eca29e25359f6a92f1ea64527cdcf1b5abe62a
+  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