diff --git a/Documentation/config.txt b/Documentation/config.txt index 7791c32bc3..5825c914fb 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -439,6 +439,10 @@ On some file system/operating system combinations, this is unreliable. Set this config setting to 'rename' there; However, This will remove the check that makes sure that existing object files will not get overwritten. +core.sparseCheckout:: + Enable "sparse checkout" feature. See section "Sparse checkout" in + linkgit:git-read-tree[1] for more information. + add.ignore-errors:: Tells 'git-add' to continue adding files when some files cannot be added due to indexing errors. Equivalent to the '--ignore-errors' diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index 8b3971685a..fc3f08b81c 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -401,7 +401,9 @@ follows: ---------------- Then you can disable sparse checkout. Sparse checkout support in "git -read-tree" and similar commands is disabled by default. +read-tree" and similar commands is disabled by default. You need to +turn `core.sparseCheckout` on in order to have sparse checkout +support. SEE ALSO diff --git a/cache.h b/cache.h index d3f81a1c7d..2de00f8120 100644 --- a/cache.h +++ b/cache.h @@ -526,6 +526,7 @@ extern size_t delta_base_cache_limit; extern int auto_crlf; extern int fsync_object_files; extern int core_preload_index; +extern int core_apply_sparse_checkout; enum safe_crlf { SAFE_CRLF_FALSE = 0, diff --git a/config.c b/config.c index e87edeab0c..abd762ebfa 100644 --- a/config.c +++ b/config.c @@ -503,6 +503,11 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.sparsecheckout")) { + core_apply_sparse_checkout = git_config_bool(var, value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } diff --git a/environment.c b/environment.c index 8f5eaa7dd8..020422c034 100644 --- a/environment.c +++ b/environment.c @@ -48,6 +48,7 @@ enum push_default_type push_default = PUSH_DEFAULT_MATCHING; #endif enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE; int grafts_replace_parents = 1; +int core_apply_sparse_checkout; /* Parallel index stat data preload? */ int core_preload_index = 0; diff --git a/unpack-trees.c b/unpack-trees.c index 8eb4b7095c..44f8fdf808 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -378,6 +378,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options { int ret; static struct cache_entry *dfc; + struct exclude_list el; if (len > MAX_UNPACK_TREES) die("unpack_trees takes at most %d trees", MAX_UNPACK_TREES); @@ -387,6 +388,16 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options state.quiet = 1; state.refresh_cache = 1; + memset(&el, 0, sizeof(el)); + if (!core_apply_sparse_checkout || !o->update) + o->skip_sparse_checkout = 1; + if (!o->skip_sparse_checkout) { + if (add_excludes_from_file_to_list(git_path("info/sparse-checkout"), "", 0, NULL, &el, 0) < 0) + o->skip_sparse_checkout = 1; + else + o->el = ⪙ + } + memset(&o->result, 0, sizeof(o->result)); o->result.initialized = 1; if (o->src_index) { @@ -407,26 +418,39 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options info.fn = unpack_callback; info.data = o; - if (traverse_trees(len, t, &info) < 0) - return unpack_failed(o, NULL); + if (traverse_trees(len, t, &info) < 0) { + ret = unpack_failed(o, NULL); + goto done; + } } /* Any left-over entries in the index? */ if (o->merge) { while (o->pos < o->src_index->cache_nr) { struct cache_entry *ce = o->src_index->cache[o->pos]; - if (unpack_index_entry(ce, o) < 0) - return unpack_failed(o, NULL); + if (unpack_index_entry(ce, o) < 0) { + ret = unpack_failed(o, NULL); + goto done; + } } } - if (o->trivial_merges_only && o->nontrivial_merge) - return unpack_failed(o, "Merge requires file-level merging"); + if (o->trivial_merges_only && o->nontrivial_merge) { + ret = unpack_failed(o, "Merge requires file-level merging"); + goto done; + } o->src_index = NULL; ret = check_updates(o) ? (-2) : 0; if (o->dst_index) *o->dst_index = o->result; + +done: + for (i = 0;i < el.nr;i++) + free(el.excludes[i]); + if (el.excludes) + free(el.excludes); + return ret; } diff --git a/unpack-trees.h b/unpack-trees.h index d19df44f40..5c9e98a666 100644 --- a/unpack-trees.h +++ b/unpack-trees.h @@ -4,6 +4,7 @@ #define MAX_UNPACK_TREES 8 struct unpack_trees_options; +struct exclude_list; typedef int (*merge_fn_t)(struct cache_entry **src, struct unpack_trees_options *options); @@ -28,6 +29,7 @@ struct unpack_trees_options { skip_unmerged, initial_checkout, diff_index_cached, + skip_sparse_checkout, gently; const char *prefix; int pos; @@ -44,6 +46,8 @@ struct unpack_trees_options { struct index_state *dst_index; struct index_state *src_index; struct index_state result; + + struct exclude_list *el; /* for internal use */ }; extern int unpack_trees(unsigned n, struct tree_desc *t,