Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Wed, 6 Oct 2010 19:10:02 +0000 (12:10 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 6 Oct 2010 19:10:02 +0000 (12:10 -0700)
* maint:
Documentation/git-clone: describe --mirror more verbosely
do not depend on signed integer overflow
work around buggy S_ISxxx(m) implementations
xdiff: cast arguments for ctype functions to unsigned char
init: plug tiny one-time memory leak
diffcore-pickaxe.c: remove unnecessary curly braces
t3020 (ls-files-error-unmatch): remove stray '1' from end of file
setup: make sure git dir path is in a permanent buffer
environment.c: remove unused variable
git-svn: fix processing of decorated commit hashes
git-svn: check_cherry_pick should exclude commits already in our history
Documentation/git-svn: discourage "noMetadata"

1  2 
diffcore-pickaxe.c
diff --combined diffcore-pickaxe.c
index 84195e47aa0a0e2fbeeb8a56d255ff5c6f42efe7,9c6544daacb6d0c7aeb2cc188d089ee5aeb06c5d..38570999c34f061524c3544892c53431db4f1623
  /*
   * Copyright (C) 2005 Junio C Hamano
 + * Copyright (C) 2010 Google Inc.
   */
  #include "cache.h"
  #include "diff.h"
  #include "diffcore.h"
 +#include "xdiff-interface.h"
 +
 +struct diffgrep_cb {
 +      regex_t *regexp;
 +      int hit;
 +};
 +
 +static void diffgrep_consume(void *priv, char *line, unsigned long len)
 +{
 +      struct diffgrep_cb *data = priv;
 +      regmatch_t regmatch;
 +      int hold;
 +
 +      if (line[0] != '+' && line[0] != '-')
 +              return;
 +      if (data->hit)
 +              /*
 +               * NEEDSWORK: we should have a way to terminate the
 +               * caller early.
 +               */
 +              return;
 +      /* Yuck -- line ought to be "const char *"! */
 +      hold = line[len];
 +      line[len] = '\0';
 +      data->hit = !regexec(data->regexp, line + 1, 1, &regmatch, 0);
 +      line[len] = hold;
 +}
 +
 +static void fill_one(struct diff_filespec *one,
 +                   mmfile_t *mf, struct userdiff_driver **textconv)
 +{
 +      if (DIFF_FILE_VALID(one)) {
 +              *textconv = get_textconv(one);
 +              mf->size = fill_textconv(*textconv, one, &mf->ptr);
 +      } else {
 +              memset(mf, 0, sizeof(*mf));
 +      }
 +}
 +
 +static int diff_grep(struct diff_filepair *p, regex_t *regexp, struct diff_options *o)
 +{
 +      regmatch_t regmatch;
 +      struct userdiff_driver *textconv_one = NULL;
 +      struct userdiff_driver *textconv_two = NULL;
 +      mmfile_t mf1, mf2;
 +      int hit;
 +
 +      if (diff_unmodified_pair(p))
 +              return 0;
 +
 +      fill_one(p->one, &mf1, &textconv_one);
 +      fill_one(p->two, &mf2, &textconv_two);
 +
 +      if (!mf1.ptr) {
 +              if (!mf2.ptr)
 +                      return 0; /* ignore unmerged */
 +              /* created "two" -- does it have what we are looking for? */
 +              hit = !regexec(regexp, p->two->data, 1, &regmatch, 0);
 +      } else if (!mf2.ptr) {
 +              /* removed "one" -- did it have what we are looking for? */
 +              hit = !regexec(regexp, p->one->data, 1, &regmatch, 0);
 +      } else {
 +              /*
 +               * We have both sides; need to run textual diff and see if
 +               * the pattern appears on added/deleted lines.
 +               */
 +              struct diffgrep_cb ecbdata;
 +              xpparam_t xpp;
 +              xdemitconf_t xecfg;
 +
 +              memset(&xpp, 0, sizeof(xpp));
 +              memset(&xecfg, 0, sizeof(xecfg));
 +              ecbdata.regexp = regexp;
 +              ecbdata.hit = 0;
 +              xecfg.ctxlen = o->context;
 +              xecfg.interhunkctxlen = o->interhunkcontext;
 +              xdi_diff_outf(&mf1, &mf2, diffgrep_consume, &ecbdata,
 +                            &xpp, &xecfg);
 +              hit = ecbdata.hit;
 +      }
 +      if (textconv_one)
 +              free(mf1.ptr);
 +      if (textconv_two)
 +              free(mf2.ptr);
 +      return hit;
 +}
 +
 +static void diffcore_pickaxe_grep(struct diff_options *o)
 +{
 +      struct diff_queue_struct *q = &diff_queued_diff;
 +      int i, has_changes, err;
 +      regex_t regex;
 +      struct diff_queue_struct outq;
 +      outq.queue = NULL;
 +      outq.nr = outq.alloc = 0;
 +
 +      err = regcomp(&regex, o->pickaxe, REG_EXTENDED | REG_NEWLINE);
 +      if (err) {
 +              char errbuf[1024];
 +              regerror(err, &regex, errbuf, 1024);
 +              regfree(&regex);
 +              die("invalid log-grep regex: %s", errbuf);
 +      }
 +
 +      if (o->pickaxe_opts & DIFF_PICKAXE_ALL) {
 +              /* Showing the whole changeset if needle exists */
 +              for (i = has_changes = 0; !has_changes && i < q->nr; i++) {
 +                      struct diff_filepair *p = q->queue[i];
 +                      if (diff_grep(p, &regex, o))
 +                              has_changes++;
 +              }
 +              if (has_changes)
 +                      return; /* do not munge the queue */
 +
 +              /*
 +               * Otherwise we will clear the whole queue by copying
 +               * the empty outq at the end of this function, but
 +               * first clear the current entries in the queue.
 +               */
 +              for (i = 0; i < q->nr; i++)
 +                      diff_free_filepair(q->queue[i]);
 +      } else {
 +              /* Showing only the filepairs that has the needle */
 +              for (i = 0; i < q->nr; i++) {
 +                      struct diff_filepair *p = q->queue[i];
 +                      if (diff_grep(p, &regex, o))
 +                              diff_q(&outq, p);
 +                      else
 +                              diff_free_filepair(p);
 +              }
 +      }
 +
 +      regfree(&regex);
 +
 +      free(q->queue);
 +      *q = outq;
 +      return;
 +}
  
  static unsigned int contains(struct diff_filespec *one,
                             const char *needle, unsigned long len,
        return cnt;
  }
  
 -void diffcore_pickaxe(const char *needle, int opts)
 +static void diffcore_pickaxe_count(struct diff_options *o)
  {
 +      const char *needle = o->pickaxe;
 +      int opts = o->pickaxe_opts;
        struct diff_queue_struct *q = &diff_queued_diff;
        unsigned long len = strlen(needle);
        int i, has_changes;
                                diff_free_filepair(p);
                }
  
-       if (opts & DIFF_PICKAXE_REGEX) {
+       if (opts & DIFF_PICKAXE_REGEX)
                regfree(&regex);
-       }
  
        free(q->queue);
        *q = outq;
        return;
  }
 +
 +void diffcore_pickaxe(struct diff_options *o)
 +{
 +      /* Might want to warn when both S and G are on; I don't care... */
 +      if (o->pickaxe_opts & DIFF_PICKAXE_KIND_G)
 +              return diffcore_pickaxe_grep(o);
 +      else
 +              return diffcore_pickaxe_count(o);
 +}