Merge branch 'jc/diff-test' into th/diff
authorJunio C Hamano <junkio@cox.net>
Tue, 27 Jun 2006 18:05:02 +0000 (11:05 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 27 Jun 2006 18:05:02 +0000 (11:05 -0700)
* jc/diff-test:
t4013: add more tests around -c and --cc
t4013: add tests for diff/log family output options.

12 files changed:
builtin-diff-files.c
builtin-diff-index.c
builtin-diff-stages.c
builtin-diff-tree.c
builtin-diff.c
builtin-log.c
combine-diff.c
diff.c
diff.h
log-tree.c
log-tree.h
revision.c
index 5afc1d7208f8a13b7363be2127cad3b43baa95dd..a655eea91ed5ac38af578e47fe6747a1b6fb968c 100644 (file)
@@ -36,6 +36,9 @@ int cmd_diff_files(int argc, const char **argv, char **envp)
                        usage(diff_files_usage);
                argv++; argc--;
        }
+       if (!rev.diffopt.output_format)
+               rev.diffopt.output_format = DIFF_FORMAT_RAW;
+
        /*
         * Make sure there are NO revision (i.e. pending object) parameter,
         * rev.max_count is reasonable (0 <= n <= 3),
index c42ef9a7a76e7d8f6bc25d593865b9343d4e74b5..b37c9e8ccb30686810ecfdb898ad360b40ca0723 100644 (file)
@@ -28,6 +28,9 @@ int cmd_diff_index(int argc, const char **argv, char **envp)
                else
                        usage(diff_cache_usage);
        }
+       if (!rev.diffopt.output_format)
+               rev.diffopt.output_format = DIFF_FORMAT_RAW;
+
        /*
         * Make sure there is one revision (i.e. pending object),
         * and there is no revision filtering parameters.
index 7c157ca889eaf85b38be2764fca83814bb83a3f4..30931fe0498753ed3a7f68be064027391a82e677 100644 (file)
@@ -85,6 +85,9 @@ int cmd_diff_stages(int ac, const char **av, char **envp)
                ac--; av++;
        }
 
+       if (!diff_options.output_format)
+               diff_options.output_format = DIFF_FORMAT_RAW;
+
        if (ac < 3 ||
            sscanf(av[1], "%d", &stage1) != 1 ||
            ! (0 <= stage1 && stage1 <= 3) ||
index 3409a39a9f73f9ed67547f5cc79619c1e402f47b..1e66fcac2186d0946b5d15a5825eb400b2e67003 100644 (file)
@@ -72,6 +72,7 @@ int cmd_diff_tree(int argc, const char **argv, char **envp)
        init_revisions(opt);
        opt->abbrev = 0;
        opt->diff = 1;
+       opt->diffopt.msg_sep = "---\n";
        argc = setup_revisions(argc, argv, opt, NULL);
 
        while (--argc > 0) {
@@ -84,6 +85,9 @@ int cmd_diff_tree(int argc, const char **argv, char **envp)
                usage(diff_tree_usage);
        }
 
+       if (!opt->diffopt.output_format)
+               opt->diffopt.output_format = DIFF_FORMAT_RAW;
+
        /*
         * NOTE! We expect "a ^b" to be equal to "a..b", so we
         * reverse the order of the objects if the second one
index 99a2f766055d6c8c3231e38bd369169d3c742782..47e0a37e212d9a7085714d1b5d6d8f2ffda8d5a6 100644 (file)
@@ -39,8 +39,6 @@ static int builtin_diff_files(struct rev_info *revs,
                        revs->max_count = 3;
                else if (!strcmp(arg, "-q"))
                        silent = 1;
-               else if (!strcmp(arg, "--raw"))
-                       revs->diffopt.output_format = DIFF_FORMAT_RAW;
                else
                        usage(builtin_diff_usage);
                argv++; argc--;
@@ -56,7 +54,7 @@ static int builtin_diff_files(struct rev_info *revs,
            3 < revs->max_count)
                usage(builtin_diff_usage);
        if (revs->max_count < 0 &&
-           (revs->diffopt.output_format == DIFF_FORMAT_PATCH))
+           (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
                revs->combine_merges = revs->dense_combined_merges = 1;
        /*
         * Backward compatibility wart - "diff-files -s" used to
@@ -107,14 +105,9 @@ static int builtin_diff_b_f(struct rev_info *revs,
        /* Blob vs file in the working tree*/
        struct stat st;
 
