X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=remote.c;h=91e3b112bb5ffa151a8ede9391d3bd88ea4d3500;hb=efb98b44536300f5daed25da3650033a1ce7fdef;hp=91cbb72ddeba1c60dab7aad2105e1c004ea6e198;hpb=761adeb4dba3305d0810b5340a71783d29484fb0;p=git.git diff --git a/remote.c b/remote.c index 91cbb72dd..91e3b112b 100644 --- a/remote.c +++ b/remote.c @@ -2,6 +2,16 @@ #include "remote.h" #include "refs.h" +static struct refspec s_tag_refspec = { + 0, + 1, + 0, + "refs/tags/", + "refs/tags/" +}; + +const struct refspec *tag_refspec = &s_tag_refspec; + struct counted_string { size_t len; const char *s; @@ -288,7 +298,7 @@ static void read_branches_file(struct remote *remote) remote->fetch_tags = 1; /* always auto-follow */ } -static int handle_config(const char *key, const char *value) +static int handle_config(const char *key, const char *value, void *cb) { const char *name; const char *subkey; @@ -410,7 +420,7 @@ static void read_config(void) current_branch = make_branch(head_ref + strlen("refs/heads/"), 0); } - git_config(handle_config); + git_config(handle_config, NULL); alias_all_urls(); } @@ -434,6 +444,16 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp } rhs = strrchr(lhs, ':'); + + /* + * Before going on, special case ":" (or "+:") as a refspec + * for matching refs. + */ + if (!fetch && rhs == lhs && rhs[1] == '\0') { + rs[i].matching = 1; + continue; + } + if (rhs) { rhs++; rlen = strlen(rhs); @@ -855,7 +875,7 @@ static int match_explicit(struct ref *src, struct ref *dst, const char *dst_value = rs->dst; char *dst_guess; - if (rs->pattern) + if (rs->pattern || rs->matching) return errs; matched_src = matched_dst = NULL; @@ -945,13 +965,23 @@ static const struct refspec *check_pattern_match(const struct refspec *rs, const struct ref *src) { int i; + int matching_refs = -1; for (i = 0; i < rs_nr; i++) { + if (rs[i].matching && + (matching_refs == -1 || rs[i].force)) { + matching_refs = i; + continue; + } + if (rs[i].pattern && !prefixcmp(src->name, rs[i].src) && src->name[strlen(rs[i].src)] == '/') return rs + i; } - return NULL; + if (matching_refs != -1) + return rs + matching_refs; + else + return NULL; } /* @@ -962,11 +992,16 @@ static const struct refspec *check_pattern_match(const struct refspec *rs, int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, int nr_refspec, const char **refspec, int flags) { - struct refspec *rs = - parse_push_refspec(nr_refspec, (const char **) refspec); + struct refspec *rs; int send_all = flags & MATCH_REFS_ALL; int send_mirror = flags & MATCH_REFS_MIRROR; + static const char *default_refspec[] = { ":", 0 }; + if (!nr_refspec) { + nr_refspec = 1; + refspec = default_refspec; + } + rs = parse_push_refspec(nr_refspec, (const char **) refspec); if (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec)) return -1; @@ -977,48 +1012,50 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, char *dst_name; if (src->peer_ref) continue; - if (nr_refspec) { - pat = check_pattern_match(rs, nr_refspec, src); - if (!pat) - continue; - } - else if (!send_mirror && prefixcmp(src->name, "refs/heads/")) + + pat = check_pattern_match(rs, nr_refspec, src); + if (!pat) + continue; + + if (pat->matching) { /* * "matching refs"; traditionally we pushed everything * including refs outside refs/heads/ hierarchy, but * that does not make much sense these days. */ - continue; + if (!send_mirror && prefixcmp(src->name, "refs/heads/")) + continue; + dst_name = xstrdup(src->name); - if (pat) { + } else { 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, dst_side); 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) { + if (dst_peer->peer_ref) + /* We're already sending something to this ref. */ + goto free_name; + + } else { + if (pat->matching && !(send_all || send_mirror)) + /* + * Remote doesn't have it, and we have no + * explicit pattern, and we don't have + * --all nor --mirror. + */ + goto free_name; - if (!dst_peer && !nr_refspec && !(send_all || send_mirror)) - /* - * Remote doesn't have it, and we have no - * explicit pattern, and we don't have - * --all nor --mirror. - */ - goto free_name; - if (!dst_peer) { /* Create a new one and link it */ dst_peer = make_linked_ref(dst_name, dst_tail); hashcpy(dst_peer->new_sha1, src->new_sha1); } dst_peer->peer_ref = src; - if (pat) - dst_peer->force = pat->force; + dst_peer->force = pat->force; free_name: free(dst_name); }