static void prefetch(struct walker *walker, unsigned char *sha1) { struct object_request *newreq; struct object_request *tail; struct walker_data *data = walker->data; char *filename = sha1_file_name(sha1); newreq = xmalloc(sizeof(*newreq)); newreq->walker = walker; hashcpy(newreq->sha1, sha1); newreq->repo = data->alt; newreq->url = NULL; newreq->local = -1; newreq->state = WAITING; snprintf(newreq->filename, sizeof(newreq->filename), "%s", filename); snprintf(newreq->tmpfile, sizeof(newreq->tmpfile), "%s.temp", filename); newreq->slot = NULL; newreq->next = NULL; if (object_queue_head == NULL) { object_queue_head = newreq; } else { tail = object_queue_head; while (tail->next != NULL) { tail = tail->next; } tail->next = newreq; } #ifdef USE_CURL_MULTI fill_active_slots(); step_active_slots(); #endif }
static void prefetch(struct walker *walker, unsigned char *sha1) { struct object_request *newreq; struct object_request *tail; struct walker_data *data = walker->data; newreq = xmalloc(sizeof(*newreq)); newreq->walker = walker; hashcpy(newreq->sha1, sha1); newreq->repo = data->alt; newreq->state = WAITING; newreq->req = NULL; newreq->next = NULL; http_is_verbose = walker->get_verbosely; if (object_queue_head == NULL) { object_queue_head = newreq; } else { tail = object_queue_head; while (tail->next != NULL) tail = tail->next; tail->next = newreq; } #ifdef USE_CURL_MULTI fill_active_slots(); step_active_slots(); #endif }
static void add_fetch_request(struct object *obj) { struct transfer_request *request; check_locks(); /* * Don't fetch the object if it's known to exist locally * or is already in the request queue */ if (remote_dir_exists[obj->oid.hash[0]] == -1) get_remote_object_list(obj->oid.hash[0]); if (obj->flags & (LOCAL | FETCHING)) return; obj->flags |= FETCHING; request = xmalloc(sizeof(*request)); request->obj = obj; request->url = NULL; request->lock = NULL; request->headers = NULL; request->state = NEED_FETCH; request->next = request_queue_head; request_queue_head = request; #ifdef USE_CURL_MULTI fill_active_slots(); step_active_slots(); #endif }
static void fetch_alternates(struct walker *walker, const char *base) { struct strbuf buffer = STRBUF_INIT; char *url; struct active_request_slot *slot; struct alternates_request alt_req; struct walker_data *cdata = walker->data; /* * If another request has already started fetching alternates, * wait for them to arrive and return to processing this request's * curl message */ #ifdef USE_CURL_MULTI while (cdata->got_alternates == 0) { step_active_slots(); } #endif /* Nothing to do if they've already been fetched */ if (cdata->got_alternates == 1) return; /* Start the fetch */ cdata->got_alternates = 0; if (walker->get_verbosely) fprintf(stderr, "Getting alternates list for %s\n", base); url = xmalloc(strlen(base) + 31); sprintf(url, "%s/objects/info/http-alternates", base); /* * Use a callback to process the result, since another request * may fail and need to have alternates loaded before continuing */ slot = get_active_slot(); slot->callback_func = process_alternates_response; alt_req.walker = walker; slot->callback_data = &alt_req; 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); alt_req.base = base; alt_req.url = url; alt_req.buffer = &buffer; alt_req.http_specific = 1; alt_req.slot = slot; if (start_active_slot(slot)) run_active_slot(slot); else cdata->got_alternates = -1; strbuf_release(&buffer); free(url); }
static int fetch_object(struct walker *walker, struct alt_base *repo, unsigned char *sha1) { char *hex = sha1_to_hex(sha1); int ret = 0; struct object_request *obj_req = object_queue_head; while (obj_req != NULL && hashcmp(obj_req->sha1, sha1)) obj_req = obj_req->next; if (obj_req == NULL) return error("Couldn't find request for %s in the queue", hex); if (has_sha1_file(obj_req->sha1)) { abort_object_request(obj_req); return 0; } #ifdef USE_CURL_MULTI while (obj_req->state == WAITING) { step_active_slots(); } #else start_object_request(walker, obj_req); #endif while (obj_req->state == ACTIVE) { run_active_slot(obj_req->slot); } if (obj_req->local != -1) { close(obj_req->local); obj_req->local = -1; } if (obj_req->state == ABORTED) { ret = error("Request for %s aborted", hex); } else if (obj_req->curl_result != CURLE_OK && obj_req->http_code != 416) { if (missing_target(obj_req)) ret = -1; /* Be silent, it is probably in a pack. */ else ret = error("%s (curl_result = %d, http_code = %ld, sha1 = %s)", obj_req->errorstr, obj_req->curl_result, obj_req->http_code, hex); } else if (obj_req->zret != Z_STREAM_END) { walker->corrupt_object_found++; ret = error("File %s (%s) corrupt", hex, obj_req->url); } else if (hashcmp(obj_req->sha1, obj_req->real_sha1)) { ret = error("File %s has bad hash", hex); } else if (obj_req->rename < 0) { ret = error("unable to write sha1 filename %s", obj_req->filename); } release_object_request(obj_req); return ret; }
static int add_send_request(struct object *obj, struct remote_lock *lock) { struct transfer_request *request; struct packed_git *target; /* Keep locks active */ check_locks(); /* * Don't push the object if it's known to exist on the remote * or is already in the request queue */ if (remote_dir_exists[obj->oid.hash[0]] == -1) get_remote_object_list(obj->oid.hash[0]); if (obj->flags & (REMOTE | PUSHING)) return 0; target = find_sha1_pack(obj->oid.hash, repo->packs); if (target) { obj->flags |= REMOTE; return 0; } obj->flags |= PUSHING; request = xmalloc(sizeof(*request)); request->obj = obj; request->url = NULL; request->lock = lock; request->headers = NULL; request->state = NEED_PUSH; request->next = request_queue_head; request_queue_head = request; #ifdef USE_CURL_MULTI fill_active_slots(); step_active_slots(); #endif return 1; }
static int fetch_object(struct walker *walker, struct alt_base *repo, unsigned char *sha1) { char *hex = sha1_to_hex(sha1); int ret = 0; struct object_request *obj_req = object_queue_head; struct http_object_request *req; while (obj_req != NULL && hashcmp(obj_req->sha1, sha1)) obj_req = obj_req->next; if (obj_req == NULL) return error("Couldn't find request for %s in the queue", hex); if (has_sha1_file(obj_req->sha1)) { if (obj_req->req != NULL) abort_http_object_request(obj_req->req); abort_object_request(obj_req); return 0; } #ifdef USE_CURL_MULTI while (obj_req->state == WAITING) step_active_slots(); #else start_object_request(walker, obj_req); #endif /* * obj_req->req might change when fetching alternates in the callback * process_object_response; therefore, the "shortcut" variable, req, * is used only after we're done with slots. */ while (obj_req->state == ACTIVE) run_active_slot(obj_req->req->slot); req = obj_req->req; if (req->localfile != -1) { close(req->localfile); req->localfile = -1; } if (obj_req->state == ABORTED) { ret = error("Request for %s aborted", hex); } else if (req->curl_result != CURLE_OK && req->http_code != 416) { if (missing_target(req)) ret = -1; /* Be silent, it is probably in a pack. */ else ret = error("%s (curl_result = %d, http_code = %ld, sha1 = %s)", req->errorstr, req->curl_result, req->http_code, hex); } else if (req->zret != Z_STREAM_END) { walker->corrupt_object_found++; ret = error("File %s (%s) corrupt", hex, req->url); } else if (hashcmp(obj_req->sha1, req->real_sha1)) { ret = error("File %s has bad hash", hex); } else if (req->rename < 0) { ret = error("unable to write sha1 filename %s", sha1_file_name(req->sha1)); } release_http_object_request(req); release_object_request(obj_req); return ret; }