struct ref *matched_src, *matched_dst;
const char *dst_value = rs[i].dst;
+
+ if (rs[i].pattern)
+ continue;
+
if (dst_value == NULL)
dst_value = rs[i].src;
return NULL;
}
+static const struct refspec *check_pattern_match(const struct refspec *rs,
+ int rs_nr,
+ const struct ref *src)
+{
+ int i;
+ for (i = 0; i < rs_nr; i++) {
+ if (rs[i].pattern && !prefixcmp(src->name, rs[i].src))
+ return rs + i;
+ }
+ return NULL;
+}
+
int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
int nr_refspec, char **refspec, int all)
{
struct refspec *rs =
parse_ref_spec(nr_refspec, (const char **) refspec);
- if (nr_refspec)
- return match_explicit_refs(src, dst, dst_tail, rs, nr_refspec);
+ if (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))
+ return -1;
/* pick the remainder */
for ( ; src; src = src->next) {
struct ref *dst_peer;
+ const struct refspec *pat = NULL;
+ char *dst_name;
if (src->peer_ref)
continue;
- dst_peer = find_ref_by_name(dst, src->name);
- if ((dst_peer && dst_peer->peer_ref) || (!dst_peer && !all))
- continue;
+ if (nr_refspec) {
+ pat = check_pattern_match(rs, nr_refspec, src);
+ if (!pat)
+ continue;
+ }
+
+ if (pat) {
+ dst_name = xmalloc(strlen(pat->dst) +
+ strlen(src->name) -
+ strlen(pat->src) + 2);
+ strcpy(dst_name, pat->dst);
+ strcat(dst_name, src->name + strlen(pat->src));
+ } else
+ 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 && !nr_refspec && !all)
+ /* Remote doesn't have it, and we have no
+ * explicit pattern, and we don't have
+ * --all. */
+ goto free_name;
if (!dst_peer) {
/* Create a new one and link it */
- int len = strlen(src->name) + 1;
+ int len = strlen(dst_name) + 1;
dst_peer = xcalloc(1, sizeof(*dst_peer) + len);
- memcpy(dst_peer->name, src->name, len);
+ memcpy(dst_peer->name, dst_name, len);
hashcpy(dst_peer->new_sha1, src->new_sha1);
link_dst_tail(dst_peer, dst_tail);
}
dst_peer->peer_ref = src;
+ free_name:
+ free(dst_name);
}
return 0;
}