]> git.ipfire.org Git - thirdparty/git.git/commitdiff
diff-lib: handle index diffs with sparse dirs
authorDerrick Stolee <dstolee@microsoft.com>
Wed, 14 Jul 2021 13:12:35 +0000 (13:12 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 14 Jul 2021 20:42:49 +0000 (13:42 -0700)
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.

Use diff_tree_oid() appropriately to compute the diff.

Reviewed-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff-lib.c

index c2ac9250fe92c21f1678ffd70e7a652c83126007..f9eadc4fc1a64b57fd0b506822c6396219763c92 100644 (file)
@@ -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;
 
+       if (new_file && S_ISSPARSEDIR(new_file->ce_mode)) {
+               diff_tree_oid(NULL, &new_file->oid, new_file->name, &revs->diffopt);
+               return;
+       }
+
        /*
         * New file in the index: it might actually be different in
         * the working tree.
@@ -347,6 +352,20 @@ static int show_modified(struct rev_info *revs,
        unsigned dirty_submodule = 0;
        struct index_state *istate = revs->diffopt.repo->index;
 
+       assert(S_ISSPARSEDIR(old_entry->ce_mode) ==
+              S_ISSPARSEDIR(new_entry->ce_mode));
+
+       /*
+        * If both are sparse directory entries, then expand the
+        * modifications to the file level. If only one was a sparse
+        * directory, then they appear as an add and delete instead of
+        * a modification.
+        */
+       if (S_ISSPARSEDIR(new_entry->ce_mode)) {
+               diff_tree_oid(&old_entry->oid, &new_entry->oid, new_entry->name, &revs->diffopt);
+               return 0;
+       }
+
        if (get_stat_data(istate, new_entry, &oid, &mode, cached, match_missing,
                          &dirty_submodule, &revs->diffopt) < 0) {
                if (report_missing)