Merge branch 'rs/pretty-add-again' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 10 Jul 2017 20:58:57 +0000 (13:58 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Jul 2017 20:58:57 +0000 (13:58 -0700)
The pretty-format specifiers like '%h', '%t', etc. had an
optimization that no longer works correctly. In preparation/hope
of getting it correctly implemented, first discard the optimization
that is broken.

* rs/pretty-add-again:
pretty: recalculate duplicate short hashes

1  2 
pretty.c
strbuf.c
strbuf.h
diff --combined pretty.c
index d0f86f5d85cab6c470871cdd6e5ead526259bf6a,37b37d0f9d435d40ab00f9b297d7935234106269..6cc812c2c72c2281299c44fd81376441bb16a0ec
+++ b/pretty.c
@@@ -10,7 -10,6 +10,7 @@@
  #include "color.h"
  #include "reflog-walk.h"
  #include "gpg-interface.h"
 +#include "trailer.h"
  
  static char *user_format;
  static struct cmt_fmt_map {
@@@ -783,29 -782,9 +783,9 @@@ struct format_commit_context 
        size_t body_off;
  
        /* The following ones are relative to the result struct strbuf. */
-       struct chunk abbrev_commit_hash;
-       struct chunk abbrev_tree_hash;
-       struct chunk abbrev_parent_hashes;
        size_t wrap_start;
  };
  
- static int add_again(struct strbuf *sb, struct chunk *chunk)
- {
-       if (chunk->len) {
-               strbuf_adddup(sb, chunk->off, chunk->len);
-               return 1;
-       }
-       /*
-        * We haven't seen this chunk before.  Our caller is surely
-        * going to add it the hard way now.  Remember the most likely
-        * start of the to-be-added chunk: the current end of the
-        * struct strbuf.
-        */
-       chunk->off = sb->len;
-       return 0;
- }
  static void parse_commit_header(struct format_commit_context *context)
  {
        const char *msg = context->message;
@@@ -890,16 -869,6 +870,16 @@@ const char *format_subject(struct strbu
        return msg;
  }
  
 +static void format_trailers(struct strbuf *sb, const char *msg)
 +{
 +      struct trailer_info info;
 +
 +      trailer_info_get(&info, msg);
 +      strbuf_add(sb, info.trailer_start,
 +                 info.trailer_end - info.trailer_start);
 +      trailer_info_release(&info);
 +}
 +
  static void parse_commit_message(struct format_commit_context *c)
  {
        const char *msg = c->message + c->message_off;
@@@ -1147,24 -1116,16 +1127,16 @@@ static size_t format_commit_one(struct 
                return 1;
        case 'h':               /* abbreviated commit hash */
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
-               if (add_again(sb, &c->abbrev_commit_hash)) {
-                       strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
-                       return 1;
-               }
                strbuf_add_unique_abbrev(sb, commit->object.oid.hash,
                                         c->pretty_ctx->abbrev);
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
-               c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
                return 1;
        case 'T':               /* tree hash */
                strbuf_addstr(sb, oid_to_hex(&commit->tree->object.oid));
                return 1;
        case 't':               /* abbreviated tree hash */
-               if (add_again(sb, &c->abbrev_tree_hash))
-                       return 1;
                strbuf_add_unique_abbrev(sb, commit->tree->object.oid.hash,
                                         c->pretty_ctx->abbrev);
-               c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
                return 1;
        case 'P':               /* parent hashes */
                for (p = commit->parents; p; p = p->next) {
                }
                return 1;
        case 'p':               /* abbreviated parent hashes */
-               if (add_again(sb, &c->abbrev_parent_hashes))
-                       return 1;
                for (p = commit->parents; p; p = p->next) {
                        if (p != commit->parents)
                                strbuf_addch(sb, ' ');
                        strbuf_add_unique_abbrev(sb, p->item->object.oid.hash,
                                                 c->pretty_ctx->abbrev);
                }
-               c->abbrev_parent_hashes.len = sb->len -
-                                             c->abbrev_parent_hashes.off;
                return 1;
        case 'm':               /* left/right/bottom */
                strbuf_addstr(sb, get_revision_mark(NULL, commit));
                        switch (c->signature_check.result) {
                        case 'G':
                        case 'B':
 +                      case 'E':
                        case 'U':
                        case 'N':
 +                      case 'X':
 +                      case 'Y':
 +                      case 'R':
                                strbuf_addch(sb, c->signature_check.result);
                        }
                        break;
                strbuf_addstr(sb, msg + c->body_off);
                return 1;
        }
 +
 +      if (starts_with(placeholder, "(trailers)")) {
 +              format_trailers(sb, msg + c->subject_off);
 +              return strlen("(trailers)");
 +      }
 +
        return 0;       /* unknown placeholder */
  }
  
@@@ -1607,9 -1554,8 +1575,9 @@@ void pp_title_line(struct pretty_print_
                                pp->preserve_subject ? "\n" : " ");
  
        strbuf_grow(sb, title.len + 1024);
 -      if (pp->subject) {
 -              strbuf_addstr(sb, pp->subject);
 +      if (pp->print_email_subject) {
 +              if (pp->rev)
 +                      fmt_output_email_subject(sb, pp->rev);
                if (needs_rfc2047_encoding(title.buf, title.len, RFC2047_SUBJECT))
                        add_rfc2047(sb, title.buf, title.len,
                                                encoding, RFC2047_SUBJECT);
@@@ -1819,7 -1765,7 +1787,7 @@@ void pretty_print_commit(struct pretty_
        }
  
        pp_header(pp, encoding, commit, &msg, sb);
 -      if (pp->fmt != CMIT_FMT_ONELINE && !pp->subject) {
 +      if (pp->fmt != CMIT_FMT_ONELINE && !pp->print_email_subject) {
                strbuf_addch(sb, '\n');
        }
  
diff --combined strbuf.c
index 00457940cfc163fed58b0206f5167c25c2c71b8a,df2c113f2143be86d3557eeb71be3859510a9e06..9103bc75e482c81bbb8f9d89c72de2935fefcddc
+++ b/strbuf.c
@@@ -204,13 -204,6 +204,6 @@@ void strbuf_addbuf(struct strbuf *sb, c
        strbuf_setlen(sb, sb->len + sb2->len);
  }
  
- void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
- {
-       strbuf_grow(sb, len);
-       memcpy(sb->buf + sb->len, sb->buf + pos, len);
-       strbuf_setlen(sb, sb->len + len);
- }
  void strbuf_addchars(struct strbuf *sb, int c, size_t n)
  {
        strbuf_grow(sb, n);
@@@ -449,17 -442,6 +442,17 @@@ int strbuf_getcwd(struct strbuf *sb
                        strbuf_setlen(sb, strlen(sb->buf));
                        return 0;
                }
 +
 +              /*
 +               * If getcwd(3) is implemented as a syscall that falls
 +               * back to a regular lookup using readdir(3) etc. then
 +               * we may be able to avoid EACCES by providing enough
 +               * space to the syscall as it's not necessarily bound
 +               * to the same restrictions as the fallback.
 +               */
 +              if (errno == EACCES && guessed_len < PATH_MAX)
 +                      continue;
 +
                if (errno != ERANGE)
                        break;
        }
@@@ -718,17 -700,6 +711,17 @@@ void strbuf_add_absolute_path(struct st
        strbuf_addstr(sb, path);
  }
  
 +void strbuf_add_real_path(struct strbuf *sb, const char *path)
 +{
 +      if (sb->len) {
 +              struct strbuf resolved = STRBUF_INIT;
 +              strbuf_realpath(&resolved, path, 1);
 +              strbuf_addbuf(sb, &resolved);
 +              strbuf_release(&resolved);
 +      } else
 +              strbuf_realpath(sb, path, 1);
 +}
 +
  int printf_ln(const char *fmt, ...)
  {
        int ret;
@@@ -892,23 -863,3 +885,23 @@@ void strbuf_stripspace(struct strbuf *s
  
        strbuf_setlen(sb, j);
  }
 +
 +int strbuf_normalize_path(struct strbuf *src)
 +{
 +      struct strbuf dst = STRBUF_INIT;
 +
 +      strbuf_grow(&dst, src->len);
 +      if (normalize_path_copy(dst.buf, src->buf) < 0) {
 +              strbuf_release(&dst);
 +              return -1;
 +      }
 +
 +      /*
 +       * normalize_path does not tell us the new length, so we have to
 +       * compute it by looking for the new NUL it placed
 +       */
 +      strbuf_setlen(&dst, strlen(dst.buf));
 +      strbuf_swap(src, &dst);
 +      strbuf_release(&dst);
 +      return 0;
 +}
diff --combined strbuf.h
index 80047b1bb7b826699deff3e8c2590a2a00a5c121,ca4eff8bff6cef22b876520f4a5befd26dc60ce9..d78525864935f84eb82e340b5ea3ffc9f755eb1e
+++ b/strbuf.h
@@@ -109,7 -109,9 +109,7 @@@ extern void strbuf_attach(struct strbu
   */
  static inline void strbuf_swap(struct strbuf *a, struct strbuf *b)
  {
 -      struct strbuf tmp = *a;
 -      *a = *b;
 -      *b = tmp;
 +      SWAP(*a, *b);
  }
  
  
@@@ -263,12 -265,6 +263,6 @@@ static inline void strbuf_addstr(struc
   */
  extern void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2);
  
- /**
-  * Copy part of the buffer from a given position till a given length to the
-  * end of the buffer.
-  */
- extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
  /**
   * This function can be used to expand a format string containing
   * placeholders. To that end, it parses the string and calls the specified
@@@ -441,28 -437,6 +435,28 @@@ extern int strbuf_getcwd(struct strbuf 
   */
  extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path);
  
 +/**
 + * Canonize `path` (make it absolute, resolve symlinks, remove extra
 + * slashes) and append it to `sb`.  Die with an informative error
 + * message if there is a problem.
 + *
 + * The directory part of `path` (i.e., everything up to the last
 + * dir_sep) must denote a valid, existing directory, but the last
 + * component need not exist.
 + *
 + * Callers that don't mind links should use the more lightweight
 + * strbuf_add_absolute_path() instead.
 + */
 +extern void strbuf_add_real_path(struct strbuf *sb, const char *path);
 +
 +
 +/**
 + * Normalize in-place the path contained in the strbuf. See
 + * normalize_path_copy() for details. If an error occurs, the contents of "sb"
 + * are left untouched, and -1 is returned.
 + */
 +extern int strbuf_normalize_path(struct strbuf *sb);
 +
  /**
   * Strip whitespace from a buffer. The second parameter controls if
   * comments are considered contents to be removed or not.
@@@ -574,26 -548,7 +568,26 @@@ static inline void strbuf_complete_line
        strbuf_complete(sb, '\n');
  }
  
 -extern int strbuf_branchname(struct strbuf *sb, const char *name);
 +/*
 + * Copy "name" to "sb", expanding any special @-marks as handled by
 + * interpret_branch_name(). The result is a non-qualified branch name
 + * (so "foo" or "origin/master" instead of "refs/heads/foo" or
 + * "refs/remotes/origin/master").
 + *
 + * Note that the resulting name may not be a syntactically valid refname.
 + *
 + * If "allowed" is non-zero, restrict the set of allowed expansions. See
 + * interpret_branch_name() for details.
 + */
 +extern void strbuf_branchname(struct strbuf *sb, const char *name,
 +                            unsigned allowed);
 +
 +/*
 + * Like strbuf_branchname() above, but confirm that the result is
 + * syntactically valid to be used as a local branch name in refs/heads/.
 + *
 + * The return value is "0" if the result is valid, and "-1" otherwise.
 + */
  extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
  
  extern void strbuf_addstr_urlencode(struct strbuf *, const char *,