From 6e66bf3c7953d68a5a2d57300e0f9077cf1767bf Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 8 Jun 2007 01:43:05 +0200 Subject: 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 Signed-off-by: Junio C Hamano --- remote.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/remote.c b/remote.c index d904616cd..33c8e5055 100644 --- a/remote.c +++ b/remote.c @@ -501,16 +501,16 @@ static struct ref *find_ref_by_name(struct ref *list, const char *name) return NULL; } -static int check_pattern_match(struct refspec *rs, int rs_nr, struct ref *src) +static const struct refspec *check_pattern_match(const struct refspec *rs, + int rs_nr, + const struct ref *src) { int i; - if (!rs_nr) - return 1; for (i = 0; i < rs_nr; i++) { if (rs[i].pattern && !prefixcmp(src->name, rs[i].src)) - return 1; + return rs + i; } - return 0; + return NULL; } 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, /* 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; - if (!check_pattern_match(rs, nr_refspec, src)) - continue; + if (nr_refspec) { + pat = check_pattern_match(rs, nr_refspec, src); + if (!pat) + continue; + } - dst_peer = find_ref_by_name(dst, src->name); + 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 = strdup(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. */ - continue; + 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. */ - continue; + 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; } -- cgit v1.2.1 From bcdb34f70d59d4e090ef9a34e4b77fe7e5369f3e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 8 Jun 2007 00:43:22 -0700 Subject: Test wildcard push/fetch Signed-off-by: Junio C Hamano --- t/t5516-fetch-push.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100755 t/t5516-fetch-push.sh diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh new file mode 100755 index 000000000..dba018f66 --- /dev/null +++ b/t/t5516-fetch-push.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +test_description='fetching and pushing, with or without wildcard' + +. ./test-lib.sh + +D=`pwd` + +mk_empty () { + rm -fr testrepo && + mkdir testrepo && + ( + cd testrepo && + git init + ) +} + +test_expect_success setup ' + + : >path1 && + git add path1 && + test_tick && + git commit -a -m repo && + the_commit=$(git show-ref -s --verify refs/heads/master) + +' + +test_expect_success 'fetch without wildcard' ' + mk_empty && + ( + cd testrepo && + git fetch .. refs/heads/master:refs/remotes/origin/master && + + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'fetch with wildcard' ' + mk_empty && + ( + cd testrepo && + git config remote.up.url .. && + git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" && + git fetch up && + + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push without wildcard' ' + mk_empty && + + git push testrepo refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push with wildcard' ' + mk_empty && + + git push testrepo "refs/heads/*:refs/remotes/origin/*" && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_done -- cgit v1.2.1