Right now, we always advertise all refs as ".have", even those outside
the current namespace. This leads to problems when trying to push to a
repository with a huge number of namespaces from a slow connection.

Add a configuration option receive.advertiseAllRefs that can be used to
determine whether refs outside the current namespace should be
advertised or not.

Signed-off-by: Lukas Fleischer <lfleisc...@lfos.de>
---
We are using Git namespaces to store a huge number of (virtual)
repositories inside a shared repository. While the blobs in the virtual
repositories are fairly similar, they do not share any refs, so
advertising any refs outside the current namespace is undesirable. See
the discussion on [1] for details.

Note that this patch is just a draft: I didn't do any testing, apart
from checking that it compiles. I would like to hear some opinions
before sending a polished version.

Is our use case considered common enough to justify the inclusion of
such a configuration option in mainline?

Are there suggestions for a better name for the option? Ideally, it
should contain the word "namespace" but I could not come up with
something sensible that is short enough.

[1] https://lists.archlinux.org/pipermail/aur-general/2015-October/031596.html

 Documentation/config.txt |  6 ++++++
 builtin/receive-pack.c   | 31 +++++++++++++++++++++----------
 2 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 315f271..aa101a7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2201,6 +2201,12 @@ receive.advertiseAtomic::
        capability to its clients. If you don't want to this capability
        to be advertised, set this variable to false.
 
+receive.advertiseAllRefs::
+       By default, git-receive-pack will advertise all refs, even those
+       outside the current namespace, so that the client can use them to
+       minimize data transfer. If you only want to advertise refs from the
+       active namespace to be advertised, set this variable to false.
+
 receive.autogc::
        By default, git-receive-pack will run "git-gc --auto" after
        receiving data from git-push and updating refs.  You can stop
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index e6b93d0..ea9a820 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -41,6 +41,7 @@ static struct strbuf fsck_msg_types = STRBUF_INIT;
 static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
 static int advertise_atomic_push = 1;
+static int advertise_all_refs = 1;
 static int unpack_limit = 100;
 static int report_status;
 static int use_sideband;
@@ -190,6 +191,11 @@ static int receive_pack_config(const char *var, const char 
*value, void *cb)
                return 0;
        }
 
+       if (strcmp(var, "receive.advertiseallrefs") == 0) {
+               advertise_all_refs = git_config_bool(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, cb);
 }
 
@@ -222,16 +228,21 @@ static void show_ref(const char *path, const unsigned 
char *sha1)
 static int show_ref_cb(const char *path, const struct object_id *oid, int 
flag, void *unused)
 {
        path = strip_namespace(path);
-       /*
-        * Advertise refs outside our current namespace as ".have"
-        * refs, so that the client can use them to minimize data
-        * transfer but will otherwise ignore them. This happens to
-        * cover ".have" that are thrown in by add_one_alternate_ref()
-        * to mark histories that are complete in our alternates as
-        * well.
-        */
-       if (!path)
-               path = ".have";
+       if (!path) {
+               if (advertise_all_refs) {
+                       /*
+                        * Advertise refs outside our current namespace as
+                        * ".have" refs, so that the client can use them to
+                        * minimize data transfer but will otherwise ignore
+                        * them. This happens to cover ".have" that are thrown
+                        * in by add_one_alternate_ref() to mark histories that
+                        * are complete in our alternates as well.
+                        */
+                       path = ".have";
+               } else {
+                       return 0;
+               }
+       }
        show_ref(path, oid->hash);
        return 0;
 }
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to