log-tree.con commit Merge branch 'master' into next (e5de825)
   1#include "cache.h"
   2#include "diff.h"
   3#include "commit.h"
   4#include "log-tree.h"
   5
   6int log_tree_diff_flush(struct rev_info *opt)
   7{
   8        diffcore_std(&opt->diffopt);
   9        if (diff_queue_is_empty()) {
  10                int saved_fmt = opt->diffopt.output_format;
  11                opt->diffopt.output_format = DIFF_FORMAT_NO_OUTPUT;
  12                diff_flush(&opt->diffopt);
  13                opt->diffopt.output_format = saved_fmt;
  14                return 0;
  15        }
  16        if (opt->header) {
  17                if (!opt->no_commit_id)
  18                        printf("%s%c", opt->header,
  19                               opt->diffopt.line_termination);
  20                opt->header = NULL;
  21        }
  22        diff_flush(&opt->diffopt);
  23        return 1;
  24}
  25
  26static int diff_root_tree(struct rev_info *opt,
  27                          const unsigned char *new, const char *base)
  28{
  29        int retval;
  30        void *tree;
  31        struct tree_desc empty, real;
  32
  33        tree = read_object_with_reference(new, tree_type, &real.size, NULL);
  34        if (!tree)
  35                die("unable to read root tree (%s)", sha1_to_hex(new));
  36        real.buf = tree;
  37
  38        empty.buf = "";
  39        empty.size = 0;
  40        retval = diff_tree(&empty, &real, base, &opt->diffopt);
  41        free(tree);
  42        log_tree_diff_flush(opt);
  43        return retval;
  44}
  45
  46static const char *get_header(struct rev_info *opt,
  47                                   const unsigned char *commit_sha1,
  48                                   const unsigned char *parent_sha1,
  49                                   const struct commit *commit)
  50{
  51        static char this_header[16384];
  52        int offset;
  53        unsigned long len;
  54        int abbrev = opt->diffopt.abbrev;
  55        const char *msg = commit->buffer;
  56
  57        if (opt->use_precomputed_header)
  58                return opt->use_precomputed_header;
  59
  60        if (!opt->verbose_header)
  61                return sha1_to_hex(commit_sha1);
  62
  63        len = strlen(msg);
  64
  65        offset = sprintf(this_header, "%s%s ",
  66                         opt->header_prefix,
  67                         diff_unique_abbrev(commit_sha1, abbrev));
  68        if (commit_sha1 != parent_sha1)
  69                offset += sprintf(this_header + offset, "(from %s)\n",
  70                                  parent_sha1
  71                                  ? diff_unique_abbrev(parent_sha1, abbrev)
  72                                  : "root");
  73        else
  74                offset += sprintf(this_header + offset, "(from parents)\n");
  75        offset += pretty_print_commit(opt->commit_format, commit, len,
  76                                      this_header + offset,
  77                                      sizeof(this_header) - offset, abbrev);
  78        return this_header;
  79}
  80
  81static const char *generate_header(struct rev_info *opt,
  82                                        const unsigned char *commit_sha1,
  83                                        const unsigned char *parent_sha1,
  84                                        const struct commit *commit)
  85{
  86        const char *header = get_header(opt, commit_sha1, parent_sha1, commit);
  87
  88        if (opt->always_show_header) {
  89                puts(header);
  90                header = NULL;
  91        }
  92        return header;
  93}
  94
  95static int do_diff_combined(struct rev_info *opt, struct commit *commit)
  96{
  97        unsigned const char *sha1 = commit->object.sha1;
  98
  99        opt->header = generate_header(opt, sha1, sha1, commit);
 100        opt->header = diff_tree_combined_merge(sha1, opt->header,
 101                                                opt->dense_combined_merges,
 102                                                &opt->diffopt);
 103        if (!opt->header && opt->verbose_header)
 104                opt->header_prefix = "\ndiff-tree ";
 105        return 0;
 106}
 107
 108int log_tree_commit(struct rev_info *opt, struct commit *commit)
 109{
 110        struct commit_list *parents;
 111        unsigned const char *sha1 = commit->object.sha1;
 112
 113        /* Root commit? */
 114        if (opt->show_root_diff && !commit->parents) {
 115                opt->header = generate_header(opt, sha1, NULL, commit);
 116                diff_root_tree(opt, sha1, "");
 117        }
 118
 119        /* More than one parent? */
 120        if (commit->parents && commit->parents->next) {
 121                if (opt->ignore_merges)
 122                        return 0;
 123                else if (opt->combine_merges)
 124                        return do_diff_combined(opt, commit);
 125        }
 126
 127        for (parents = commit->parents; parents; parents = parents->next) {
 128                struct commit *parent = parents->item;
 129                unsigned const char *psha1 = parent->object.sha1;
 130                opt->header = generate_header(opt, sha1, psha1, commit);
 131                diff_tree_sha1(psha1, sha1, "", &opt->diffopt);
 132                log_tree_diff_flush(opt);               
 133
 134                if (!opt->header && opt->verbose_header)
 135                        opt->header_prefix = "\ndiff-tree ";
 136        }
 137        return 0;
 138}