Code

http*: add http_get_info_packs
authorTay Ray Chuan <rctay89@gmail.com>
Sat, 6 Jun 2009 08:43:59 +0000 (16:43 +0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 6 Jun 2009 18:03:11 +0000 (11:03 -0700)
http-push.c and http-walker.c no longer have to use fetch_index or
setup_index; they simply need to use http_get_info_packs, a new http
method, in their fetch_indices implementations.

Move fetch_index() and rename to fetch_pack_index() in http.c; this
method is not meant to be used outside of http.c. It invokes
end_url_with_slash with base_url; apart from that change, the code is
identical.

Move setup_index() and rename to fetch_and_setup_pack_index() in
http.c; this method is not meant to be used outside of http.c.

Do not immediately set ret to 0 in http-walker.c::fetch_indices();
instead do it in the HTTP_MISSING_TARGET case, to make it clear that
the HTTP_OK and HTTP_MISSING_TARGET cases both return 0.

Signed-off-by: Tay Ray Chuan <rctay89@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
http-push.c
http-walker.c
http.c
http.h

index 34905214755856c1671324c2b47e263775e27b8d..7ad3b690bbe696f50bd7bcd28ae1f5e156c4ccb3 100644 (file)
@@ -953,184 +953,23 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
        return 1;
 }
 
-static int fetch_index(unsigned char *sha1)
-{
-       int ret = 0;
-       char *hex = xstrdup(sha1_to_hex(sha1));
-       char *filename;
-       char *url;
-       char tmpfile[PATH_MAX];
-       long prev_posn = 0;
-       char range[RANGE_HEADER_SIZE];
-       struct curl_slist *range_header = NULL;
-
-       FILE *indexfile;
-       struct active_request_slot *slot;
-       struct slot_results results;
-
-       /* Don't use the index if the pack isn't there */
-       url = xmalloc(strlen(repo->url) + 64);
-       sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
-       slot = get_active_slot();
-       slot->results = &results;
-       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-       curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (results.curl_result != CURLE_OK) {
-                       ret = error("Unable to verify pack %s is available",
-                                   hex);
-                       goto cleanup_pack;
-               }
-       } else {
-               ret = error("Unable to start request");
-               goto cleanup_pack;
-       }
-
-       if (has_pack_index(sha1)) {
-               ret = 0;
-               goto cleanup_pack;
-       }
-
-       if (push_verbosely)
-               fprintf(stderr, "Getting index for pack %s\n", hex);
-
-       sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex);
-
-       filename = sha1_pack_index_name(sha1);
-       snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
-       indexfile = fopen(tmpfile, "a");
-       if (!indexfile) {
-               ret = error("Unable to open local file %s for pack index",
-                           tmpfile);
-               goto cleanup_pack;
-       }
-
-       slot = get_active_slot();
-       slot->results = &results;
-       curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
-       curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
-       slot->local = indexfile;
-
-       /*
-        * If there is data present from a previous transfer attempt,
-        * resume where it left off
-        */
-       prev_posn = ftell(indexfile);
-       if (prev_posn>0) {
-               if (push_verbosely)
-                       fprintf(stderr,
-                               "Resuming fetch of index for pack %s at byte %ld\n",
-                               hex, prev_posn);
-               sprintf(range, "Range: bytes=%ld-", prev_posn);
-               range_header = curl_slist_append(range_header, range);
-               curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
-       }
-
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (results.curl_result != CURLE_OK) {
-                       ret = error("Unable to get pack index %s\n%s", url,
-                                   curl_errorstr);
-                       goto cleanup_index;
-               }
-       } else {
-               ret = error("Unable to start request");
-               goto cleanup_index;
-       }
-
-       ret = move_temp_to_file(tmpfile, filename);
-
-cleanup_index:
-       fclose(indexfile);
-       slot->local = NULL;
-cleanup_pack:
-       free(url);
-       free(hex);
-       return ret;
-}
-
-static int setup_index(unsigned char *sha1)
-{
-       struct packed_git *new_pack;
-
-       if (fetch_index(sha1))
-               return -1;
-
-       new_pack = parse_pack_index(sha1);
-       if (!new_pack)
-               return -1; /* parse_pack_index() already issued error message */
-       new_pack->next = repo->packs;
-       repo->packs = new_pack;
-       return 0;
-}
-
 static int fetch_indices(void)
 {
-       unsigned char sha1[20];
-       char *url;
-       struct strbuf buffer = STRBUF_INIT;
-       char *data;
-       int i = 0;
-
-       struct active_request_slot *slot;
-       struct slot_results results;
+       int ret;
 
        if (push_verbosely)
                fprintf(stderr, "Getting pack list\n");
 
-       url = xmalloc(strlen(repo->url) + 20);
-       sprintf(url, "%sobjects/info/packs", repo->url);
-
-       slot = get_active_slot();
-       slot->results = &results;
-       curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (results.curl_result != CURLE_OK) {
-                       strbuf_release(&buffer);
-                       free(url);
-                       if (results.http_code == 404)
-                               return 0;
-                       else
-                               return error("%s", curl_errorstr);
-               }
-       } else {
-               strbuf_release(&buffer);
-               free(url);
-               return error("Unable to start request");
-       }
-       free(url);
-
-       data = buffer.buf;
-       while (i < buffer.len) {
-               switch (data[i]) {
-               case 'P':
-                       i++;
-                       if (i + 52 < buffer.len &&
-                           !prefixcmp(data + i, " pack-") &&
-                           !prefixcmp(data + i + 46, ".pack\n")) {
-                               get_sha1_hex(data + i + 6, sha1);
-                               setup_index(sha1);
-                               i += 51;
-                               break;
-                       }
-               default:
-                       while (data[i] != '\n')
-                               i++;
-               }
-               i++;
+       switch (http_get_info_packs(repo->url, &repo->packs)) {
+       case HTTP_OK:
+       case HTTP_MISSING_TARGET:
+               ret = 0;
+               break;
+       default:
+               ret = -1;
        }
 
-       strbuf_release(&buffer);
-       return 0;
+       return ret;
 }
 
 static void one_remote_object(const char *hex)
