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

Re: [RFC/WIP PATCH 04/11] upload-pack-2: Implement the version 2 of upload-pack

From
Stefan Beller <sbeller@google.com>
Date
May 27, 2015, 17:40 UTC
Message-ID
<CAGZ79kYaoViDrz9TKXWebif4mfyUjzJ6b3id8ozTqtwsmjAC1A@mail.gmail.com>
In-Reply-To
<20150527063558.GB885@peff.net>
On Tue, May 26, 2015 at 11:35 PM, Jeff King <peff@peff.net> wrote:
Show 21 quoted lines
> On Tue, May 26, 2015 at 03:01:08PM -0700, Stefan Beller wrote:
>
>> --- a/upload-pack.c
>> +++ b/upload-pack.c
>> @@ -716,10 +716,47 @@ static void format_symref_info(struct strbuf *buf, struct string_list *symref)
>>               strbuf_addf(buf, " symref=%s:%s", item->string, (char *)item->util);
>>  }
>>
>> -static const char *advertise_capabilities = "multi_ack thin-pack side-band"
>> +static char *advertise_capabilities = "multi_ack thin-pack side-band"
>>               " side-band-64k ofs-delta shallow no-progress"
>>               " include-tag multi_ack_detailed";
>
> If we are upload-pack-2, should we advertise that in the capabilities? I
> think it may make things easier later if we try to provide some
> opportunistic out-of-band data. E.g., if see tell git-daemon:
>
>   git-upload-pack repo\0host=whatever\0\0version=2
>
> how do we know whether version=2 was understood and kicked us into v2
> mode, versus an old server that ignored it?

So in my vision we would call git-upload-pack-2 instead of having a "version=2". and if git-upload-pack-2 doesn't exist, the whole conversation is over, the client it is left to make up some good error message or retry version 1.

But I think advertising both which versions the server could deal with, as well as the currently expected version is a good thing.

capability: can_speak=1,2 capability: speaking_now=2

Show 13 quoted lines
>
> It also just makes the protocol more self-describing; from the
> conversation you can see which version is in use.
>
>> +static void send_capabilities(void)
>> +{
>> +     char buf[100];
>> +
>> +     while (next_capability(buf))
>> +             packet_write(1, "capability:%s\n", buf);
>
> Having a static-sized buffer and then passing it to a function which has
> no idea of the buffer size seems like a recipe for a buffer overflow. :)

Yes. All patches I proposed are very brittle. My first goal was to have the last test passing (an actual fetch with version 2). Now I will start looking at making things robust, as by now you all seem to not disagree totally.

Show 18 quoted lines
>
> You are fine here because you are parsing the hard-coded capabilities
> string, and we know 100 is enough there. But it's nice to avoid such
> magic.
>
> Like Eric, I find the whole next_capability thing a little ugly. His
> suggestion to pass in the parsing state is an improvement, but I wonder
> why we need to parse at all. Can we keep the capabilities as:
>
>   const char *capabilities[] = {
>         "multi_ack",
>         "thin-pack",
>         ... etc ...
>   };
>
> and then loop over the array? The v1 writer will need to be modified,
> but it should be fairly straightforward (loop and add them to the buffer
> rather than dumping the whole string).
Thanks for the design guidance! I'll change that.
>
> Also, do we need the capability noise-word?

I thought it opens up a new possible door in the future. As we ignore anything not starting with "capability" for now, you could introduce your foo and bar ping pong easily and still be version 2 compatible.

S: capability: thin
S: capability: another-capability
S: ping-pong foo
S: done
C: (not having understood ping-pong) just answering with capability: thin
C: done, let's proceed to refs advertisement
The alternative client would do:
C: ping-pong: foo-data1a
S: ping-pong: foo-data1b
C: ping-pong: foo-data2a
C: capability: thin
...
Show 24 quoted lines
> They all have it, except
> for:
>
>> +     packet_write(1, "agent:%s\n", git_user_agent_sanitized());
>
> But isn't that basically a capability, too (I agree it is stretching the
> definition of "capability", but I think that ship has sailed; the
> client's response is not "I support this, too" but "I want to enable
> this").
>
> IOW, is there a reason that the initial conversation is not just:
>
>   pkt-line("multi_ack");
>   pkt-line("thin-pack");
>   ...
>   pkt-line("agent=v2.5.0");
>   pkt-line(0000);
>
> We already have framing for each capability due to the use of pkt-line.
> The "capability:" is just one more thing the client has to parse past.
> The keys are already unique up to any "=", so I don't think there is any
> ambiguity (e.g., we don't care about "capability:agent"; we have already
> assigned a meaning to the term "agent", and will never introduce a
> standalone capability with the same name).

