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

Re: [PATCH 5/8] odb: remove mutual recursion when parsing alternates

From
Justin Tobler <jltobler@gmail.com>
Date
Dec 9, 2025, 17:31 UTC
Message-ID
<qhwjdvcilzbd7bpj64jwmxfwldlzge5w23bsgrz3yma4rtwlw6@6becwkk4u4vj>
In-Reply-To
<20251208-b4-pks-odb-alternates-via-source-v1-5-e7ebb8b18c03@pks.im>
On 25/12/08 09:04AM, Patrick Steinhardt wrote:
Show 66 quoted lines
> When adding an alternative object database source we not only have to
> consider the added source itself, but we also have to add _its_ sources
> to our database. We implement this via mutual recursion:
> 
>   1. We first call `link_alt_odb_entries()`.
> 
>   2. `link_alt_odb_entries()` calls `parse_alternates()`.
> 
>   3. We then add each parsed alternate via `odb_add_source()`.
> 
>   4. `odb_add_source()` calls `link_alt_odb_entries()` again.
> 
> This flow is somewhat hard to follow, but more importantly it means that
> parsing of alternates is somewhat tied to the recursive behaviour.
> 
> Refactor the function to remove the mutual recursion between adding
> sources and parsing alternates. The parsing step thus becomes completely
> oblivious to the fact that there is recursive behaviour going on at all.
> Instead, the recursion is handled exclusively by `odb_add_source()`,
> which now recurses with itself.
> 
> This refactoring allows us to move parsing of alternates into object
> database sources in a subsequent step.
> 
> Signed-off-by: Patrick Steinhardt <ps@pks.im>
> ---
>  odb.c | 60 +++++++++++++++++++++++++++---------------------------------
>  1 file changed, 27 insertions(+), 33 deletions(-)
> 
> diff --git a/odb.c b/odb.c
> index 94cff19221..27f3c8e263 100644
> --- a/odb.c
> +++ b/odb.c
> @@ -147,9 +147,8 @@ static bool odb_is_source_usable(struct object_database *o, const char *path)
>   * of the object ID, an extra slash for the first level indirection, and
>   * the terminating NUL.
>   */
> -static void read_info_alternates(struct object_database *odb,
> -				 const char *relative_base,
> -				 int depth);
> +static void read_info_alternates(const char *relative_base,
> +				 struct strvec *out);
>  
>  static struct odb_source *odb_source_new(struct object_database *odb,
>  					 const char *path,
> @@ -171,6 +170,7 @@ static struct odb_source *odb_add_source(struct object_database *odb,
>  					 int depth)
>  {
>  	struct odb_source *alternate = NULL;
> +	struct strvec sources = STRVEC_INIT;
>  	khiter_t pos;
>  	int ret;
>  
> @@ -189,9 +189,17 @@ static struct odb_source *odb_add_source(struct object_database *odb,
>  	kh_value(odb->source_by_path, pos) = alternate;
>  
>  	/* recursively add alternates */
> -	read_info_alternates(odb, alternate->path, depth + 1);
> +	read_info_alternates(alternate->path, &sources);
> +	if (sources.nr && depth + 1 > 5) {
> +		error(_("%s: ignoring alternate object stores, nesting too deep"),
> +		      source);
> +	} else {
> +		for (size_t i = 0; i < sources.nr; i++)
> +			odb_add_source(odb, sources.v[i], depth + 1);
> +	}

Ok, prior to this, read_info_alternates() would not only parse the alternates file for the ODB source at hand, but also recursively parse and add alternates of alternates. Now, read_info_alternates() is only responsible for parsing a single alternates file at a time.

Recursing into child alternates is now handled by odb_add_source(). IMO this is much easier to reason about and ultimately matches the previous behavior.

Show 6 quoted lines
>  
>   error:
> +	strvec_clear(&sources);
>  	return alternate;
>  }
>  
[snip]
Show 14 quoted lines
> @@ -622,13 +610,19 @@ int odb_for_each_alternate(struct object_database *odb,
>  
>  void odb_prepare_alternates(struct object_database *odb)
>  {
> +	struct strvec sources = STRVEC_INIT;
> +
>  	if (odb->loaded_alternates)
>  		return;
>  
> -	link_alt_odb_entries(odb, odb->alternate_db, PATH_SEP, NULL, 0);
> +	parse_alternates(odb->alternate_db, PATH_SEP, NULL, &sources);
> +	read_info_alternates(odb->sources->path, &sources);
> +	for (size_t i = 0; i < sources.nr; i++)
> +		odb_add_source(odb, sources.v[i], 0);

When preparing alternates, sources from the environment and alternates file are parsed first and then added. Adding sources is now handled explicitly and is responsible for add child alternates. Looks good.

-Justin
Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 14 of 41 in “Refactor handling of alternates to work via sources”
  1. 0/8 Refactor handling of alternates to work via sourcesPatrick Steinhardt, Dec 8, 2025
  2. 1/8 odb: refactor parsing of alternates to be self-containedPatrick Steinhardt, Dec 8, 2025
  3. Justin ToblerDec 8, 2025
  4. 2/8 odb: resolve relative alternative paths when parsingPatrick Steinhardt, Dec 8, 2025
  5. Justin ToblerDec 9, 2025
  6. Patrick SteinhardtDec 9, 2025
  7. Justin ToblerDec 9, 2025
  8. Patrick SteinhardtDec 10, 2025
  9. 3/8 odb: move computation of normalized objdir into `alt_odb_usable()`Patrick Steinhardt, Dec 8, 2025
  10. Justin ToblerDec 9, 2025
  11. Patrick SteinhardtDec 9, 2025
  12. 4/8 odb: adapt `odb_add_to_alternates_file()` to call `odb_add_source()`Patrick Steinhardt, Dec 8, 2025
  13. 5/8 odb: remove mutual recursion when parsing alternatesPatrick Steinhardt, Dec 8, 2025
  14. Justin ToblerDec 9, 2025
  15. 6/8 odb: drop forward declaration of `read_info_alternates()`Patrick Steinhardt, Dec 8, 2025
  16. 7/8 odb: read alternates via sourcesPatrick Steinhardt, Dec 8, 2025
  17. Justin ToblerDec 9, 2025
  18. Patrick SteinhardtDec 10, 2025
  19. 8/8 odb: write alternates via sourcesPatrick Steinhardt, Dec 8, 2025
  20. 0/8 Refactor handling of alternates to work via sourcesPatrick Steinhardt, Dec 10, 2025
  21. 1/8 odb: refactor parsing of alternates to be self-containedPatrick Steinhardt, Dec 10, 2025
  22. 2/8 odb: resolve relative alternative paths when parsingPatrick Steinhardt, Dec 10, 2025
  23. 3/8 odb: move computation of normalized objdir into `alt_odb_usable()`Patrick Steinhardt, Dec 10, 2025
  24. 4/8 odb: adapt `odb_add_to_alternates_file()` to call `odb_add_source()`Patrick Steinhardt, Dec 10, 2025
  25. SZEDER GáborDec 11, 2025
  26. Patrick SteinhardtDec 11, 2025
  27. 5/8 odb: remove mutual recursion when parsing alternatesPatrick Steinhardt, Dec 10, 2025
  28. 6/8 odb: drop forward declaration of `read_info_alternates()`Patrick Steinhardt, Dec 10, 2025
  29. 7/8 odb: read alternates via sourcesPatrick Steinhardt, Dec 10, 2025
  30. 8/8 odb: write alternates via sourcesPatrick Steinhardt, Dec 10, 2025
  31. Justin ToblerDec 10, 2025
  32. Patrick SteinhardtDec 11, 2025
  33. 0/8 Refactor handling of alternates to work via sourcesPatrick Steinhardt, Dec 11, 2025
  34. 1/8 odb: refactor parsing of alternates to be self-containedPatrick Steinhardt, Dec 11, 2025
  35. 2/8 odb: resolve relative alternative paths when parsingPatrick Steinhardt, Dec 11, 2025
  36. 3/8 odb: move computation of normalized objdir into `alt_odb_usable()`Patrick Steinhardt, Dec 11, 2025
  37. 4/8 odb: stop splitting alternate in `odb_add_to_alternates_file()`Patrick Steinhardt, Dec 11, 2025
  38. 5/8 odb: remove mutual recursion when parsing alternatesPatrick Steinhardt, Dec 11, 2025
  39. 6/8 odb: drop forward declaration of `read_info_alternates()`Patrick Steinhardt, Dec 11, 2025
  40. 7/8 odb: read alternates via sourcesPatrick Steinhardt, Dec 11, 2025
  41. 8/8 odb: write alternates via sourcesPatrick Steinhardt, Dec 11, 2025

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.