static int fetch_pack(const unsigned char *sha1) { struct packed_git *target; char filename[PATH_MAX]; if (setup_indices()) return -1; target = find_sha1_pack(sha1, packs); if (!target) return error("Couldn't find %s: not separate or in any pack", sha1_to_hex(sha1)); if (get_verbosely) { fprintf(stderr, "Getting pack %s\n", sha1_to_hex(target->sha1)); fprintf(stderr, " which contains %s\n", sha1_to_hex(sha1)); } sprintf(filename, "%s/objects/pack/pack-%s.pack", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_name(target->sha1), sha1_to_hex(target->sha1), 1); sprintf(filename, "%s/objects/pack/pack-%s.idx", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_index_name(target->sha1), sha1_to_hex(target->sha1), 1); install_packed_git(target); return 0; }
static int verify_one_pack(const char *path, unsigned int flags) { char arg[PATH_MAX]; int len; int verbose = flags & VERIFY_PACK_VERBOSE; int stat_only = flags & VERIFY_PACK_STAT_ONLY; struct packed_git *pack; int err; len = strlcpy(arg, path, PATH_MAX); if (len >= PATH_MAX) return error("name too long: %s", path); /* * In addition to "foo.idx" we accept "foo.pack" and "foo"; * normalize these forms to "foo.idx" for add_packed_git(). */ if (has_extension(arg, ".pack")) { strcpy(arg + len - 5, ".idx"); len--; } else if (!has_extension(arg, ".idx")) { if (len + 4 >= PATH_MAX) return error("name too long: %s.idx", arg); strcpy(arg + len, ".idx"); len += 4; } /* * add_packed_git() uses our buffer (containing "foo.idx") to * build the pack filename ("foo.pack"). Make sure it fits. */ if (len + 1 >= PATH_MAX) { arg[len - 4] = '\0'; return error("name too long: %s.pack", arg); } pack = add_packed_git(arg, len, 1); if (!pack) return error("packfile %s not found.", arg); install_packed_git(pack); if (!stat_only) err = verify_pack(pack); else err = open_pack_index(pack); if (verbose || stat_only) { if (err) printf("%s: bad\n", pack->pack_name); else { show_pack_info(pack, flags); if (!stat_only) printf("%s: ok\n", pack->pack_name); } } return err; }
static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1) { char *url; struct packed_git *target; struct packed_git **lst; FILE *packfile; char *filename; char tmpfile[PATH_MAX]; int ret; long prev_posn = 0; char range[RANGE_HEADER_SIZE]; struct curl_slist *range_header = NULL; struct walker_data *data = walker->data; struct active_request_slot *slot; struct slot_results results; if (fetch_indices(walker, repo)) return -1; target = find_sha1_pack(sha1, repo->packs); if (!target) return -1; if (walker->get_verbosely) { fprintf(stderr, "Getting pack %s\n", sha1_to_hex(target->sha1)); fprintf(stderr, " which contains %s\n", sha1_to_hex(sha1)); } url = xmalloc(strlen(repo->base) + 65); sprintf(url, "%s/objects/pack/pack-%s.pack", repo->base, sha1_to_hex(target->sha1)); filename = sha1_pack_name(target->sha1); snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename); packfile = fopen(tmpfile, "a"); if (!packfile) return error("Unable to open local file %s for pack", tmpfile); slot = get_active_slot(); slot->results = &results; curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile); curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite); curl_easy_setopt(slot->curl, CURLOPT_URL, url); curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, data->no_pragma_header); slot->local = packfile; /* If there is data present from a previous transfer attempt, resume where it left off */ prev_posn = ftell(packfile); if (prev_posn>0) { if (walker->get_verbosely) fprintf(stderr, "Resuming fetch of pack %s at byte %ld\n", sha1_to_hex(target->sha1), 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) { fclose(packfile); return error("Unable to get pack file %s\n%s", url, curl_errorstr); } } else { fclose(packfile); return error("Unable to start request"); } target->pack_size = ftell(packfile); fclose(packfile); ret = move_temp_to_file(tmpfile, filename); if (ret) return ret; lst = &repo->packs; while (*lst != target) lst = &((*lst)->next); *lst = (*lst)->next; if (verify_pack(target)) return -1; install_packed_git(target); return 0; }