Skip to content

Commit 0243930

Browse files
derrickstoleegitster
authored andcommitted
sparse-index: partially expand directories
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2d44338 commit 0243930

File tree

1 file changed

+50
-7
lines changed

1 file changed

+50
-7
lines changed

sparse-index.c

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
#include "dir.h"
1010
#include "fsmonitor.h"
1111

12+
struct modify_index_context {
13+
struct index_state *write;
14+
struct pattern_list *pl;
15+
};
16+
1217
static struct cache_entry *construct_sparse_dir_entry(
1318
struct index_state *istate,
1419
const char *sparse_dir,
@@ -231,18 +236,52 @@ static int add_path_to_index(const struct object_id *oid,
231236
struct strbuf *base, const char *path,
232237
unsigned int mode, void *context)
233238
{
234-
struct index_state *istate = (struct index_state *)context;
239+
struct modify_index_context *ctx = (struct modify_index_context *)context;
235240
struct cache_entry *ce;
236241
size_t len = base->len;
237242

238-
if (S_ISDIR(mode))
239-
return READ_TREE_RECURSIVE;
243+
if (S_ISDIR(mode)) {
244+
int dtype;
245+
size_t baselen = base->len;
246+
if (!ctx->pl)
247+
return READ_TREE_RECURSIVE;
240248

241-
strbuf_addstr(base, path);
249+
/*
250+
* Have we expanded to a point outside of the sparse-checkout?
251+
*
252+
* Artificially pad the path name with a slash "/" to
253+
* indicate it as a directory, and add an arbitrary file
254+
* name ("-") so we can consider base->buf as a file name
255+
* to match against the cone-mode patterns.
256+
*
257+
* If we compared just "path", then we would expand more
258+
* than we should. Since every file at root is always
259+
* included, we would expand every directory at root at
260+
* least one level deep instead of using sparse directory
261+
* entries.
262+
*/
263+
strbuf_addstr(base, path);
264+
strbuf_add(base, "/-", 2);
265+
266+
if (path_matches_pattern_list(base->buf, base->len,
267+
NULL, &dtype,
268+
ctx->pl, ctx->write)) {
269+
strbuf_setlen(base, baselen);
270+
return READ_TREE_RECURSIVE;
271+
}
242272

243-
ce = make_cache_entry(istate, mode, oid, base->buf, 0, 0);
273+
/*
274+
* The path "{base}{path}/" is a sparse directory. Create the correct
275+
* name for inserting the entry into the index.
276+
*/
277+
strbuf_setlen(base, base->len - 1);
278+
} else {
279+
strbuf_addstr(base, path);
280+
}
281+
282+
ce = make_cache_entry(ctx->write, mode, oid, base->buf, 0, 0);
244283
ce->ce_flags |= CE_SKIP_WORKTREE | CE_EXTENDED;
245-
set_index_entry(istate, istate->cache_nr++, ce);
284+
set_index_entry(ctx->write, ctx->write->cache_nr++, ce);
246285

247286
strbuf_setlen(base, len);
248287
return 0;
@@ -254,6 +293,7 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
254293
struct index_state *full;
255294
struct strbuf base = STRBUF_INIT;
256295
const char *tr_region;
296+
struct modify_index_context ctx;
257297

258298
/*
259299
* If the index is already full, then keep it full. We will convert
@@ -293,6 +333,9 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
293333
full->cache_nr = 0;
294334
ALLOC_ARRAY(full->cache, full->cache_alloc);
295335

336+
ctx.write = full;
337+
ctx.pl = pl;
338+
296339
for (i = 0; i < istate->cache_nr; i++) {
297340
struct cache_entry *ce = istate->cache[i];
298341
struct tree *tree;
@@ -318,7 +361,7 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
318361
strbuf_add(&base, ce->name, strlen(ce->name));
319362

320363
read_tree_at(istate->repo, tree, &base, &ps,
321-
add_path_to_index, full);
364+
add_path_to_index, &ctx);
322365

323366
/* free directory entries. full entries are re-used */
324367
discard_cache_entry(ce);

0 commit comments

Comments
 (0)