--- v3
+++ v7
@@ -1,113 +1,56 @@
From: Derrick Stolee <dstolee@microsoft.com>
-If we need to expand a sparse-index into a full one, then the FS Monitor
-bitmap is going to be incorrect. Ensure that we start fresh at such an
-event.
+While comparing an index to a tree, we may see a sparse directory entry.
+In this case, we should compare that portion of the tree to the tree
+represented by that entry. This could include a new tree which needs to
+be expanded to a full list of added files. It could also include an
+existing tree, in which case all of the changes inside are important to
+describe, including the modifications, additions, and deletions. Note
+that the case where the tree has a path and the index does not remains
+identical to before: the lack of a cache entry is the same with a sparse
+index.
-While this is currently a performance drawback, the eventual hope of the
-sparse-index feature is that these expansions will be rare and hence we
-will be able to keep the FS Monitor data accurate across multiple Git
-commands.
-
-These tests are added to demonstrate that the behavior is the same
-across a full index and a sparse index, but also that file modifications
-to a tracked directory outside of the sparse cone will trigger
-ensure_full_index().
+Use diff_tree_oid() appropriately to compute the diff.
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
---
- sparse-index.c | 7 ++++++
- t/t7519-status-fsmonitor.sh | 48 +++++++++++++++++++++++++++++++++++++
- 2 files changed, 55 insertions(+)
+ diff-lib.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
-diff --git a/sparse-index.c b/sparse-index.c
-index b2b3fbd75050..32ba0d17ef7c 100644
---- a/sparse-index.c
-+++ b/sparse-index.c
-@@ -195,6 +195,10 @@ int convert_to_sparse(struct index_state *istate)
- cache_tree_free(&istate->cache_tree);
- cache_tree_update(istate, 0);
+diff --git a/diff-lib.c b/diff-lib.c
+index c2ac9250fe9..3f32f038371 100644
+--- a/diff-lib.c
++++ b/diff-lib.c
+@@ -325,6 +325,11 @@ static void show_new_file(struct rev_info *revs,
+ unsigned dirty_submodule = 0;
+ struct index_state *istate = revs->diffopt.repo->index;
-+ istate->fsmonitor_has_run_once = 0;
-+ FREE_AND_NULL(istate->fsmonitor_dirty);
-+ FREE_AND_NULL(istate->fsmonitor_last_update);
++ if (new_file && S_ISSPARSEDIR(new_file->ce_mode)) {
++ diff_tree_oid(NULL, &new_file->oid, new_file->name, &revs->diffopt);
++ return;
++ }
+
- istate->sparse_index = 1;
- trace2_region_leave("index", "convert_to_sparse", istate->repo);
- return 0;
-@@ -291,6 +295,9 @@ void ensure_full_index(struct index_state *istate)
- istate->cache = full->cache;
- istate->cache_nr = full->cache_nr;
- istate->cache_alloc = full->cache_alloc;
-+ istate->fsmonitor_has_run_once = 0;
-+ FREE_AND_NULL(istate->fsmonitor_dirty);
-+ FREE_AND_NULL(istate->fsmonitor_last_update);
+ /*
+ * New file in the index: it might actually be different in
+ * the working tree.
+@@ -347,6 +352,17 @@ static int show_modified(struct rev_info *revs,
+ unsigned dirty_submodule = 0;
+ struct index_state *istate = revs->diffopt.repo->index;
- strbuf_release(&base);
- free(full);
-diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
-index 45d025f96010..f70fe961902e 100755
---- a/t/t7519-status-fsmonitor.sh
-+++ b/t/t7519-status-fsmonitor.sh
-@@ -73,6 +73,7 @@ test_expect_success 'setup' '
- expect*
- actual*
- marker*
-+ trace2*
- EOF
- '
-
-@@ -383,4 +384,51 @@ test_expect_success 'status succeeds after staging/unstaging' '
- )
- '
-
-+# Usage:
-+# check_sparse_index_behavior [!]
-+# If "!" is supplied, then we verify that we do not call ensure_full_index
-+# during a call to 'git status'. Otherwise, we verify that we _do_ call it.
-+check_sparse_index_behavior () {
-+ git status --porcelain=v2 >expect &&
-+ git sparse-checkout init --cone --sparse-index &&
-+ git sparse-checkout set dir1 dir2 &&
-+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" GIT_TRACE2_EVENT_NESTING=10 \
-+ git status --porcelain=v2 >actual &&
-+ test_region $1 index ensure_full_index trace2.txt &&
-+ test_cmp expect actual &&
-+ rm trace2.txt &&
-+ git sparse-checkout disable
-+}
++ /*
++ * If both are sparse directory entries, then expand the
++ * modifications to the file level.
++ */
++ if (old_entry && new_entry &&
++ S_ISSPARSEDIR(old_entry->ce_mode) &&
++ S_ISSPARSEDIR(new_entry->ce_mode)) {
++ diff_tree_oid(&old_entry->oid, &new_entry->oid, new_entry->name, &revs->diffopt);
++ return 0;
++ }
+
-+test_expect_success 'status succeeds with sparse index' '
-+ git reset --hard &&
-+
-+ test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-all" &&
-+ check_sparse_index_behavior ! &&
-+
-+ write_script .git/hooks/fsmonitor-test<<-\EOF &&
-+ printf "last_update_token\0"
-+ EOF
-+ git config core.fsmonitor .git/hooks/fsmonitor-test &&
-+ check_sparse_index_behavior ! &&
-+
-+ write_script .git/hooks/fsmonitor-test<<-\EOF &&
-+ printf "last_update_token\0"
-+ printf "dir1/modified\0"
-+ EOF
-+ check_sparse_index_behavior ! &&
-+
-+ cp -r dir1 dir1a &&
-+ git add dir1a &&
-+ git commit -m "add dir1a" &&
-+
-+ # This one modifies outside the sparse-checkout definition
-+ # and hence we expect to expand the sparse-index.
-+ write_script .git/hooks/fsmonitor-test<<-\EOF &&
-+ printf "last_update_token\0"
-+ printf "dir1a/modified\0"
-+ EOF
-+ check_sparse_index_behavior
-+'
-+
- test_done
+ if (get_stat_data(istate, new_entry, &oid, &mode, cached, match_missing,
+ &dirty_submodule, &revs->diffopt) < 0) {
+ if (report_missing)
--
gitgitgadget
+