Merge branch 'tr/copy-revisions-from-stdin'
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Apr 2013 20:40:13 +0000 (13:40 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Apr 2013 20:40:13 +0000 (13:40 -0700)
A fix to a long-standing issue in the command line parser for
revisions, which was triggered by mv/sequence-pick-error-diag topic.

* tr/copy-revisions-from-stdin:
read_revisions_from_stdin: make copies for handle_revision_arg

1  2 
revision.c
diff --combined revision.c
index eb981288686a2c7cd8c854e3f414b606ed4f8c69,a50df66c50ed4c9b8118ba511f0d67fc7ed7e5ab..56d666d69a8a961d33651c0658f7009967e0b7ab
@@@ -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;
  
        /*
@@@ -1049,9 -1048,9 +1049,9 @@@ void init_revisions(struct rev_info *re
  
        revs->commit_format = CMIT_FMT_DEFAULT;
  
 +      init_grep_defaults();
 +      grep_init(&revs->grep_filter, prefix);
        revs->grep_filter.status_only = 1;
 -      revs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);
 -      revs->grep_filter.header_tail = &(revs->grep_filter.header_list);
        revs->grep_filter.regflags = REG_NEWLINE;
  
        diff_setup(&revs->diffopt);
@@@ -1276,7 -1275,8 +1276,8 @@@ static void read_revisions_from_stdin(s
                        }
                        die("options not supported in --stdin mode");
                }
-               if (handle_revision_arg(sb.buf, revs, 0, REVARG_CANNOT_BE_FILENAME))
+               if (handle_revision_arg(xstrdup(sb.buf), revs, 0,
+                                       REVARG_CANNOT_BE_FILENAME))
                        die("bad revision '%s'", sb.buf);
        }
        if (seen_dashdash)
@@@ -1596,25 -1596,18 +1597,25 @@@ static int handle_revision_opt(struct r
        } else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
                add_header_grep(revs, GREP_HEADER_COMMITTER, optarg);
                return argcount;
 +      } else if ((argcount = parse_long_opt("grep-reflog", argv, &optarg))) {
 +              add_header_grep(revs, GREP_HEADER_REFLOG, optarg);
 +              return argcount;
        } else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
                add_message_grep(revs, optarg);
                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")) {
 -              revs->grep_filter.regflags |= REG_EXTENDED;
 +              grep_set_pattern_type_option(GREP_PATTERN_TYPE_ERE, &revs->grep_filter);
        } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
                revs->grep_filter.regflags |= REG_ICASE;
                DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
        } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
 -              revs->grep_filter.fixed = 1;
 +              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))) {
@@@ -1898,8 -1891,6 +1899,8 @@@ int setup_revisions(int argc, const cha
        revs->diffopt.abbrev = revs->abbrev;
        diff_setup_done(&revs->diffopt);
  
 +      grep_commit_pattern_type(GREP_PATTERN_TYPE_UNSPECIFIED,
 +                               &revs->grep_filter);
        compile_grep_patterns(&revs->grep_filter);
  
        if (revs->reverse && revs->reflog_info)
  
        if (revs->reflog_info && revs->graph)
                die("cannot combine --walk-reflogs with --graph");
 +      if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
 +              die("cannot use --grep-reflog without --walk-reflogs");
  
        return left;
  }
@@@ -2022,11 -2011,10 +2023,11 @@@ static struct commit_list **simplify_on
                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
 +              cnt = remove_duplicate_parents(commit);
  
        /*
         * It is possible that we are a merge and one side branch
@@@ -2221,106 -2209,12 +2222,106 @@@ 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;
 -      return grep_buffer(&opt->grep_filter,
 -                         commit->buffer, strlen(commit->buffer));
 +
 +      /* Prepend "fake" headers as needed */
 +      if (opt->grep_filter.use_reflog_filter) {
 +              strbuf_addstr(&buf, "reflog ");
 +              get_reflog_message(&buf, opt->reflog_info);
 +              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, 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, message);
 +              format_display_notes(commit->object.sha1, &buf, encoding, 1);
 +      }
 +
 +      /* 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,
 +                                   message, strlen(message));
 +      strbuf_release(&buf);
 +      logmsg_free(message, commit);
 +      return retval;
  }
  
  static inline int want_ancestry(struct rev_info *revs)