Merge branch 'jk/maint-tformat-with-z' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 14 May 2012 18:42:34 +0000 (11:42 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 14 May 2012 18:42:34 +0000 (11:42 -0700)
By Jan Krüger (1) and Junio C Hamano (1)
* jk/maint-tformat-with-z:
log-tree: the previous one is still not quite right
log-tree: use custom line terminator in line termination mode

1  2 
log-tree.c
diff --combined log-tree.c
index 34c49e7b3322d32ead03844bdc478a2e27836f16,f4e2ba369f8a43ca9a19ace6e8b820735fab9c6f..44f02683722c5b9181f94f1a6380f8ad191eb08f
@@@ -8,7 -8,6 +8,7 @@@
  #include "refs.h"
  #include "string-list.h"
  #include "color.h"
 +#include "gpg-interface.h"
  
  struct decoration name_decoration = { "object names" };
  
@@@ -19,7 -18,6 +19,7 @@@ enum decoration_type 
        DECORATION_REF_TAG,
        DECORATION_REF_STASH,
        DECORATION_REF_HEAD,
 +      DECORATION_GRAFTED,
  };
  
  static char decoration_colors[][COLOR_MAXLEN] = {
        GIT_COLOR_BOLD_YELLOW,  /* REF_TAG */
        GIT_COLOR_BOLD_MAGENTA, /* REF_STASH */
        GIT_COLOR_BOLD_CYAN,    /* REF_HEAD */
 +      GIT_COLOR_BOLD_BLUE,    /* GRAFTED */
  };
  
  static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix)
  {
 -      if (decorate_use_color)
 +      if (want_color(decorate_use_color))
                return decoration_colors[ix];
        return "";
  }
