Merge branch 'jc/remote'
authorJunio C Hamano <gitster@pobox.com>
Sat, 16 Jun 2007 08:22:45 +0000 (01:22 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 16 Jun 2007 08:22:45 +0000 (01:22 -0700)
* jc/remote:
git-push: Update description of refspecs and add examples
remote.c: "git-push frotz" should update what matches at the source.
remote.c: fix "git push" weak match disambiguation
remote.c: minor clean-up of match_explicit()
remote.c: refactor creation of new dst ref
remote.c: refactor match_explicit_refs()

1  2 
remote.c
diff --combined remote.c
index 54c9401a6bc37ad1c138c6c2c68e79b7796006d5,754d5130e3895acc59e43eb1d46338a835ad72ef..500ca4d968753485ac38d44e238e93ab86372c1c
+++ b/remote.c
@@@ -333,7 -333,6 +333,6 @@@ static int count_refspec_match(const ch
        for (weak_match = match = 0; refs; refs = refs->next) {
                char *name = refs->name;
                int namelen = strlen(name);
-               int weak_match;
  
                if (namelen < patlen ||
                    memcmp(name + namelen - patlen, pattern, patlen))
@@@ -406,90 -405,96 +405,96 @@@ static struct ref *try_explicit_object_
        return ref;
  }
  
- static int match_explicit_refs(struct ref *src, struct ref *dst,
-                              struct ref ***dst_tail, struct refspec *rs,
-                              int rs_nr)
+ static struct ref *make_dst(const char *name, struct ref ***dst_tail)
  {
-       int i, errs;
-       for (i = errs = 0; i < rs_nr; i++) {
-               struct ref *matched_src, *matched_dst;
+       struct ref *dst;
+       size_t len;
  
-               const char *dst_value = rs[i].dst;
+       len = strlen(name) + 1;
+       dst = xcalloc(1, sizeof(*dst) + len);
+       memcpy(dst->name, name, len);
+       link_dst_tail(dst, dst_tail);
+       return dst;
+ }
  
-               if (rs[i].pattern)
-                       continue;
+ static int match_explicit(struct ref *src, struct ref *dst,
+                         struct ref ***dst_tail,
+                         struct refspec *rs,
+                         int errs)
+ {
+       struct ref *matched_src, *matched_dst;
  
-               if (dst_value == NULL)
-                       dst_value = rs[i].src;
+       const char *dst_value = rs->dst;
  
-               matched_src = matched_dst = NULL;
-               switch (count_refspec_match(rs[i].src, src, &matched_src)) {
-               case 1:
-                       break;
-               case 0:
-                       /* The source could be in the get_sha1() format
-                        * not a reference name.  :refs/other is a
-                        * way to delete 'other' ref at the remote end.
-                        */
-                       matched_src = try_explicit_object_name(rs[i].src);
-                       if (matched_src)
-                               break;
-                       errs = 1;
-                       error("src refspec %s does not match any.",
-                             rs[i].src);
-                       break;
-               default:
-                       errs = 1;
-                       error("src refspec %s matches more than one.",
-                             rs[i].src);
-                       break;
-               }
-               switch (count_refspec_match(dst_value, dst, &matched_dst)) {
-               case 1:
-                       break;
-               case 0:
-                       if (!memcmp(dst_value, "refs/", 5)) {
-                               int len = strlen(dst_value) + 1;
-                               matched_dst = xcalloc(1, sizeof(*dst) + len);
-                               memcpy(matched_dst->name, dst_value, len);
-                               link_dst_tail(matched_dst, dst_tail);
-                       }
-                       else if (!strcmp(rs[i].src, dst_value) &&
-                                matched_src) {
-                               /* pushing "master:master" when
-                                * remote does not have master yet.
-                                */
-                               int len = strlen(matched_src->name) + 1;
-                               matched_dst = xcalloc(1, sizeof(*dst) + len);
-                               memcpy(matched_dst->name, matched_src->name,
-                                      len);
-                               link_dst_tail(matched_dst, dst_tail);
-                       }
-                       else {
-                               errs = 1;
-                               error("dst refspec %s does not match any "
-                                     "existing ref on the remote and does "
-                                     "not start with refs/.", dst_value);
-                       }
-                       break;
-               default:
-                       errs = 1;
-                       error("dst refspec %s matches more than one.",
-                             dst_value);
+       if (rs->pattern)
+               return errs;
+       matched_src = matched_dst = NULL;
+       switch (count_refspec_match(rs->src, src, &matched_src)) {
+       case 1:
+               break;
+       case 0:
+               /* The source could be in the get_sha1() format
+                * not a reference name.  :refs/other is a
+                * way to delete 'other' ref at the remote end.
+                */
+               matched_src = try_explicit_object_name(rs->src);
+               if (matched_src)
                        break;
-               }
-               if (errs)
-                       continue;
-               if (matched_dst->peer_ref) {
-                       errs = 1;
-                       error("dst ref %s receives from more than one src.",
-                             matched_dst->name);
-               }
-               else {
-                       matched_dst->peer_ref = matched_src;
-                       matched_dst->force = rs[i].force;
-               }
+               error("src refspec %s does not match any.",
+                     rs->src);
+               break;
+       default:
+               matched_src = NULL;
+               error("src refspec %s matches more than one.",
+                     rs->src);
+               break;
+       }
+       if (!matched_src)
+               errs = 1;
+       if (dst_value == NULL)
+               dst_value = matched_src->name;
+       switch (count_refspec_match(dst_value, dst, &matched_dst)) {
+       case 1:
+               break;
+       case 0:
+               if (!memcmp(dst_value, "refs/", 5))
+                       matched_dst = make_dst(dst_value, dst_tail);
+               else
+                       error("dst refspec %s does not match any "
+                             "existing ref on the remote and does "
+                             "not start with refs/.", dst_value);
+               break;
+       default:
+               matched_dst = NULL;
+               error("dst refspec %s matches more than one.",
+                     dst_value);
+               break;
+       }
+       if (errs || matched_dst == NULL)
+               return 1;
+       if (matched_dst->peer_ref) {
+               errs = 1;
+               error("dst ref %s receives from more than one src.",
+                     matched_dst->name);
+       }
+       else {
+               matched_dst->peer_ref = matched_src;
+               matched_dst->force = rs->force;
        }
+       return errs;
+ }
+ static int match_explicit_refs(struct ref *src, struct ref *dst,
+                              struct ref ***dst_tail, struct refspec *rs,
+                              int rs_nr)
+ {
+       int i, errs;
+       for (i = errs = 0; i < rs_nr; i++)
+               errs |= match_explicit(src, dst, dst_tail, &rs[i], errs);
        return -errs;
  }
  
@@@ -513,6 -518,11 +518,11 @@@ static const struct refspec *check_patt
        return NULL;
  }
  
+ /*
+  * Note. This is used only by "push"; refspec matching rules for
+  * push and fetch are subtly different, so do not try to reuse it
+  * without thinking.
+  */
  int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
               int nr_refspec, char **refspec, int all)
  {
                }
  
                if (pat) {
 -                      dst_name = xmalloc(strlen(pat->dst) +
 +                      const char *dst_side = pat->dst ? pat->dst : pat->src;
 +                      dst_name = xmalloc(strlen(dst_side) +
                                           strlen(src->name) -
                                           strlen(pat->src) + 2);
 -                      strcpy(dst_name, pat->dst);
 +                      strcpy(dst_name, dst_side);
                        strcat(dst_name, src->name + strlen(pat->src));
                } else
 -                      dst_name = strdup(src->name);
 +                      dst_name = xstrdup(src->name);
                dst_peer = find_ref_by_name(dst, dst_name);
                if (dst_peer && dst_peer->peer_ref)
                        /* We're already sending something to this ref. */
                        goto free_name;
                if (!dst_peer) {
                        /* Create a new one and link it */
-                       int len = strlen(dst_name) + 1;
-                       dst_peer = xcalloc(1, sizeof(*dst_peer) + len);
-                       memcpy(dst_peer->name, dst_name, len);
+                       dst_peer = make_dst(dst_name, dst_tail);
                        hashcpy(dst_peer->new_sha1, src->new_sha1);
-                       link_dst_tail(dst_peer, dst_tail);
                }
                dst_peer->peer_ref = src;
        free_name: