summaryrefslogtreecommitdiff
path: root/http-fetch.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2005-10-10 23:22:02 -0700
committerJunio C Hamano <junkio@cox.net>2005-10-11 22:05:09 -0700
commit94fa447ace56bc6514bdd66cafe8f56f0e3ce936 (patch)
tree48fa9a3fb29727a6cc7c00f63768c6828cab4622 /http-fetch.c
parentd06b689a933f6d2130f8afdf1ac0ddb83eeb59ab (diff)
downloadgit-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.c55
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);