Skip to content

Commit 6e66bf3

Browse files
raalkmlgitster
authored andcommitted
Fix push with refspecs containing wildcards
Otherwise git push 'remote-name' 'refs/heads/*:refs/remotes/other/*' will consider references in "refs/heads" of the remote repository "remote-name", instead of the ones in "refs/remotes/other", which the given refspec clearly means. Signed-off-by: Alex Riesen <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a6080a0 commit 6e66bf3

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

remote.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -501,16 +501,16 @@ static struct ref *find_ref_by_name(struct ref *list, const char *name)
501501
return NULL;
502502
}
503503

504-
static int check_pattern_match(struct refspec *rs, int rs_nr, struct ref *src)
504+
static const struct refspec *check_pattern_match(const struct refspec *rs,
505+
int rs_nr,
506+
const struct ref *src)
505507
{
506508
int i;
507-
if (!rs_nr)
508-
return 1;
509509
for (i = 0; i < rs_nr; i++) {
510510
if (rs[i].pattern && !prefixcmp(src->name, rs[i].src))
511-
return 1;
511+
return rs + i;
512512
}
513-
return 0;
513+
return NULL;
514514
}
515515

516516
int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
@@ -525,29 +525,44 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
525525
/* pick the remainder */
526526
for ( ; src; src = src->next) {
527527
struct ref *dst_peer;
528+
const struct refspec *pat = NULL;
529+
char *dst_name;
528530
if (src->peer_ref)
529531
continue;
530-
if (!check_pattern_match(rs, nr_refspec, src))
531-
continue;
532+
if (nr_refspec) {
533+
pat = check_pattern_match(rs, nr_refspec, src);
534+
if (!pat)
535+
continue;
536+
}
532537

533-
dst_peer = find_ref_by_name(dst, src->name);
538+
if (pat) {
539+
dst_name = xmalloc(strlen(pat->dst) +
540+
strlen(src->name) -
541+
strlen(pat->src) + 2);
542+
strcpy(dst_name, pat->dst);
543+
strcat(dst_name, src->name + strlen(pat->src));
544+
} else
545+
dst_name = strdup(src->name);
546+
dst_peer = find_ref_by_name(dst, dst_name);
534547
if (dst_peer && dst_peer->peer_ref)
535548
/* We're already sending something to this ref. */
536-
continue;
549+
goto free_name;
537550
if (!dst_peer && !nr_refspec && !all)
538551
/* Remote doesn't have it, and we have no
539552
* explicit pattern, and we don't have
540553
* --all. */
541-
continue;
554+
goto free_name;
542555
if (!dst_peer) {
543556
/* Create a new one and link it */
544-
int len = strlen(src->name) + 1;
557+
int len = strlen(dst_name) + 1;
545558
dst_peer = xcalloc(1, sizeof(*dst_peer) + len);
546-
memcpy(dst_peer->name, src->name, len);
559+
memcpy(dst_peer->name, dst_name, len);
547560
hashcpy(dst_peer->new_sha1, src->new_sha1);
548561
link_dst_tail(dst_peer, dst_tail);
549562
}
550563
dst_peer->peer_ref = src;
564+
free_name:
565+
free(dst_name);
551566
}
552567
return 0;
553568
}

0 commit comments

Comments
 (0)