]> git.ipfire.org Git - thirdparty/git.git/commitdiff
diff: have submodule_format logic avoid additional diff headers
authorElijah Newren <newren@gmail.com>
Fri, 2 Sep 2022 03:53:28 +0000 (03:53 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 2 Sep 2022 16:22:25 +0000 (09:22 -0700)
Commit 95433eeed9 ("diff: add ability to insert additional headers for
paths", 2022-02-02) introduced the possibility of additional headers,
created in create_filepairs_for_header_only_notifications().  These are
represented by inserting additional pairs in diff_queued_diff which
always have a mode of 0 and a null_oid.  When these were added, one
code path was noted to assume that at least one of the diff_filespecs
in the pair were valid, and that codepath was corrected.

The submodule_format handling is another codepath with the same issue;
it would operate on these additional headers and attempt to display them
as submodule changes.  Prevent that by explicitly checking for "phoney"
filepairs (i.e. filepairs with both modes being 0).

Reported-by: Philippe Blain <levraiphilippeblain@gmail.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff.c
t/t4069-remerge-diff.sh

diff --git a/diff.c b/diff.c
index 974626a6211514b25af43e8f48933c6929826aa5..7f8637f300622f8a5c3d15ba7c66480b749ecb63 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -3398,6 +3398,21 @@ static void add_formatted_headers(struct strbuf *msg,
                                     line_prefix, meta, reset);
 }
 
+static int diff_filepair_is_phoney(struct diff_filespec *one,
+                                  struct diff_filespec *two)
+{
+       /*
+        * This function specifically looks for pairs injected by
+        * create_filepairs_for_header_only_notifications().  Such
+        * pairs are "phoney" in that they do not represent any
+        * content or even mode difference, but were inserted because
+        * diff_queued_diff previously had no pair associated with
+        * that path but we needed some pair to avoid losing the
+        * "remerge CONFLICT" header associated with the path.
+        */
+       return !DIFF_FILE_VALID(one) && !DIFF_FILE_VALID(two);
+}
+
 static void builtin_diff(const char *name_a,
                         const char *name_b,
                         struct diff_filespec *one,
@@ -3429,14 +3444,16 @@ static void builtin_diff(const char *name_a,
 
        if (o->submodule_format == DIFF_SUBMODULE_LOG &&
            (!one->mode || S_ISGITLINK(one->mode)) &&
-           (!two->mode || S_ISGITLINK(two->mode))) {
+           (!two->mode || S_ISGITLINK(two->mode)) &&
+           (!diff_filepair_is_phoney(one, two))) {
                show_submodule_diff_summary(o, one->path ? one->path : two->path,
                                &one->oid, &two->oid,
                                two->dirty_submodule);
                return;
        } else if (o->submodule_format == DIFF_SUBMODULE_INLINE_DIFF &&
                   (!one->mode || S_ISGITLINK(one->mode)) &&
-                  (!two->mode || S_ISGITLINK(two->mode))) {
+                  (!two->mode || S_ISGITLINK(two->mode)) &&
+                  (!diff_filepair_is_phoney(one, two))) {
                show_submodule_inline_diff(o, one->path ? one->path : two->path,
                                &one->oid, &two->oid,
                                two->dirty_submodule);
@@ -3456,12 +3473,12 @@ static void builtin_diff(const char *name_a,
        b_two = quote_two(b_prefix, name_b + (*name_b == '/'));
        lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
        lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
-       if (!DIFF_FILE_VALID(one) && !DIFF_FILE_VALID(two)) {
+       if (diff_filepair_is_phoney(one, two)) {
                /*
-                * We should only reach this point for pairs from
+                * We should only reach this point for pairs generated from
                 * create_filepairs_for_header_only_notifications().  For
-                * these, we should avoid the "/dev/null" special casing
-                * above, meaning we avoid showing such pairs as either
+                * these, we want to avoid the "/dev/null" special casing
+                * above, because we do not want such pairs shown as either
                 * "new file" or "deleted file" below.
                 */
                lbl[0] = a_one;
index 9e7cac68b1ce3735237661e14e6c2c8c84cf4665..e3e6fbd97b215cb1823818c1b791eb1bce23d01e 100755 (executable)
@@ -185,6 +185,14 @@ test_expect_success 'remerge-diff w/ diff-filter=U: all conflict headers, no dif
        test_cmp expect actual
 '
 
+test_expect_success 'submodule formatting ignores additional headers' '
+       # Reuses "expect" from last testcase
+
+       git show --oneline --remerge-diff --diff-filter=U --submodule=log >tmp &&
+       sed -e "s/[0-9a-f]\{7,\}/HASH/g" tmp >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'remerge-diff w/ diff-filter=R: relevant file + conflict header' '
        git log -1 --oneline resolution >tmp &&
        cat <<-EOF >>tmp &&