index 032a7be62ea1b21d97e444fe9e3d38f22fe6a24f..ac343fd191571895eec0bec0089620e64a23f709 100644 (file)
@@ -368,124 +368,6 @@ static void prefetch(struct walker *walker, unsigned char *sha1)
 #endif
 }
 
-static int fetch_index(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
-{
-       int ret = 0;
-       char *hex = xstrdup(sha1_to_hex(sha1));
-       char *filename;
-       char *url;
-       char tmpfile[PATH_MAX];
-       long prev_posn = 0;
-       char range[RANGE_HEADER_SIZE];
-       struct curl_slist *range_header = NULL;
-
-       FILE *indexfile;
-       struct active_request_slot *slot;
-       struct slot_results results;
-
-       /* Don't use the index if the pack isn't there */
-       url = xmalloc(strlen(repo->base) + 64);
-       sprintf(url, "%s/objects/pack/pack-%s.pack", repo->base, hex);
-       slot = get_active_slot();
-       slot->results = &results;
-       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-       curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (results.curl_result != CURLE_OK) {
-                       ret = error("Unable to verify pack %s is available",
-                                    hex);
-                       goto cleanup_pack;
-               }
-       } else {
-               ret = error("Unable to start request");
-               goto cleanup_pack;
-       }
-
-       if (has_pack_index(sha1)) {
-               ret = 0;
-               goto cleanup_pack;
-       }
-
-       if (walker->get_verbosely)
-               fprintf(stderr, "Getting index for pack %s\n", hex);
-
-       sprintf(url, "%s/objects/pack/pack-%s.idx", repo->base, hex);
-
-       filename = sha1_pack_index_name(sha1);
-       snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
-       indexfile = fopen(tmpfile, "a");
-       if (!indexfile) {
-               ret = error("Unable to open local file %s for pack index",
-                           tmpfile);
-               goto cleanup_pack;
-       }
-
-       slot = get_active_slot();
-       slot->results = &results;
-       curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
-       curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
-       slot->local = indexfile;
-
-       /*
-        * If there is data present from a previous transfer attempt,
-        * resume where it left off
-        */
-       prev_posn = ftell(indexfile);
-       if (prev_posn>0) {
-               if (walker->get_verbosely)
-                       fprintf(stderr,
-                               "Resuming fetch of index for pack %s at byte %ld\n",
-                               hex, prev_posn);
-               sprintf(range, "Range: bytes=%ld-", prev_posn);
-               range_header = curl_slist_append(range_header, range);
-               curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
-       }
-
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (results.curl_result != CURLE_OK) {
-                       ret = error("Unable to get pack index %s\n%s", url,
-                                   curl_errorstr);
-                       goto cleanup_index;
-               }
-       } else {
-               ret = error("Unable to start request");
-               goto cleanup_index;
-       }
-
-       ret = move_temp_to_file(tmpfile, filename);
-
-cleanup_index:
-       fclose(indexfile);
-       slot->local = NULL;
-cleanup_pack:
-       free(url);
-       free(hex);
-       return ret;
-}
-
-static int setup_index(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
-{
-       struct packed_git *new_pack;
-       if (has_pack_file(sha1))
-               return 0; /* don't list this as something we can get */
-
-       if (fetch_index(walker, repo, sha1))
-               return -1;
-
-       new_pack = parse_pack_index(sha1);
-       if (!new_pack)
-               return -1; /* parse_pack_index() already issued error message */
-       new_pack->next = repo->packs;
-       repo->packs = new_pack;
-       return 0;
-}
-
 static void process_alternates_response(void *callback_data)
 {
        struct alternates_request *alt_req =
@@ -684,15 +566,7 @@ static void fetch_alternates(struct walker *walker, const char *base)
 
 static int fetch_indices(struct walker *walker, struct alt_base *repo)
 {
-       unsigned char sha1[20];
-       char *url;
-       struct strbuf buffer = STRBUF_INIT;
-       char *data;
-       int i = 0;
-       int ret = 0;
-
-       struct active_request_slot *slot;
-       struct slot_results results;
+       int ret;
 
        if (repo->got_indices)
                return 0;
@@ -700,57 +574,17 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo)
        if (walker->get_verbosely)
                fprintf(stderr, "Getting pack list for %s\n", repo->base);
 
-       url = xmalloc(strlen(repo->base) + 21);
-       sprintf(url, "%s/objects/info/packs", repo->base);
-
-       slot = get_active_slot();
-       slot->results = &results;
-       curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
-       if (start_active_slot(slot)) {
-               run_active_slot(slot);
-               if (results.curl_result != CURLE_OK) {
-                       if (missing_target(&results)) {
-                               repo->got_indices = 1;
-                               goto cleanup;
-                       } else {
-                               repo->got_indices = 0;
-                               ret = error("%s", curl_errorstr);
-                               goto cleanup;
-                       }
-               }
-       } else {
+       switch (http_get_info_packs(repo->base, &repo->packs)) {
+       case HTTP_OK:
+       case HTTP_MISSING_TARGET:
+               repo->got_indices = 1;
+               ret = 0;
+               break;
+       default:
                repo->got_indices = 0;
-               ret = error("Unable to start request");
-               goto cleanup;
+               ret = -1;
        }
 
-       data = buffer.buf;
-       while (i < buffer.len) {
-               switch (data[i]) {
-               case 'P':
-                       i++;
-                       if (i + 52 <= buffer.len &&
-                           !prefixcmp(data + i, " pack-") &&
-                           !prefixcmp(data + i + 46, ".pack\n")) {
-                               get_sha1_hex(data + i + 6, sha1);
-                               setup_index(walker, repo, sha1);
-                               i += 51;
-                               break;
-                       }
-               default:
-                       while (i < buffer.len && data[i] != '\n')
-                               i++;
-               }
-               i++;
-       }
-
-       repo->got_indices = 1;
-cleanup:
-       strbuf_release(&buffer);
-       free(url);
        return ret;
 }
 
diff --git a/http.c b/http.c
index 2a493720126009fad0eba12fcadbae7264d5b72b..96d83d5c3cfaea66ae9471b84024e34fdd7d5b3b 100644 (file)
--- a/http.c
+++ b/http.c
@@ -790,3 +790,167 @@ int http_fetch_ref(const char *base, struct ref *ref)
        free(url);
        return ret;
 }
+
+/* Helpers for fetching packs */
+static int fetch_pack_index(unsigned char *sha1, const char *base_url)
+{
+       int ret = 0;
+       char *hex = xstrdup(sha1_to_hex(sha1));
+       char *filename;
+       char *url;
+       char tmpfile[PATH_MAX];
+       long prev_posn = 0;
+       char range[RANGE_HEADER_SIZE];
+       struct strbuf buf = STRBUF_INIT;
+       struct curl_slist *range_header = NULL;
+
+       FILE *indexfile;
+       struct active_request_slot *slot;
+       struct slot_results results;
+
+       /* Don't use the index if the pack isn't there */
+       end_url_with_slash(&buf, base_url);
+       strbuf_addf(&buf, "objects/pack/pack-%s.pack", hex);
+       url = strbuf_detach(&buf, 0);
+
+       slot = get_active_slot();
+       slot->results = &results;
+       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+       curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
+       if (start_active_slot(slot)) {
+               run_active_slot(slot);
+               if (results.curl_result != CURLE_OK) {
+                       ret = error("Unable to verify pack %s is available",
+                                   hex);
+                       goto cleanup_pack;
+               }
+       } else {
+               ret = error("Unable to start request");
+               goto cleanup_pack;
+       }
+
+       if (has_pack_index(sha1)) {
+               ret = 0;
+               goto cleanup_pack;
+       }
+
+       if (http_is_verbose)
+               fprintf(stderr, "Getting index for pack %s\n", hex);
+
+       end_url_with_slash(&buf, base_url);
+       strbuf_addf(&buf, "objects/pack/pack-%s.idx", hex);
+       url = strbuf_detach(&buf, NULL);
+
+       filename = sha1_pack_index_name(sha1);
+       snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
+       indexfile = fopen(tmpfile, "a");
+       if (!indexfile) {
+               ret = error("Unable to open local file %s for pack index",
+                           tmpfile);
+               goto cleanup_pack;
+       }
+
+       slot = get_active_slot();
+       slot->results = &results;
+       curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
+       curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
+       curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
+       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
+       curl_easy_setopt(slot->curl, CURLOPT_URL, url);
+       curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
+       slot->local = indexfile;
+
+       /*
+        * If there is data present from a previous transfer attempt,
+        * resume where it left off
+        */
+       prev_posn = ftell(indexfile);
+       if (prev_posn>0) {
+               if (http_is_verbose)
+                       fprintf(stderr,
+                               "Resuming fetch of index for pack %s at byte %ld\n",
+                               hex, prev_posn);
+               sprintf(range, "Range: bytes=%ld-", prev_posn);
+               range_header = curl_slist_append(range_header, range);
+               curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
+       }
+
+       if (start_active_slot(slot)) {
+               run_active_slot(slot);
+               if (results.curl_result != CURLE_OK) {
+                       ret = error("Unable to get pack index %s\n%s",
+                                   url, curl_errorstr);
+                       goto cleanup_index;
+               }
+       } else {
+               ret = error("Unable to start request");
+               goto cleanup_index;
+       }
+
+       ret = move_temp_to_file(tmpfile, filename);
+
+cleanup_index:
+       fclose(indexfile);
+       slot->local = NULL;
+cleanup_pack:
+       free(hex);
+       free(url);
+       return ret;
+}
+
+static int fetch_and_setup_pack_index(struct packed_git **packs_head,
+       unsigned char *sha1, const char *base_url)
+{
+       struct packed_git *new_pack;
+
+       if (fetch_pack_index(sha1, base_url))
+               return -1;
+
+       new_pack = parse_pack_index(sha1);
+       if (!new_pack)
+               return -1; /* parse_pack_index() already issued error message */
+       new_pack->next = *packs_head;
+       *packs_head = new_pack;
+       return 0;
+}
+
+int http_get_info_packs(const char *base_url, struct packed_git **packs_head)
+{
+       int ret = 0, i = 0;
+       char *url, *data;
+       struct strbuf buf = STRBUF_INIT;
+       unsigned char sha1[20];
+
+       end_url_with_slash(&buf, base_url);
+       strbuf_addstr(&buf, "objects/info/packs");
+       url = strbuf_detach(&buf, NULL);
+
+       ret = http_get_strbuf(url, &buf, HTTP_NO_CACHE);
+       if (ret != HTTP_OK)
+               goto cleanup;
+
+       data = buf.buf;
+       while (i < buf.len) {
+               switch (data[i]) {
+               case 'P':
+                       i++;
+                       if (i + 52 <= buf.len &&
+                           !prefixcmp(data + i, " pack-") &&
+                           !prefixcmp(data + i + 46, ".pack\n")) {
+                               get_sha1_hex(data + i + 6, sha1);
+                               fetch_and_setup_pack_index(packs_head, sha1,
+                                                     base_url);
+                               i += 51;
+                               break;
+                       }
+               default:
+                       while (i < buf.len && data[i] != '\n')
+                               i++;
+               }
+               i++;
+       }
+
+cleanup:
+       free(url);
+       return ret;
+}
diff --git a/http.h b/http.h
index 3d878d5126bbe1f40311cb7f7860847028da12f7..180b1c2ae2fc1ae2115d9f3f65ec062703feb9df 100644 (file)
--- a/http.h
+++ b/http.h
@@ -146,4 +146,8 @@ int http_error(const char *url, int ret);
 
 extern int http_fetch_ref(const char *base, struct ref *ref);
 
+/* Helpers for fetching packs */
+extern int http_get_info_packs(const char *base_url,
+       struct packed_git **packs_head);
+
 #endif /* HTTP_H */