Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Fri, 17 Oct 2008 08:52:32 +0000 (01:52 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 17 Oct 2008 08:52:32 +0000 (01:52 -0700)
* maint:
t1301-shared-repo.sh: don't let a default ACL interfere with the test
git-check-attr(1): add output and example sections
xdiff-interface.c: strip newline (and cr) from line before pattern matching
t4018-diff-funcname: demonstrate end of line funcname matching flaw
t4018-diff-funcname: rework negated last expression test
Typo "does not exists" when git remote update remote.
remote.c: correct the check for a leading '/' in a remote name
Add testcase to ensure merging an early part of a branch is done properly

Conflicts:
t/t7600-merge.sh

1  2 
remote.c
t/t4018-diff-funcname.sh
t/t7600-merge.sh
xdiff-interface.c
diff --combined remote.c
index d5efadd93d63b2c39176763eb325ecddb6c1215a,7688f3b04d197007bce64a2bcc54c0b62c0b5922..8a04066d6142823183033aaff8754febe31ad1b0
+++ b/remote.c
@@@ -69,7 -69,7 +69,7 @@@ static const char *alias_url(const cha
        if (!longest)
                return url;
  
 -      ret = malloc(rewrite[longest_i]->baselen +
 +      ret = xmalloc(rewrite[longest_i]->baselen +
                     (strlen(url) - longest->len) + 1);
        strcpy(ret, rewrite[longest_i]->base);
        strcpy(ret + rewrite[longest_i]->baselen, url + longest->len);
@@@ -152,7 -152,7 +152,7 @@@ static struct branch *make_branch(cons
                ret->name = xstrndup(name, len);
        else
                ret->name = xstrdup(name);
 -      refname = malloc(strlen(name) + strlen("refs/heads/") + 1);
 +      refname = xmalloc(strlen(name) + strlen("refs/heads/") + 1);
        strcpy(refname, "refs/heads/");
        strcpy(refname + strlen("refs/heads/"), ret->name);
        ret->refname = refname;
@@@ -245,7 -245,7 +245,7 @@@ static void read_branches_file(struct r
  {
        const char *slash = strchr(remote->name, '/');
        char *frag;
 -      struct strbuf branch;
 +      struct strbuf branch = STRBUF_INIT;
        int n = slash ? slash - remote->name : 1000;
        FILE *f = fopen(git_path("branches/%.*s", n, remote->name), "r");
        char *s, *p;
         * #branch specified.  The "master" (or specified) branch is
         * fetched and stored in the local branch of the same name.
         */
 -      strbuf_init(&branch, 0);
        frag = strchr(p, '#');
        if (frag) {
                *(frag++) = '\0';
@@@ -341,13 -342,14 +341,14 @@@ static int handle_config(const char *ke
        if (prefixcmp(key,  "remote."))
                return 0;
        name = key + 7;
+       if (*name == '/') {
+               warning("Config remote shorthand cannot begin with '/': %s",
+                       name);
+               return 0;
+       }
        subkey = strrchr(name, '.');
        if (!subkey)
                return error("Config with no key for remote %s", name);
-       if (*subkey == '/') {
-               warning("Config remote shorthand cannot begin with '/': %s", name);
-               return 0;
-       }
        remote = make_remote(name, subkey - name);
        if (!strcmp(subkey, ".mirror"))
                remote->mirror = git_config_bool(key, value);
@@@ -448,26 -450,6 +449,26 @@@ static int verify_refname(char *name, i
        return result;
  }
  
 +/*
 + * This function frees a refspec array.
 + * Warning: code paths should be checked to ensure that the src
 + *          and dst pointers are always freeable pointers as well
 + *          as the refspec pointer itself.
 + */
 +static void free_refspecs(struct refspec *refspec, int nr_refspec)
 +{
 +      int i;
 +
 +      if (!refspec)
 +              return;
 +
 +      for (i = 0; i < nr_refspec; i++) {
 +              free(refspec[i].src);
 +              free(refspec[i].dst);
 +      }
 +      free(refspec);
 +}
 +
  static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
  {
        int i;
  
   invalid:
        if (verify) {
 -              free(rs);
 +              /*
 +               * nr_refspec must be greater than zero and i must be valid
 +               * since it is only possible to reach this point from within
 +               * the for loop above.
 +               */
 +              free_refspecs(rs, i+1);
                return NULL;
        }
        die("Invalid refspec '%s'", refspec[i]);
@@@ -603,7 -580,7 +604,7 @@@ int valid_fetch_refspec(const char *fet
        struct refspec *refspec;
  
        refspec = parse_refspec_internal(1, fetch_refspec, 1, 1);
 -      free(refspec);
 +      free_refspecs(refspec, 1);
        return !!refspec;
  }
  
@@@ -612,7 -589,7 +613,7 @@@ struct refspec *parse_fetch_refspec(in
        return parse_refspec_internal(nr_refspec, refspec, 1, 0);
  }
  
 -struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
 +static struct refspec *parse_push_refspec(int nr_refspec, const char **refspec)
  {
        return parse_refspec_internal(nr_refspec, refspec, 0, 0);
  }
@@@ -750,7 -727,8 +751,7 @@@ int remote_find_tracking(struct remote 
  
  struct ref *alloc_ref(unsigned namelen)
  {
 -      struct ref *ret = xmalloc(sizeof(struct ref) + namelen);
 -      memset(ret, 0, sizeof(struct ref) + namelen);
 +      struct ref *ret = xcalloc(1, sizeof(struct ref) + namelen);
        return ret;
  }
  
@@@ -781,7 -759,7 +782,7 @@@ struct ref *copy_ref_list(const struct 
        return ret;
  }
  
 -void free_ref(struct ref *ref)
 +static void free_ref(struct ref *ref)
  {
        if (!ref)
                return;
diff --combined t/t4018-diff-funcname.sh
index 0320e19770fbb4d16ace939d0e23a8c6b878ab05,398bf4b5d8e3d85562563059eaeb7bc8b8e4ce59..be541348c6f8d469428e2fcc7abaf6d25168c08f
@@@ -32,7 -32,7 +32,7 @@@ EO
  
  sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java
  
 -builtin_patterns="bibtex java pascal ruby tex"
 +builtin_patterns="bibtex html java objc pascal php python ruby tex"
  for p in $builtin_patterns
  do
        test_expect_success "builtin $p pattern compiles" '
@@@ -65,7 -65,14 +65,14 @@@ test_expect_success 'custom pattern' 
  
  test_expect_success 'last regexp must not be negated' '
        git config diff.java.funcname "!static" &&
-       test_must_fail git diff --no-index Beer.java Beer-correct.java
+       git diff --no-index Beer.java Beer-correct.java 2>&1 |
+       grep "fatal: Last expression must not be negated:"
+ '
+ test_expect_success 'pattern which matches to end of line' '
+       git config diff.java.funcname "Beer$" &&
+       git diff --no-index Beer.java Beer-correct.java |
+       grep "^@@.*@@ Beer"
  '
  
  test_expect_success 'alternation in pattern' '
diff --combined t/t7600-merge.sh
index 7313ac278cb7cb1d741e49f261e65d929ddeffb7,5abce3119bb2d0c0379b28d40b4919b8b0de0171..3a36a95b9ac42b35e680109df4daf87fc219fb53
@@@ -230,10 -230,6 +230,10 @@@ test_expect_success 'test option parsin
        test_must_fail git merge
  '
  
 +test_expect_success 'reject non-strategy with a git-merge-foo name' '
 +      test_must_fail git merge -s index c1
 +'
 +
  test_expect_success 'merge c0 with c1' '
        git reset --hard c0 &&
        git merge c1 &&
@@@ -511,13 -507,30 +511,37 @@@ test_expect_success 'in-index merge' 
  
  test_debug 'gitk --all'
  
 +test_expect_success 'refresh the index before merging' '
 +      git reset --hard c1 &&
 +      sleep 1 &&
 +      touch file &&
 +      git merge c3
 +'
 +
+ cat >expected <<EOF
+ Merge branch 'c5' (early part)
+ EOF
+ test_expect_success 'merge early part of c2' '
+       git reset --hard c3 &&
+       echo c4 > c4.c &&
+       git add c4.c &&
+       git commit -m c4 &&
+       git tag c4 &&
+       echo c5 > c5.c &&
+       git add c5.c &&
+       git commit -m c5 &&
+       git tag c5 &&
+       git reset --hard c3 &&
+       echo c6 > c6.c &&
+       git add c6.c &&
+       git commit -m c6 &&
+       git tag c6 &&
+       git merge c5~1 &&
+       git show -s --pretty=format:%s HEAD > actual &&
+       test_cmp actual expected
+ '
  test_debug 'gitk --all'
  
  test_done
diff --combined xdiff-interface.c
index f3f6db3297e4fd367d7af05a4755037aaf2aaf42,3bf83f81e38d4a4cc114f3c577241cf7b9eddc7e..49e06af710ceee5538eb10f0c6cf9c30f31748b4
@@@ -1,12 -1,5 +1,12 @@@
  #include "cache.h"
  #include "xdiff-interface.h"
 +#include "strbuf.h"
 +
 +struct xdiff_emit_state {
 +      xdiff_emit_consume_fn consume;
 +      void *consume_callback_data;
 +      struct strbuf remainder;
 +};
  
  static int parse_num(char **cp_p, int *num_p)
  {
@@@ -62,13 -55,13 +62,13 @@@ static void consume_one(void *priv_, ch
                unsigned long this_size;
                ep = memchr(s, '\n', size);
                this_size = (ep == NULL) ? size : (ep - s + 1);
 -              priv->consume(priv, s, this_size);
 +              priv->consume(priv->consume_callback_data, s, this_size);
                size -= this_size;
                s += this_size;
        }
  }
  
 -int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
 +static int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
  {
        struct xdiff_emit_state *priv = priv_;
        int i;
        for (i = 0; i < nbuf; i++) {
                if (mb[i].ptr[mb[i].size-1] != '\n') {
                        /* Incomplete line */
 -                      priv->remainder = xrealloc(priv->remainder,
 -                                                 priv->remainder_size +
 -                                                 mb[i].size);
 -                      memcpy(priv->remainder + priv->remainder_size,
 -                             mb[i].ptr, mb[i].size);
 -                      priv->remainder_size += mb[i].size;
 +                      strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);
                        continue;
                }
  
                /* we have a complete line */
 -              if (!priv->remainder) {
 +              if (!priv->remainder.len) {
                        consume_one(priv, mb[i].ptr, mb[i].size);
                        continue;
                }
 -              priv->remainder = xrealloc(priv->remainder,
 -                                         priv->remainder_size +
 -                                         mb[i].size);
 -              memcpy(priv->remainder + priv->remainder_size,
 -                     mb[i].ptr, mb[i].size);
 -              consume_one(priv, priv->remainder,
 -                          priv->remainder_size + mb[i].size);
 -              free(priv->remainder);
 -              priv->remainder = NULL;
 -              priv->remainder_size = 0;
 +              strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);
 +              consume_one(priv, priv->remainder.buf, priv->remainder.len);
 +              strbuf_reset(&priv->remainder);
        }
 -      if (priv->remainder) {
 -              consume_one(priv, priv->remainder, priv->remainder_size);
 -              free(priv->remainder);
 -              priv->remainder = NULL;
 -              priv->remainder_size = 0;
 +      if (priv->remainder.len) {
 +              consume_one(priv, priv->remainder.buf, priv->remainder.len);
 +              strbuf_reset(&priv->remainder);
        }
        return 0;
  }
@@@ -134,25 -141,6 +134,25 @@@ int xdi_diff(mmfile_t *mf1, mmfile_t *m
        return xdl_diff(&a, &b, xpp, xecfg, xecb);
  }
  
 +int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
 +                xdiff_emit_consume_fn fn, void *consume_callback_data,
 +                xpparam_t const *xpp,
 +                xdemitconf_t const *xecfg, xdemitcb_t *xecb)
 +{
 +      int ret;
 +      struct xdiff_emit_state state;
 +
 +      memset(&state, 0, sizeof(state));
 +      state.consume = fn;
 +      state.consume_callback_data = consume_callback_data;
 +      xecb->outf = xdiff_outf;
 +      xecb->priv = &state;
 +      strbuf_init(&state.remainder, 0);
 +      ret = xdi_diff(mf1, mf2, xpp, xecfg, xecb);
 +      strbuf_release(&state.remainder);
 +      return ret;
 +}
 +
  int read_mmfile(mmfile_t *ptr, const char *filename)
  {
        struct stat st;
@@@ -194,11 -182,10 +194,21 @@@ static long ff_regexp(const char *line
        char *line_buffer;
        struct ff_regs *regs = priv;
        regmatch_t pmatch[2];
 -      int result = 0, i;
 +      int i;
 +      int result = -1;
 +
 +      /* Exclude terminating newline (and cr) from matching */
 +      if (len > 0 && line[len-1] == '\n') {
++              if (len > 1 && line[len-2] == '\r')
++                      len -= 2;
++              else
++                      len--;
++      }
++
++      line_buffer = xstrndup(line, len); /* make NUL terminated */
+       /* Exclude terminating newline (and cr) from matching */
+       if (len > 0 && line[len-1] == '\n') {
                if (len > 1 && line[len-2] == '\r')
                        len -= 2;
                else
  
        for (i = 0; i < regs->nr; i++) {
                struct ff_reg *reg = regs->array + i;
 -              if (reg->negate ^ !!regexec(&reg->re,
 -                                      line_buffer, 2, pmatch, 0)) {
 -                      free(line_buffer);
 -                      return -1;
 +              if (!regexec(&reg->re, line_buffer, 2, pmatch, 0)) {
 +                      if (reg->negate)
 +                              goto fail;
 +                      break;
                }
        }
 +      if (regs->nr <= i)
 +              goto fail;
        i = pmatch[1].rm_so >= 0 ? 1 : 0;
        line += pmatch[i].rm_so;
        result = pmatch[i].rm_eo - pmatch[i].rm_so;
        if (result > buffer_size)
                result = buffer_size;
        else
 -              while (result > 0 && (isspace(line[result - 1]) ||
 -                                      line[result - 1] == '\n'))
 +              while (result > 0 && (isspace(line[result - 1])))
                        result--;
        memcpy(buffer, line, result);
 + fail:
        free(line_buffer);
        return result;
  }
@@@ -262,23 -247,3 +272,23 @@@ void xdiff_set_find_func(xdemitconf_t *
                value = ep + 1;
        }
  }
 +
 +int git_xmerge_style = -1;
 +
 +int git_xmerge_config(const char *var, const char *value, void *cb)
 +{
 +      if (!strcasecmp(var, "merge.conflictstyle")) {
 +              if (!value)
 +                      die("'%s' is not a boolean", var);
 +              if (!strcmp(value, "diff3"))
 +                      git_xmerge_style = XDL_MERGE_DIFF3;
 +              else if (!strcmp(value, "merge"))
 +                      git_xmerge_style = 0;
 +              else
 +                      die("unknown style '%s' given for '%s'",
 +                          value, var);
 +              return 0;
 +      }
 +      return git_default_config(var, value, cb);
 +}
 +