@@@ -80,7 -77,7 +80,7 @@@ int parse_decorate_color_config(const c
   * for showing the commit sha1, use the same check for --decorate
   */
  #define decorate_get_color_opt(o, ix) \
 -      decorate_get_color(DIFF_OPT_TST((o), COLOR_DIFF), ix)
 +      decorate_get_color((o)->use_color, ix)
  
  static void add_name_decoration(enum decoration_type type, const char *name, struct object *obj)
  {
  
  static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
  {
 -      struct object *obj = parse_object(sha1);
 +      struct object *obj;
        enum decoration_type type = DECORATION_NONE;
 +
 +      if (!prefixcmp(refname, "refs/replace/")) {
 +              unsigned char original_sha1[20];
 +              if (!read_replace_refs)
 +                      return 0;
 +              if (get_sha1_hex(refname + 13, original_sha1)) {
 +                      warning("invalid replace ref %s", refname);
 +                      return 0;
 +              }
 +              obj = parse_object(original_sha1);
 +              if (obj)
 +                      add_name_decoration(DECORATION_GRAFTED, "replaced", obj);
 +              return 0;
 +      }
 +
 +      obj = parse_object(sha1);
        if (!obj)
                return 0;
  
 -      if (!prefixcmp(refname, "refs/heads"))
 +      if (!prefixcmp(refname, "refs/heads/"))
                type = DECORATION_REF_LOCAL;
 -      else if (!prefixcmp(refname, "refs/remotes"))
 +      else if (!prefixcmp(refname, "refs/remotes/"))
                type = DECORATION_REF_REMOTE;
 -      else if (!prefixcmp(refname, "refs/tags"))
 +      else if (!prefixcmp(refname, "refs/tags/"))
                type = DECORATION_REF_TAG;
 -      else if (!prefixcmp(refname, "refs/stash"))
 +      else if (!strcmp(refname, "refs/stash"))
                type = DECORATION_REF_STASH;
 -      else if (!prefixcmp(refname, "HEAD"))
 +      else if (!strcmp(refname, "HEAD"))
                type = DECORATION_REF_HEAD;
  
        if (!cb_data || *(int *)cb_data == DECORATE_SHORT_REFS)
        return 0;
  }
  
 +static int add_graft_decoration(const struct commit_graft *graft, void *cb_data)
 +{
 +      struct commit *commit = lookup_commit(graft->sha1);
 +      if (!commit)
 +              return 0;
 +      add_name_decoration(DECORATION_GRAFTED, "grafted", &commit->object);
 +      return 0;
 +}
 +
  void load_ref_decorations(int flags)
  {
        static int loaded;
                loaded = 1;
                for_each_ref(add_ref_decoration, &flags);
                head_ref(add_ref_decoration, &flags);
 +              for_each_commit_graft(add_graft_decoration, NULL);
        }
  }
  
@@@ -166,14 -137,6 +166,14 @@@ static void show_parents(struct commit 
        }
  }
  
 +static void show_children(struct rev_info *opt, struct commit *commit, int abbrev)
 +{
 +      struct commit_list *p = lookup_decoration(&opt->children, &commit->object);
 +      for ( ; p; p = p->next) {
 +              printf(" %s", find_unique_abbrev(p->item->object.sha1, abbrev));
 +      }
 +}
 +
  void show_decorations(struct rev_info *opt, struct commit *commit)
  {
        const char *prefix;
@@@ -404,129 -367,6 +404,129 @@@ void log_write_email_headers(struct rev
        *extra_headers_p = extra_headers;
  }
  
 +static void show_sig_lines(struct rev_info *opt, int status, const char *bol)
 +{
 +      const char *color, *reset, *eol;
 +
 +      color = diff_get_color_opt(&opt->diffopt,
 +                                 status ? DIFF_WHITESPACE : DIFF_FRAGINFO);
 +      reset = diff_get_color_opt(&opt->diffopt, DIFF_RESET);
 +      while (*bol) {
 +              eol = strchrnul(bol, '\n');
 +              printf("%s%.*s%s%s", color, (int)(eol - bol), bol, reset,
 +                     *eol ? "\n" : "");
 +              bol = (*eol) ? (eol + 1) : eol;
 +      }
 +}
 +
 +static void show_signature(struct rev_info *opt, struct commit *commit)
 +{
 +      struct strbuf payload = STRBUF_INIT;
 +      struct strbuf signature = STRBUF_INIT;
 +      struct strbuf gpg_output = STRBUF_INIT;
 +      int status;
 +
 +      if (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0)
 +              goto out;
 +
 +      status = verify_signed_buffer(payload.buf, payload.len,
 +                                    signature.buf, signature.len,
 +                                    &gpg_output);
 +      if (status && !gpg_output.len)
 +              strbuf_addstr(&gpg_output, "No signature\n");
 +
 +      show_sig_lines(opt, status, gpg_output.buf);
 +
 + out:
 +      strbuf_release(&gpg_output);
 +      strbuf_release(&payload);
 +      strbuf_release(&signature);
 +}
 +
 +static int which_parent(const unsigned char *sha1, const struct commit *commit)
 +{
 +      int nth;
 +      const struct commit_list *parent;
 +
 +      for (nth = 0, parent = commit->parents; parent; parent = parent->next) {
 +              if (!hashcmp(parent->item->object.sha1, sha1))
 +                      return nth;
 +              nth++;
 +      }
 +      return -1;
 +}
 +
 +static int is_common_merge(const struct commit *commit)
 +{
 +      return (commit->parents
 +              && commit->parents->next
 +              && !commit->parents->next->next);
 +}
 +
 +static void show_one_mergetag(struct rev_info *opt,
 +                            struct commit_extra_header *extra,
 +                            struct commit *commit)
 +{
 +      unsigned char sha1[20];
 +      struct tag *tag;
 +      struct strbuf verify_message;
 +      int status, nth;
 +      size_t payload_size, gpg_message_offset;
 +
 +      hash_sha1_file(extra->value, extra->len, typename(OBJ_TAG), sha1);
 +      tag = lookup_tag(sha1);
 +      if (!tag)
 +              return; /* error message already given */
 +
 +      strbuf_init(&verify_message, 256);
 +      if (parse_tag_buffer(tag, extra->value, extra->len))
 +              strbuf_addstr(&verify_message, "malformed mergetag\n");
 +      else if (is_common_merge(commit) &&
 +               !hashcmp(tag->tagged->sha1,
 +                        commit->parents->next->item->object.sha1))
 +              strbuf_addf(&verify_message,
 +                          "merged tag '%s'\n", tag->tag);
 +      else if ((nth = which_parent(tag->tagged->sha1, commit)) < 0)
 +              strbuf_addf(&verify_message, "tag %s names a non-parent %s\n",
 +                                  tag->tag, tag->tagged->sha1);
 +      else
 +              strbuf_addf(&verify_message,
 +                          "parent #%d, tagged '%s'\n", nth + 1, tag->tag);
 +      gpg_message_offset = verify_message.len;
 +
 +      payload_size = parse_signature(extra->value, extra->len);
 +      if ((extra->len <= payload_size) ||
 +          (verify_signed_buffer(extra->value, payload_size,
 +                                extra->value + payload_size,
 +                                extra->len - payload_size,
 +                                &verify_message) &&
 +           verify_message.len <= gpg_message_offset)) {
 +              strbuf_addstr(&verify_message, "No signature\n");
 +              status = -1;
 +      }
 +      else if (strstr(verify_message.buf + gpg_message_offset,
 +                      ": Good signature from "))
 +              status = 0;
 +      else
 +              status = -1;
 +
 +      show_sig_lines(opt, status, verify_message.buf);
 +      strbuf_release(&verify_message);
 +}
 +
 +static void show_mergetag(struct rev_info *opt, struct commit *commit)
 +{
 +      struct commit_extra_header *extra, *to_free;
 +
 +      to_free = read_commit_extra_headers(commit, NULL);
 +      for (extra = to_free; extra; extra = extra->next) {
 +              if (strcmp(extra->key, "mergetag"))
 +                      continue; /* not a merge tag */
 +              show_one_mergetag(opt, extra, commit);
 +      }
 +      free_commit_extra_headers(to_free);
 +}
 +
  void show_log(struct rev_info *opt)
  {
        struct strbuf msgbuf = STRBUF_INIT;
                fputs(find_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
                if (opt->print_parents)
                        show_parents(commit, abbrev_commit);
 +              if (opt->children.name)
 +                      show_children(opt, commit, abbrev_commit);
                show_decorations(opt, commit);
                if (opt->graph && !graph_is_commit_finished(opt->graph)) {
                        putchar('\n');
                      stdout);
                if (opt->print_parents)
                        show_parents(commit, abbrev_commit);
 +              if (opt->children.name)
 +                      show_children(opt, commit, abbrev_commit);
                if (parent)
                        printf(" (from %s)",
                               find_unique_abbrev(parent->object.sha1,
                }
        }
  
 +      if (opt->show_signature) {
 +              show_signature(opt, commit);
 +              show_mergetag(opt, commit);
 +      }
 +
        if (!commit->buffer)
                return;
  
        if (opt->use_terminator) {
                if (!opt->missing_newline)
                        graph_show_padding(opt->graph);
-               putchar('\n');
+               putchar(opt->diffopt.line_termination);
        }
  
        strbuf_release(&msgbuf);
@@@ -711,15 -542,14 +711,15 @@@ int log_tree_diff_flush(struct rev_inf
                    opt->verbose_header &&
                    opt->commit_format != CMIT_FMT_ONELINE) {
                        int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH;
 -                      if ((pch & opt->diffopt.output_format) == pch)
 -                              printf("---");
                        if (opt->diffopt.output_prefix) {
                                struct strbuf *msg = NULL;
                                msg = opt->diffopt.output_prefix(&opt->diffopt,
                                        opt->diffopt.output_prefix_data);
                                fwrite(msg->buf, msg->len, 1, stdout);
                        }
 +                      if ((pch & opt->diffopt.output_format) == pch) {
 +                              printf("---");
 +                      }
                        putchar('\n');
                }
        }
  
  static int do_diff_combined(struct rev_info *opt, struct commit *commit)
  {
 -      unsigned const char *sha1 = commit->object.sha1;
 -
 -      diff_tree_combined_merge(sha1, opt->dense_combined_merges, opt);
 +      diff_tree_combined_merge(commit, opt->dense_combined_merges, opt);
        return !opt->loginfo;
  }