summaryrefslogtreecommitdiff
path: root/sparse-index.c
diff options
context:
space:
mode:
Diffstat (limited to 'sparse-index.c')
-rw-r--r--sparse-index.c106
1 files changed, 72 insertions, 34 deletions
diff --git a/sparse-index.c b/sparse-index.c
index 56eb65dc34..a1d505d50e 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -33,19 +33,14 @@ static int convert_to_sparse_rec(struct index_state *istate,
{
int i, can_convert = 1;
int start_converted = num_converted;
- enum pattern_match_result match;
- int dtype = DT_UNKNOWN;
struct strbuf child_path = STRBUF_INIT;
- struct pattern_list *pl = istate->sparse_checkout_patterns;
/*
* Is the current path outside of the sparse cone?
* Then check if the region can be replaced by a sparse
* directory entry (everything is sparse and merged).
*/
- match = path_matches_pattern_list(ct_path, ct_pathlen,
- NULL, &dtype, pl, istate);
- if (match != NOT_MATCHED)
+ if (path_in_sparse_checkout(ct_path, istate))
can_convert = 0;
for (i = start; can_convert && i < end; i++) {
@@ -127,41 +122,64 @@ static int index_has_unmerged_entries(struct index_state *istate)
return 0;
}
-int convert_to_sparse(struct index_state *istate)
+static int is_sparse_index_allowed(struct index_state *istate, int flags)
{
- int test_env;
- if (istate->split_index || istate->sparse_index ||
- !core_apply_sparse_checkout || !core_sparse_checkout_cone)
+ if (!core_apply_sparse_checkout || !core_sparse_checkout_cone)
return 0;
if (!istate->repo)
istate->repo = the_repository;
- /*
- * The GIT_TEST_SPARSE_INDEX environment variable triggers the
- * index.sparse config variable to be on.
- */
- test_env = git_env_bool("GIT_TEST_SPARSE_INDEX", -1);
- if (test_env >= 0)
- set_sparse_index_config(istate->repo, test_env);
+ if (!(flags & SPARSE_INDEX_MEMORY_ONLY)) {
+ int test_env;
+
+ /*
+ * The sparse index is not (yet) integrated with a split index.
+ */
+ if (istate->split_index)
+ return 0;
+ /*
+ * The GIT_TEST_SPARSE_INDEX environment variable triggers the
+ * index.sparse config variable to be on.
+ */
+ test_env = git_env_bool("GIT_TEST_SPARSE_INDEX", -1);
+ if (test_env >= 0)
+ set_sparse_index_config(istate->repo, test_env);
+
+ /*
+ * Only convert to sparse if index.sparse is set.
+ */
+ prepare_repo_settings(istate->repo);
+ if (!istate->repo->settings.sparse_index)
+ return 0;
+ }
+
+ if (init_sparse_checkout_patterns(istate))
+ return 0;
/*
- * Only convert to sparse if index.sparse is set.
+ * We need cone-mode patterns to use sparse-index. If a user edits
+ * their sparse-checkout file manually, then we can detect during
+ * parsing that they are not actually using cone-mode patterns and
+ * hence we need to abort this conversion _without error_. Warnings
+ * already exist in the pattern parsing to inform the user of their
+ * bad patterns.
*/
- prepare_repo_settings(istate->repo);
- if (!istate->repo->settings.sparse_index)
+ if (!istate->sparse_checkout_patterns->use_cone_patterns)
return 0;
- if (!istate->sparse_checkout_patterns) {
- istate->sparse_checkout_patterns = xcalloc(1, sizeof(struct pattern_list));
- if (get_sparse_checkout_patterns(istate->sparse_checkout_patterns) < 0)
- return 0;
- }
+ return 1;
+}
- if (!istate->sparse_checkout_patterns->use_cone_patterns) {
- warning(_("attempting to use sparse-index without cone mode"));
- return -1;
- }
+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 ||
+ !is_sparse_index_allowed(istate, flags))
+ return 0;
/*
* NEEDSWORK: If we have unmerged entries, then stay full.
@@ -170,11 +188,19 @@ int convert_to_sparse(struct index_state *istate)
if (index_has_unmerged_entries(istate))
return 0;
- /* Clear and recompute the cache-tree */
- cache_tree_free(&istate->cache_tree);
- if (cache_tree_update(istate, 0)) {
- warning(_("unable to update cache-tree, staying full"));
- return -1;
+ if (!cache_tree_fully_valid(istate->cache_tree)) {
+ /* Clear and recompute the cache-tree */
+ cache_tree_free(&istate->cache_tree);
+
+ /*
+ * Silently return if there is a problem with the cache tree update,
+ * which might just be due to a conflict state in some entry.
+ *
+ * This might create new tree objects, so be sure to use
+ * WRITE_TREE_MISSING_OK.
+ */
+ if (cache_tree_update(istate, WRITE_TREE_MISSING_OK))
+ return 0;
}
remove_fsmonitor(istate);
@@ -303,6 +329,18 @@ void ensure_full_index(struct index_state *istate)
trace2_region_leave("index", "ensure_full_index", istate->repo);
}
+void ensure_correct_sparsity(struct index_state *istate)
+{
+ /*
+ * If the index can be sparse, make it sparse. Otherwise,
+ * ensure the index is full.
+ */
+ if (is_sparse_index_allowed(istate, 0))
+ convert_to_sparse(istate, 0);
+ else
+ ensure_full_index(istate);
+}
+
/*
* This static global helps avoid infinite recursion between
* expand_to_path() and index_file_exists().