Merge branch 'kk/revwalk-slop-too-many-commit-within-a-second'
authorJunio C Hamano <gitster@pobox.com>
Thu, 28 Mar 2013 21:38:25 +0000 (14:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 28 Mar 2013 21:38:25 +0000 (14:38 -0700)
Allow the revision "slop" code to look deeper while commits with
exactly the same timestamps come next to each other (which can
often happen after a large "am" and "rebase" session).

* kk/revwalk-slop-too-many-commit-within-a-second:
Fix revision walk for commits with the same dates

1  2 
revision.c
diff --combined revision.c
index 78397d6486203a6b7242c8ea866780979876e685,6a9a8b3c8066cb0d3f536c1a3bf861ab16da8179..71e62d831229773a9af2c4a81d72be5b33d3c921
@@@ -13,7 -13,6 +13,7 @@@
  #include "decorate.h"
  #include "log-tree.h"
  #include "string-list.h"
 +#include "mailmap.h"
  
  volatile show_early_output_fn_t show_early_output;
  
@@@ -709,7 -708,7 +709,7 @@@ static int still_interesting(struct com
         * Does the destination list contain entries with a date
         * before the source list? Definitely _not_ done.
         */
-       if (date < src->item->date)
+       if (date <= src->item->date)
                return SLOP;
  
        /*
@@@ -1604,8 -1603,6 +1604,8 @@@ static int handle_revision_opt(struct r
                return argcount;
        } else if (!strcmp(arg, "--grep-debug")) {
                revs->grep_filter.debug = 1;
 +      } else if (!strcmp(arg, "--basic-regexp")) {
 +              grep_set_pattern_type_option(GREP_PATTERN_TYPE_BRE, &revs->grep_filter);
        } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
                grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, &revs->grep_filter);
        } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
                DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
                grep_set_pattern_type_option(GREP_PATTERN_TYPE_FIXED, &revs->grep_filter);
 +      } else if (!strcmp(arg, "--perl-regexp")) {
 +              grep_set_pattern_type_option(GREP_PATTERN_TYPE_PCRE, &revs->grep_filter);
        } else if (!strcmp(arg, "--all-match")) {
                revs->grep_filter.all_match = 1;
        } else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
@@@ -1970,22 -1965,6 +1970,22 @@@ static struct merge_simplify_state *loc
        return st;
  }
  
 +static void remove_treesame_parents(struct commit *commit)
 +{
 +      struct commit_list **pp, *p;
 +
 +      pp = &commit->parents;
 +      while ((p = *pp) != NULL) {
 +              struct commit *parent = p->item;
 +              if (parent->object.flags & TREESAME) {
 +                      *pp = p->next;
 +                      free(p);
 +                      continue;
 +              }
 +              pp = &p->next;
 +      }
 +}
 +
  static struct commit_list **simplify_one(struct rev_info *revs, struct commit *commit, struct commit_list **tail)
  {
        struct commit_list *p;
                if (revs->first_parent_only)
                        break;
        }
 -      if (!revs->first_parent_only)
 -              cnt = remove_duplicate_parents(commit);
 -      else
 +
 +      if (revs->first_parent_only) {
                cnt = 1;
 +      } else {
 +              /*
 +               * A merge with a tree-same parent is useless
 +               */
 +              if (commit->parents && commit->parents->next)
 +                      remove_treesame_parents(commit);
 +
 +              cnt = remove_duplicate_parents(commit);
 +      }
  
        /*
         * It is possible that we are a merge and one side branch
@@@ -2244,58 -2215,10 +2244,58 @@@ static int rewrite_parents(struct rev_i
        return 0;
  }
  
 +static int commit_rewrite_person(struct strbuf *buf, const char *what, struct string_list *mailmap)
 +{
 +      char *person, *endp;
 +      size_t len, namelen, maillen;
 +      const char *name;
 +      const char *mail;
 +      struct ident_split ident;
 +
 +      person = strstr(buf->buf, what);
 +      if (!person)
 +              return 0;
 +
 +      person += strlen(what);
 +      endp = strchr(person, '\n');
 +      if (!endp)
 +              return 0;
 +
 +      len = endp - person;
 +
 +      if (split_ident_line(&ident, person, len))
 +              return 0;
 +
 +      mail = ident.mail_begin;
 +      maillen = ident.mail_end - ident.mail_begin;
 +      name = ident.name_begin;
 +      namelen = ident.name_end - ident.name_begin;
 +
 +      if (map_user(mailmap, &mail, &maillen, &name, &namelen)) {
 +              struct strbuf namemail = STRBUF_INIT;
 +
 +              strbuf_addf(&namemail, "%.*s <%.*s>",
 +                          (int)namelen, name, (int)maillen, mail);
 +
 +              strbuf_splice(buf, ident.name_begin - buf->buf,
 +                            ident.mail_end - ident.name_begin + 1,
 +                            namemail.buf, namemail.len);
 +
 +              strbuf_release(&namemail);
 +
 +              return 1;
 +      }
 +
 +      return 0;
 +}
 +
  static int commit_match(struct commit *commit, struct rev_info *opt)
  {
        int retval;
 +      const char *encoding;
 +      char *message;
        struct strbuf buf = STRBUF_INIT;
 +
        if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
                return 1;
  
                strbuf_addch(&buf, '\n');
        }
  
 +      /*
 +       * We grep in the user's output encoding, under the assumption that it
 +       * is the encoding they are most likely to write their grep pattern
 +       * for. In addition, it means we will match the "notes" encoding below,
 +       * so we will not end up with a buffer that has two different encodings
 +       * in it.
 +       */
 +      encoding = get_log_output_encoding();
 +      message = logmsg_reencode(commit, encoding);
 +
        /* Copy the commit to temporary if we are using "fake" headers */
        if (buf.len)
 -              strbuf_addstr(&buf, commit->buffer);
 +              strbuf_addstr(&buf, message);
 +
 +      if (opt->grep_filter.header_list && opt->mailmap) {
 +              if (!buf.len)
 +                      strbuf_addstr(&buf, message);
 +
 +              commit_rewrite_person(&buf, "\nauthor ", opt->mailmap);
 +              commit_rewrite_person(&buf, "\ncommitter ", opt->mailmap);
 +      }
  
        /* Append "fake" message parts as needed */
        if (opt->show_notes) {
                if (!buf.len)
 -                      strbuf_addstr(&buf, commit->buffer);
 -              format_display_notes(commit->object.sha1, &buf,
 -                                   get_log_output_encoding(), 0);
 +                      strbuf_addstr(&buf, message);
 +              format_display_notes(commit->object.sha1, &buf, encoding, 1);
        }
  
 -      /* Find either in the commit object, or in the temporary */
 +      /* Find either in the original commit message, or in the temporary */
        if (buf.len)
                retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
        else
                retval = grep_buffer(&opt->grep_filter,
 -                                   commit->buffer, strlen(commit->buffer));
 +                                   message, strlen(message));
        strbuf_release(&buf);
 +      logmsg_free(message, commit);
        return retval;
  }