summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--unpack-trees.c77
-rw-r--r--unpack-trees.h9
2 files changed, 86 insertions, 0 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index 4733e7eaf8..a5bc0a3a16 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1714,6 +1714,83 @@ return_failed:
goto done;
}
+/*
+ * Update SKIP_WORKTREE bits according to sparsity patterns, and update
+ * working directory to match.
+ *
+ * CE_NEW_SKIP_WORKTREE is used internally.
+ */
+enum update_sparsity_result update_sparsity(struct unpack_trees_options *o)
+{
+ enum update_sparsity_result ret = UPDATE_SPARSITY_SUCCESS;
+ struct pattern_list pl;
+ int i, empty_worktree;
+ unsigned old_show_all_errors;
+ int free_pattern_list = 0;
+
+ old_show_all_errors = o->show_all_errors;
+ o->show_all_errors = 1;
+
+ /* Sanity checks */
+ if (!o->update || o->index_only || o->skip_sparse_checkout)
+ BUG("update_sparsity() is for reflecting sparsity patterns in working directory");
+ if (o->src_index != o->dst_index || o->fn)
+ BUG("update_sparsity() called wrong");
+
+ trace_performance_enter();
+
+ /* If we weren't given patterns, use the recorded ones */
+ if (!o->pl) {
+ memset(&pl, 0, sizeof(pl));
+ free_pattern_list = 1;
+ populate_from_existing_patterns(o, &pl);
+ if (o->skip_sparse_checkout)
+ goto skip_sparse_checkout;
+ }
+
+ /* Set NEW_SKIP_WORKTREE on existing entries. */
+ mark_all_ce_unused(o->src_index);
+ mark_new_skip_worktree(o->pl, o->src_index, 0,
+ CE_NEW_SKIP_WORKTREE, o->verbose_update);
+
+ /* Then loop over entries and update/remove as needed */
+ ret = UPDATE_SPARSITY_SUCCESS;
+ empty_worktree = 1;
+ for (i = 0; i < o->src_index->cache_nr; i++) {
+ struct cache_entry *ce = o->src_index->cache[i];
+
+ if (apply_sparse_checkout(o->src_index, ce, o))
+ ret = UPDATE_SPARSITY_WARNINGS;
+
+ if (!ce_skip_worktree(ce))
+ empty_worktree = 0;
+ }
+
+ /*
+ * Sparse checkout is meant to narrow down checkout area
+ * but it does not make sense to narrow down to empty working
+ * tree. This is usually a mistake in sparse checkout rules.
+ * Do not allow users to do that.
+ */
+ if (o->src_index->cache_nr && empty_worktree) {
+ unpack_failed(o, "Sparse checkout leaves no entry on working directory");
+ ret = UPDATE_SPARSITY_INDEX_UPDATE_FAILURES;
+ goto done;
+ }
+
+skip_sparse_checkout:
+ if (check_updates(o, o->src_index))
+ ret = UPDATE_SPARSITY_WORKTREE_UPDATE_FAILURES;
+
+done:
+ display_error_msgs(o);
+ o->show_all_errors = old_show_all_errors;
+ if (free_pattern_list)
+ clear_pattern_list(&pl);
+ trace_performance_leave("update_sparsity");
+ return ret;
+}
+
/* Here come the merge functions */
static int reject_merge(const struct cache_entry *ce,
diff --git a/unpack-trees.h b/unpack-trees.h
index d3516267f3..5cf41ef5b5 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -88,6 +88,15 @@ struct unpack_trees_options {
int unpack_trees(unsigned n, struct tree_desc *t,
struct unpack_trees_options *options);
+enum update_sparsity_result {
+ UPDATE_SPARSITY_SUCCESS = 0,
+ UPDATE_SPARSITY_WARNINGS = 1,
+ UPDATE_SPARSITY_INDEX_UPDATE_FAILURES = -1,
+ UPDATE_SPARSITY_WORKTREE_UPDATE_FAILURES = -2
+};
+
+enum update_sparsity_result update_sparsity(struct unpack_trees_options *options);
+
int verify_uptodate(const struct cache_entry *ce,
struct unpack_trees_options *o);