git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/3] protocol v2: specify static seeding of clone/fetch via "bundle-uri"

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Oct 27, 2021, 18:01 UTC
Message-ID
<211027.86ilxixoxz.gmgdl@evledraar.gmail.com>
In-Reply-To
<756524c1-a3b9-29b5-bb72-f75a0c76ea1f@gmail.com>
On Wed, Oct 27 2021, Derrick Stolee wrote:
Show 82 quoted lines
> On 10/27/2021 4:29 AM, Ævar Arnfjörð Bjarmason wrote:
>> 
>> On Tue, Oct 26 2021, Derrick Stolee wrote:
>> 
>>> On 10/25/2021 5:25 PM, Ævar Arnfjörð Bjarmason wrote:
>>>> Add a server-side implementation of a new "bundle-uri" command to
>>>> protocol v2. As discussed in the updated "protocol-v2.txt" this will
>>>> allow conforming clients to optionally seed their initial clones or
>>>> incremental fetches from URLs containing "*.bundle" files created with
>>>> "git bundle create".
>>>
>>> ...
>>>
>>>> +DISCUSSION of bundle-uri
>>>> +^^^^^^^^^^^^^^^^^^^^^^^^
>>>> +
>>>> +The intent of the feature is optimize for server resource consumption
>>>> +in the common case by changing the common case of fetching a very
>>>> +large PACK during linkgit:git-clone[1] into a smaller incremental
>>>> +fetch.
>>>> +
>>>> +It also allows servers to achieve better caching in combination with
>>>> +an `uploadpack.packObjectsHook` (see linkgit:git-config[1]).
>>>> +
>>>> +By having new clones or fetches be a more predictable and common
>>>> +negotiation against the tips of recently produces *.bundle file(s).
>>>> +Servers might even pre-generate the results of such negotiations for
>>>> +the `uploadpack.packObjectsHook` as new pushes come in.
>>>> +
>>>> +I.e. the server would anticipate that fresh clones will download a
>>>> +known bundle, followed by catching up to the current state of the
>>>> +repository using ref tips found in that bundle (or bundles).
>>>> +
>>>> +PROTOCOL for bundle-uri
>>>> +^^^^^^^^^^^^^^^^^^^^^^^
>>>> +
>>>> +A `bundle-uri` request takes no arguments, and as noted above does not
>>>> +currently advertise a capability value. Both may be added in the
>>>> +future.
>>>
>>> One thing I realized was missing from this proposal is any interaction
>>> with partial clone. It would be disappointing if we could not advertise
>>> bundles of commit-and-tree packfiles for blobless partial clones.
>>>
>>> There is currently no way for the client to signal the filter type
>>> during this command. Not having any way to extend to include that
>>> seems like an oversight we should remedy before committing to a
>>> protocol that can't be extended.
>>>
>>> (This also seems like a good enough reason to group the URIs into a
>>> struct-like storage, because the filter type could be stored next to
>>> the URI.)
>> 
>> I'll update the docs to note that. I'd definitely like to leave out any
>> implementation of filter/shallow for an initial iteration of this for
>> simplicity, but the protocol keyword/behavior is open-ended enough to
>> permit any extension.
>
> It would be good to be explicit about how this would work. Looking at
> it fresh, it seems that the server could send multiple bundle URIs with
> the extra metadata to say which ones have a filter (and what that filter
> is). The client could then check if a bundle matches the given filter.
>
> But this is a bit inverted: the filter mechanism currently has the client
> request a given filter and the server responds with _at least_ that much
> data. This allows the server to ignore things like pathspec-filters or
> certain size-based filters. If the client just ignores a bundle URI
> because it doesn't match the exact filter, this could lead the client to
> ask for the data without a bundle, even if it would be faster to just
> download the advertised bundle.
>
> For this reason, I think it would be valuable for the client to tell
> the server the intended filter, and the server responds with bundle
> URIs that contain a subset of the information that would be provided
> by a later fetch request with that filter.
>
>> I.e. the server can start advertising "bundle-uri=shallow", and future
>> clients can request arbitrary key-value pairs in addition to just
>> "bundle-uri" now.
>> 
>> Having said that I think that *probably* this is something that'll never
>> be implemented, but maybe I'll eat my words there.

I didn't mean to elide past "filter", but was just using "shallow" as a short-hand for one thing in the "fetch" dialog that a client can mention that'll impact PACK generation, just like filter.

