Merge branch 'jk/dumb-http-finalize'
The dumb-http code regressed when the result of re-indexing a pack yielded an *.idx file that differs in content from the *.idx file it downloaded from the remote. This has been corrected by no longer relying on the *.idx file we got from the remote. * jk/dumb-http-finalize: packfile: use oidread() instead of hashcpy() to fill object_id packfile: use object_id in find_pack_entry_one() packfile: convert find_sha1_pack() to use object_id http-walker: use object_id instead of bare hash packfile: warn people away from parse_packed_git() packfile: drop sha1_pack_index_name() packfile: drop sha1_pack_name() packfile: drop has_pack_index() dumb-http: store downloaded pack idx as tempfile t5550: count fetches in "previously-fetched .idx" test midx: avoid duplicate packed_git entries
This commit is contained in:
@ -966,8 +966,7 @@ static int store_object(
|
|||||||
if (e->idx.offset) {
|
if (e->idx.offset) {
|
||||||
duplicate_count_by_type[type]++;
|
duplicate_count_by_type[type]++;
|
||||||
return 1;
|
return 1;
|
||||||
} else if (find_sha1_pack(oid.hash,
|
} else if (find_oid_pack(&oid, get_all_packs(the_repository))) {
|
||||||
get_all_packs(the_repository))) {
|
|
||||||
e->type = type;
|
e->type = type;
|
||||||
e->pack_id = MAX_PACK_ID;
|
e->pack_id = MAX_PACK_ID;
|
||||||
e->idx.offset = 1; /* just not zero! */
|
e->idx.offset = 1; /* just not zero! */
|
||||||
@ -1167,8 +1166,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
|
|||||||
duplicate_count_by_type[OBJ_BLOB]++;
|
duplicate_count_by_type[OBJ_BLOB]++;
|
||||||
truncate_pack(&checkpoint);
|
truncate_pack(&checkpoint);
|
||||||
|
|
||||||
} else if (find_sha1_pack(oid.hash,
|
} else if (find_oid_pack(&oid, get_all_packs(the_repository))) {
|
||||||
get_all_packs(the_repository))) {
|
|
||||||
e->type = OBJ_BLOB;
|
e->type = OBJ_BLOB;
|
||||||
e->pack_id = MAX_PACK_ID;
|
e->pack_id = MAX_PACK_ID;
|
||||||
e->idx.offset = 1; /* just not zero! */
|
e->idx.offset = 1; /* just not zero! */
|
||||||
|
@ -1556,7 +1556,7 @@ static int want_object_in_pack_one(struct packed_git *p,
|
|||||||
if (p == *found_pack)
|
if (p == *found_pack)
|
||||||
offset = *found_offset;
|
offset = *found_offset;
|
||||||
else
|
else
|
||||||
offset = find_pack_entry_one(oid->hash, p);
|
offset = find_pack_entry_one(oid, p);
|
||||||
|
|
||||||
if (offset) {
|
if (offset) {
|
||||||
if (!*found_pack) {
|
if (!*found_pack) {
|
||||||
@ -3984,7 +3984,7 @@ static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid)
|
|||||||
while (p) {
|
while (p) {
|
||||||
if ((!p->pack_local || p->pack_keep ||
|
if ((!p->pack_local || p->pack_keep ||
|
||||||
p->pack_keep_in_core) &&
|
p->pack_keep_in_core) &&
|
||||||
find_pack_entry_one(oid->hash, p)) {
|
find_pack_entry_one(oid, p)) {
|
||||||
last_found = p;
|
last_found = p;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "packfile.h"
|
#include "packfile.h"
|
||||||
#include "object-store-ll.h"
|
#include "object-store-ll.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
|
||||||
#define BLKSIZE 512
|
#define BLKSIZE 512
|
||||||
|
|
||||||
@ -591,6 +592,7 @@ static void load_all(void)
|
|||||||
int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) {
|
int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) {
|
||||||
int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl;
|
int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl;
|
||||||
struct llist *ignore;
|
struct llist *ignore;
|
||||||
|
struct strbuf idx_name = STRBUF_INIT;
|
||||||
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
|
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
|
||||||
|
|
||||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||||
@ -688,7 +690,7 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
|
|||||||
pl = red = pack_list_difference(local_packs, min);
|
pl = red = pack_list_difference(local_packs, min);
|
||||||
while (pl) {
|
while (pl) {
|
||||||
printf("%s\n%s\n",
|
printf("%s\n%s\n",
|
||||||
sha1_pack_index_name(pl->pack->hash),
|
odb_pack_name(&idx_name, pl->pack->hash, "idx"),
|
||||||
pl->pack->pack_name);
|
pl->pack->pack_name);
|
||||||
pl = pl->next;
|
pl = pl->next;
|
||||||
}
|
}
|
||||||
@ -699,5 +701,6 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
|
|||||||
pack_list_free(red);
|
pack_list_free(red);
|
||||||
pack_list_free(min);
|
pack_list_free(min);
|
||||||
llist_free(ignore);
|
llist_free(ignore);
|
||||||
|
strbuf_release(&idx_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
|
|||||||
for (p = get_all_packs(the_repository); p; p = p->next) {
|
for (p = get_all_packs(the_repository); p; p = p->next) {
|
||||||
if (!p->pack_promisor)
|
if (!p->pack_promisor)
|
||||||
continue;
|
continue;
|
||||||
if (find_pack_entry_one(oid->hash, p))
|
if (find_pack_entry_one(oid, p))
|
||||||
goto promisor_pack_found;
|
goto promisor_pack_found;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -144,7 +144,7 @@ no_promisor_pack_found:
|
|||||||
* are sure the ref is good and not sending it to
|
* are sure the ref is good and not sending it to
|
||||||
* rev-list for verification.
|
* rev-list for verification.
|
||||||
*/
|
*/
|
||||||
if (new_pack && find_pack_entry_one(oid->hash, new_pack))
|
if (new_pack && find_pack_entry_one(oid, new_pack))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (fprintf(rev_list_in, "%s\n", oid_to_hex(oid)) < 0)
|
if (fprintf(rev_list_in, "%s\n", oid_to_hex(oid)) < 0)
|
||||||
|
@ -309,7 +309,7 @@ static void start_fetch_packed(struct transfer_request *request)
|
|||||||
struct transfer_request *check_request = request_queue_head;
|
struct transfer_request *check_request = request_queue_head;
|
||||||
struct http_pack_request *preq;
|
struct http_pack_request *preq;
|
||||||
|
|
||||||
target = find_sha1_pack(request->obj->oid.hash, repo->packs);
|
target = find_oid_pack(&request->obj->oid, repo->packs);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", oid_to_hex(&request->obj->oid));
|
fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", oid_to_hex(&request->obj->oid));
|
||||||
repo->can_update_info_refs = 0;
|
repo->can_update_info_refs = 0;
|
||||||
@ -681,7 +681,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
|
|||||||
get_remote_object_list(obj->oid.hash[0]);
|
get_remote_object_list(obj->oid.hash[0]);
|
||||||
if (obj->flags & (REMOTE | PUSHING))
|
if (obj->flags & (REMOTE | PUSHING))
|
||||||
return 0;
|
return 0;
|
||||||
target = find_sha1_pack(obj->oid.hash, repo->packs);
|
target = find_oid_pack(&obj->oid, repo->packs);
|
||||||
if (target) {
|
if (target) {
|
||||||
obj->flags |= REMOTE;
|
obj->flags |= REMOTE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -147,14 +147,14 @@ static int fill_active_slot(void *data UNUSED)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prefetch(struct walker *walker, unsigned char *sha1)
|
static void prefetch(struct walker *walker, const struct object_id *oid)
|
||||||
{
|
{
|
||||||
struct object_request *newreq;
|
struct object_request *newreq;
|
||||||
struct walker_data *data = walker->data;
|
struct walker_data *data = walker->data;
|
||||||
|
|
||||||
newreq = xmalloc(sizeof(*newreq));
|
newreq = xmalloc(sizeof(*newreq));
|
||||||
newreq->walker = walker;
|
newreq->walker = walker;
|
||||||
oidread(&newreq->oid, sha1, the_repository->hash_algo);
|
oidcpy(&newreq->oid, oid);
|
||||||
newreq->repo = data->alt;
|
newreq->repo = data->alt;
|
||||||
newreq->state = WAITING;
|
newreq->state = WAITING;
|
||||||
newreq->req = NULL;
|
newreq->req = NULL;
|
||||||
@ -422,7 +422,8 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigned char *sha1)
|
static int http_fetch_pack(struct walker *walker, struct alt_base *repo,
|
||||||
|
const struct object_id *oid)
|
||||||
{
|
{
|
||||||
struct packed_git *target;
|
struct packed_git *target;
|
||||||
int ret;
|
int ret;
|
||||||
@ -431,7 +432,7 @@ static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigne
|
|||||||
|
|
||||||
if (fetch_indices(walker, repo))
|
if (fetch_indices(walker, repo))
|
||||||
return -1;
|
return -1;
|
||||||
target = find_sha1_pack(sha1, repo->packs);
|
target = find_oid_pack(oid, repo->packs);
|
||||||
if (!target)
|
if (!target)
|
||||||
return -1;
|
return -1;
|
||||||
close_pack_index(target);
|
close_pack_index(target);
|
||||||
@ -440,7 +441,7 @@ static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigne
|
|||||||
fprintf(stderr, "Getting pack %s\n",
|
fprintf(stderr, "Getting pack %s\n",
|
||||||
hash_to_hex(target->hash));
|
hash_to_hex(target->hash));
|
||||||
fprintf(stderr, " which contains %s\n",
|
fprintf(stderr, " which contains %s\n",
|
||||||
hash_to_hex(sha1));
|
oid_to_hex(oid));
|
||||||
}
|
}
|
||||||
|
|
||||||
preq = new_http_pack_request(target->hash, repo->base);
|
preq = new_http_pack_request(target->hash, repo->base);
|
||||||
@ -477,9 +478,9 @@ static void abort_object_request(struct object_request *obj_req)
|
|||||||
release_object_request(obj_req);
|
release_object_request(obj_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fetch_object(struct walker *walker, unsigned char *hash)
|
static int fetch_object(struct walker *walker, const struct object_id *oid)
|
||||||
{
|
{
|
||||||
char *hex = hash_to_hex(hash);
|
char *hex = oid_to_hex(oid);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct object_request *obj_req = NULL;
|
struct object_request *obj_req = NULL;
|
||||||
struct http_object_request *req;
|
struct http_object_request *req;
|
||||||
@ -487,7 +488,7 @@ static int fetch_object(struct walker *walker, unsigned char *hash)
|
|||||||
|
|
||||||
list_for_each(pos, head) {
|
list_for_each(pos, head) {
|
||||||
obj_req = list_entry(pos, struct object_request, node);
|
obj_req = list_entry(pos, struct object_request, node);
|
||||||
if (hasheq(obj_req->oid.hash, hash, the_repository->hash_algo))
|
if (oideq(&obj_req->oid, oid))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!obj_req)
|
if (!obj_req)
|
||||||
@ -548,20 +549,20 @@ static int fetch_object(struct walker *walker, unsigned char *hash)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fetch(struct walker *walker, unsigned char *hash)
|
static int fetch(struct walker *walker, const struct object_id *oid)
|
||||||
{
|
{
|
||||||
struct walker_data *data = walker->data;
|
struct walker_data *data = walker->data;
|
||||||
struct alt_base *altbase = data->alt;
|
struct alt_base *altbase = data->alt;
|
||||||
|
|
||||||
if (!fetch_object(walker, hash))
|
if (!fetch_object(walker, oid))
|
||||||
return 0;
|
return 0;
|
||||||
while (altbase) {
|
while (altbase) {
|
||||||
if (!http_fetch_pack(walker, altbase, hash))
|
if (!http_fetch_pack(walker, altbase, oid))
|
||||||
return 0;
|
return 0;
|
||||||
fetch_alternates(walker, data->alt->base);
|
fetch_alternates(walker, data->alt->base);
|
||||||
altbase = altbase->next;
|
altbase = altbase->next;
|
||||||
}
|
}
|
||||||
return error("Unable to find %s under %s", hash_to_hex(hash),
|
return error("Unable to find %s under %s", oid_to_hex(oid),
|
||||||
data->alt->base);
|
data->alt->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
http.c
43
http.c
@ -19,6 +19,7 @@
|
|||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
#include "object-file.h"
|
#include "object-file.h"
|
||||||
#include "object-store-ll.h"
|
#include "object-store-ll.h"
|
||||||
|
#include "tempfile.h"
|
||||||
|
|
||||||
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
|
static struct trace_key trace_curl = TRACE_KEY_INIT(CURL);
|
||||||
static int trace_curl_data = 1;
|
static int trace_curl_data = 1;
|
||||||
@ -2390,8 +2391,24 @@ static char *fetch_pack_index(unsigned char *hash, const char *base_url)
|
|||||||
strbuf_addf(&buf, "objects/pack/pack-%s.idx", hash_to_hex(hash));
|
strbuf_addf(&buf, "objects/pack/pack-%s.idx", hash_to_hex(hash));
|
||||||
url = strbuf_detach(&buf, NULL);
|
url = strbuf_detach(&buf, NULL);
|
||||||
|
|
||||||
strbuf_addf(&buf, "%s.temp", sha1_pack_index_name(hash));
|
/*
|
||||||
tmp = strbuf_detach(&buf, NULL);
|
* Don't put this into packs/, since it's just temporary and we don't
|
||||||
|
* want to confuse it with our local .idx files. We'll generate our
|
||||||
|
* own index if we choose to download the matching packfile.
|
||||||
|
*
|
||||||
|
* It's tempting to use xmks_tempfile() here, but it's important that
|
||||||
|
* the file not exist, otherwise http_get_file() complains. So we
|
||||||
|
* create a filename that should be unique, and then just register it
|
||||||
|
* as a tempfile so that it will get cleaned up on exit.
|
||||||
|
*
|
||||||
|
* In theory we could hold on to the tempfile and delete these as soon
|
||||||
|
* as we download the matching pack, but it would take a bit of
|
||||||
|
* refactoring. Leaving them until the process ends is probably OK.
|
||||||
|
*/
|
||||||
|
tmp = xstrfmt("%s/tmp_pack_%s.idx",
|
||||||
|
repo_get_object_directory(the_repository),
|
||||||
|
hash_to_hex(hash));
|
||||||
|
register_tempfile(tmp);
|
||||||
|
|
||||||
if (http_get_file(url, tmp, NULL) != HTTP_OK) {
|
if (http_get_file(url, tmp, NULL) != HTTP_OK) {
|
||||||
error("Unable to get pack index %s", url);
|
error("Unable to get pack index %s", url);
|
||||||
@ -2405,15 +2422,17 @@ static char *fetch_pack_index(unsigned char *hash, const char *base_url)
|
|||||||
static int fetch_and_setup_pack_index(struct packed_git **packs_head,
|
static int fetch_and_setup_pack_index(struct packed_git **packs_head,
|
||||||
unsigned char *sha1, const char *base_url)
|
unsigned char *sha1, const char *base_url)
|
||||||
{
|
{
|
||||||
struct packed_git *new_pack;
|
struct packed_git *new_pack, *p;
|
||||||
char *tmp_idx = NULL;
|
char *tmp_idx = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (has_pack_index(sha1)) {
|
/*
|
||||||
new_pack = parse_pack_index(sha1, sha1_pack_index_name(sha1));
|
* If we already have the pack locally, no need to fetch its index or
|
||||||
if (!new_pack)
|
* even add it to list; we already have all of its objects.
|
||||||
return -1; /* parse_pack_index() already issued error message */
|
*/
|
||||||
goto add_pack;
|
for (p = get_all_packs(the_repository); p; p = p->next) {
|
||||||
|
if (hasheq(p->hash, sha1, the_repository->hash_algo))
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_idx = fetch_pack_index(sha1, base_url);
|
tmp_idx = fetch_pack_index(sha1, base_url);
|
||||||
@ -2429,15 +2448,12 @@ static int fetch_and_setup_pack_index(struct packed_git **packs_head,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = verify_pack_index(new_pack);
|
ret = verify_pack_index(new_pack);
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
close_pack_index(new_pack);
|
close_pack_index(new_pack);
|
||||||
ret = finalize_object_file(tmp_idx, sha1_pack_index_name(sha1));
|
|
||||||
}
|
|
||||||
free(tmp_idx);
|
free(tmp_idx);
|
||||||
if (ret)
|
if (ret)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
add_pack:
|
|
||||||
new_pack->next = *packs_head;
|
new_pack->next = *packs_head;
|
||||||
*packs_head = new_pack;
|
*packs_head = new_pack;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2565,7 +2581,8 @@ struct http_pack_request *new_direct_http_pack_request(
|
|||||||
|
|
||||||
preq->url = url;
|
preq->url = url;
|
||||||
|
|
||||||
strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(packed_git_hash));
|
odb_pack_name(&preq->tmpfile, packed_git_hash, "pack");
|
||||||
|
strbuf_addstr(&preq->tmpfile, ".temp");
|
||||||
preq->packfile = fopen(preq->tmpfile.buf, "a");
|
preq->packfile = fopen(preq->tmpfile.buf, "a");
|
||||||
if (!preq->packfile) {
|
if (!preq->packfile) {
|
||||||
error("Unable to open local file %s for pack",
|
error("Unable to open local file %s for pack",
|
||||||
|
22
midx.c
22
midx.c
@ -445,6 +445,7 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m,
|
|||||||
uint32_t pack_int_id)
|
uint32_t pack_int_id)
|
||||||
{
|
{
|
||||||
struct strbuf pack_name = STRBUF_INIT;
|
struct strbuf pack_name = STRBUF_INIT;
|
||||||
|
struct strbuf key = STRBUF_INIT;
|
||||||
struct packed_git *p;
|
struct packed_git *p;
|
||||||
|
|
||||||
pack_int_id = midx_for_pack(&m, pack_int_id);
|
pack_int_id = midx_for_pack(&m, pack_int_id);
|
||||||
@ -455,16 +456,29 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m,
|
|||||||
strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir,
|
strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir,
|
||||||
m->pack_names[pack_int_id]);
|
m->pack_names[pack_int_id]);
|
||||||
|
|
||||||
p = add_packed_git(pack_name.buf, pack_name.len, m->local);
|
/* pack_map holds the ".pack" name, but we have the .idx */
|
||||||
|
strbuf_addbuf(&key, &pack_name);
|
||||||
|
strbuf_strip_suffix(&key, ".idx");
|
||||||
|
strbuf_addstr(&key, ".pack");
|
||||||
|
p = hashmap_get_entry_from_hash(&r->objects->pack_map,
|
||||||
|
strhash(key.buf), key.buf,
|
||||||
|
struct packed_git, packmap_ent);
|
||||||
|
if (!p) {
|
||||||
|
p = add_packed_git(pack_name.buf, pack_name.len, m->local);
|
||||||
|
if (p) {
|
||||||
|
install_packed_git(r, p);
|
||||||
|
list_add_tail(&p->mru, &r->objects->packed_git_mru);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
strbuf_release(&pack_name);
|
strbuf_release(&pack_name);
|
||||||
|
strbuf_release(&key);
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
p->multi_pack_index = 1;
|
p->multi_pack_index = 1;
|
||||||
m->packs[pack_int_id] = p;
|
m->packs[pack_int_id] = p;
|
||||||
install_packed_git(r, p);
|
|
||||||
list_add_tail(&p->mru, &r->objects->packed_git_mru);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -973,7 +987,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_offset = e.offset;
|
m_offset = e.offset;
|
||||||
p_offset = find_pack_entry_one(oid.hash, e.p);
|
p_offset = find_pack_entry_one(&oid, e.p);
|
||||||
|
|
||||||
if (m_offset != p_offset)
|
if (m_offset != p_offset)
|
||||||
midx_report(_("incorrect object offset for oid[%d] = %s: %"PRIx64" != %"PRIx64),
|
midx_report(_("incorrect object offset for oid[%d] = %s: %"PRIx64" != %"PRIx64),
|
||||||
|
@ -935,7 +935,7 @@ static inline int bitmap_position_packfile(struct bitmap_index *bitmap_git,
|
|||||||
const struct object_id *oid)
|
const struct object_id *oid)
|
||||||
{
|
{
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
off_t offset = find_pack_entry_one(oid->hash, bitmap_git->pack);
|
off_t offset = find_pack_entry_one(oid, bitmap_git->pack);
|
||||||
if (!offset)
|
if (!offset)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -1609,7 +1609,7 @@ static int in_bitmapped_pack(struct bitmap_index *bitmap_git,
|
|||||||
if (bsearch_midx(&object->oid, bitmap_git->midx, NULL))
|
if (bsearch_midx(&object->oid, bitmap_git->midx, NULL))
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
if (find_pack_entry_one(object->oid.hash, bitmap_git->pack) > 0)
|
if (find_pack_entry_one(&object->oid, bitmap_git->pack) > 0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
packfile.c
51
packfile.c
@ -35,18 +35,6 @@ char *odb_pack_name(struct strbuf *buf,
|
|||||||
return buf->buf;
|
return buf->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *sha1_pack_name(const unsigned char *sha1)
|
|
||||||
{
|
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
|
||||||
return odb_pack_name(&buf, sha1, "pack");
|
|
||||||
}
|
|
||||||
|
|
||||||
char *sha1_pack_index_name(const unsigned char *sha1)
|
|
||||||
{
|
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
|
||||||
return odb_pack_name(&buf, sha1, "idx");
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int pack_used_ctr;
|
static unsigned int pack_used_ctr;
|
||||||
static unsigned int pack_mmap_calls;
|
static unsigned int pack_mmap_calls;
|
||||||
static unsigned int peak_pack_open_windows;
|
static unsigned int peak_pack_open_windows;
|
||||||
@ -237,13 +225,22 @@ static struct packed_git *alloc_packed_git(int extra)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *pack_path_from_idx(const char *idx_path)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
if (!strip_suffix(idx_path, ".idx", &len))
|
||||||
|
BUG("idx path does not end in .idx: %s", idx_path);
|
||||||
|
return xstrfmt("%.*s.pack", (int)len, idx_path);
|
||||||
|
}
|
||||||
|
|
||||||
struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
|
struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path)
|
||||||
{
|
{
|
||||||
const char *path = sha1_pack_name(sha1);
|
char *path = pack_path_from_idx(idx_path);
|
||||||
size_t alloc = st_add(strlen(path), 1);
|
size_t alloc = st_add(strlen(path), 1);
|
||||||
struct packed_git *p = alloc_packed_git(alloc);
|
struct packed_git *p = alloc_packed_git(alloc);
|
||||||
|
|
||||||
memcpy(p->pack_name, path, alloc); /* includes NUL */
|
memcpy(p->pack_name, path, alloc); /* includes NUL */
|
||||||
|
free(path);
|
||||||
hashcpy(p->hash, sha1, the_repository->hash_algo);
|
hashcpy(p->hash, sha1, the_repository->hash_algo);
|
||||||
if (check_packed_git_idx(idx_path, p)) {
|
if (check_packed_git_idx(idx_path, p)) {
|
||||||
free(p);
|
free(p);
|
||||||
@ -1242,7 +1239,9 @@ off_t get_delta_base(struct packed_git *p,
|
|||||||
*curpos += used;
|
*curpos += used;
|
||||||
} else if (type == OBJ_REF_DELTA) {
|
} else if (type == OBJ_REF_DELTA) {
|
||||||
/* The base entry _must_ be in the same pack */
|
/* The base entry _must_ be in the same pack */
|
||||||
base_offset = find_pack_entry_one(base_info, p);
|
struct object_id oid;
|
||||||
|
oidread(&oid, base_info, the_repository->hash_algo);
|
||||||
|
base_offset = find_pack_entry_one(&oid, p);
|
||||||
*curpos += the_hash_algo->rawsz;
|
*curpos += the_hash_algo->rawsz;
|
||||||
} else
|
} else
|
||||||
die("I am totally screwed");
|
die("I am totally screwed");
|
||||||
@ -1974,11 +1973,10 @@ off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t find_pack_entry_one(const unsigned char *sha1,
|
off_t find_pack_entry_one(const struct object_id *oid,
|
||||||
struct packed_git *p)
|
struct packed_git *p)
|
||||||
{
|
{
|
||||||
const unsigned char *index = p->index_data;
|
const unsigned char *index = p->index_data;
|
||||||
struct object_id oid;
|
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
|
|
||||||
if (!index) {
|
if (!index) {
|
||||||
@ -1986,8 +1984,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashcpy(oid.hash, sha1, the_repository->hash_algo);
|
if (bsearch_pack(oid, p, &result))
|
||||||
if (bsearch_pack(&oid, p, &result))
|
|
||||||
return nth_packed_object_offset(p, result);
|
return nth_packed_object_offset(p, result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2013,13 +2010,13 @@ int is_pack_valid(struct packed_git *p)
|
|||||||
return !open_packed_git(p);
|
return !open_packed_git(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct packed_git *find_sha1_pack(const unsigned char *sha1,
|
struct packed_git *find_oid_pack(const struct object_id *oid,
|
||||||
struct packed_git *packs)
|
struct packed_git *packs)
|
||||||
{
|
{
|
||||||
struct packed_git *p;
|
struct packed_git *p;
|
||||||
|
|
||||||
for (p = packs; p; p = p->next) {
|
for (p = packs; p; p = p->next) {
|
||||||
if (find_pack_entry_one(sha1, p))
|
if (find_pack_entry_one(oid, p))
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2036,7 +2033,7 @@ static int fill_pack_entry(const struct object_id *oid,
|
|||||||
oidset_contains(&p->bad_objects, oid))
|
oidset_contains(&p->bad_objects, oid))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
offset = find_pack_entry_one(oid->hash, p);
|
offset = find_pack_entry_one(oid, p);
|
||||||
if (!offset)
|
if (!offset)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -2151,14 +2148,6 @@ int has_object_kept_pack(const struct object_id *oid, unsigned flags)
|
|||||||
return find_kept_pack_entry(the_repository, oid, flags, &e);
|
return find_kept_pack_entry(the_repository, oid, flags, &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int has_pack_index(const unsigned char *sha1)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
if (stat(sha1_pack_index_name(sha1), &st))
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int for_each_object_in_pack(struct packed_git *p,
|
int for_each_object_in_pack(struct packed_git *p,
|
||||||
each_packed_object_fn cb, void *data,
|
each_packed_object_fn cb, void *data,
|
||||||
enum for_each_object_flags flags)
|
enum for_each_object_flags flags)
|
||||||
|
40
packfile.h
40
packfile.h
@ -31,26 +31,21 @@ struct pack_entry {
|
|||||||
*/
|
*/
|
||||||
char *odb_pack_name(struct strbuf *buf, const unsigned char *sha1, const char *ext);
|
char *odb_pack_name(struct strbuf *buf, const unsigned char *sha1, const char *ext);
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the name of the (local) packfile with the specified sha1 in
|
|
||||||
* its name. The return value is a pointer to memory that is
|
|
||||||
* overwritten each time this function is called.
|
|
||||||
*/
|
|
||||||
char *sha1_pack_name(const unsigned char *sha1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the name of the (local) pack index file with the specified
|
|
||||||
* sha1 in its name. The return value is a pointer to memory that is
|
|
||||||
* overwritten each time this function is called.
|
|
||||||
*/
|
|
||||||
char *sha1_pack_index_name(const unsigned char *sha1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the basename of the packfile, omitting any containing directory
|
* Return the basename of the packfile, omitting any containing directory
|
||||||
* (e.g., "pack-1234abcd[...].pack").
|
* (e.g., "pack-1234abcd[...].pack").
|
||||||
*/
|
*/
|
||||||
const char *pack_basename(struct packed_git *p);
|
const char *pack_basename(struct packed_git *p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the pack idx file found at idx_path and create a packed_git struct
|
||||||
|
* which can be used with find_pack_entry_one().
|
||||||
|
*
|
||||||
|
* You probably don't want to use this function! It skips most of the normal
|
||||||
|
* sanity checks (including whether we even have the matching .pack file),
|
||||||
|
* and does not add the resulting packed_git struct to the internal list of
|
||||||
|
* packs. You probably want add_packed_git() instead.
|
||||||
|
*/
|
||||||
struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
|
struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
|
||||||
|
|
||||||
typedef void each_file_in_pack_dir_fn(const char *full_path, size_t full_path_len,
|
typedef void each_file_in_pack_dir_fn(const char *full_path, size_t full_path_len,
|
||||||
@ -84,8 +79,13 @@ struct packed_git *get_all_packs(struct repository *r);
|
|||||||
*/
|
*/
|
||||||
unsigned long repo_approximate_object_count(struct repository *r);
|
unsigned long repo_approximate_object_count(struct repository *r);
|
||||||
|
|
||||||
struct packed_git *find_sha1_pack(const unsigned char *sha1,
|
/*
|
||||||
struct packed_git *packs);
|
* Find the pack within the "packs" list whose index contains the object "oid".
|
||||||
|
* For general object lookups, you probably don't want this; use
|
||||||
|
* find_pack_entry() instead.
|
||||||
|
*/
|
||||||
|
struct packed_git *find_oid_pack(const struct object_id *oid,
|
||||||
|
struct packed_git *packs);
|
||||||
|
|
||||||
void pack_report(void);
|
void pack_report(void);
|
||||||
|
|
||||||
@ -154,10 +154,10 @@ int nth_packed_object_id(struct object_id *, struct packed_git *, uint32_t n);
|
|||||||
off_t nth_packed_object_offset(const struct packed_git *, uint32_t n);
|
off_t nth_packed_object_offset(const struct packed_git *, uint32_t n);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the object named sha1 is present in the specified packfile,
|
* If the object named by oid is present in the specified packfile,
|
||||||
* return its offset within the packfile; otherwise, return 0.
|
* return its offset within the packfile; otherwise, return 0.
|
||||||
*/
|
*/
|
||||||
off_t find_pack_entry_one(const unsigned char *sha1, struct packed_git *);
|
off_t find_pack_entry_one(const struct object_id *oid, struct packed_git *);
|
||||||
|
|
||||||
int is_pack_valid(struct packed_git *);
|
int is_pack_valid(struct packed_git *);
|
||||||
void *unpack_entry(struct repository *r, struct packed_git *, off_t, enum object_type *, unsigned long *);
|
void *unpack_entry(struct repository *r, struct packed_git *, off_t, enum object_type *, unsigned long *);
|
||||||
@ -193,8 +193,6 @@ int find_kept_pack_entry(struct repository *r, const struct object_id *oid, unsi
|
|||||||
int has_object_pack(const struct object_id *oid);
|
int has_object_pack(const struct object_id *oid);
|
||||||
int has_object_kept_pack(const struct object_id *oid, unsigned flags);
|
int has_object_kept_pack(const struct object_id *oid, unsigned flags);
|
||||||
|
|
||||||
int has_pack_index(const unsigned char *sha1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return 1 if an object in a promisor packfile is or refers to the given
|
* Return 1 if an object in a promisor packfile is or refers to the given
|
||||||
* object, 0 otherwise.
|
* object, 0 otherwise.
|
||||||
@ -209,7 +207,7 @@ int is_promisor_object(const struct object_id *oid);
|
|||||||
*
|
*
|
||||||
* This function should not be used directly. It is exposed here only so that we
|
* This function should not be used directly. It is exposed here only so that we
|
||||||
* have a convenient entry-point for fuzz testing. For real uses, you should
|
* have a convenient entry-point for fuzz testing. For real uses, you should
|
||||||
* probably use open_pack_index() or parse_pack_index() instead.
|
* probably use open_pack_index() instead.
|
||||||
*/
|
*/
|
||||||
int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
|
int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
|
||||||
size_t idx_size, struct packed_git *p);
|
size_t idx_size, struct packed_git *p);
|
||||||
|
@ -40,7 +40,7 @@ int cmd__find_pack(int argc, const char **argv)
|
|||||||
die("cannot parse %s as an object name", argv[0]);
|
die("cannot parse %s as an object name", argv[0]);
|
||||||
|
|
||||||
for (p = get_all_packs(the_repository); p; p = p->next)
|
for (p = get_all_packs(the_repository); p; p = p->next)
|
||||||
if (find_pack_entry_one(oid.hash, p)) {
|
if (find_pack_entry_one(&oid, p)) {
|
||||||
printf("%s\n", p->pack_name);
|
printf("%s\n", p->pack_name);
|
||||||
actual_count++;
|
actual_count++;
|
||||||
}
|
}
|
||||||
|
@ -39,4 +39,12 @@ test_expect_success 'info/refs updates when changes are made' '
|
|||||||
! test_cmp a b
|
! test_cmp a b
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'midx does not create duplicate pack entries' '
|
||||||
|
git repack -d --write-midx &&
|
||||||
|
git repack -d &&
|
||||||
|
grep ^P .git/objects/info/packs >packs &&
|
||||||
|
uniq -d <packs >dups &&
|
||||||
|
test_must_be_empty dups
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -307,6 +307,14 @@ test_expect_success 'fetch notices corrupt idx' '
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
# usage: count_fetches <nr> <extension> <trace_file>
|
||||||
|
count_fetches () {
|
||||||
|
# ignore grep exit code; it may return non-zero if we are expecting no
|
||||||
|
# matches
|
||||||
|
grep "GET .*objects/pack/pack-[a-z0-9]*.$2" "$3" >trace.count
|
||||||
|
test_line_count = "$1" trace.count
|
||||||
|
}
|
||||||
|
|
||||||
test_expect_success 'fetch can handle previously-fetched .idx files' '
|
test_expect_success 'fetch can handle previously-fetched .idx files' '
|
||||||
git checkout --orphan branch1 &&
|
git checkout --orphan branch1 &&
|
||||||
echo base >file &&
|
echo base >file &&
|
||||||
@ -321,8 +329,14 @@ test_expect_success 'fetch can handle previously-fetched .idx files' '
|
|||||||
git push "$HTTPD_DOCUMENT_ROOT_PATH"/repo_packed_branches.git branch2 &&
|
git push "$HTTPD_DOCUMENT_ROOT_PATH"/repo_packed_branches.git branch2 &&
|
||||||
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH"/repo_packed_branches.git repack -d &&
|
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH"/repo_packed_branches.git repack -d &&
|
||||||
git --bare init clone_packed_branches.git &&
|
git --bare init clone_packed_branches.git &&
|
||||||
git --git-dir=clone_packed_branches.git fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch1:branch1 &&
|
GIT_TRACE_CURL=$PWD/one.trace git --git-dir=clone_packed_branches.git \
|
||||||
git --git-dir=clone_packed_branches.git fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch2:branch2
|
fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch1:branch1 &&
|
||||||
|
count_fetches 2 idx one.trace &&
|
||||||
|
count_fetches 1 pack one.trace &&
|
||||||
|
GIT_TRACE_CURL=$PWD/two.trace git --git-dir=clone_packed_branches.git \
|
||||||
|
fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch2:branch2 &&
|
||||||
|
count_fetches 1 idx two.trace &&
|
||||||
|
count_fetches 1 pack two.trace
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'did not use upload-pack service' '
|
test_expect_success 'did not use upload-pack service' '
|
||||||
@ -507,4 +521,14 @@ test_expect_success 'fetching via http alternates works' '
|
|||||||
git -c http.followredirects=true clone "$HTTPD_URL/dumb/alt-child.git"
|
git -c http.followredirects=true clone "$HTTPD_URL/dumb/alt-child.git"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'dumb http can fetch index v1' '
|
||||||
|
server=$HTTPD_DOCUMENT_ROOT_PATH/idx-v1.git &&
|
||||||
|
git init --bare "$server" &&
|
||||||
|
git -C "$server" --work-tree=. commit --allow-empty -m foo &&
|
||||||
|
git -C "$server" -c pack.indexVersion=1 gc &&
|
||||||
|
|
||||||
|
git clone "$HTTPD_URL/dumb/idx-v1.git" &&
|
||||||
|
git -C idx-v1 fsck
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
4
walker.c
4
walker.c
@ -157,7 +157,7 @@ static int process(struct walker *walker, struct object *obj)
|
|||||||
else {
|
else {
|
||||||
if (obj->flags & COMPLETE)
|
if (obj->flags & COMPLETE)
|
||||||
return 0;
|
return 0;
|
||||||
walker->prefetch(walker, obj->oid.hash);
|
walker->prefetch(walker, &obj->oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
object_list_insert(obj, process_queue_end);
|
object_list_insert(obj, process_queue_end);
|
||||||
@ -186,7 +186,7 @@ static int loop(struct walker *walker)
|
|||||||
* the queue because we needed to fetch it first.
|
* the queue because we needed to fetch it first.
|
||||||
*/
|
*/
|
||||||
if (! (obj->flags & TO_SCAN)) {
|
if (! (obj->flags & TO_SCAN)) {
|
||||||
if (walker->fetch(walker, obj->oid.hash)) {
|
if (walker->fetch(walker, &obj->oid)) {
|
||||||
stop_progress(&progress);
|
stop_progress(&progress);
|
||||||
report_missing(obj);
|
report_missing(obj);
|
||||||
return -1;
|
return -1;
|
||||||
|
4
walker.h
4
walker.h
@ -6,8 +6,8 @@
|
|||||||
struct walker {
|
struct walker {
|
||||||
void *data;
|
void *data;
|
||||||
int (*fetch_ref)(struct walker *, struct ref *ref);
|
int (*fetch_ref)(struct walker *, struct ref *ref);
|
||||||
void (*prefetch)(struct walker *, unsigned char *sha1);
|
void (*prefetch)(struct walker *, const struct object_id *oid);
|
||||||
int (*fetch)(struct walker *, unsigned char *sha1);
|
int (*fetch)(struct walker *, const struct object_id *oid);
|
||||||
void (*cleanup)(struct walker *);
|
void (*cleanup)(struct walker *);
|
||||||
int get_verbosely;
|
int get_verbosely;
|
||||||
int get_progress;
|
int get_progress;
|
||||||
|
Reference in New Issue
Block a user