diff-tree -c raw output
authorLinus Torvalds <torvalds@osdl.org>
Thu, 9 Feb 2006 18:30:28 +0000 (10:30 -0800)
committerJunio C Hamano <junkio@cox.net>
Thu, 9 Feb 2006 19:46:05 +0000 (11:46 -0800)
NOTE! This makes "-c" be the default, which effectively means that merges
are never ignored any more, and "-m" is a no-op. So it changes semantics.

I would also like to make "--cc" the default if you do patches, but didn't
actually do that.

The raw output format is not wonderfully pretty, but it's distinguishable
from a "normal patch" in that a normal patch with just one parent has just
one colon at the beginning, while a multi-parent raw diff has <n> colons
for <n> parents.

So now, in the kernel, when you do

git-diff-tree cce0cac125623f9b68f25dd1350f6d616220a8dd

(to see the manual ARM merge that had a conflict in arch/arm/Kconfig), you
get

cce0cac125623f9b68f25dd1350f6d616220a8dd
::100644 100644 100644 4a63a8e2e45247a11c068c6ed66c6e7aba29ddd9 77eee38762d69d3de95ae45dd9278df9b8225e2c 2f61726d2f4b636f6e66696700dbf71a59dad287       arch/arm/Kconfig

ie you see two colons (two parents), then three modes (parent modes
followed by result mode), then three sha1s (parent sha1s followed by
result sha1).

Which is pretty close to the normal raw diff output.

Cool/stupid exercise:

$ git-whatchanged | grep '^::' | cut -f2- | sort |
  uniq -c | sort -n | less -S

will show which files have needed the most file-level merge conflict
resolution. Useful? Probably not. But kind of interesting.

For the kernel, it's

     ....
     10 arch/ia64/Kconfig
     11 drivers/scsi/Kconfig
     12 drivers/net/Makefile
     17 include/linux/libata.h
     18 include/linux/pci_ids.h
     23 drivers/net/Kconfig
     24 drivers/scsi/libata-scsi.c
     28 drivers/scsi/libata-core.c
     43 MAINTAINERS

Signed-off-by: Junio C Hamano <junkio@cox.net>
combine-diff.c
diff-tree.c
diff.h

index 6a9f3683c51879ab147f9a3f37c38fc1e8a46b47..15f369e8e689fa320ced538987564d708a934642 100644 (file)
@@ -776,8 +776,52 @@ int show_combined_diff(struct combine_diff_path *elem, int num_parent,
        return shown_header;
 }
 
-int diff_tree_combined_merge(const unsigned char *sha1,
-                            const char *header, int dense)
+#define COLONS "::::::::::::::::::::::::::::::::"
+
+static void show_raw_diff(struct combine_diff_path *p, int num_parent, const char *header, struct diff_options *opt)
+{
+       int i, offset, mod_type = 'A';
+       const char *prefix;
+       int line_termination, inter_name_termination;
+
+       line_termination = opt->line_termination;
+       inter_name_termination = '\t';
+       if (!line_termination)
+               inter_name_termination = 0;
+
+       if (header)
+               puts(header);
+       offset = strlen(COLONS) - num_parent;
+       if (offset < 0)
+               offset = 0;
+       prefix = COLONS + offset;
+
+       /* Show the modes */
+       for (i = 0; i < num_parent; i++) {
+               int mode = p->parent[i].mode;
+               if (mode)
+                       mod_type = 'M';
+               printf("%s%06o", prefix, mode);
+               prefix = " ";
+       }
+       printf("%s%06o", prefix, p->mode);
+       if (!p->mode)
+               mod_type = 'D';
+
+       /* Show sha1's */
+       for (i = 0; i < num_parent; i++) {
+               printf("%s%s", prefix, diff_unique_abbrev(p->parent[i].sha1, opt->abbrev));
+               prefix = " ";
+       }
+       printf("%s%s", prefix, diff_unique_abbrev(p->sha1, opt->abbrev));
+
+       /* Modification type, terminations, filename */
+       printf(" %c%c%s%c", mod_type, inter_name_termination, p->path, line_termination);
+}
+
+const char *diff_tree_combined_merge(const unsigned char *sha1,
+                            const char *header, int dense,
+                            struct diff_options *opt)
 {
        struct commit *commit = lookup_commit(sha1);
        struct diff_options diffopts;
@@ -815,6 +859,11 @@ int diff_tree_combined_merge(const unsigned char *sha1,
                for (p = paths; p; p = p->next) {
                        if (!p->len)
                                continue;
+                       if (opt->output_format == DIFF_FORMAT_RAW) {
+                               show_raw_diff(p, num_parent, header, opt);
+                               header = NULL;
+                               continue;
+                       }
                        if (show_combined_diff(p, num_parent, dense, header))
                                header = NULL;
                }
@@ -826,5 +875,5 @@ int diff_tree_combined_merge(const unsigned char *sha1,
                paths = paths->next;
                free(tmp);
        }
-       return 0;
+       return header;
 }
index 71483233481eca8b0a88bfa02beb5c1bc2396bb7..df6fd97fca04369726e92b54ab54c59f808b4742 100644 (file)
@@ -6,7 +6,7 @@ static int show_root_diff = 0;
 static int no_commit_id = 0;
 static int verbose_header = 0;
 static int ignore_merges = 1;
-static int combine_merges = 0;
+static int combine_merges = 1;
 static int dense_combined_merges = 0;
 static int read_stdin = 0;
 static int always_show_header = 0;
@@ -117,8 +117,12 @@ static int diff_tree_commit(struct commit *commit)
                        return 0;
                else if (combine_merges) {
                        header = generate_header(sha1, sha1, commit);
-                       return diff_tree_combined_merge(sha1, header,
-                                                       dense_combined_merges);
+                       header = diff_tree_combined_merge(sha1, header,
+                                                       dense_combined_merges,
+                                                       &diff_options);
+                       if (!header && verbose_header)
+                               header_prefix = "\ndiff-tree ";
+                       return 0;
                }
        }
 
@@ -285,10 +289,12 @@ int main(int argc, const char **argv)
                usage(diff_tree_usage);
        }
 
-       if (combine_merges) {
-               diff_options.output_format = DIFF_FORMAT_PATCH;
+       if (combine_merges)
                ignore_merges = 0;
-       }
+
+       /* We can only do dense combined merges with diff output */
+       if (dense_combined_merges)
+               diff_options.output_format = DIFF_FORMAT_PATCH;
 
        if (diff_options.output_format == DIFF_FORMAT_PATCH)
                diff_options.recursive = 1;
diff --git a/diff.h b/diff.h
index 5c5e7fa91fc943e56759da556be733694184ee88..9088519af0dd29df4cefb1183f51e5970489c98e 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -74,10 +74,10 @@ struct combine_diff_path {
        (sizeof(struct combine_diff_path) + \
         sizeof(struct combine_diff_parent) * (n) + (l) + 1)
 
-int show_combined_diff(struct combine_diff_path *elem, int num_parent,
-                      int dense, const char *header);
+extern int show_combined_diff(struct combine_diff_path *elem, int num_parent,
+                             int dense, const char *header);
 
-extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int);
+extern const char *diff_tree_combined_merge(const unsigned char *sha1, const char *, int, struct diff_options *opt);
 
 extern void diff_addremove(struct diff_options *,
                           int addremove,