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

Re: [PATCH v4 5/8] negotiator: add have_sent() interface

From
Matthew John Cheetham <mjcheetham@outlook.com>
Date
May 18, 2026, 16:57 UTC
Message-ID
<VI0PR03MB11634279CBA717D6C6B977C3EC0032@VI0PR03MB11634.eurprd03.prod.outlook.com>
In-Reply-To
<94b79784fe6a4f22dba32a2e1d44316b3e84da48.1778762495.git.gitgitgadget@gmail.com>
On 2026-05-14 13:41, Derrick Stolee via GitGitGadget wrote:
Show 20 quoted lines
> From: Derrick Stolee <stolee@gmail.com>
> 
> In a future change, we will introduce a capability to choose specific commit
> OIDs as 'have's in fetch negotiation, with the ability to have the
> negotiator choose more 'have's to increase coverage beyond that required
> core set. The negotiator works to avoid emitting 'have's that can reach each
> other, but that logic is hidden beneath the negotiator's iterator function
> pointer ('next'). We need a way to communicate to the negotiator that we
> have picked a 'have' so it could incorporate that into its logic.
> 
> Add a have_sent() method to the fetch_negotiator interface. This is the
> signal that allows the negotiator to track the commit as already shown and
> can perform the proper bookkeeping to avoid emitting those objects or
> anything they can reach.
> 
> For our non-trivial negotiators, it is sufficient to mark these commits as
> common, so the implementation is quite simple. This logic will be exercised
> in the next change.
> 
> Signed-off-by: Derrick Stolee <stolee@gmail.com>

This is a new patch in v4, and is in response to the COMMON (bit 2) vs COMMON (bit 6) issue of v3.

Having a defined have_sent() API on the negotiator, and letting the negotiator handle its own book-keeping is much nicer and safer.

