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

Re: [PATCH v2 07/10] sparse-index: partially expand directories

From
Junio C Hamano <gitster@pobox.com>
Date
May 20, 2022, 18:17 UTC
Message-ID
<xmqqbkvshxvn.fsf@gitster.g>
In-Reply-To
<346c56bf2560c5a89850ef4f8a58fbe17cde10fc.1652982759.git.gitgitgadget@gmail.com>
"Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes:
> @@ -231,18 +236,41 @@ static int add_path_to_index(const struct object_id *oid,
>  			     struct strbuf *base, const char *path,
>  			     unsigned int mode, void *context)
>  {

OK, this function is a callback of read_tree_at(), whose caller is walking the source (=current) index, and while it is copying existing non-directory entries to the destination (=ctx->write) index, it found a tree in the source in-core index that does not match the cone pattern (or we are expanding fully). Our job is to expand the given tree as a "subdirectory" in the project into the destination index.

We used to just let the calling read_tree_at() fully and recursively walk the tree while adding any non-tree entries to the destination. Now, we have the pattern list in the context, we go more selective.

The design makes sense.
Show 9 quoted lines
> +	struct modify_index_context *ctx = (struct modify_index_context *)context;
>  	struct cache_entry *ce;
>  	size_t len = base->len;
>  
> +	if (S_ISDIR(mode)) {
> +		int dtype;
> +		size_t baselen = base->len;
> +		if (!ctx->pl)
> +			return READ_TREE_RECURSIVE;

Fully recursive case. We can do without any match, just like the caller (i.e. expand_to_pattern_list) did, when the pattern list is NULL.

Show 9 quoted lines
> +		/*
> +		 * Have we expanded to a point outside of the sparse-checkout?
> +		 */
> +		strbuf_addstr(base, path);
> +		strbuf_add(base, "/-", 2);
> +
> +		if (path_matches_pattern_list(base->buf, base->len,
> +					      NULL, &dtype,
> +					      ctx->pl, ctx->write)) {

If that sample path in the directory matches (MATCHED or MATCHED_RECURSIVE) the patterns, we recurse into the tree to expand.

Can the function return UNDECIDED here? If so what should happen? As written, the code will behave as if it matched, and it is not quite clear if that is the behaviour intended by this patch or an accident.

> +			strbuf_setlen(base, baselen);
> +			return READ_TREE_RECURSIVE;
> +		}

The caller found a tree at path <path> in the index. We check if our patterns match a fictitious path <path> + "/-", which may exist if the <path> is a directory and if there is a funny named file or directory "-" in it.

Why "-"? Are we trying ot see if "ctx->pl" matches "anything" in the directory that is at <path>? Is the assumption here that pl only names directories literally without blobs (I presume that is the same thing as assuming the cone mode)?

I am trying to see if there is a way that expresses the intention of this code more clearly than using an arbitrary path "-" (and trying to figure out if I got the intention right in the first place ;-)..

Show 5 quoted lines
> +		/*
> +		 * The path "{base}{path}/" is a sparse directory. Create the correct
> +		 * name for inserting the entry into the index.
> +		 */
> +		strbuf_setlen(base, base->len - 1);

This removes that phoney "-" while keeping the trailing "/". Just like "-" was unclear, understanding this "- 1" requires that the reader understands why "/-" was used earlier.

The resulting "base" is used in the newly created cache entry to represent the (unexpanded) directory below, and such a cache entry is supposed to have a path with a trailing slash, so it makes sense.

> +	} else {
> +		strbuf_addstr(base, path);

For any non-tree thing, we use the given path for the cache entry to represent it.

Show 6 quoted lines
> +	}
> +
> +	ce = make_cache_entry(ctx->write, mode, oid, base->buf, 0, 0);
>  	ce->ce_flags |= CE_SKIP_WORKTREE | CE_EXTENDED;
> -	set_index_entry(istate, istate->cache_nr++, ce);
> +	set_index_entry(ctx->write, ctx->write->cache_nr++, ce);

And the cache entry (newly created) is added to the destination. Unlike what happens in the caller (i.e. expand_to_pattern_list) that moves the cache entry taken from the source index to the destination index, the caller will discard the cache entry taken from the source index after read_tree_at() returns, and we create a new instance for ourselves here, even if we _could_ have reused it (by passing it in the context structure, for example).

>  	strbuf_setlen(base, len);

And we restore the length of the path in the base to the original before we return.

>  	return 0;

Returning 0 as opposed to READ_TREE_RECURSIVE here means "we've dealt with the entry; don't recurse into subtree even if you called us with a tree", which is the right thing to do here, as we did have done all we need to here.

OK, except for that "/-" thing, all of the above makes sense to me.
Thanks.
Show 27 quoted lines
> @@ -254,6 +282,7 @@ void expand_to_pattern_list(struct index_state *istate,
>  	int i;
>  	struct index_state *full;
>  	struct strbuf base = STRBUF_INIT;
> +	struct modify_index_context ctx;
>  
>  	/*
>  	 * If the index is already full, then keep it full. We will convert
> @@ -294,6 +323,9 @@ void expand_to_pattern_list(struct index_state *istate,
>  	full->cache_nr = 0;
>  	ALLOC_ARRAY(full->cache, full->cache_alloc);
>  
> +	ctx.write = full;
> +	ctx.pl = pl;
> +
>  	for (i = 0; i < istate->cache_nr; i++) {
>  		struct cache_entry *ce = istate->cache[i];
>  		struct tree *tree;
> @@ -319,7 +351,7 @@ void expand_to_pattern_list(struct index_state *istate,
>  		strbuf_add(&base, ce->name, strlen(ce->name));
>  
>  		read_tree_at(istate->repo, tree, &base, &ps,
> -			     add_path_to_index, full);
> +			     add_path_to_index, &ctx);
>  
>  		/* free directory entries. full entries are re-used */
>  		discard_cache_entry(ce);
Previous: Derrick Stolee via GitGitGadgetNext: Derrick Stolee
Message 31 of 55 in “Sparse index: integrate with sparse-checkout”
  1. 0/8 Sparse index: integrate with sparse-checkoutDerrick Stolee via GitGitGadget, May 16, 2022
  2. 1/8 sparse-index: create expand_to_pattern_list()Derrick Stolee via GitGitGadget, May 16, 2022
  3. Victoria DyeMay 16, 2022
  4. Derrick StoleeMay 16, 2022
  5. 4/8 sparse-checkout: --no-sparse-index needs a full indexDerrick Stolee via GitGitGadget, May 16, 2022
  6. 2/8 sparse-index: introduce partially-sparse indexesDerrick Stolee via GitGitGadget, May 16, 2022
  7. 6/8 sparse-index: complete partial expansionDerrick Stolee via GitGitGadget, May 16, 2022
  8. Victoria DyeMay 16, 2022
  9. Derrick StoleeMay 17, 2022
  10. 7/8 p2000: add test for 'git sparse-checkout [add|set]'Derrick Stolee via GitGitGadget, May 16, 2022
  11. 5/8 sparse-index: partially expand directoriesDerrick Stolee via GitGitGadget, May 16, 2022
  12. Victoria DyeMay 16, 2022
  13. 3/8 cache-tree: implement cache_tree_find_path()Derrick Stolee via GitGitGadget, May 16, 2022
  14. 8/8 sparse-checkout: integrate with sparse indexDerrick Stolee via GitGitGadget, May 16, 2022
  15. Victoria DyeMay 16, 2022
  16. Derrick StoleeMay 17, 2022
  17. 00/10 Sparse index: integrate with sparse-checkoutDerrick Stolee via GitGitGadget, May 19, 2022
  18. 02/10 t1092: stress test 'git sparse-checkout set'Derrick Stolee via GitGitGadget, May 19, 2022
  19. 03/10 sparse-index: create expand_to_pattern_list()Derrick Stolee via GitGitGadget, May 19, 2022
  20. Junio C HamanoMay 19, 2022
  21. Derrick StoleeMay 20, 2022
  22. 04/10 sparse-index: introduce partially-sparse indexesDerrick Stolee via GitGitGadget, May 19, 2022
  23. Junio C HamanoMay 19, 2022
  24. Derrick StoleeMay 20, 2022
  25. Junio C HamanoMay 20, 2022
  26. 01/10 t1092: refactor 'sparse-index contents' testDerrick Stolee via GitGitGadget, May 19, 2022
  27. 05/10 cache-tree: implement cache_tree_find_path()Derrick Stolee via GitGitGadget, May 19, 2022
  28. Junio C HamanoMay 19, 2022
  29. Derrick StoleeMay 20, 2022
  30. 07/10 sparse-index: partially expand directoriesDerrick Stolee via GitGitGadget, May 19, 2022
  31. Junio C HamanoMay 20, 2022
  32. Derrick StoleeMay 20, 2022
  33. 06/10 sparse-checkout: --no-sparse-index needs a full indexDerrick Stolee via GitGitGadget, May 19, 2022
  34. Junio C HamanoMay 19, 2022
  35. 09/10 p2000: add test for 'git sparse-checkout [add|set]'Derrick Stolee via GitGitGadget, May 19, 2022
  36. 10/10 sparse-checkout: integrate with sparse indexDerrick Stolee via GitGitGadget, May 19, 2022
  37. 08/10 sparse-index: complete partial expansionDerrick Stolee via GitGitGadget, May 19, 2022
  38. Junio C HamanoMay 21, 2022
  39. Derrick StoleeMay 23, 2022
  40. Derrick StoleeMay 23, 2022
  41. Junio C HamanoMay 23, 2022
  42. Junio C HamanoMay 23, 2022
  43. Derrick StoleeMay 25, 2022
  44. Junio C HamanoMay 25, 2022
  45. 00/10 Sparse index: integrate with sparse-checkoutDerrick Stolee via GitGitGadget, May 23, 2022
  46. 01/10 t1092: refactor 'sparse-index contents' testDerrick Stolee via GitGitGadget, May 23, 2022
  47. 04/10 sparse-index: introduce partially-sparse indexesDerrick Stolee via GitGitGadget, May 23, 2022
  48. 03/10 sparse-index: create expand_index()Derrick Stolee via GitGitGadget, May 23, 2022
  49. 02/10 t1092: stress test 'git sparse-checkout set'Derrick Stolee via GitGitGadget, May 23, 2022
  50. 05/10 cache-tree: implement cache_tree_find_path()Derrick Stolee via GitGitGadget, May 23, 2022
  51. 07/10 sparse-index: partially expand directoriesDerrick Stolee via GitGitGadget, May 23, 2022
  52. 06/10 sparse-checkout: --no-sparse-index needs a full indexDerrick Stolee via GitGitGadget, May 23, 2022
  53. 09/10 p2000: add test for 'git sparse-checkout [add|set]'Derrick Stolee via GitGitGadget, May 23, 2022
  54. 08/10 sparse-index: complete partial expansionDerrick Stolee via GitGitGadget, May 23, 2022
  55. 10/10 sparse-checkout: integrate with sparse indexDerrick Stolee via GitGitGadget, May 23, 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.