Having thought about this a bit more, I think it should be an invariant in any bundle-uri design that the server shouldn't communicate any side-channel information whatsoever about a bundle it advertises, if that information can't be discovered in the header of that bundle file.

Mind you, this means throwing out large parts of my current proposed over-the-wire design, but I think for the better. I.e. the whole response part where we communicate:

    (bundle-uri (SP bundle-feature-key (=bundle-feature-val)?)* LF)*
    flush-pkt
Would just become something like:
    (bundle-uri delim-pkt bundle-header? delim-pkt)*
    flush-pkt

I.e. we'd optionally transfer the content of the bundle header (content up to the first "\n\n") to the client, but *only* ever as a shorthand for saving the client a roundtrip.

The pointed-to bundle is still 100% the source of truth, and when retrieving the bundle-uri we'd ignore whatever "bundle-header" we got earlier (except insofar as we'd like to say emit a warning() if the two don't match).

(I'd not thought too carefully about these shallow/filter etc. edge cases, my main intended use-case has been pre-seeding full clones, and having this feedback to make me think about it is very valuable).

> You continue focusing on the shallow option, which I agree is not
> important. The filter option, specifically --filter=blob:none, seems
> to be critical to have a short-term plan for implementing with this
> in mind.

Per the above this then just becomes a question of "how do we produce a bundle with those attributes?".

I *think* that currently there isn't a way to do that, i.e. the PACK payload of a bundle is the output of "git pack-objects", but due to it including refs, tips and prerequisites.

I don't think you can say "this bundle has no blobs". The "prerequisites" hard map to the same thing you could put on a "want/have" line during PACK negotiation.

I think we could/should fix that, i.e. we can bump the bundle format version and have it encode some extended prerequisites/filter/shallow etc information. You'd then have a 1=1 match between the features of git-upload-pack and what you can transfer via the bundle side-channel.

But the more I think about it, the more strongly I feel that we should always add that to the bundle *format*, and not as some side-channel information in this "bundle-uri" protocol keyword.

To me *the* point of this feature is to have servers provide a shorthand for something that's been a well-established trick you can do today, and of which there are any number of pre-existing implementations.

I'm not trying to break any new ground here, just make "git [fetch|clone]" support a well-known trick as a first-class feature via protocol v2.

I'm not the first person to whip up some custom "git-clone-via-bundle.sh" that takes bundle URI(s) and a repo URI, wget's the bundle, calls "git bundle unbundle", updates ref tips, and then does a "git fetch".

The benefit of making that a first-class protocol feature over a full negotiation is essentially synonymous with how it's easier in practice to widely deploy static assets on CDNs v.s. guaranteeing the same network locality, caching etc. when serving up the same payload by running a custom binary.

One reason not to add any side-channel information not found in the bundle header(s) is that we can also guarantee that there won't be any feature gap between the "transfer.injectBundleURI" config key I've already got implemented (and is in the earlier RFC version of this series). I.e. you can do:

    # You can specify this N number of times to inject N bundles
    git clone \
	-c transfer.injectBundleURI="https://something.local/some-repo.bundle" \
        https://example.com/some-repo.git

To inject CDN support to any remote server that doesn't know about "bundle-uri", or add to the bundles of a server that does. That URI can even be a file:// if you add "-c fetch.uriProtocols=file".

I realize that all of the above does *not* answer part of your question about filters, which I think I can accurately rephrase as:

    Ok, so you can dump a static list of bundle URIs from config, but
    that's always going to be a small list, what about the combinatorial
    explosion arbitrary upload-pack options? Filters, shallow,
    include-tag etc.

My main answer to that is that YAGNI. If you need to spew out an URL for a PACK after a client describes any of its arbitrary wants, needs, filters etc. you've exactly re-invented what "packfile-uri" is today. I think that feature is very useful, and I've got no intention of trying to replace it.

I think the sweet spot for "bundle-uri" is to advertise a small number of bundles that encompass common clone/fetch patterns. I.e. something like a bundle for a full clone with the repo data up to today, and maybe a couple of other bundles covering a time period that clients would be likely to incrementally update within, e.g. 1 week ago..today && yesterday..now.

I agree that adding say "full clone, --depth=1" and "full clone, no blobs" etc. to that might be *very* useful for some deployments, but per the above I think we should really add that to the bundle format first, not protocol v2.

Previous: Derrick StoleeNext: Derrick Stolee
Message 11 of 77 in “bundle-uri: "dumb" static CDN offloading, spec & server implementation”
  1. 0/3 bundle-uri: "dumb" static CDN offloading, spec & server implementationÆvar Arnfjörð Bjarmason, Oct 25, 2021
  2. 1/3 leak tests: mark t5701-git-serve.sh as passing SANITIZE=leakÆvar Arnfjörð Bjarmason, Oct 25, 2021
  3. 2/3 protocol v2: specify static seeding of clone/fetch via "bundle-uri"Ævar Arnfjörð Bjarmason, Oct 25, 2021
  4. Derrick StoleeOct 26, 2021
  5. Ævar Arnfjörð BjarmasonOct 26, 2021
  6. Derrick StoleeOct 27, 2021
  7. Ævar Arnfjörð BjarmasonOct 27, 2021
  8. Derrick StoleeOct 27, 2021
  9. Ævar Arnfjörð BjarmasonOct 27, 2021
  10. Derrick StoleeOct 27, 2021
  11. Ævar Arnfjörð BjarmasonOct 27, 2021
  12. Derrick StoleeOct 27, 2021
  13. Ævar Arnfjörð BjarmasonOct 27, 2021
  14. Derrick StoleeOct 29, 2021
  15. Philip OakleyOct 30, 2021
  16. 3/3 bundle-uri client: add "bundle-uri" parsing + testsÆvar Arnfjörð Bjarmason, Oct 25, 2021
  17. Derrick StoleeOct 26, 2021
  18. Derrick StoleeOct 29, 2021
  19. Ævar Arnfjörð BjarmasonOct 30, 2021
  20. Derrick StoleeNov 1, 2021
  21. Ævar Arnfjörð BjarmasonNov 1, 2021
  22. 00/13 bundle-uri: a "dumb CDN" for gitÆvar Arnfjörð Bjarmason, Mar 11, 2022
  23. 02/13 bundle-uri docs: add design notesÆvar Arnfjörð Bjarmason, Mar 11, 2022
  24. 01/13 protocol v2: add server-side "bundle-uri" skeletonÆvar Arnfjörð Bjarmason, Mar 11, 2022
  25. 04/13 connect.c: refactor sending of agent & object-formatÆvar Arnfjörð Bjarmason, Mar 11, 2022
  26. 06/13 bundle-uri client: add "git ls-remote-bundle-uri"Ævar Arnfjörð Bjarmason, Mar 11, 2022
  27. 05/13 bundle-uri client: add minimal NOOP clientÆvar Arnfjörð Bjarmason, Mar 11, 2022
  28. 07/13 bundle-uri client: add transfer.injectBundleURI supportÆvar Arnfjörð Bjarmason, Mar 11, 2022
  29. 03/13 bundle-uri client: add "bundle-uri" parsing + testsÆvar Arnfjörð Bjarmason, Mar 11, 2022
  30. 08/13 bundle-uri client: add boolean transfer.bundleURI settingÆvar Arnfjörð Bjarmason, Mar 11, 2022
  31. 09/13 fetch-pack: add a deref_without_lazy_fetch_extended()Ævar Arnfjörð Bjarmason, Mar 11, 2022
  32. 10/13 fetch-pack: move --keep=* option filling to a functionÆvar Arnfjörð Bjarmason, Mar 11, 2022
  33. 13/13 bundle-uri: make the download program configurableÆvar Arnfjörð Bjarmason, Mar 11, 2022
  34. 11/13 bundle.h: make "fd" version of read_bundle_header() publicÆvar Arnfjörð Bjarmason, Mar 11, 2022
  35. 12/13 bundle-uri client: support for bundle-uri with "clone"Ævar Arnfjörð Bjarmason, Mar 11, 2022
  36. Derrick StoleeMar 11, 2022
  37. 00/36 bundle-uri: a "dumb CDN" for git + TOC formatÆvar Arnfjörð Bjarmason, Apr 18, 2022
  38. 01/36 connect.c: refactor sending of agent & object-formatÆvar Arnfjörð Bjarmason, Apr 18, 2022
  39. 02/36 dir API: add a generalized path_match_flags() functionÆvar Arnfjörð Bjarmason, Apr 18, 2022
  40. Derrick StoleeApr 21, 2022
  41. 03/36 fetch-pack: add a deref_without_lazy_fetch_extended()Ævar Arnfjörð Bjarmason, Apr 18, 2022
  42. Derrick StoleeApr 21, 2022
  43. 04/36 fetch-pack: move --keep=* option filling to a functionÆvar Arnfjörð Bjarmason, Apr 18, 2022
  44. 05/36 http: make http_get_file() externalÆvar Arnfjörð Bjarmason, Apr 18, 2022
  45. 07/36 remote: allow relative_url() to return an absolute urlÆvar Arnfjörð Bjarmason, Apr 18, 2022
  46. 06/36 remote: move relative_url()Ævar Arnfjörð Bjarmason, Apr 18, 2022
  47. 08/36 bundle.h: make "fd" version of read_bundle_header() publicÆvar Arnfjörð Bjarmason, Apr 18, 2022
  48. 09/36 protocol v2: add server-side "bundle-uri" skeletonÆvar Arnfjörð Bjarmason, Apr 18, 2022
  49. 10/36 bundle-uri client: add "bundle-uri" parsing + testsÆvar Arnfjörð Bjarmason, Apr 18, 2022
  50. 11/36 bundle-uri client: add minimal NOOP clientÆvar Arnfjörð Bjarmason, Apr 18, 2022
  51. 12/36 bundle-uri client: add "git ls-remote-bundle-uri"Ævar Arnfjörð Bjarmason, Apr 18, 2022
  52. 14/36 bundle-uri client: add boolean transfer.bundleURI settingÆvar Arnfjörð Bjarmason, Apr 18, 2022
  53. 15/36 bundle-uri client: support for bundle-uri with "clone"Ævar Arnfjörð Bjarmason, Apr 18, 2022
  54. 13/36 bundle-uri client: add transfer.injectBundleURI supportÆvar Arnfjörð Bjarmason, Apr 18, 2022
  55. 16/36 bundle-uri: make the download program configurableÆvar Arnfjörð Bjarmason, Apr 18, 2022
  56. 18/36 bundle: implement 'fetch' command for direct bundlesÆvar Arnfjörð Bjarmason, Apr 18, 2022
  57. 17/36 remote-curl: add 'get' capabilityÆvar Arnfjörð Bjarmason, Apr 18, 2022
  58. 19/36 bundle: parse table of contents during 'fetch'Ævar Arnfjörð Bjarmason, Apr 18, 2022
  59. 20/36 bundle: add --filter option to 'fetch'Ævar Arnfjörð Bjarmason, Apr 18, 2022
  60. 21/36 bundle: allow relative URLs in table of contentsÆvar Arnfjörð Bjarmason, Apr 18, 2022
  61. 22/36 bundle: make it easy to call 'git bundle fetch'Ævar Arnfjörð Bjarmason, Apr 18, 2022
  62. 23/36 clone: add --bundle-uri optionÆvar Arnfjörð Bjarmason, Apr 18, 2022
  63. 26/36 fetch: fetch bundles before fetching original dataÆvar Arnfjörð Bjarmason, Apr 18, 2022
  64. 25/36 bundle: only fetch bundles if timestamp is newÆvar Arnfjörð Bjarmason, Apr 18, 2022
  65. 24/36 clone: --bundle-uri cannot be combined with --depthÆvar Arnfjörð Bjarmason, Apr 18, 2022
  66. 28/36 serve: understand but do not advertise 'features' capabilityÆvar Arnfjörð Bjarmason, Apr 18, 2022
  67. 27/36 protocol-caps: implement cap_features()Ævar Arnfjörð Bjarmason, Apr 18, 2022
  68. 30/36 connect: implement get_recommended_features()Ævar Arnfjörð Bjarmason, Apr 18, 2022
  69. 29/36 serve: advertise 'features' when config existsÆvar Arnfjörð Bjarmason, Apr 18, 2022
  70. 33/36 t5601: basic bundle URI testÆvar Arnfjörð Bjarmason, Apr 18, 2022
  71. 32/36 clone: use server-recommended bundle URIÆvar Arnfjörð Bjarmason, Apr 18, 2022
  72. 31/36 transport: add connections for 'features' capabilityÆvar Arnfjörð Bjarmason, Apr 18, 2022
  73. 34/36 protocol v2: add server-side "bundle-uri" skeleton (docs)Ævar Arnfjörð Bjarmason, Apr 18, 2022
  74. 35/36 bundle-uri docs: add design notesÆvar Arnfjörð Bjarmason, Apr 18, 2022
  75. 36/36 docs: document bundle URI standardÆvar Arnfjörð Bjarmason, Apr 18, 2022
  76. Derrick StoleeApr 21, 2022
  77. Ævar Arnfjörð BjarmasonApr 22, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.