Show 24 quoted lines
> ---
>   fetch-negotiator.h    | 9 +++++++++
>   negotiator/default.c  | 8 ++++++++
>   negotiator/noop.c     | 7 +++++++
>   negotiator/skipping.c | 8 ++++++++
>   4 files changed, 32 insertions(+)
> 
> diff --git a/fetch-negotiator.h b/fetch-negotiator.h
> index e348905a1f..6ca422a064 100644
> --- a/fetch-negotiator.h
> +++ b/fetch-negotiator.h
> @@ -47,6 +47,15 @@ struct fetch_negotiator {
>   	 */
>   	int (*ack)(struct fetch_negotiator *, struct commit *);
>   
> +	/*
> +	 * Inform the negotiator that this commit has already been sent as
> +	 * a "have" line outside of the negotiator's control. The negotiator
> +	 * should avoid outputting it from next() and may use it to optimize
> +	 * further negotiation (e.g., by treating it and its ancestors as
> +	 * common).
> +	 */
> +	void (*have_sent)(struct fetch_negotiator *, struct commit *);
> +
Doc comment captures the contract well.
Show 29 quoted lines
>   	void (*release)(struct fetch_negotiator *);
>   
>   	/* internal use */
> diff --git a/negotiator/default.c b/negotiator/default.c
> index 116dedcf83..05ab616f39 100644
> --- a/negotiator/default.c
> +++ b/negotiator/default.c
> @@ -175,6 +175,13 @@ static int ack(struct fetch_negotiator *n, struct commit *c)
>   	return known_to_be_common;
>   }
>   
> +static void have_sent(struct fetch_negotiator *n, struct commit *c)
> +{
> +	if (repo_parse_commit(the_repository, c))
> +		return;
> +	mark_common(n->data, c, 0, 0);
> +}
> +
>   static void release(struct fetch_negotiator *n)
>   {
>   	clear_prio_queue(&((struct negotiation_state *)n->data)->rev_list);
> @@ -188,6 +195,7 @@ void default_negotiator_init(struct fetch_negotiator *negotiator)
>   	negotiator->add_tip = add_tip;
>   	negotiator->next = next;
>   	negotiator->ack = ack;
> +	negotiator->have_sent = have_sent;
>   	negotiator->release = release;
>   	negotiator->data = CALLOC_ARRAY(ns, 1);
>   	ns->rev_list.compare = compare_commits_by_commit_date;

I traced this through default.c's mark_common() to confirm this does what we want.. sets the COMMON bit (bit 2) and propogates COMMON to the ancestors correctly. Good!

Show 25 quoted lines
> diff --git a/negotiator/noop.c b/negotiator/noop.c
> index 65e3c20008..edf1b456f3 100644
> --- a/negotiator/noop.c
> +++ b/negotiator/noop.c
> @@ -29,6 +29,12 @@ static int ack(struct fetch_negotiator *n UNUSED, struct commit *c UNUSED)
>   	return 0;
>   }
>   
> +static void have_sent(struct fetch_negotiator *n UNUSED,
> +		      struct commit *c UNUSED)
> +{
> +	/* nothing to do */
> +}
> +
>   static void release(struct fetch_negotiator *n UNUSED)
>   {
>   	/* nothing to release */
> @@ -40,6 +46,7 @@ void noop_negotiator_init(struct fetch_negotiator *negotiator)
>   	negotiator->add_tip = add_tip;
>   	negotiator->next = next;
>   	negotiator->ack = ack;
> +	negotiator->have_sent = have_sent;
>   	negotiator->release = release;
>   	negotiator->data = NULL;
>   }
Trivial implementation of the noop negotiator. Good.
Show 26 quoted lines
> diff --git a/negotiator/skipping.c b/negotiator/skipping.c
> index 0a272130fb..69472c58e1 100644
> --- a/negotiator/skipping.c
> +++ b/negotiator/skipping.c
> @@ -243,6 +243,13 @@ static int ack(struct fetch_negotiator *n, struct commit *c)
>   	return known_to_be_common;
>   }
>   
> +static void have_sent(struct fetch_negotiator *n, struct commit *c)
> +{
> +	if (repo_parse_commit(the_repository, c))
> +		return;
> +	mark_common(n->data, c);
> +}
> +
>   static void release(struct fetch_negotiator *n)
>   {
>   	struct data *data = n->data;
> @@ -259,6 +266,7 @@ void skipping_negotiator_init(struct fetch_negotiator *negotiator)
>   	negotiator->add_tip = add_tip;
>   	negotiator->next = next;
>   	negotiator->ack = ack;
> +	negotiator->have_sent = have_sent;
>   	negotiator->release = release;
>   	negotiator->data = CALLOC_ARRAY(data, 1);
>   	data->rev_list.compare = compare;

I traced this too, to skipping.c's mark_common(), and it sets the COMMON bit correctly.

This patch is a welcome addition and LGTM!

Thanks, Matthew

Previous: Derrick Stolee via GitGitGadgetNext: Derrick Stolee via GitGitGadget
Message 56 of 86 in “fetch: add --must-have and remote.*.mustHave”
  1. 0/4 fetch: add --must-have and remote.*.mustHaveDerrick Stolee via GitGitGadget, Apr 8, 2026
  2. 1/4 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, Apr 8, 2026
  3. 2/4 fetch: add --must-have option for negotiationDerrick Stolee via GitGitGadget, Apr 8, 2026
  4. 3/4 remote: add mustHave config as default for --must-haveDerrick Stolee via GitGitGadget, Apr 8, 2026
  5. 4/4 send-pack: pass --must-have for push negotiationDerrick Stolee via GitGitGadget, Apr 8, 2026
  6. Junio C HamanoApr 8, 2026
  7. Derrick StoleeApr 9, 2026
  8. 0/7 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, Apr 15, 2026
  9. 1/7 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, Apr 15, 2026
  10. 2/7 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, Apr 15, 2026
  11. Junio C HamanoApr 15, 2026
  12. Derrick StoleeApr 19, 2026
  13. Junio C HamanoApr 20, 2026
  14. Derrick StoleeApr 20, 2026
  15. 3/7 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, Apr 15, 2026
  16. Patrick SteinhardtApr 20, 2026
  17. 4/7 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, Apr 15, 2026
  18. Junio C HamanoApr 15, 2026
  19. 5/7 fetch: add --negotiation-require option for negotiationDerrick Stolee via GitGitGadget, Apr 15, 2026
  20. Junio C HamanoApr 15, 2026
  21. Derrick StoleeApr 21, 2026
  22. Patrick SteinhardtApr 20, 2026
  23. Derrick StoleeApr 20, 2026
  24. 6/7 remote: add negotiationRequire config as default for --negotiation-requireDerrick Stolee via GitGitGadget, Apr 15, 2026
  25. 7/7 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, Apr 15, 2026
  26. 0/7 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, Apr 22, 2026
  27. 1/7 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, Apr 22, 2026
  28. Matthew John CheethamMay 12, 2026
  29. 2/7 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, Apr 22, 2026
  30. Matthew John CheethamMay 12, 2026
  31. Derrick StoleeMay 12, 2026
  32. 3/7 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, Apr 22, 2026
  33. Matthew John CheethamMay 12, 2026
  34. Derrick StoleeMay 12, 2026
  35. 4/7 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, Apr 22, 2026
  36. Matthew John CheethamMay 12, 2026
  37. Derrick StoleeMay 12, 2026
  38. 5/7 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, Apr 22, 2026
  39. Matthew John CheethamMay 12, 2026
  40. Derrick StoleeMay 12, 2026
  41. 6/7 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, Apr 22, 2026
  42. Matthew John CheethamMay 12, 2026
  43. Derrick StoleeMay 12, 2026
  44. 7/7 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, Apr 22, 2026
  45. Matthew John CheethamMay 12, 2026
  46. 0/8 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, May 14, 2026
  47. 1/8 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, May 14, 2026
  48. Matthew John CheethamMay 18, 2026
  49. 2/8 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, May 14, 2026
  50. Matthew John CheethamMay 18, 2026
  51. 3/8 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, May 14, 2026
  52. Matthew John CheethamMay 18, 2026
  53. 4/8 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, May 14, 2026
  54. Matthew John CheethamMay 18, 2026
  55. 5/8 negotiator: add have_sent() interfaceDerrick Stolee via GitGitGadget, May 14, 2026
  56. Matthew John CheethamMay 18, 2026
  57. 6/8 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, May 14, 2026
  58. Matthew John CheethamMay 18, 2026
  59. 7/8 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, May 14, 2026
  60. Matthew John CheethamMay 18, 2026
  61. 8/8 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, May 14, 2026
  62. Matthew John CheethamMay 18, 2026
  63. Matthew John CheethamMay 18, 2026
  64. Derrick StoleeMay 18, 2026
  65. 0/8 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, May 18, 2026
  66. 2/8 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, May 18, 2026
  67. 3/8 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, May 18, 2026
  68. 4/8 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, May 18, 2026
  69. 5/8 negotiator: add have_sent() interfaceDerrick Stolee via GitGitGadget, May 18, 2026
  70. 6/8 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, May 18, 2026
  71. 7/8 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, May 18, 2026
  72. 8/8 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, May 18, 2026
  73. 1/8 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, May 18, 2026
  74. Matthew John CheethamMay 19, 2026
  75. Derrick StoleeMay 19, 2026
  76. 0/8 fetch: rework negotiation tip optionsDerrick Stolee via GitGitGadget, May 19, 2026
  77. 1/8 t5516: fix test order flakinessDerrick Stolee via GitGitGadget, May 19, 2026
  78. 2/8 fetch: add --negotiation-restrict optionDerrick Stolee via GitGitGadget, May 19, 2026
  79. 3/8 transport: rename negotiation_tipsDerrick Stolee via GitGitGadget, May 19, 2026
  80. 4/8 remote: add remote.*.negotiationRestrict configDerrick Stolee via GitGitGadget, May 19, 2026
  81. 5/8 negotiator: add have_sent() interfaceDerrick Stolee via GitGitGadget, May 19, 2026
  82. 6/8 fetch: add --negotiation-include option for negotiationDerrick Stolee via GitGitGadget, May 19, 2026
  83. 7/8 remote: add remote.*.negotiationInclude configDerrick Stolee via GitGitGadget, May 19, 2026
  84. 8/8 send-pack: pass negotiation config in pushDerrick Stolee via GitGitGadget, May 19, 2026
  85. Matthew John CheethamMay 19, 2026
  86. Junio C HamanoMay 20, 2026

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.