diff options
Diffstat (limited to 'remote.c')
-rw-r--r-- | remote.c | 32 |
1 files changed, 29 insertions, 3 deletions
@@ -817,6 +817,26 @@ static struct ref *make_linked_ref(const char *name, struct ref ***tail) return ret; } +static char *guess_ref(const char *name, struct ref *peer) +{ + struct strbuf buf = STRBUF_INIT; + unsigned char sha1[20]; + + const char *r = resolve_ref(peer->name, sha1, 1, NULL); + if (!r) + return NULL; + + if (!prefixcmp(r, "refs/heads/")) + strbuf_addstr(&buf, "refs/heads/"); + else if (!prefixcmp(r, "refs/tags/")) + strbuf_addstr(&buf, "refs/tags/"); + else + return NULL; + + strbuf_addstr(&buf, name); + return strbuf_detach(&buf, NULL); +} + static int match_explicit(struct ref *src, struct ref *dst, struct ref ***dst_tail, struct refspec *rs, @@ -825,6 +845,7 @@ static int match_explicit(struct ref *src, struct ref *dst, struct ref *matched_src, *matched_dst; const char *dst_value = rs->dst; + char *dst_guess; if (rs->pattern) return errs; @@ -871,10 +892,15 @@ static int match_explicit(struct ref *src, struct ref *dst, case 0: if (!memcmp(dst_value, "refs/", 5)) matched_dst = make_linked_ref(dst_value, dst_tail); + else if((dst_guess = guess_ref(dst_value, matched_src))) + matched_dst = make_linked_ref(dst_guess, dst_tail); else - error("dst refspec %s does not match any " - "existing ref on the remote and does " - "not start with refs/.", dst_value); + error("unable to push to unqualified destination: %s\n" + "The destination refspec neither matches an " + "existing ref on the remote nor\n" + "begins with refs/, and we are unable to " + "guess a prefix based on the source ref.", + dst_value); break; default: matched_dst = NULL; |