git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v5 12/21] sparse-index: convert from full to sparse

From
Derrick Stolee via GitGitGadget <gitgitgadget@gmail.com>
Date
Mar 30, 2021, 13:10 UTC
Message-ID
<c870ae5e8749bb04c1290b607607ac056552e3f9.1617109864.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.883.v5.git.1617109864.gitgitgadget@gmail.com>
From: Derrick Stolee <dstolee@microsoft.com>

If we have a full index, then we can convert it to a sparse index by replacing directories outside of the sparse cone with sparse directory entries. The convert_to_sparse() method does this, when the situation is appropriate.

For now, we avoid converting the index to a sparse index if:
 1. the index is split.
 2. the index is already sparse.
 3. sparse-checkout is disabled.
 4. sparse-checkout does not use cone mode.

Finally, we currently limit the conversion to when the GIT_TEST_SPARSE_INDEX environment variable is enabled. A mode using Git config will be added in a later change.

The trickiest thing about this conversion is that we might not be able to mark a directory as a sparse directory just because it is outside the sparse cone. There might be unmerged files within that directory, so we need to look for those. Also, if there is some strange reason why a file is not marked with CE_SKIP_WORKTREE, then we should give up on converting that directory. There is still hope that some of its subdirectories might be able to convert to sparse, so we keep looking deeper.

The conversion process is assisted by the cache-tree extension. This is calculated from the full index if it does not already exist. We then abandon the cache-tree as it no longer applies to the newly-sparse index. Thus, this cache-tree will be recalculated in every sparse-full-sparse round-trip until we integrate the cache-tree extension with the sparse index.

Some Git commands use the index after writing it. For example, 'git add' will update the index, then write it to disk, then read its entries to report information. To keep the in-memory index in a full state after writing, we re-expand it to a full one after the write. This is wasteful for commands that only write the index and do not read from it again, but that is only the case until we make those commands "sparse aware."

We can compare the behavior of the sparse-index in t1092-sparse-checkout-compability.sh by using GIT_TEST_SPARSE_INDEX=1 when operating on the 'sparse-index' repo. We can also compare the two sparse repos directly, such as comparing their indexes (when expanded to full in the case of the 'sparse-index' repo). We also verify that the index is actually populated with sparse directory entries.

The 'checkout and reset (mixed)' test is marked for failure when comparing a sparse repo to a full repo, but we can compare the two sparse-checkout cases directly to ensure that we are not changing the behavior when using a sparse index.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
---
 cache-tree.c                             |   3 +
 cache.h                                  |   2 +
 read-cache.c                             |  26 ++++-
 sparse-index.c                           | 139 +++++++++++++++++++++++
 sparse-index.h                           |   1 +
 t/t1092-sparse-checkout-compatibility.sh |  61 +++++++++-
 6 files changed, 228 insertions(+), 4 deletions(-)
diff --git a/cache-tree.c b/cache-tree.c
index 2fb483d3c083..5f07a39e501e 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -6,6 +6,7 @@
 #include "object-store.h"
 #include "replace-object.h"
 #include "promisor-remote.h"
+#include "sparse-index.h"
 
 #ifndef DEBUG_CACHE_TREE
 #define DEBUG_CACHE_TREE 0
@@ -442,6 +443,8 @@ int cache_tree_update(struct index_state *istate, int flags)
 	if (i)
 		return i;
 
+	ensure_full_index(istate);
+
 	if (!istate->cache_tree)
 		istate->cache_tree = cache_tree();
 
diff --git a/cache.h b/cache.h
index 8c4464420d0a..74b43aaa2bd1 100644
--- a/cache.h
+++ b/cache.h
@@ -251,6 +251,8 @@ static inline unsigned int create_ce_mode(unsigned int mode)
 {
 	if (S_ISLNK(mode))
 		return S_IFLNK;
+	if (S_ISSPARSEDIR(mode))
+		return S_IFDIR;
 	if (S_ISDIR(mode) || S_ISGITLINK(mode))
 		return S_IFGITLINK;
 	return S_IFREG | ce_permissions(mode);
diff --git a/read-cache.c b/read-cache.c
index b8f092d1b7eb..2410e6e0df13 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -25,6 +25,7 @@
 #include "fsmonitor.h"
 #include "thread-utils.h"
 #include "progress.h"
+#include "sparse-index.h"
 
 /* Mask for the name length in ce_flags in the on-disk index */
 
@@ -1003,8 +1004,14 @@ int verify_path(const char *path, unsigned mode)
 
 			c = *path++;
 			if ((c == '.' && !verify_dotfile(path, mode)) ||
-			    is_dir_sep(c) || c == '\0')
+			    is_dir_sep(c))
 				return 0;
