diff options
author | Junio C Hamano <junkio@cox.net> | 2005-10-10 23:22:02 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2005-10-11 22:05:09 -0700 |
commit | 94fa447ace56bc6514bdd66cafe8f56f0e3ce936 (patch) | |
tree | 48fa9a3fb29727a6cc7c00f63768c6828cab4622 /http-fetch.c | |
parent | d06b689a933f6d2130f8afdf1ac0ddb83eeb59ab (diff) | |
download | git-94fa447ace56bc6514bdd66cafe8f56f0e3ce936.tar.gz |
Quote reference names while fetching with curl.
curl_escape ought to do this, but we should not let it quote
slashes (nobody said refs/tags cannot have subdirectories), so
we roll our own safer version. With this, the last part of
git-clone from Martin's moodle repository that used to fail now
works, which reads:
$ git-http-fetch -v -a -w 'tags/MOODLE_15_MERGED **INVALID**' \
'tags/MOODLE_15_MERGED **INVALID**' \
http://locke.catalyst.net.nz/git/moodle.git/
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'http-fetch.c')
-rw-r--r-- | http-fetch.c | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/http-fetch.c b/http-fetch.c index e537591edb..0aba891754 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -969,9 +969,54 @@ int fetch(unsigned char *sha1) alt->base); } +static inline int needs_quote(int ch) +{ + switch (ch) { + case '/': case '-': case '.': + case 'A'...'Z': case 'a'...'z': case '0'...'9': + return 0; + default: + return 1; + } +} + +static inline int hex(int v) +{ + if (v < 10) return '0' + v; + else return 'A' + v - 10; +} + +static char *quote_ref_url(const char *base, const char *ref) +{ + const char *cp; + char *dp, *qref; + int len, baselen, ch; + + baselen = strlen(base); + len = baselen + 6; /* "refs/" + NUL */ + for (cp = ref; (ch = *cp) != 0; cp++, len++) + if (needs_quote(ch)) + len += 2; /* extra two hex plus replacement % */ + qref = xmalloc(len); + memcpy(qref, base, baselen); + memcpy(qref + baselen, "refs/", 5); + for (cp = ref, dp = qref + baselen + 5; (ch = *cp) != 0; cp++) { + if (needs_quote(ch)) { + *dp++ = '%'; + *dp++ = hex((ch >> 4) & 0xF); + *dp++ = hex(ch & 0xF); + } + else + *dp++ = ch; + } + *dp = 0; + + return qref; +} + int fetch_ref(char *ref, unsigned char *sha1) { - char *url, *posn; + char *url; char hex[42]; struct buffer buffer; char *base = alt->base; @@ -981,13 +1026,7 @@ int fetch_ref(char *ref, unsigned char *sha1) buffer.buffer = hex; hex[41] = '\0'; - url = xmalloc(strlen(base) + 6 + strlen(ref)); - strcpy(url, base); - posn = url + strlen(base); - strcpy(posn, "refs/"); - posn += 5; - strcpy(posn, ref); - + url = quote_ref_url(base, ref); slot = get_active_slot(); curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer); |