sparse-index: introduce partially-sparse indexes

A future change will present a temporary, in-memory mode where the index
can both contain sparse directory entries but also not be completely
collapsed to the smallest possible sparse directories. This will be
necessary for modifying the sparse-checkout definition while using a
sparse index.

For now, convert the single-bit member 'sparse_index' in 'struct
index_state' to be a an 'enum sparse_index_mode' with three modes:

* INDEX_EXPANDED (0): No sparse directories exist. This is always the
  case for repositories that do not use cone-mode sparse-checkout.

* INDEX_COLLAPSED: Sparse directories may exist. Files outside the
  sparse-checkout cone are reduced to sparse directory entries whenever
  possible.

* INDEX_PARTIALLY_SPARSE: Sparse directories may exist. Some file
  entries outside the sparse-checkout cone may exist. Running
  convert_to_sparse() may further reduce those files to sparse directory
  entries.

The main reason to store this extra information is to allow
convert_to_sparse() to short-circuit when the index is already in
INDEX_EXPANDED mode but to actually do the necessary work when in
INDEX_PARTIALLY_SPARSE mode.

The INDEX_PARTIALLY_SPARSE mode will be used in an upcoming change.

Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Derrick Stolee 2022-05-23 13:48:40 +00:00 committed by Junio C Hamano
parent dce241b020
commit 9fadb373dd
4 changed files with 32 additions and 15 deletions

View File

@ -128,7 +128,7 @@ static void clean_tracked_sparse_directories(struct repository *r)
* sparse index will not delete directories that contain
* conflicted entries or submodules.
*/
if (!r->index->sparse_index) {
if (r->index->sparse_index == INDEX_EXPANDED) {
/*
* If something, such as a merge conflict or other concern,
* prevents us from converting to a sparse index, then do

33
cache.h
View File

@ -310,6 +310,29 @@ struct untracked_cache;
struct progress;
struct pattern_list;
enum sparse_index_mode {
/*
* There are no sparse directories in the index at all.
*
* Repositories that don't use cone-mode sparse-checkout will
* always have their indexes in this mode.
*/
INDEX_EXPANDED = 0,
/*
* The index has already been collapsed to sparse directories
* whereever possible.
*/
INDEX_COLLAPSED,
/*
* The sparse directories that exist are outside the
* sparse-checkout boundary, but it is possible that some file
* entries could collapse to sparse directory entries.
*/
INDEX_PARTIALLY_SPARSE,
};
struct index_state {
struct cache_entry **cache;
unsigned int version;
@ -323,14 +346,8 @@ struct index_state {
drop_cache_tree : 1,
updated_workdir : 1,
updated_skipworktree : 1,
fsmonitor_has_run_once : 1,
/*
* sparse_index == 1 when sparse-directory
* entries exist. Requires sparse-checkout
* in cone mode.
*/
sparse_index : 1;
fsmonitor_has_run_once : 1;
enum sparse_index_mode sparse_index;
struct hashmap name_hash;
struct hashmap dir_hash;
struct object_id oid;

View File

@ -112,7 +112,7 @@ static const char *alternate_index_output;
static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
{
if (S_ISSPARSEDIR(ce->ce_mode))
istate->sparse_index = 1;
istate->sparse_index = INDEX_COLLAPSED;
istate->cache[nr] = ce;
add_name_hash(istate, ce);
@ -1856,7 +1856,7 @@ static int read_index_extension(struct index_state *istate,
break;
case CACHE_EXT_SPARSE_DIRECTORIES:
/* no content, only an indicator */
istate->sparse_index = 1;
istate->sparse_index = INDEX_COLLAPSED;
break;
default:
if (*ext < 'A' || 'Z' < *ext)
@ -3149,7 +3149,7 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
unsigned flags)
{
int ret;
int was_full = !istate->sparse_index;
int was_full = istate->sparse_index == INDEX_EXPANDED;
ret = convert_to_sparse(istate, 0);

View File

@ -173,7 +173,7 @@ int convert_to_sparse(struct index_state *istate, int flags)
* If the index is already sparse, empty, or otherwise
* cannot be converted to sparse, do not convert.
*/
if (istate->sparse_index || !istate->cache_nr ||
if (istate->sparse_index == INDEX_COLLAPSED || !istate->cache_nr ||
!is_sparse_index_allowed(istate, flags))
return 0;
@ -214,7 +214,7 @@ int convert_to_sparse(struct index_state *istate, int flags)
FREE_AND_NULL(istate->fsmonitor_dirty);
FREE_AND_NULL(istate->fsmonitor_last_update);
istate->sparse_index = 1;
istate->sparse_index = INDEX_COLLAPSED;
trace2_region_leave("index", "convert_to_sparse", istate->repo);
return 0;
}
@ -259,7 +259,7 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
* If the index is already full, then keep it full. We will convert
* it to a sparse index on write, if possible.
*/
if (!istate || !istate->sparse_index)
if (!istate || istate->sparse_index == INDEX_EXPANDED)
return;
/*