+			/*
+			 * allow terminating directory separators for
+			 * sparse directory entries.
+			 */
+			if (c == '\0')
+				return S_ISDIR(mode);
 		} else if (c == '\\' && protect_ntfs) {
 			if (is_ntfs_dotgit(path))
 				return 0;
@@ -3088,6 +3095,14 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
 				 unsigned flags)
 {
 	int ret;
+	int was_full = !istate->sparse_index;
+
+	ret = convert_to_sparse(istate);
+
+	if (ret) {
+		warning(_("failed to convert to a sparse-index"));
+		return ret;
+	}
 
 	/*
 	 * TODO trace2: replace "the_repository" with the actual repo instance
@@ -3099,6 +3114,9 @@ static int do_write_locked_index(struct index_state *istate, struct lock_file *l
 	trace2_region_leave_printf("index", "do_write_index", the_repository,
 				   "%s", get_lock_file_path(lock));
 
+	if (was_full)
+		ensure_full_index(istate);
+
 	if (ret)
 		return ret;
 	if (flags & COMMIT_LOCK)
@@ -3189,9 +3207,10 @@ static int write_shared_index(struct index_state *istate,
 			      struct tempfile **temp)
 {
 	struct split_index *si = istate->split_index;
-	int ret;
+	int ret, was_full = !istate->sparse_index;
 
 	move_cache_to_base_index(istate);
+	convert_to_sparse(istate);
 
 	trace2_region_enter_printf("index", "shared/do_write_index",
 				   the_repository, "%s", get_tempfile_path(*temp));
@@ -3199,6 +3218,9 @@ static int write_shared_index(struct index_state *istate,
 	trace2_region_leave_printf("index", "shared/do_write_index",
 				   the_repository, "%s", get_tempfile_path(*temp));
 
+	if (was_full)
+		ensure_full_index(istate);
+
 	if (ret)
 		return ret;
 	ret = adjust_shared_perm(get_tempfile_path(*temp));
diff --git a/sparse-index.c b/sparse-index.c
index 7095378a1b28..619ff7c2e217 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -4,6 +4,145 @@
 #include "tree.h"
 #include "pathspec.h"
 #include "trace2.h"
+#include "cache-tree.h"
+#include "config.h"
+#include "dir.h"
+#include "fsmonitor.h"
+
+static struct cache_entry *construct_sparse_dir_entry(
+				struct index_state *istate,
+				const char *sparse_dir,
+				struct cache_tree *tree)
+{
+	struct cache_entry *de;
+
+	de = make_cache_entry(istate, S_IFDIR, &tree->oid, sparse_dir, 0, 0);
+
+	de->ce_flags |= CE_SKIP_WORKTREE;
+	return de;
+}
+
+/*
+ * Returns the number of entries "inserted" into the index.
+ */
+static int convert_to_sparse_rec(struct index_state *istate,
+				 int num_converted,
+				 int start, int end,
+				 const char *ct_path, size_t ct_pathlen,
+				 struct cache_tree *ct)
+{
+	int i, can_convert = 1;
+	int start_converted = num_converted;
+	enum pattern_match_result match;
+	int dtype;
+	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)
+		can_convert = 0;
+
+	for (i = start; can_convert && i < end; i++) {
+		struct cache_entry *ce = istate->cache[i];
+
+		if (ce_stage(ce) ||
+		    !(ce->ce_flags & CE_SKIP_WORKTREE))
+			can_convert = 0;
+	}
+
+	if (can_convert) {
+		struct cache_entry *se;
+		se = construct_sparse_dir_entry(istate, ct_path, ct);
+
+		istate->cache[num_converted++] = se;
+		return 1;
+	}
+
+	for (i = start; i < end; ) {
+		int count, span, pos = -1;
+		const char *base, *slash;
+		struct cache_entry *ce = istate->cache[i];
+
+		/*
+		 * Detect if this is a normal entry outside of any subtree
+		 * entry.
+		 */
+		base = ce->name + ct_pathlen;
+		slash = strchr(base, '/');
+
+		if (slash)
+			pos = cache_tree_subtree_pos(ct, base, slash - base);
+
+		if (pos < 0) {
+			istate->cache[num_converted++] = ce;
+			i++;
+			continue;
+		}
+
+		strbuf_setlen(&child_path, 0);
+		strbuf_add(&child_path, ce->name, slash - ce->name + 1);
+
+		span = ct->down[pos]->cache_tree->entry_count;
+		count = convert_to_sparse_rec(istate,
+					      num_converted, i, i + span,
+					      child_path.buf, child_path.len,
+					      ct->down[pos]->cache_tree);
+		num_converted += count;
+		i += span;
+	}
+
+	strbuf_release(&child_path);
+	return num_converted - start_converted;
+}
+
+int convert_to_sparse(struct index_state *istate)
+{
+	if (istate->split_index || istate->sparse_index ||
+	    !core_apply_sparse_checkout || !core_sparse_checkout_cone)
+		return 0;
+
+	/*
+	 * For now, only create a sparse index with the
+	 * GIT_TEST_SPARSE_INDEX environment variable. We will relax
+	 * this once we have a proper way to opt-in (and later still,
+	 * opt-out).
+	 */
+	if (!git_env_bool("GIT_TEST_SPARSE_INDEX", 0))
+		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;
+	}
+
+	if (!istate->sparse_checkout_patterns->use_cone_patterns) {
+		warning(_("attempting to use sparse-index without cone mode"));
+		return -1;
+	}
+
+	if (cache_tree_update(istate, 0)) {
+		warning(_("unable to update cache-tree, staying full"));
+		return -1;
+	}
+
+	remove_fsmonitor(istate);
+
+	trace2_region_enter("index", "convert_to_sparse", istate->repo);
+	istate->cache_nr = convert_to_sparse_rec(istate,
+						 0, 0, istate->cache_nr,
+						 "", 0, istate->cache_tree);
+	istate->drop_cache_tree = 1;
+	istate->sparse_index = 1;
+	trace2_region_leave("index", "convert_to_sparse", istate->repo);
+	return 0;
+}
 
 static void set_index_entry(struct index_state *istate, int nr, struct cache_entry *ce)
 {
diff --git a/sparse-index.h b/sparse-index.h
index 09a20d036c46..64380e121d80 100644
--- a/sparse-index.h
+++ b/sparse-index.h
@@ -3,5 +3,6 @@
 
 struct index_state;
 void ensure_full_index(struct index_state *istate);
+int convert_to_sparse(struct index_state *istate);
 
 #endif
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index a1aea141c62c..1e888d195122 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -2,6 +2,11 @@
 
 test_description='compare full workdir to sparse workdir'
 
+# The verify_cache_tree() check is not sparse-aware (yet).
+# So, disable the check until that integration is complete.
+GIT_TEST_CHECK_CACHE_TREE=0
+GIT_TEST_SPLIT_INDEX=0
+
 . ./test-lib.sh
 
 test_expect_success 'setup' '
@@ -121,7 +126,9 @@ run_on_all () {
 test_all_match () {
 	run_on_all "$@" &&
 	test_cmp full-checkout-out sparse-checkout-out &&
-	test_cmp full-checkout-err sparse-checkout-err
+	test_cmp full-checkout-out sparse-index-out &&
+	test_cmp full-checkout-err sparse-checkout-err &&
+	test_cmp full-checkout-err sparse-index-err
 }
 
 test_sparse_match () {
@@ -130,6 +137,38 @@ test_sparse_match () {
 	test_cmp sparse-checkout-err sparse-index-err
 }
 
+test_expect_success 'sparse-index contents' '
+	init_repos &&
+
+	test-tool -C sparse-index read-cache --table >cache &&
+	for dir in folder1 folder2 x
+	do
+		TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
+		grep "040000 tree $TREE	$dir/" cache \
+			|| return 1
+	done &&
+
+	GIT_TEST_SPARSE_INDEX=1 git -C sparse-index sparse-checkout set folder1 &&
+
+	test-tool -C sparse-index read-cache --table >cache &&
+	for dir in deep folder2 x
+	do
+		TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
+		grep "040000 tree $TREE	$dir/" cache \
+			|| return 1
+	done &&
+
+	GIT_TEST_SPARSE_INDEX=1 git -C sparse-index sparse-checkout set deep/deeper1 &&
+
+	test-tool -C sparse-index read-cache --table >cache &&
+	for dir in deep/deeper2 folder1 folder2 x
+	do
+		TREE=$(git -C sparse-index rev-parse HEAD:$dir) &&
+		grep "040000 tree $TREE	$dir/" cache \
+			|| return 1
+	done
+'
+
 test_expect_success 'expanded in-memory index matches full index' '
 	init_repos &&
 	test_sparse_match test-tool read-cache --expand --table
@@ -137,6 +176,7 @@ test_expect_success 'expanded in-memory index matches full index' '
 
 test_expect_success 'status with options' '
 	init_repos &&
+	test_sparse_match ls &&
 	test_all_match git status --porcelain=v2 &&
 	test_all_match git status --porcelain=v2 -z -u &&
 	test_all_match git status --porcelain=v2 -uno &&
@@ -273,6 +313,17 @@ test_expect_failure 'checkout and reset (mixed)' '
 	test_all_match git reset update-folder2
 '
 
+# Ensure that sparse-index behaves identically to
+# sparse-checkout with a full index.
+test_expect_success 'checkout and reset (mixed) [sparse]' '
+	init_repos &&
+
+	test_sparse_match git checkout -b reset-test update-deep &&
+	test_sparse_match git reset deepest &&
+	test_sparse_match git reset update-folder1 &&
+	test_sparse_match git reset update-folder2
+'
+
 test_expect_success 'merge' '
 	init_repos &&
 
@@ -309,14 +360,20 @@ test_expect_success 'clean' '
 	test_all_match git status --porcelain=v2 &&
 	test_all_match git clean -f &&
 	test_all_match git status --porcelain=v2 &&
+	test_sparse_match ls &&
+	test_sparse_match ls folder1 &&
 
 	test_all_match git clean -xf &&
 	test_all_match git status --porcelain=v2 &&
+	test_sparse_match ls &&
+	test_sparse_match ls folder1 &&
 
 	test_all_match git clean -xdf &&
 	test_all_match git status --porcelain=v2 &&
+	test_sparse_match ls &&
+	test_sparse_match ls folder1 &&
 
-	test_path_is_dir sparse-checkout/folder1
+	test_sparse_match test_path_is_dir folder1
 '
 
 test_done
-- 
gitgitgadget
Previous: Derrick Stolee via GitGitGadgetNext: Derrick Stolee via GitGitGadget
Message 195 of 203 in “Sparse Index: Design, Format, Tests”
  1. 00/20 Sparse Index: Design, Format, TestsDerrick Stolee via GitGitGadget, Feb 23, 2021
  2. 01/20 sparse-index: design doc and format updateDerrick Stolee via GitGitGadget, Feb 23, 2021
  3. Elijah NewrenFeb 24, 2021
  4. Derrick StoleeFeb 25, 2021
  5. Elijah NewrenFeb 25, 2021
  6. 03/20 t1092: clean up script quotingDerrick Stolee via GitGitGadget, Feb 23, 2021
  7. 02/20 t/perf: add performance test for sparse operationsDerrick Stolee via GitGitGadget, Feb 23, 2021
  8. Elijah NewrenFeb 24, 2021
  9. Derrick StoleeMar 9, 2021
  10. 04/20 sparse-index: add guard to ensure full indexDerrick Stolee via GitGitGadget, Feb 23, 2021
  11. Elijah NewrenFeb 24, 2021
  12. 05/20 sparse-index: implement ensure_full_index()Derrick Stolee via GitGitGadget, Feb 23, 2021
  13. Elijah NewrenFeb 24, 2021
  14. 14/20 sparse-index: check index conversion happensDerrick Stolee via GitGitGadget, Feb 23, 2021
  15. 16/20 sparse-checkout: toggle sparse index from builtinDerrick Stolee via GitGitGadget, Feb 23, 2021
  16. Martin ÅgrenFeb 24, 2021
  17. Derrick StoleeMar 9, 2021
  18. Elijah NewrenMar 9, 2021
  19. Derrick StoleeMar 9, 2021
  20. Elijah NewrenMar 9, 2021
  21. Martin ÅgrenMar 14, 2021
  22. Derrick StoleeMar 15, 2021
  23. 07/20 test-read-cache: print cache entries with --tableDerrick Stolee via GitGitGadget, Feb 23, 2021
  24. Elijah NewrenFeb 25, 2021
  25. Derrick StoleeMar 9, 2021
  26. 06/20 t1092: compare sparse-checkout to sparse-indexDerrick Stolee via GitGitGadget, Feb 23, 2021
  27. Elijah NewrenFeb 25, 2021
  28. 11/20 sparse-index: convert from full to sparseDerrick Stolee via GitGitGadget, Feb 23, 2021
  29. Elijah NewrenFeb 25, 2021
  30. Derrick StoleeMar 9, 2021
  31. 10/20 sparse-checkout: hold pattern list in indexDerrick Stolee via GitGitGadget, Feb 23, 2021
  32. Elijah NewrenFeb 25, 2021
  33. 09/20 unpack-trees: ensure full indexDerrick Stolee via GitGitGadget, Feb 23, 2021
  34. 08/20 test-tool: don't force full indexDerrick Stolee via GitGitGadget, Feb 23, 2021
  35. 13/20 unpack-trees: allow sparse directoriesDerrick Stolee via GitGitGadget, Feb 23, 2021
  36. Elijah NewrenFeb 25, 2021
  37. Derrick StoleeMar 9, 2021
  38. Elijah NewrenMar 9, 2021
  39. 12/20 submodule: sparse-index should not collapse linksDerrick Stolee via GitGitGadget, Feb 23, 2021
  40. 15/20 sparse-index: create extension for compatibilityDerrick Stolee via GitGitGadget, Feb 23, 2021
  41. Elijah NewrenFeb 25, 2021
  42. Derrick StoleeMar 9, 2021
  43. 17/20 sparse-checkout: disable sparse-indexDerrick Stolee via GitGitGadget, Feb 23, 2021
  44. SZEDER GáborFeb 27, 2021
  45. Derrick StoleeMar 9, 2021
  46. Derrick StoleeMar 10, 2021
  47. 18/20 cache-tree: integrate with sparse directory entriesDerrick Stolee via GitGitGadget, Feb 23, 2021
  48. 20/20 p2000: add sparse-index reposDerrick Stolee via GitGitGadget, Feb 23, 2021
  49. 19/20 sparse-index: loose integration with cache_tree_verify()Derrick Stolee via GitGitGadget, Feb 23, 2021
  50. Elijah NewrenFeb 23, 2021
  51. Elijah NewrenFeb 26, 2021
  52. 00/20 Sparse Index: Design, Format, TestsDerrick Stolee via GitGitGadget, Mar 10, 2021
  53. 01/20 sparse-index: design doc and format updateDerrick Stolee via GitGitGadget, Mar 10, 2021
  54. Elijah NewrenMar 10, 2021
  55. 02/20 t/perf: add performance test for sparse operationsDerrick Stolee via GitGitGadget, Mar 10, 2021
  56. 05/20 sparse-index: implement ensure_full_index()Derrick Stolee via GitGitGadget, Mar 10, 2021
  57. Junio C HamanoMar 12, 2021
  58. Derrick StoleeMar 12, 2021
  59. Junio C HamanoMar 12, 2021
  60. Derrick StoleeMar 12, 2021
  61. Ævar Arnfjörð BjarmasonMar 15, 2021
  62. 04/20 sparse-index: add guard to ensure full indexDerrick Stolee via GitGitGadget, Mar 10, 2021
  63. 03/20 t1092: clean up script quotingDerrick Stolee via GitGitGadget, Mar 10, 2021
  64. 06/20 t1092: compare sparse-checkout to sparse-indexDerrick Stolee via GitGitGadget, Mar 10, 2021
  65. Elijah NewrenMar 10, 2021
  66. Derrick StoleeMar 11, 2021
  67. 07/20 test-read-cache: print cache entries with --tableDerrick Stolee via GitGitGadget, Mar 10, 2021
  68. 14/20 sparse-index: check index conversion happensDerrick Stolee via GitGitGadget, Mar 10, 2021
  69. 08/20 test-tool: don't force full indexDerrick Stolee via GitGitGadget, Mar 10, 2021
  70. 12/20 submodule: sparse-index should not collapse linksDerrick Stolee via GitGitGadget, Mar 10, 2021
  71. 13/20 unpack-trees: allow sparse directoriesDerrick Stolee via GitGitGadget, Mar 10, 2021
  72. 11/20 sparse-index: convert from full to sparseDerrick Stolee via GitGitGadget, Mar 10, 2021
  73. Elijah NewrenMar 10, 2021
  74. Derrick StoleeMar 11, 2021
  75. 09/20 unpack-trees: ensure full indexDerrick Stolee via GitGitGadget, Mar 10, 2021
  76. 15/20 sparse-index: create extension for compatibilityDerrick Stolee via GitGitGadget, Mar 10, 2021
  77. 19/20 sparse-index: loose integration with cache_tree_verify()Derrick Stolee via GitGitGadget, Mar 10, 2021
  78. 10/20 sparse-checkout: hold pattern list in indexDerrick Stolee via GitGitGadget, Mar 10, 2021
  79. 17/20 sparse-checkout: disable sparse-indexDerrick Stolee via GitGitGadget, Mar 10, 2021
  80. 18/20 cache-tree: integrate with sparse directory entriesDerrick Stolee via GitGitGadget, Mar 10, 2021
  81. 20/20 p2000: add sparse-index reposDerrick Stolee via GitGitGadget, Mar 10, 2021
  82. 16/20 sparse-checkout: toggle sparse index from builtinDerrick Stolee via GitGitGadget, Mar 10, 2021
  83. Elijah NewrenMar 11, 2021
  84. 00/20 Sparse Index: Design, Format, TestsDerrick Stolee via GitGitGadget, Mar 16, 2021
  85. 01/20 sparse-index: design doc and format updateDerrick Stolee via GitGitGadget, Mar 16, 2021
  86. Junio C HamanoMar 19, 2021
  87. Derrick StoleeMar 23, 2021
  88. Junio C HamanoMar 23, 2021
  89. Derrick StoleeMar 23, 2021
  90. 03/20 t1092: clean up script quotingDerrick Stolee via GitGitGadget, Mar 16, 2021
  91. Ævar Arnfjörð BjarmasonMar 17, 2021
  92. 02/20 t/perf: add performance test for sparse operationsDerrick Stolee via GitGitGadget, Mar 16, 2021
  93. Ævar Arnfjörð BjarmasonMar 17, 2021
  94. Derrick StoleeMar 17, 2021
  95. Ævar Arnfjörð BjarmasonMar 17, 2021
  96. Derrick StoleeMar 17, 2021
  97. 08/20 test-tool: don't force full indexDerrick Stolee via GitGitGadget, Mar 16, 2021
  98. 06/20 t1092: compare sparse-checkout to sparse-indexDerrick Stolee via GitGitGadget, Mar 16, 2021
  99. 04/20 sparse-index: add guard to ensure full indexDerrick Stolee via GitGitGadget, Mar 16, 2021
  100. 09/20 unpack-trees: ensure full indexDerrick Stolee via GitGitGadget, Mar 16, 2021
  101. 07/20 test-read-cache: print cache entries with --tableDerrick Stolee via GitGitGadget, Mar 16, 2021
  102. 1/5 ls-files: defer read_index() after parse_options() etc.Ævar Arnfjörð Bjarmason, Mar 17, 2021
  103. 2/5 ls-files: make "mode" in show_ce() loop a variableÆvar Arnfjörð Bjarmason, Mar 17, 2021
  104. Elijah NewrenMar 17, 2021
  105. Ævar Arnfjörð BjarmasonMar 24, 2021
  106. 3/5 ls-files: add and use a new --sparse optionÆvar Arnfjörð Bjarmason, Mar 17, 2021
  107. Elijah NewrenMar 17, 2021
  108. Ævar Arnfjörð BjarmasonMar 17, 2021
  109. Elijah NewrenMar 17, 2021
  110. Derrick StoleeMar 17, 2021
  111. Ævar Arnfjörð BjarmasonMar 24, 2021
  112. 4/5 test-tool read-cache: --table is redundant to ls-filesÆvar Arnfjörð Bjarmason, Mar 17, 2021
  113. 0/5 Re: [PATCH v3 07/20] test-read-cache: print cache entries with --tableÆvar Arnfjörð Bjarmason, Mar 17, 2021
  114. Elijah NewrenMar 17, 2021
  115. Derrick StoleeMar 17, 2021
  116. Elijah NewrenMar 17, 2021
  117. Derrick StoleeMar 17, 2021
  118. 5/5 test-tool: split up test-tool read-cacheÆvar Arnfjörð Bjarmason, Mar 17, 2021
  119. Ævar Arnfjörð BjarmasonMar 17, 2021
  120. 05/20 sparse-index: implement ensure_full_index()Derrick Stolee via GitGitGadget, Mar 16, 2021
  121. Ævar Arnfjörð BjarmasonMar 17, 2021
  122. 13/20 unpack-trees: allow sparse directoriesDerrick Stolee via GitGitGadget, Mar 16, 2021
  123. Ævar Arnfjörð BjarmasonMar 17, 2021
  124. 12/20 submodule: sparse-index should not collapse linksDerrick Stolee via GitGitGadget, Mar 16, 2021
  125. 10/20 sparse-checkout: hold pattern list in indexDerrick Stolee via GitGitGadget, Mar 16, 2021
  126. 11/20 sparse-index: convert from full to sparseDerrick Stolee via GitGitGadget, Mar 16, 2021
  127. Ævar Arnfjörð BjarmasonMar 17, 2021
  128. Derrick StoleeMar 17, 2021
  129. Derrick StoleeMar 18, 2021
  130. 14/20 sparse-index: check index conversion happensDerrick Stolee via GitGitGadget, Mar 16, 2021
  131. 15/20 sparse-index: create extension for compatibilityDerrick Stolee via GitGitGadget, Mar 16, 2021
  132. 17/20 sparse-checkout: disable sparse-indexDerrick Stolee via GitGitGadget, Mar 16, 2021
  133. 16/20 sparse-checkout: toggle sparse index from builtinDerrick Stolee via GitGitGadget, Mar 16, 2021
  134. 18/20 cache-tree: integrate with sparse directory entriesDerrick Stolee via GitGitGadget, Mar 16, 2021
  135. 19/20 sparse-index: loose integration with cache_tree_verify()Derrick Stolee via GitGitGadget, Mar 16, 2021
  136. 20/20 p2000: add sparse-index reposDerrick Stolee via GitGitGadget, Mar 16, 2021
  137. Derrick StoleeMar 16, 2021
  138. Elijah NewrenMar 16, 2021
  139. Junio C HamanoMar 18, 2021
  140. Derrick StoleeMar 19, 2021
  141. 00/20 Sparse Index: Design, Format, TestsDerrick Stolee via GitGitGadget, Mar 23, 2021
  142. 01/20 sparse-index: design doc and format updateDerrick Stolee via GitGitGadget, Mar 23, 2021
  143. SZEDER GáborMar 26, 2021
  144. Junio C HamanoMar 28, 2021
  145. Derrick StoleeMar 29, 2021
  146. 05/20 sparse-index: implement ensure_full_index()Derrick Stolee via GitGitGadget, Mar 23, 2021
  147. 04/20 sparse-index: add guard to ensure full indexDerrick Stolee via GitGitGadget, Mar 23, 2021
  148. 03/20 t1092: clean up script quotingDerrick Stolee via GitGitGadget, Mar 23, 2021
  149. 02/20 t/perf: add performance test for sparse operationsDerrick Stolee via GitGitGadget, Mar 23, 2021
  150. 10/20 sparse-checkout: hold pattern list in indexDerrick Stolee via GitGitGadget, Mar 23, 2021
  151. 07/20 test-read-cache: print cache entries with --tableDerrick Stolee via GitGitGadget, Mar 23, 2021
  152. Ævar Arnfjörð BjarmasonMar 24, 2021
  153. Derrick StoleeMar 24, 2021
  154. Ævar Arnfjörð BjarmasonMar 25, 2021
  155. Elijah NewrenMar 26, 2021
  156. Ævar Arnfjörð BjarmasonMar 28, 2021
  157. Derrick StoleeMar 29, 2021
  158. Junio C HamanoMar 29, 2021
  159. Derrick StoleeMar 30, 2021
  160. Ævar Arnfjörð BjarmasonMar 29, 2021
  161. Derrick StoleeMar 30, 2021
  162. Elijah NewrenMar 29, 2021
  163. 08/20 test-tool: don't force full indexDerrick Stolee via GitGitGadget, Mar 23, 2021
  164. 09/20 unpack-trees: ensure full indexDerrick Stolee via GitGitGadget, Mar 23, 2021
  165. 12/20 submodule: sparse-index should not collapse linksDerrick Stolee via GitGitGadget, Mar 23, 2021
  166. 06/20 t1092: compare sparse-checkout to sparse-indexDerrick Stolee via GitGitGadget, Mar 23, 2021
  167. 13/20 unpack-trees: allow sparse directoriesDerrick Stolee via GitGitGadget, Mar 23, 2021
  168. 11/20 sparse-index: convert from full to sparseDerrick Stolee via GitGitGadget, Mar 23, 2021
  169. 18/20 cache-tree: integrate with sparse directory entriesDerrick Stolee via GitGitGadget, Mar 23, 2021
  170. 15/20 sparse-index: create extension for compatibilityDerrick Stolee via GitGitGadget, Mar 23, 2021
  171. 16/20 sparse-checkout: toggle sparse index from builtinDerrick Stolee via GitGitGadget, Mar 23, 2021
  172. 14/20 sparse-index: check index conversion happensDerrick Stolee via GitGitGadget, Mar 23, 2021
  173. 17/20 sparse-checkout: disable sparse-indexDerrick Stolee via GitGitGadget, Mar 23, 2021
  174. 19/20 sparse-index: loose integration with cache_tree_verify()Derrick Stolee via GitGitGadget, Mar 23, 2021
  175. 20/20 p2000: add sparse-index reposDerrick Stolee via GitGitGadget, Mar 23, 2021
  176. Elijah NewrenMar 23, 2021
  177. 00/21 Sparse Index: Design, Format, TestsDerrick Stolee via GitGitGadget, Mar 30, 2021
  178. 09/21 unpack-trees: ensure full indexDerrick Stolee via GitGitGadget, Mar 30, 2021
  179. 01/21 sparse-index: design doc and format updateDerrick Stolee via GitGitGadget, Mar 30, 2021
  180. 05/21 sparse-index: implement ensure_full_index()Derrick Stolee via GitGitGadget, Mar 30, 2021
  181. 08/21 test-tool: don't force full indexDerrick Stolee via GitGitGadget, Mar 30, 2021
  182. 06/21 t1092: compare sparse-checkout to sparse-indexDerrick Stolee via GitGitGadget, Mar 30, 2021
  183. 04/21 sparse-index: add guard to ensure full indexDerrick Stolee via GitGitGadget, Mar 30, 2021
  184. 10/21 sparse-checkout: hold pattern list in indexDerrick Stolee via GitGitGadget, Mar 30, 2021
  185. 02/21 t/perf: add performance test for sparse operationsDerrick Stolee via GitGitGadget, Mar 30, 2021
  186. 13/21 submodule: sparse-index should not collapse linksDerrick Stolee via GitGitGadget, Mar 30, 2021
  187. 15/21 sparse-index: check index conversion happensDerrick Stolee via GitGitGadget, Mar 30, 2021
  188. 16/21 sparse-index: add index.sparse config optionDerrick Stolee via GitGitGadget, Mar 30, 2021
  189. 17/21 sparse-checkout: toggle sparse index from builtinDerrick Stolee via GitGitGadget, Mar 30, 2021
  190. 03/21 t1092: clean up script quotingDerrick Stolee via GitGitGadget, Mar 30, 2021
  191. 07/21 test-read-cache: print cache entries with --tableDerrick Stolee via GitGitGadget, Mar 30, 2021
  192. 11/21 sparse-index: add 'sdir' index extensionDerrick Stolee via GitGitGadget, Mar 30, 2021
  193. 20/21 sparse-index: loose integration with cache_tree_verify()Derrick Stolee via GitGitGadget, Mar 30, 2021
  194. 14/21 unpack-trees: allow sparse directoriesDerrick Stolee via GitGitGadget, Mar 30, 2021
  195. 12/21 sparse-index: convert from full to sparseDerrick Stolee via GitGitGadget, Mar 30, 2021
  196. 21/21 p2000: add sparse-index reposDerrick Stolee via GitGitGadget, Mar 30, 2021
  197. 18/21 sparse-checkout: disable sparse-indexDerrick Stolee via GitGitGadget, Mar 30, 2021
  198. 19/21 cache-tree: integrate with sparse directory entriesDerrick Stolee via GitGitGadget, Mar 30, 2021
  199. Junio C HamanoMar 30, 2021
  200. Derrick StoleeMar 30, 2021
  201. Junio C HamanoMar 30, 2021
  202. Elijah NewrenApr 1, 2021
  203. Elijah NewrenApr 1, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.