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

Re: [PATCH v5 04/16] promisor-remote: implement promisor_remote_get_direct()

From
Derrick Stolee <stolee@gmail.com>
Date
May 30, 2019, 17:21 UTC
Message-ID
<b4d69d2b-dc0d-fffb-2909-c54060fe9cd1@gmail.com>
In-Reply-To
<20190409161116.30256-5-chriscool@tuxfamily.org>
On 4/9/2019 12:11 PM, Christian Couder wrote:
> From: Christian Couder <christian.couder@gmail.com>
> 
> This is implemented for now by calling fetch_objects(). It fetches
> from all the promisor remotes.
Hi Christian,

Sorry for jumping on the thread late, but I noticed some peculiarities when looking at the test coverage report.

> +static int remove_fetched_oids(struct object_id **oids, int oid_nr, int to_free)

This method does not seem to be covered by the test suite at all. Is this scenario difficult to set up for a test?

Show 8 quoted lines
> +{
> +	int i, missing_nr = 0;
> +	int *missing = xcalloc(oid_nr, sizeof(*missing));
> +	struct object_id *old_oids = *oids;
> +	struct object_id *new_oids;
> +	int old_fetch_if_missing = fetch_if_missing;
> +
> +	fetch_if_missing = 0;

This global 'fetch_if_missing' swap seems very fragile. I'm guessing you are using it to prevent a loop when calling oid_object_info_extended() below. Can you instead pass a flag to the method that disables the fetch_if_missing behavior?

> +
> +	for (i = 0; i < oid_nr; i++)
> +		if (oid_object_info_extended(the_repository, &old_oids[i], NULL, 0)) {

A use of "the_repository" this deep in new code is asking for a refactor later to remove it. Please try to pass a "struct repository *r" through your methods so we minimize references to the_repository (and the amount of work required to remove them later).

Show 27 quoted lines
> +			missing[i] = 1;
> +			missing_nr++;
> +		}
> +
> +	fetch_if_missing = old_fetch_if_missing;
> +
> +	if (missing_nr) {
> +		int j = 0;
> +		new_oids = xcalloc(missing_nr, sizeof(*new_oids));
> +		for (i = 0; i < oid_nr; i++)
> +			if (missing[i])
> +				oidcpy(&new_oids[j++], &old_oids[i]);
> +		*oids = new_oids;
> +		if (to_free)
> +			free(old_oids);
> +	}
> +
> +	free(missing);
> +
> +	return missing_nr;
> +}
> +
> +int promisor_remote_get_direct(const struct object_id *oids, int oid_nr)
> +{
> +	struct promisor_remote *r;
> +	struct object_id *missing_oids = (struct object_id *)oids;
> +	int missing_nr = oid_nr;
Note that for this method, "missing_nr" actually means "number of oids still in the list".
Show 7 quoted lines
> +	int to_free = 0;
> +	int res = -1;
> +
> +	promisor_remote_init();
> +
> +	for (r = promisors; r; r = r->next) {
> +		if (fetch_objects(r->name, missing_oids, missing_nr) < 0) {

This block hits if we have any missing objects. This is not currently hit by the test suite.

> +			if (missing_nr == 1)
> +				continue;

But we skip the call below if there is exactly one object in the list, as it must be the one missing object. So, to be interesting we need to try fetching multiple objects.

> +			missing_nr = remove_fetched_oids(&missing_oids, missing_nr, to_free);

Here is the one call, and after this assignment "missing_nr" does mean the number of missing objects. However, I do think this could be clarified by using remaining_nr and remaining_oids.

> +			if (missing_nr) {
> +				to_free = 1;
> +				continue;
> +			}

Now this block took a bit to grok. You use to_free in the if(to_free) free(missing_oids); below. But it also changes the behavior of remove_fetched_oids(). This means that the first time remove_fetched_oids() will preserve the list (because it is the input list) but all later calls will free the newly-created intermediate list. This checks out.

What is confusing to me: is there any reason that missing_nr would be zero in this situation? I guess if the fetch_objects() failed to find some objects, but we ended up having them locally in a new call to oid_object_info_extended(). That's a fringe case that is worth guarding against but I wouldn't worry about testing.

Show 10 quoted lines
> +		}
> +		res = 0;
> +		break;
> +	}
> +
> +	if (to_free)
> +		free(missing_oids);
> +
> +	return res;
> +}

While the test coverage report brought this patch to my attention, it does seem correct. I still think a test exposing this method would be good, especially one that requires a fetch_objects() call to multiple remotes to really exercise the details of remove_fetched_oids().

Thanks, -Stolee

Previous: Christian CouderNext: Johannes Schindelin
Message 8 of 28 in “Many promisor remotes”
  1. 00/16 Many promisor remotesChristian Couder, Apr 9, 2019
  2. 01/16 t0410: remove pipes after git commandsChristian Couder, Apr 9, 2019
  3. 02/16 fetch-object: make functions return an error codeChristian Couder, Apr 9, 2019
  4. 03/16 Add initial support for many promisor remotesChristian Couder, Apr 9, 2019
  5. 05/16 promisor-remote: add promisor_remote_reinit()Christian Couder, Apr 9, 2019
  6. 06/16 promisor-remote: use repository_format_partial_cloneChristian Couder, Apr 9, 2019
  7. 04/16 promisor-remote: implement promisor_remote_get_direct()Christian Couder, Apr 9, 2019
  8. Derrick StoleeMay 30, 2019
  9. Johannes SchindelinMay 30, 2019
  10. Derrick StoleeMay 30, 2019
  11. Johannes SchindelinMay 31, 2019
  12. Junio C HamanoMay 31, 2019
  13. Christian CouderMay 31, 2019
  14. Christian CouderJun 25, 2019
  15. 07/16 Use promisor_remote_get_direct() and has_promisor_remote()Christian Couder, Apr 9, 2019
  16. 08/16 diff: use promisor-remote.h instead of fetch-object.hChristian Couder, Apr 9, 2019
  17. 09/16 promisor-remote: parse remote.*.partialclonefilterChristian Couder, Apr 9, 2019
  18. 10/16 builtin/fetch: remove unique promisor remote limitationChristian Couder, Apr 9, 2019
  19. 12/16 partial-clone: add multiple remotes in the docChristian Couder, Apr 9, 2019
  20. 11/16 t0410: test fetching from many promisor remotesChristian Couder, Apr 9, 2019
  21. 13/16 remote: add promisor and partial clone config to the docChristian Couder, Apr 9, 2019
  22. 14/16 Remove fetch-object.{c,h} in favor of promisor-remote.{c,h}Christian Couder, Apr 9, 2019
  23. 15/16 Move repository_format_partial_clone to promisor-remote.cChristian Couder, Apr 9, 2019
  24. 16/16 Move core_partial_clone_filter_default to promisor-remote.cChristian Couder, Apr 9, 2019
  25. Junio C HamanoApr 15, 2019
  26. Junio C HamanoApr 15, 2019
  27. Christian CouderApr 15, 2019
  28. Christian CouderApr 15, 2019

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.