On Tue, Jul 29, 2014 at 08:00:56AM -0400, Jeff King wrote:

> The implementation just cuts the number of parents down to 1, but
> otherwise runs through the same combined-diff code.  The resulting
> pairwise combined-diff differs from a normal diff in a few ways:
> 
>   1. The header line is still "diff --combined" (or "--cc") instead of
>      "diff --git", and it mentions the filename only once.
> 
>   2. The index lines do not contain the file mode; for combined diffs,
>      we generate a separate mode line (but only when it has something
>      interesting to show).
> 
>   3. The hunk header for a single-line change says "-1" in the regular
>      code path, but "-1,1" in the combined code path.
> 
> Is there any value in keeping this as a pseudo-combined diff (i.e., with
> the combined header, but only a single parent)? It should not be too
> hard to just punt to the regular builtin_diff code path when
> "num_parents == 1".

It's not too hard; mostly we just have to massage the data into a
diff_filepair. Patch is below (I'd squash it, and the further commits
will need fixups to their tests, too).

---
 combine-diff.c           | 32 +++++++++++++++++++++++++++++---
 diff.c                   |  2 +-
 diff.h                   |  2 ++
 t/t4038-diff-combined.sh | 18 +++++++++---------
 4 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/combine-diff.c b/combine-diff.c
index 60e54a7..0588c86 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -965,6 +965,28 @@ static int simplify_parents(struct combine_diff_path *p, 
int nr)
        return 1;
 }
 
+static void show_single_parent_patch(struct combine_diff_path *elem,
+                                    int working_tree_file,
+                                    struct rev_info *rev)
+{
+       struct diff_filepair pair;
+
+       memset(&pair, 0, sizeof(pair));
+       pair.one = alloc_filespec(elem->path);
+       pair.two = alloc_filespec(elem->path);
+       pair.status = elem->parent[0].status;
+
+       fill_filespec(pair.one, elem->parent[0].sha1, 1, elem->parent[0].mode);
+       if (working_tree_file)
+               fill_filespec(pair.two, null_sha1, 0, elem->mode);
+       else
+               fill_filespec(pair.two, elem->sha1, 1, elem->mode);
+
+       run_diff(&pair, &rev->diffopt);
+       free_filespec(pair.one);
+       free_filespec(pair.two);
+}
+
 static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
                            int dense, int working_tree_file,
                            struct rev_info *rev)
@@ -982,6 +1004,13 @@ static void show_patch_diff(struct combine_diff_path 
*elem, int num_parent,
        int is_binary;
        const char *line_prefix = diff_line_prefix(opt);
 
+       if (rev->simplify_combined_diff)
+               num_parent = simplify_parents(elem, num_parent);
+       if (num_parent == 1) {
+               show_single_parent_patch(elem, working_tree_file, rev);
+               return;
+       }
+
        context = opt->context;
        userdiff = userdiff_find_by_path(elem->path);
        if (!userdiff)
@@ -989,9 +1018,6 @@ static void show_patch_diff(struct combine_diff_path 
*elem, int num_parent,
        if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV))
                textconv = userdiff_get_textconv(userdiff);
 
-       if (rev->simplify_combined_diff)
-               num_parent = simplify_parents(elem, num_parent);
-
        /* Read the result of merge first */
        if (!working_tree_file)
                result = grab_blob(elem->sha1, elem->mode, &result_size,
diff --git a/diff.c b/diff.c
index 867f034..558a520 100644
--- a/diff.c
+++ b/diff.c
@@ -3089,7 +3089,7 @@ static void strip_prefix(int prefix_length, const char 
**namep, const char **oth
        }
 }
 
-static void run_diff(struct diff_filepair *p, struct diff_options *o)
+void run_diff(struct diff_filepair *p, struct diff_options *o)
 {
        const char *pgm = external_diff();
        struct strbuf msg;
diff --git a/diff.h b/diff.h
index b4a624d..a669be0 100644
--- a/diff.h
+++ b/diff.h
@@ -356,4 +356,6 @@ extern int print_stat_summary(FILE *fp, int files,
                              int insertions, int deletions);
 extern void setup_diff_pager(struct diff_options *);
 
+extern void run_diff(struct diff_filepair *p, struct diff_options *o);
+
 #endif /* DIFF_H */
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index d522474..29cdb45 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -455,11 +455,11 @@ test_expect_success 'simplify combined --patch' '
        merge=$(mkcommit new new $side1 $side2) &&
        cat >expect <<-\EOF &&
 
-       diff --combined one
-       index df967b9..3e75765
+       diff --git a/one b/one
+       index df967b9..3e75765 100644
        --- a/one
        +++ b/one
-       @@ -1,1 +1,1 @@
+       @@ -1 +1 @@
        -base
        +new
        diff --combined two
@@ -485,11 +485,11 @@ test_expect_success 'do not simplify unless all parents 
are identical' '
        merge=$(mkcommit new new $side1 $side2 $side3) &&
        cat >expect <<-\EOF &&
 
-       diff --combined one
-       index df967b9..3e75765
+       diff --git a/one b/one
+       index df967b9..3e75765 100644
        --- a/one
        +++ b/one
-       @@ -1,1 +1,1 @@
+       @@ -1 +1 @@
        -base
        +new
        diff --combined two
@@ -513,11 +513,11 @@ test_expect_success 'do not simplify away mode changes' '
        merge=$(mkcommit new new $side1 $side2) &&
        cat >expect <<-\EOF &&
 
-       diff --combined one
-       index df967b9..3e75765
+       diff --git a/one b/one
+       index df967b9..3e75765 100644
        --- a/one
        +++ b/one
-       @@ -1,1 +1,1 @@
+       @@ -1 +1 @@
        -base
        +new
        diff --combined two
-- 
2.1.0.rc0.286.g5c67d74

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to