It looks clearer to me (we're not wasting band-width), maybe this ping pong thing can be part of the capabilities announcement too, so we're good this way.

Show 25 quoted lines
>
> Likewise, if we introduce new protocol items here, the client should
> either ignore them (if it does not understand them) or know what to do
> with them.
>
>> +static void receive_capabilities(void)
>> +{
>> +     int done = 0;
>> +     while (1) {
>> +             char *line = packet_read_line(0, NULL);
>> +             if (!line)
>> +                     break;
>> +             if (starts_with(line, "capability:"))
>> +                     parse_features(line + strlen("capability:"));
>> +     }
>
> Use:
>
>   const char *cap;
>   if (skip_prefix(line, "capability:", &cap))
>         parse_features(cap);
>
> Or better yet, if you take my suggestion above:
>
>   parse_features(line);
will do.
Show 12 quoted lines
>
> :)
>
>> +static int endswith(const char *teststring, const char *ending)
>> +{
>> +     int slen = strlen(teststring);
>> +     int elen = strlen(ending);
>> +     return !strcmp(teststring + slen - elen, ending);
>> +}
>
> Eric mentioned the underflow problems here, but I wonder even more:
> what's wrong with the global ends_with() that we already provide?

I was missing knowledge we have that, and apparently I was thinking it's faster to come up with my own version than to look for it. :)

>
> -Peff
Previous: Jeff KingNext: Jeff King
Message 12 of 61 in “Protocol version 2, again!”
  1. 00/11 Protocol version 2, again!Stefan Beller, May 26, 2015
  2. 01/11 upload-pack: make client capability parsing code a separate functionStefan Beller, May 26, 2015
  3. 02/11 upload-pack: only accept capabilities on the first "want" lineStefan Beller, May 26, 2015
  4. Junio C HamanoMay 26, 2015
  5. Stefan BellerMay 26, 2015
  6. 03/11 upload-pack: move capabilities out of send_refStefan Beller, May 26, 2015
  7. 04/11 upload-pack-2: Implement the version 2 of upload-packStefan Beller, May 26, 2015
  8. Eric SunshineMay 27, 2015
  9. Jeff KingMay 27, 2015
  10. Eric SunshineMay 27, 2015
  11. Jeff KingMay 27, 2015
  12. Stefan BellerMay 27, 2015
  13. Jeff KingMay 27, 2015
  14. Stefan BellerMay 27, 2015
  15. Jeff KingMay 27, 2015
  16. 05/11 transport: add infrastructure to support a protocol version numberStefan Beller, May 26, 2015
  17. Jeff KingMay 27, 2015
  18. Stefan BellerMay 27, 2015
  19. Jeff KingMay 27, 2015
  20. Junio C HamanoMay 27, 2015
  21. 06/11 remote.h: add get_remote_capabilities, request_capabilitiesStefan Beller, May 26, 2015
  22. Eric SunshineMay 27, 2015
  23. Jeff KingMay 27, 2015
  24. Eric SunshineMay 27, 2015
  25. Jeff KingMay 27, 2015
  26. Jeff KingMay 27, 2015
  27. Stefan BellerMay 29, 2015
  28. Jeff KingMay 29, 2015
  29. 07/11 fetch-pack: use the configured transport protocolStefan Beller, May 26, 2015
  30. Junio C HamanoMay 26, 2015
  31. Stefan BellerMay 26, 2015
  32. Jeff KingMay 27, 2015
  33. 08/11 transport: connect_setup appends protocol version numberStefan Beller, May 26, 2015
  34. Junio C HamanoMay 26, 2015
  35. Stefan BellerMay 26, 2015
  36. Junio C HamanoMay 27, 2015
  37. Jeff KingMay 27, 2015
  38. Eric SunshineMay 27, 2015
  39. Jeff KingMay 27, 2015
  40. 09/11 transport: get_refs_via_connect exchanges capabilities before refs.Stefan Beller, May 26, 2015
  41. Eric SunshineMay 27, 2015
  42. Jeff KingMay 27, 2015
  43. 10/11 t5544: add a test case for the new protocolStefan Beller, May 26, 2015
  44. Eric SunshineMay 27, 2015
  45. Jeff KingMay 27, 2015
  46. 11/11 Document protocol version 2Stefan Beller, May 26, 2015
  47. Junio C HamanoMay 29, 2015
  48. Stefan BellerMay 29, 2015
  49. Junio C HamanoMay 29, 2015
  50. Jeff KingMay 29, 2015
  51. Stefan BellerJun 1, 2015
  52. Stefan BellerJun 1, 2015
  53. Jeff KingJun 4, 2015
  54. Junio C HamanoJun 4, 2015
  55. Junio C HamanoJun 2, 2015
  56. Jeff KingMay 27, 2015
  57. Jeff KingMay 27, 2015
  58. Stefan BellerJun 1, 2015
  59. Duy NguyenJun 2, 2015
  60. Jeff KingJun 4, 2015
  61. Stefan BellerJun 4, 2015

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.