log-tree.con commit Merge branch 'jc/pager-cat' into next (e4284db)
   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 *generate_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->verbose_header)
  58                return sha1_to_hex(commit_sha1);
  59
  60        len = strlen(msg);
  61
  62        offset = sprintf(this_header, "%s%s ",
  63                         opt->header_prefix,
  64                         diff_unique_abbrev(commit_sha1, abbrev));
  65        if (commit_sha1 != parent_sha1)
  66                offset += sprintf(this_header + offset, "(from %s)\n",
  67                                  parent_sha1
  68                                  ? diff_unique_abbrev(parent_sha1, abbrev)
  69                                  : "root");
  70        else
  71                offset += sprintf(this_header + offset, "(from parents)\n");
  72        offset += pretty_print_commit(opt->commit_format, commit, len,
  73                                      this_header + offset,
  74                                      sizeof(this_header) - offset, abbrev);
  75        if (opt->always_show_header) {
  76                puts(this_header);
  77                return NULL;
  78        }
  79        return this_header;
  80}
  81
  82static int do_diff_combined(struct rev_info *opt, struct commit *commit)
  83{
  84        unsigned const char *sha1 = commit->object.sha1;
  85
  86        opt->header = generate_header(opt, sha1, sha1, commit);
  87        opt->header = diff_tree_combined_merge(sha1, opt->header,
  88                                                opt->dense_combined_merges,
  89                                                &opt->diffopt);
  90        if (!opt->header && opt->verbose_header)
  91                opt->header_prefix = "\ndiff-tree ";
  92        return 0;
  93}
  94
  95int log_tree_commit(struct rev_info *opt, struct commit *commit)
  96{
  97        struct commit_list *parents;
  98        unsigned const char *sha1 = commit->object.sha1;
  99
 100        /* Root commit? */
 101        if (opt->show_root_diff && !commit->parents) {
 102                opt->header = generate_header(opt, sha1, NULL, commit);
 103                diff_root_tree(opt, sha1, "");
 104        }
 105
 106        /* More than one parent? */
 107        if (commit->parents && commit->parents->next) {
 108                if (opt->ignore_merges)
 109                        return 0;
 110                else if (opt->combine_merges)
 111                        return do_diff_combined(opt, commit);
 112        }
 113
 114        for (parents = commit->parents; parents; parents = parents->next) {
 115                struct commit *parent = parents->item;
 116                unsigned const char *psha1 = parent->object.sha1;
 117                opt->header = generate_header(opt, sha1, psha1, commit);
 118                diff_tree_sha1(psha1, sha1, "", &opt->diffopt);
 119                log_tree_diff_flush(opt);               
 120
 121                if (!opt->header && opt->verbose_header)
 122                        opt->header_prefix = "\ndiff-tree ";
 123        }
 124        return 0;
 125}