-       while (1 < argc) {
-               const char *arg = argv[1];
-               if (!strcmp(arg, "--raw"))
-                       revs->diffopt.output_format = DIFF_FORMAT_RAW;
-               else
-                       usage(builtin_diff_usage);
-               argv++; argc--;
-       }
+       if (argc > 1)
+               usage(builtin_diff_usage);
+
        if (lstat(path, &st))
                die("'%s': %s", path, strerror(errno));
        if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
@@ -137,14 +130,9 @@ static int builtin_diff_blobs(struct rev_info *revs,
         */
        unsigned mode = canon_mode(S_IFREG | 0644);
 
-       while (1 < argc) {
-               const char *arg = argv[1];
-               if (!strcmp(arg, "--raw"))
-                       revs->diffopt.output_format = DIFF_FORMAT_RAW;
-               else
-                       usage(builtin_diff_usage);
-               argv++; argc--;
-       }
+       if (argc > 1)
+               usage(builtin_diff_usage);
+
        stuff_change(&revs->diffopt,
                     mode, mode,
                     blob[1].sha1, blob[0].sha1,
@@ -162,8 +150,6 @@ static int builtin_diff_index(struct rev_info *revs,
                const char *arg = argv[1];
                if (!strcmp(arg, "--cached"))
                        cached = 1;
-               else if (!strcmp(arg, "--raw"))
-                       revs->diffopt.output_format = DIFF_FORMAT_RAW;
                else
                        usage(builtin_diff_usage);
                argv++; argc--;
@@ -185,14 +171,9 @@ static int builtin_diff_tree(struct rev_info *revs,
 {
        const unsigned char *(sha1[2]);
        int swap = 0;
-       while (1 < argc) {
-               const char *arg = argv[1];
-               if (!strcmp(arg, "--raw"))
-                       revs->diffopt.output_format = DIFF_FORMAT_RAW;
-               else
-                       usage(builtin_diff_usage);
-               argv++; argc--;
-       }
+
+       if (argc > 1)
+               usage(builtin_diff_usage);
 
        /* We saw two trees, ent[0] and ent[1].
         * if ent[1] is unintesting, they are swapped
@@ -214,14 +195,9 @@ static int builtin_diff_combined(struct rev_info *revs,
        const unsigned char (*parent)[20];
        int i;
 
-       while (1 < argc) {
-               const char *arg = argv[1];
-               if (!strcmp(arg, "--raw"))
-                       revs->diffopt.output_format = DIFF_FORMAT_RAW;
-               else
-                       usage(builtin_diff_usage);
-               argv++; argc--;
-       }
+       if (argc > 1)
+               usage(builtin_diff_usage);
+
        if (!revs->dense_combined_merges && !revs->combine_merges)
                revs->dense_combined_merges = revs->combine_merges = 1;
        parent = xmalloc(ents * sizeof(*parent));
@@ -276,9 +252,11 @@ int cmd_diff(int argc, const char **argv, char **envp)
 
        git_config(git_diff_config);
        init_revisions(&rev);
-       rev.diffopt.output_format = DIFF_FORMAT_PATCH;
 
        argc = setup_revisions(argc, argv, &rev, NULL);
+       if (!rev.diffopt.output_format)
+               rev.diffopt.output_format = DIFF_FORMAT_PATCH;
+
        /* Do we have --cached and not have a pending object, then
         * default to HEAD by hand.  Eek.
         */
index 44d2d136f585a74e462556a4f756c7a297cadd51..debddb97a09eba5ba926087f76ebd6da0e258e86 100644 (file)
 /* this is in builtin-diff.c */
 void add_head(struct rev_info *revs);
 
-static int cmd_log_wc(int argc, const char **argv, char **envp,
+static void cmd_log_init(int argc, const char **argv, char **envp,
                      struct rev_info *rev)
 {
-       struct commit *commit;
-
        rev->abbrev = DEFAULT_ABBREV;
        rev->commit_format = CMIT_FMT_DEFAULT;
        rev->verbose_header = 1;
        argc = setup_revisions(argc, argv, rev, "HEAD");
-       if (rev->always_show_header) {
-               if (rev->diffopt.pickaxe || rev->diffopt.filter) {
-                       rev->always_show_header = 0;
-                       if (rev->diffopt.output_format == DIFF_FORMAT_RAW)
-                               rev->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT;
-               }
-       }
-
+       if (rev->diffopt.pickaxe || rev->diffopt.filter)
+               rev->always_show_header = 0;
        if (argc > 1)
                die("unrecognized argument: %s", argv[1]);
+}
+
+static int cmd_log_walk(struct rev_info *rev)
+{
+       struct commit *commit;
 
        prepare_revision_walk(rev);
        setup_pager();
@@ -54,7 +51,10 @@ int cmd_whatchanged(int argc, const char **argv, char **envp)
        rev.diff = 1;
        rev.diffopt.recursive = 1;
        rev.simplify_history = 0;
-       return cmd_log_wc(argc, argv, envp, &rev);
+       cmd_log_init(argc, argv, envp, &rev);
+       if (!rev.diffopt.output_format)
+               rev.diffopt.output_format = DIFF_FORMAT_RAW;
+       return cmd_log_walk(&rev);
 }
 
 int cmd_show(int argc, const char **argv, char **envp)
@@ -69,7 +69,8 @@ int cmd_show(int argc, const char **argv, char **envp)
        rev.always_show_header = 1;
        rev.ignore_merges = 0;
        rev.no_walk = 1;
-       return cmd_log_wc(argc, argv, envp, &rev);
+       cmd_log_init(argc, argv, envp, &rev);
+       return cmd_log_walk(&rev);
 }
 
 int cmd_log(int argc, const char **argv, char **envp)
@@ -78,8 +79,8 @@ int cmd_log(int argc, const char **argv, char **envp)
 
        init_revisions(&rev);
        rev.always_show_header = 1;
-       rev.diffopt.recursive = 1;
-       return cmd_log_wc(argc, argv, envp, &rev);
+       cmd_log_init(argc, argv, envp, &rev);
+       return cmd_log_walk(&rev);
 }
 
 static int istitlechar(char c)
@@ -176,11 +177,9 @@ int cmd_format_patch(int argc, const char **argv, char **envp)
        rev.commit_format = CMIT_FMT_EMAIL;
        rev.verbose_header = 1;
        rev.diff = 1;
-       rev.diffopt.with_raw = 0;
-       rev.diffopt.with_stat = 1;
        rev.combine_merges = 0;
        rev.ignore_merges = 1;
-       rev.diffopt.output_format = DIFF_FORMAT_PATCH;
+       rev.diffopt.msg_sep = "---\n";
 
        git_config(git_format_config);
        rev.extra_headers = extra_headers;
@@ -249,6 +248,9 @@ int cmd_format_patch(int argc, const char **argv, char **envp)
        if (argc > 1)
                die ("unrecognized argument: %s", argv[1]);
 
+       if (!rev.diffopt.output_format)
+               rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH;
+
        if (output_directory) {
                if (use_stdout)
                        die("standard output, or directory, which one?");
index 64b20cce2427fcf0cd9565f5e24efce78abb0088..39fb10c1457c96fd86dd25443b49a4a7cafa0134 100644 (file)
@@ -701,7 +701,7 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
                const char *abb;
 
                if (rev->loginfo)
-                       show_log(rev, rev->loginfo, "\n");
+                       show_log(rev, opt->msg_sep);
                dump_quoted_path(dense ? "diff --cc " : "diff --combined ", elem->path);
                printf("index ");
                for (i = 0; i < num_parent; i++) {
@@ -769,9 +769,9 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
                inter_name_termination = 0;
 
        if (rev->loginfo)
-               show_log(rev, rev->loginfo, "\n");
+               show_log(rev, opt->msg_sep);
 
-       if (opt->output_format == DIFF_FORMAT_RAW) {
+       if (opt->output_format & DIFF_FORMAT_RAW) {
                offset = strlen(COLONS) - num_parent;
                if (offset < 0)
                        offset = 0;
@@ -791,8 +791,7 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
                printf(" %s ", diff_unique_abbrev(p->sha1, opt->abbrev));
        }
 
-       if (opt->output_format == DIFF_FORMAT_RAW ||
-           opt->output_format == DIFF_FORMAT_NAME_STATUS) {
+       if (opt->output_format & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS)) {
                for (i = 0; i < num_parent; i++)
                        putchar(p->parent[i].status);
                putchar(inter_name_termination);
@@ -818,17 +817,12 @@ void show_combined_diff(struct combine_diff_path *p,
        struct diff_options *opt = &rev->diffopt;
        if (!p->len)
                return;
-       switch (opt->output_format) {
-       case DIFF_FORMAT_RAW:
-       case DIFF_FORMAT_NAME_STATUS:
-       case DIFF_FORMAT_NAME:
+       if (opt->output_format & (DIFF_FORMAT_RAW |
+                                 DIFF_FORMAT_NAME |
+                                 DIFF_FORMAT_NAME_STATUS)) {
                show_raw_diff(p, num_parent, rev);
-               return;
-       case DIFF_FORMAT_PATCH:
+       } else if (opt->output_format & DIFF_FORMAT_PATCH) {
                show_patch_diff(p, num_parent, dense, rev);
-               return;
-       default:
-               return;
        }
 }
 
@@ -842,13 +836,9 @@ void diff_tree_combined(const unsigned char *sha1,
        struct diff_options diffopts;
        struct combine_diff_path *p, *paths = NULL;
        int i, num_paths;
-       int do_diffstat;
 
-       do_diffstat = (opt->output_format == DIFF_FORMAT_DIFFSTAT ||
-                      opt->with_stat);
        diffopts = *opt;
-       diffopts.with_raw = 0;
-       diffopts.with_stat = 0;
+       diffopts.output_format &= ~(DIFF_FORMAT_RAW | DIFF_FORMAT_DIFFSTAT);
        diffopts.recursive = 1;
 
        /* find set of paths that everybody touches */
@@ -856,19 +846,19 @@ void diff_tree_combined(const unsigned char *sha1,
                /* show stat against the first parent even
                 * when doing combined diff.
                 */
-               if (i == 0 && do_diffstat)
-                       diffopts.output_format = DIFF_FORMAT_DIFFSTAT;
+               if (i == 0 && opt->output_format & DIFF_FORMAT_DIFFSTAT)
+                       diffopts.output_format |= DIFF_FORMAT_DIFFSTAT;
                else
-                       diffopts.output_format = DIFF_FORMAT_NO_OUTPUT;
+                       diffopts.output_format |= DIFF_FORMAT_NO_OUTPUT;
                diff_tree_sha1(parent[i], sha1, "", &diffopts);
                diffcore_std(&diffopts);
                paths = intersect_paths(paths, i, num_parent);
 
-               if (do_diffstat && rev->loginfo)
-                       show_log(rev, rev->loginfo,
-                                opt->with_stat ? "---\n" : "\n");
+               if (opt->output_format & DIFF_FORMAT_DIFFSTAT && rev->loginfo)
+                       show_log(rev, opt->msg_sep);
+
                diff_flush(&diffopts);
-               if (opt->with_stat)
+               if (opt->output_format & DIFF_FORMAT_DIFFSTAT)
                        putchar('\n');
        }
 
@@ -878,17 +868,21 @@ void diff_tree_combined(const unsigned char *sha1,
                        num_paths++;
        }
        if (num_paths) {
-               if (opt->with_raw) {
-                       int saved_format = opt->output_format;
-                       opt->output_format = DIFF_FORMAT_RAW;
+               if (opt->output_format & (DIFF_FORMAT_RAW |
+                                         DIFF_FORMAT_NAME |
+                                         DIFF_FORMAT_NAME_STATUS)) {
                        for (p = paths; p; p = p->next) {
-                               show_combined_diff(p, num_parent, dense, rev);
+                               if (p->len)
+                                       show_raw_diff(p, num_parent, rev);
                        }
-                       opt->output_format = saved_format;
                        putchar(opt->line_termination);
                }
-               for (p = paths; p; p = p->next) {
-                       show_combined_diff(p, num_parent, dense, rev);
+               if (opt->output_format & DIFF_FORMAT_PATCH) {
+                       for (p = paths; p; p = p->next) {
+                               if (p->len)
+                                       show_patch_diff(p, num_parent, dense,
+                                                       rev);
+                       }
                }
        }
 
diff --git a/diff.c b/diff.c
index fbb6c26cd9266e0ae453bb6c321f52d4996446a6..6d04be49dea83d319c68257d25dde6587179bdc5 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1420,11 +1420,11 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
 void diff_setup(struct diff_options *options)
 {
        memset(options, 0, sizeof(*options));
-       options->output_format = DIFF_FORMAT_RAW;
        options->line_termination = '\n';
        options->break_opt = -1;
        options->rename_limit = -1;
        options->context = 3;
+       options->msg_sep = "\n";
 
        options->change = diff_change;
        options->add_remove = diff_addremove;
@@ -1438,23 +1438,24 @@ int diff_setup_done(struct diff_options *options)
            (0 <= options->rename_limit && !options->detect_rename))
                return -1;
 
+       if (options->output_format & (DIFF_FORMAT_NAME |
+                                     DIFF_FORMAT_NAME_STATUS |
+                                     DIFF_FORMAT_CHECKDIFF |
+                                     DIFF_FORMAT_NO_OUTPUT))
+               options->output_format &= ~(DIFF_FORMAT_RAW |
+                                           DIFF_FORMAT_DIFFSTAT |
+                                           DIFF_FORMAT_SUMMARY |
+                                           DIFF_FORMAT_PATCH);
+
        /*
         * These cases always need recursive; we do not drop caller-supplied
         * recursive bits for other formats here.
         */
-       if ((options->output_format == DIFF_FORMAT_PATCH) ||
-           (options->output_format == DIFF_FORMAT_DIFFSTAT) ||
-           (options->output_format == DIFF_FORMAT_CHECKDIFF))
+       if (options->output_format & (DIFF_FORMAT_PATCH |
+                                     DIFF_FORMAT_DIFFSTAT |
+                                     DIFF_FORMAT_CHECKDIFF))
                options->recursive = 1;
 
-       /*
-        * These combinations do not make sense.
-        */
-       if (options->output_format == DIFF_FORMAT_RAW)
-               options->with_raw = 0;
-       if (options->output_format == DIFF_FORMAT_DIFFSTAT)
-               options->with_stat  = 0;
-
        if (options->detect_rename && options->rename_limit < 0)
                options->rename_limit = diff_rename_limit_default;
        if (options->setup & DIFF_SETUP_USE_CACHE) {
@@ -1526,22 +1527,22 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 {
        const char *arg = av[0];
        if (!strcmp(arg, "-p") || !strcmp(arg, "-u"))
-               options->output_format = DIFF_FORMAT_PATCH;
+               options->output_format |= DIFF_FORMAT_PATCH;
        else if (opt_arg(arg, 'U', "unified", &options->context))
-               options->output_format = DIFF_FORMAT_PATCH;
+               options->output_format |= DIFF_FORMAT_PATCH;
+       else if (!strcmp(arg, "--raw"))
+               options->output_format |= DIFF_FORMAT_RAW;
        else if (!strcmp(arg, "--patch-with-raw")) {
-               options->output_format = DIFF_FORMAT_PATCH;
-               options->with_raw = 1;
+               options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW;
        }
        else if (!strcmp(arg, "--stat"))
-               options->output_format = DIFF_FORMAT_DIFFSTAT;
+               options->output_format |= DIFF_FORMAT_DIFFSTAT;
        else if (!strcmp(arg, "--check"))
-               options->output_format = DIFF_FORMAT_CHECKDIFF;
+               options->output_format |= DIFF_FORMAT_CHECKDIFF;
        else if (!strcmp(arg, "--summary"))
-               options->summary = 1;
+               options->output_format |= DIFF_FORMAT_SUMMARY;
        else if (!strcmp(arg, "--patch-with-stat")) {
-               options->output_format = DIFF_FORMAT_PATCH;
-               options->with_stat = 1;
+               options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT;
        }
        else if (!strcmp(arg, "-z"))
                options->line_termination = 0;
@@ -1550,19 +1551,20 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        else if (!strcmp(arg, "--full-index"))
                options->full_index = 1;
        else if (!strcmp(arg, "--binary")) {
-               options->output_format = DIFF_FORMAT_PATCH;
+               options->output_format |= DIFF_FORMAT_PATCH;
                options->full_index = options->binary = 1;
        }
        else if (!strcmp(arg, "--name-only"))
-               options->output_format = DIFF_FORMAT_NAME;
+               options->output_format |= DIFF_FORMAT_NAME;
        else if (!strcmp(arg, "--name-status"))
-               options->output_format = DIFF_FORMAT_NAME_STATUS;
+               options->output_format |= DIFF_FORMAT_NAME_STATUS;
        else if (!strcmp(arg, "-R"))
                options->reverse_diff = 1;
        else if (!strncmp(arg, "-S", 2))
                options->pickaxe = arg + 2;
-       else if (!strcmp(arg, "-s"))
-               options->output_format = DIFF_FORMAT_NO_OUTPUT;
+       else if (!strcmp(arg, "-s")) {
+               options->output_format |= DIFF_FORMAT_NO_OUTPUT;
+       }
        else if (!strncmp(arg, "-O", 2))
                options->orderfile = arg + 2;
        else if (!strncmp(arg, "--diff-filter=", 14))
@@ -1737,15 +1739,17 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len)
 }
 
 static void diff_flush_raw(struct diff_filepair *p,
-                          int line_termination,
-                          int inter_name_termination,
-                          struct diff_options *options,
-                          int output_format)
+                          struct diff_options *options)
 {
        int two_paths;
        char status[10];
        int abbrev = options->abbrev;
        const char *path_one, *path_two;
+       int inter_name_termination = '\t';
+       int line_termination = options->line_termination;
+
+       if (!line_termination)
+               inter_name_termination = 0;
 
        path_one = p->one->path;
        path_two = p->two->path;
@@ -1774,7 +1778,7 @@ static void diff_flush_raw(struct diff_filepair *p,
                two_paths = 0;
                break;
        }
-       if (output_format != DIFF_FORMAT_NAME_STATUS) {
+       if (!(options->output_format & DIFF_FORMAT_NAME_STATUS)) {
                printf(":%06o %06o %s ",
                       p->one->mode, p->two->mode,
                       diff_unique_abbrev(p->one->sha1, abbrev));
@@ -1983,48 +1987,30 @@ static void diff_resolve_rename_copy(void)
        diff_debug_queue("resolve-rename-copy done", q);
 }
 
-static void flush_one_pair(struct diff_filepair *p,
-                          int diff_output_format,
-                          struct diff_options *options,
-                          struct diffstat_t *diffstat)
+static int check_pair_status(struct diff_filepair *p)
 {
-       int inter_name_termination = '\t';
-       int line_termination = options->line_termination;
-       if (!line_termination)
-               inter_name_termination = 0;
-
        switch (p->status) {
        case DIFF_STATUS_UNKNOWN:
-               break;
+               return 0;
        case 0:
                die("internal error in diff-resolve-rename-copy");
-               break;
        default:
-               switch (diff_output_format) {
-               case DIFF_FORMAT_DIFFSTAT:
-                       diff_flush_stat(p, options, diffstat);
-                       break;
-               case DIFF_FORMAT_CHECKDIFF:
-                       diff_flush_checkdiff(p, options);
-                       break;
-               case DIFF_FORMAT_PATCH:
-                       diff_flush_patch(p, options);
-                       break;
-               case DIFF_FORMAT_RAW:
-               case DIFF_FORMAT_NAME_STATUS:
-                       diff_flush_raw(p, line_termination,
-                                      inter_name_termination,
-                                      options, diff_output_format);
-                       break;
-               case DIFF_FORMAT_NAME:
-                       diff_flush_name(p, line_termination);
-                       break;
-               case DIFF_FORMAT_NO_OUTPUT:
-                       break;
-               }
+               return 1;
        }
 }
 
+static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt)
+{
+       int fmt = opt->output_format;
+
+       if (fmt & DIFF_FORMAT_CHECKDIFF)
+               diff_flush_checkdiff(p, opt);
+       else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS))
+               diff_flush_raw(p, opt);
+       else if (fmt & DIFF_FORMAT_NAME)
+               diff_flush_name(p, opt->line_termination);
+}
+
 static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs)
 {
        if (fs->mode)
@@ -2104,58 +2090,100 @@ static void diff_summary(struct diff_filepair *p)
        }
 }
 
-void diff_flush(struct diff_options *options)
+static int is_summary_empty(const struct diff_queue_struct *q)
 {
-       struct diff_queue_struct *q = &diff_queued_diff;
        int i;
-       int diff_output_format = options->output_format;
-       struct diffstat_t *diffstat = NULL;
 
-       if (diff_output_format == DIFF_FORMAT_DIFFSTAT || options->with_stat) {
-               diffstat = xcalloc(sizeof (struct diffstat_t), 1);
-               diffstat->xm.consume = diffstat_consume;
+       for (i = 0; i < q->nr; i++) {
+               const struct diff_filepair *p = q->queue[i];
+
+               switch (p->status) {
+               case DIFF_STATUS_DELETED:
+               case DIFF_STATUS_ADDED:
+               case DIFF_STATUS_COPIED:
+               case DIFF_STATUS_RENAMED:
+                       return 0;
+               default:
+                       if (p->score)
+                               return 0;
+                       if (p->one->mode && p->two->mode &&
+                           p->one->mode != p->two->mode)
+                               return 0;
+                       break;
+               }
        }
+       return 1;
+}
 
-       if (options->with_raw) {
+void diff_flush(struct diff_options *options)
+{
+       struct diff_queue_struct *q = &diff_queued_diff;
+       int i, output_format = options->output_format;
+       int separator = 0;
+
+       /*
+        * Order: raw, stat, summary, patch
+        * or:    name/name-status/checkdiff (other bits clear)
+        */
+       if (!q->nr)
+               goto free_queue;
+
+       if (output_format & (DIFF_FORMAT_RAW |
+                            DIFF_FORMAT_NAME |
+                            DIFF_FORMAT_NAME_STATUS |
+                            DIFF_FORMAT_CHECKDIFF)) {
                for (i = 0; i < q->nr; i++) {
                        struct diff_filepair *p = q->queue[i];
-                       flush_one_pair(p, DIFF_FORMAT_RAW, options, NULL);
+                       if (check_pair_status(p))
+                               flush_one_pair(p, options);
                }
-               putchar(options->line_termination);
+               separator++;
        }
-       if (options->with_stat) {
+
+       if (output_format & DIFF_FORMAT_DIFFSTAT) {
+               struct diffstat_t diffstat;
+
+               if (separator++)
+                       putchar('\n');
+
+               memset(&diffstat, 0, sizeof(struct diffstat_t));
+               diffstat.xm.consume = diffstat_consume;
                for (i = 0; i < q->nr; i++) {
                        struct diff_filepair *p = q->queue[i];
-                       flush_one_pair(p, DIFF_FORMAT_DIFFSTAT, options,
-                                      diffstat);
+                       if (check_pair_status(p))
+                               diff_flush_stat(p, options, &diffstat);
                }
-               show_stats(diffstat);
-               free(diffstat);
-               diffstat = NULL;
-               if (options->summary)
-                       for (i = 0; i < q->nr; i++)
-                               diff_summary(q->queue[i]);
-               if (options->stat_sep)
-                       fputs(options->stat_sep, stdout);
-               else
-                       putchar(options->line_termination);
-       }
-       for (i = 0; i < q->nr; i++) {
-               struct diff_filepair *p = q->queue[i];
-               flush_one_pair(p, diff_output_format, options, diffstat);
+               show_stats(&diffstat);
        }
 
-       if (diffstat) {
-               show_stats(diffstat);
-               free(diffstat);
-       }
+       if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) {
+               if (separator++)
+                       putchar('\n');
 
-       for (i = 0; i < q->nr; i++) {
-               if (diffstat && options->summary)
+               for (i = 0; i < q->nr; i++)
                        diff_summary(q->queue[i]);
-               diff_free_filepair(q->queue[i]);
        }
 
+       if (output_format & DIFF_FORMAT_PATCH) {
+               if (separator) {
+                       if (options->stat_sep) {
+                               /* attach patch instead of inline */
+                               fputs(options->stat_sep, stdout);
+                       } else {
+                               putchar(options->line_termination);
+                       }
+               }
+
+               for (i = 0; i < q->nr; i++) {
+                       struct diff_filepair *p = q->queue[i];
+                       if (check_pair_status(p))
+                               diff_flush_patch(p, options);
+               }
+       }
+
+       for (i = 0; i < q->nr; i++)
+               diff_free_filepair(q->queue[i]);
+free_queue:
        free(q->queue);
        q->queue = NULL;
        q->nr = q->alloc = 0;
diff --git a/diff.h b/diff.h
index b61fdc8f1e4f34b608ed69cbbac6f74b81d47b53..729cd02510cfb3d39646475131ee523f03def8fb 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -20,19 +20,31 @@ typedef void (*add_remove_fn_t)(struct diff_options *options,
                    const unsigned char *sha1,
                    const char *base, const char *path);
 
+#define DIFF_FORMAT_RAW                0x0001
+#define DIFF_FORMAT_DIFFSTAT   0x0002
+#define DIFF_FORMAT_SUMMARY    0x0004
+#define DIFF_FORMAT_PATCH      0x0008
+
+/* These override all above */
+#define DIFF_FORMAT_NAME       0x0010
+#define DIFF_FORMAT_NAME_STATUS        0x0020
+#define DIFF_FORMAT_CHECKDIFF  0x0040
+
+/* Same as output_format = 0 but we know that -s flag was given
+ * and we should not give default value to output_format.
+ */
+#define DIFF_FORMAT_NO_OUTPUT  0x0080
+
 struct diff_options {
        const char *filter;
        const char *orderfile;
        const char *pickaxe;
        unsigned recursive:1,
-                with_raw:1,
-                with_stat:1,
                 tree_in_recursive:1,
                 binary:1,
                 full_index:1,
                 silent_on_remove:1,
                 find_copies_harder:1,
-                summary:1,
                 color_diff:1;
        int context;
        int break_opt;
@@ -45,6 +57,7 @@ struct diff_options {
        int rename_limit;
        int setup;
        int abbrev;
+       const char *msg_sep;
        const char *stat_sep;
        long xdl_opts;
 
@@ -151,15 +164,6 @@ extern void diffcore_std_no_resolve(struct diff_options *);
 "                show all files diff when -S is used and hit is found.\n"
 
 extern int diff_queue_is_empty(void);
-
-#define DIFF_FORMAT_RAW                1
-#define DIFF_FORMAT_PATCH      2
-#define DIFF_FORMAT_NO_OUTPUT  3
-#define DIFF_FORMAT_NAME       4
-#define DIFF_FORMAT_NAME_STATUS        5
-#define DIFF_FORMAT_DIFFSTAT   6
-#define DIFF_FORMAT_CHECKDIFF  7
-
 extern void diff_flush(struct diff_options*);
 
 /* diff-raw status letters */
index ebb49f29701b2435d66eb92fc2a5c382299e8ee8..ab6b6822237c2e0fc520092344854d7b13f4a24d 100644 (file)
@@ -43,9 +43,10 @@ static int append_signoff(char *buf, int buf_sz, int at, const char *signoff)
        return at;
 }
 
-void show_log(struct rev_info *opt, struct log_info *log, const char *sep)
+void show_log(struct rev_info *opt, const char *sep)
 {
        static char this_header[16384];
+       struct log_info *log = opt->loginfo;
        struct commit *commit = log->commit, *parent = log->parent;
        int abbrev = opt->diffopt.abbrev;
        int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40;
@@ -164,7 +165,8 @@ int log_tree_diff_flush(struct rev_info *opt)
        }
 
        if (opt->loginfo && !opt->no_commit_id)
-               show_log(opt, opt->loginfo, opt->diffopt.with_stat ? "---\n" : "\n");
+               show_log(opt, opt->diffopt.msg_sep);
+
        diff_flush(&opt->diffopt);
        return 1;
 }
@@ -261,7 +263,7 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit)
        shown = log_tree_diff(opt, commit, &log);
        if (!shown && opt->loginfo && opt->always_show_header) {
                log.parent = NULL;
-               show_log(opt, opt->loginfo, "");
+               show_log(opt, "");
                shown = 1;
        }
        opt->loginfo = NULL;
index a26e4841ff9f568f8536f286e3fc40f09b9dff3b..e82b56a20d3cfad318a4af6ea78fbe098653211d 100644 (file)
@@ -11,6 +11,6 @@ void init_log_tree_opt(struct rev_info *);
 int log_tree_diff_flush(struct rev_info *);
 int log_tree_commit(struct rev_info *, struct commit *);
 int log_tree_opt_parse(struct rev_info *, const char **, int);
-void show_log(struct rev_info *opt, struct log_info *log, const char *sep);
+void show_log(struct rev_info *opt, const char *sep);
 
 #endif
index b963f2adfd92050310f7327e1ee10e21d5996a7c..ae4ca8200367a919ed5166a96624abbbe8fef15c 100644 (file)
@@ -851,8 +851,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
        }
        if (revs->combine_merges) {
                revs->ignore_merges = 0;
-               if (revs->dense_combined_merges &&
-                   (revs->diffopt.output_format != DIFF_FORMAT_DIFFSTAT))
+               if (revs->dense_combined_merges && !revs->diffopt.output_format)
                        revs->diffopt.output_format = DIFF_FORMAT_PATCH;
        }
        revs->diffopt.abbrev = revs->abbrev;