Derrick Stolee via GitGitGadget wrote: > From: Derrick Stolee <dstolee@xxxxxxxxxxxxx> > > The expand_to_pattern_list() method expands sparse directory entries > to their list of contained files when either the pattern list is NULL or > the directory is contained in the new pattern list's cone mode patterns. > > It is possible that the pattern list has a recursive match with a > directory 'A/B/C/' and so an existing sparse directory 'A/B/' would need > to be expanded. If there exists a directory 'A/B/D/', then that > directory should not be expanded and instead we can create a sparse > directory. > > To implement this, we plug into the add_path_to_index() callback for the > call to read_tree_at(). Since we now need access to both the index we > are writing and the pattern list we are comparing, create a 'struct > modify_index_context' to use as a data transfer object. It is important > that we use the given pattern list since we will use this pattern list > to change the sparse-checkout patterns and cannot use > istate->sparse_checkout_patterns. > > Signed-off-by: Derrick Stolee <derrickstolee@xxxxxxxxxx> > --- > sparse-index.c | 46 +++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 39 insertions(+), 7 deletions(-) > > diff --git a/sparse-index.c b/sparse-index.c > index 79e8ff087bc..3d8eed585b5 100644 > --- a/sparse-index.c > +++ b/sparse-index.c > @@ -9,6 +9,11 @@ > #include "dir.h" > #include "fsmonitor.h" > > +struct modify_index_context { > + struct index_state *write; > + struct pattern_list *pl; > +}; > + > static struct cache_entry *construct_sparse_dir_entry( > struct index_state *istate, > const char *sparse_dir, > @@ -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) > { > - struct index_state *istate = (struct index_state *)context; > + struct modify_index_context *ctx = (struct modify_index_context *)context; > struct cache_entry *ce; > size_t len = base->len; > > - if (S_ISDIR(mode)) > - return READ_TREE_RECURSIVE; > + if (S_ISDIR(mode)) { > + int dtype; > + size_t baselen = base->len; > + if (!ctx->pl) > + return READ_TREE_RECURSIVE; > > - strbuf_addstr(base, path); > + /* > + * 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)) { > + strbuf_setlen(base, baselen); > + return READ_TREE_RECURSIVE; > + } > > - ce = make_cache_entry(istate, mode, oid, base->buf, 0, 0); > + /* > + * The path "{base}{path}/" is a sparse directory. Create the correct > + * name for inserting the entry into the idnex. s/idnex/index > + */ > + strbuf_setlen(base, base->len - 1); > + } else { > + strbuf_addstr(base, path); > + } > + > + 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); > > strbuf_setlen(base, len); > return 0; > @@ -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);