Subject: Re: [PATCH v2 08/10] sparse-index: complete partial expansion

From: Junio C Hamano <[email-masked]>
Date: Sat, 21 May 2022 00:45:57 -0700

"Derrick Stolee via GitGitGadget" <[email-masked]> writes:

> +	if (pl && !pl->use_cone_patterns) {
>  		pl = NULL;
> +	} else {
> +		/*
> +		 * We might contract file entries into sparse-directory
> +		 * entries, and for that we will need the cache tree to
> +		 * be recomputed.
> +		 */
> +		cache_tree_free(&istate->cache_tree);
> +
> +		/*
> +		 * If there is a problem creating the cache tree, then we
> +		 * need to expand to a full index since we cannot satisfy
> +		 * the current request as a sparse index.
> +		 */
> +		if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
> +			pl = NULL;
> +	}

So, if the current index has some irrelevant (i.e. do not match the
pattern list) subtrees in collapsed form, presense of an unmerged
entry, presumably inside the cone(s) we are interested in, makes us
lose the pattern list here, and we end up expanding everything?

I suspect that is a situation that is not so uncommon.  Working
inside a narrow cone of a wide tree, performing a merge would
hopefully allow many subtrees that are outside of the cones of our
interest merged without getting expanded at all (e.g. only the other
side touched these subtrees we are not working on, so their version
will become the merge result), while changes to some paths in the
cone of our interest may result in true conflicts represented as
cache entries at higher stages, needing conflict resolution
concluded with "git add".  Having to expand these subtrees that we
managed to merge while still collapsed, only because we have
conflicts in some other parts of the tree, feels somewhat sad.

By the way, why are we passing the "--missing-ok" option to "git
write-tree" here?

> @@ -330,11 +352,22 @@ void expand_to_pattern_list(struct index_state *istate,
>  		struct cache_entry *ce = istate->cache[i];
>  		struct tree *tree;
>  		struct pathspec ps;
> +		int dtype;
>  
>  		if (!S_ISSPARSEDIR(ce->ce_mode)) {
>  			set_index_entry(full, full->cache_nr++, ce);
>  			continue;
>  		}
> +
> +		/* We now have a sparse directory entry. Should we expand? */
> +		if (pl &&
> +		    path_matches_pattern_list(ce->name, ce->ce_namelen,
> +					      NULL, &dtype,
> +					      pl, istate) == NOT_MATCHED) {
> +			set_index_entry(full, full->cache_nr++, ce);
> +			continue;
> +		}
> +
>  		if (!(ce->ce_flags & CE_SKIP_WORKTREE))
>  			warning(_("index entry is a directory, but not sparse (%08x)"),
>  				ce->ce_flags);
> @@ -360,7 +393,7 @@ void expand_to_pattern_list(struct index_state *istate,
>  	/* Copy back into original index. */
>  	memcpy(&istate->name_hash, &full->name_hash, sizeof(full->name_hash));
>  	memcpy(&istate->dir_hash, &full->dir_hash, sizeof(full->dir_hash));
> -	istate->sparse_index = 0;
> +	istate->sparse_index = pl ? PARTIALLY_SPARSE : COMPLETELY_FULL;
>  	free(istate->cache);
>  	istate->cache = full->cache;
>  	istate->cache_nr = full->cache_nr;
> @@ -374,7 +407,7 @@ void expand_to_pattern_list(struct index_state *istate,
>  
>  	/* Clear and recompute the cache-tree */
>  	cache_tree_free(&istate->cache_tree);
> -	cache_tree_update(istate, 0);
> +	cache_tree_update(istate, WRITE_TREE_MISSING_OK);

The same question here.  We didn't say "missing trees are OK".  What
made it OK in this change?