Merge branch 'ds/status-with-sparse-index'

"git status" codepath learned to work with sparsely populated index
without hydrating it fully.

* ds/status-with-sparse-index:
  t1092: document bad sparse-checkout behavior
  fsmonitor: integrate with sparse index
  wt-status: expand added sparse directory entries
  status: use sparse-index throughout
  status: skip sparse-checkout percentage with sparse-index
  diff-lib: handle index diffs with sparse dirs
  dir.c: accept a directory as part of cone-mode patterns
  unpack-trees: unpack sparse directory entries
  unpack-trees: rename unpack_nondirectories()
  unpack-trees: compare sparse directories correctly
  unpack-trees: preserve cache_bottom
  t1092: add tests for status/add and sparse files
  t1092: expand repository data shape
  t1092: replace incorrect 'echo' with 'cat'
  sparse-index: include EXTENDED flag when expanding
  sparse-index: skip indexes with unmerged entries
This commit is contained in:
Junio C Hamano
2021-07-28 13:18:01 -07:00
10 changed files with 471 additions and 39 deletions

View File

@@ -657,6 +657,36 @@ static void wt_status_collect_changes_index(struct wt_status *s)
clear_pathspec(&rev.prune_data);
}
static int add_file_to_list(const struct object_id *oid,
struct strbuf *base, const char *path,
unsigned int mode, void *context)
{
struct string_list_item *it;
struct wt_status_change_data *d;
struct wt_status *s = context;
struct strbuf full_name = STRBUF_INIT;
if (S_ISDIR(mode))
return READ_TREE_RECURSIVE;
strbuf_add(&full_name, base->buf, base->len);
strbuf_addstr(&full_name, path);
it = string_list_insert(&s->change, full_name.buf);
d = it->util;
if (!d) {
CALLOC_ARRAY(d, 1);
it->util = d;
}
d->index_status = DIFF_STATUS_ADDED;
/* Leave {mode,oid}_head zero for adds. */
d->mode_index = mode;
oidcpy(&d->oid_index, oid);
s->committable = 1;
strbuf_release(&full_name);
return 0;
}
static void wt_status_collect_changes_initial(struct wt_status *s)
{
struct index_state *istate = s->repo->index;
@@ -671,6 +701,27 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
continue;
if (ce_intent_to_add(ce))
continue;
if (S_ISSPARSEDIR(ce->ce_mode)) {
/*
* This is a sparse directory entry, so we want to collect all
* of the added files within the tree. This requires recursively
* expanding the trees to find the elements that are new in this
* tree and marking them with DIFF_STATUS_ADDED.
*/
struct strbuf base = STRBUF_INIT;
struct pathspec ps = { 0 };
struct tree *tree = lookup_tree(istate->repo, &ce->oid);
ps.recursive = 1;
ps.has_wildcard = 1;
ps.max_depth = -1;
strbuf_add(&base, ce->name, ce->ce_namelen);
read_tree_at(istate->repo, tree, &base, &ps,
add_file_to_list, s);
continue;
}
it = string_list_insert(&s->change, ce->name);
d = it->util;
if (!d) {
@@ -1492,9 +1543,12 @@ static void show_sparse_checkout_in_use(struct wt_status *s,
if (s->state.sparse_checkout_percentage == SPARSE_CHECKOUT_DISABLED)
return;
status_printf_ln(s, color,
_("You are in a sparse checkout with %d%% of tracked files present."),
s->state.sparse_checkout_percentage);
if (s->state.sparse_checkout_percentage == SPARSE_CHECKOUT_SPARSE_INDEX)
status_printf_ln(s, color, _("You are in a sparse checkout."));
else
status_printf_ln(s, color,
_("You are in a sparse checkout with %d%% of tracked files present."),
s->state.sparse_checkout_percentage);
wt_longstatus_print_trailer(s);
}
@@ -1652,6 +1706,11 @@ static void wt_status_check_sparse_checkout(struct repository *r,
return;
}
if (r->index->sparse_index) {
state->sparse_checkout_percentage = SPARSE_CHECKOUT_SPARSE_INDEX;
return;
}
for (i = 0; i < r->index->cache_nr; i++) {
struct cache_entry *ce = r->index->cache[i];
if (ce_skip_worktree(ce))