diff options
author | Taylor Blau <me@ttaylorr.com> | 2024-11-01 17:53:31 +0100 |
---|---|---|
committer | Taylor Blau <me@ttaylorr.com> | 2024-11-01 17:53:32 +0100 |
commit | 1c5a712f26b67e07672a4bcda017046f45545369 (patch) | |
tree | 39ea8e5868816aea5695bb51c47b2570fe4f3168 | |
parent | Merge branch 'kh/update-ref' (diff) | |
parent | packfile: use oidread() instead of hashcpy() to fill object_id (diff) | |
download | git-1c5a712f26b67e07672a4bcda017046f45545369.tar.xz git-1c5a712f26b67e07672a4bcda017046f45545369.zip |
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
-rw-r--r-- | builtin/fast-import.c | 6 | ||||
-rw-r--r-- | builtin/pack-objects.c | 4 | ||||
-rw-r--r-- | builtin/pack-redundant.c | 5 | ||||
-rw-r--r-- | connected.c | 4 | ||||
-rw-r--r-- | http-push.c | 4 | ||||
-rw-r--r-- | http-walker.c | 25 | ||||
-rw-r--r-- | http.c | 43 | ||||
-rw-r--r-- | midx.c | 22 | ||||
-rw-r--r-- | pack-bitmap.c | 4 | ||||
-rw-r--r-- | packfile.c | 51 | ||||
-rw-r--r-- | packfile.h | 40 | ||||
-rw-r--r-- | t/helper/test-find-pack.c | 2 | ||||
-rwxr-xr-x | t/t5200-update-server-info.sh | 8 | ||||
-rwxr-xr-x | t/t5550-http-fetch-dumb.sh | 28 | ||||
-rw-r--r-- | walker.c | 4 | ||||
-rw-r--r-- | walker.h | 4 |
16 files changed, 153 insertions, 101 deletions
diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 1e7ab67f6e..76d5c20f14 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -966,8 +966,7 @@ static int store_object( if (e->idx.offset) { duplicate_count_by_type[type]++; return 1; - } else if (find_sha1_pack(oid.hash, - get_all_packs(the_repository))) { + } else if (find_oid_pack(&oid, get_all_packs(the_repository))) { e->type = type; e->pack_id = MAX_PACK_ID; 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]++; truncate_pack(&checkpoint); - } else if (find_sha1_pack(oid.hash, - get_all_packs(the_repository))) { + } else if (find_oid_pack(&oid, get_all_packs(the_repository))) { e->type = OBJ_BLOB; e->pack_id = MAX_PACK_ID; e->idx.offset = 1; /* just not zero! */ diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 0fc0680b40..0800714267 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1556,7 +1556,7 @@ static int want_object_in_pack_one(struct packed_git *p, if (p == *found_pack) offset = *found_offset; else - offset = find_pack_entry_one(oid->hash, p); + offset = find_pack_entry_one(oid, p); if (offset) { if (!*found_pack) { @@ -3984,7 +3984,7 @@ static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid) while (p) { if ((!p->pack_local || p->pack_keep || p->pack_keep_in_core) && - find_pack_entry_one(oid->hash, p)) { + find_pack_entry_one(oid, p)) { last_found = p; return 1; } diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c index 5809613002..d2c1c4e5ec 100644 --- a/builtin/pack-redundant.c +++ b/builtin/pack-redundant.c @@ -13,6 +13,7 @@ #include "packfile.h" #include "object-store-ll.h" +#include "strbuf.h" #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 i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl; struct llist *ignore; + struct strbuf idx_name = STRBUF_INIT; char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */ 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); while (pl) { 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 = 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(min); llist_free(ignore); + strbuf_release(&idx_name); return 0; } diff --git a/connected.c b/connected.c index 87cc4b57a1..a9e2e13995 100644 --- a/connected.c +++ b/connected.c @@ -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) { if (!p->pack_promisor) continue; - if (find_pack_entry_one(oid->hash, p)) + if (find_pack_entry_one(oid, p)) goto promisor_pack_found; } /* @@ -144,7 +144,7 @@ no_promisor_pack_found: * are sure the ref is good and not sending it to * 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; if (fprintf(rev_list_in, "%s\n", oid_to_hex(oid)) < 0) diff --git a/http-push.c b/http-push.c index aad89f2eab..4d24e6b8d4 100644 --- a/http-push.c +++ b/http-push.c @@ -309,7 +309,7 @@ static void start_fetch_packed(struct transfer_request *request) struct transfer_request *check_request = request_queue_head; 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) { 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; @@ -681,7 +681,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock) get_remote_object_list(obj->oid.hash[0]); if (obj->flags & (REMOTE | PUSHING)) return 0; - target = find_sha1_pack(obj->oid.hash, repo->packs); + target = find_oid_pack(&obj->oid, repo->packs); if (target) { obj->flags |= REMOTE; return 0; diff --git a/http-walker.c b/http-walker.c index fb2d86d5e7..43cde0ebe5 100644 --- a/http-walker.c +++ b/http-walker.c @@ -147,14 +147,14 @@ static int fill_active_slot(void *data UNUSED) 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 walker_data *data = walker->data; newreq = xmalloc(sizeof(*newreq)); newreq->walker = walker; - oidread(&newreq->oid, sha1, the_repository->hash_algo); + oidcpy(&newreq->oid, oid); newreq->repo = data->alt; newreq->state = WAITING; newreq->req = NULL; @@ -422,7 +422,8 @@ static int fetch_indices(struct walker *walker, struct alt_base *repo) 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; int ret; @@ -431,7 +432,7 @@ static int http_fetch_pack(struct walker *walker, struct alt_base *repo, unsigne if (fetch_indices(walker, repo)) return -1; - target = find_sha1_pack(sha1, repo->packs); + target = find_oid_pack(oid, repo->packs); if (!target) return -1; 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", hash_to_hex(target->hash)); fprintf(stderr, " which contains %s\n", - hash_to_hex(sha1)); + oid_to_hex(oid)); } 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); } -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; struct object_request *obj_req = NULL; struct http_object_request *req; @@ -487,7 +488,7 @@ static int fetch_object(struct walker *walker, unsigned char *hash) list_for_each(pos, head) { 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; } if (!obj_req) @@ -548,20 +549,20 @@ static int fetch_object(struct walker *walker, unsigned char *hash) 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 alt_base *altbase = data->alt; - if (!fetch_object(walker, hash)) + if (!fetch_object(walker, oid)) return 0; while (altbase) { - if (!http_fetch_pack(walker, altbase, hash)) + if (!http_fetch_pack(walker, altbase, oid)) return 0; fetch_alternates(walker, data->alt->base); 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); } @@ -19,6 +19,7 @@ #include "string-list.h" #include "object-file.h" #include "object-store-ll.h" +#include "tempfile.h" static struct trace_key trace_curl = TRACE_KEY_INIT(CURL); 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)); 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) { 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, unsigned char *sha1, const char *base_url) { - struct packed_git *new_pack; + struct packed_git *new_pack, *p; char *tmp_idx = NULL; int ret; - if (has_pack_index(sha1)) { - new_pack = parse_pack_index(sha1, sha1_pack_index_name(sha1)); - if (!new_pack) - return -1; /* parse_pack_index() already issued error message */ - goto add_pack; + /* + * If we already have the pack locally, no need to fetch its index or + * even add it to list; we already have all of its objects. + */ + 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); @@ -2429,15 +2448,12 @@ static int fetch_and_setup_pack_index(struct packed_git **packs_head, } ret = verify_pack_index(new_pack); - if (!ret) { + if (!ret) close_pack_index(new_pack); - ret = finalize_object_file(tmp_idx, sha1_pack_index_name(sha1)); - } free(tmp_idx); if (ret) return -1; -add_pack: new_pack->next = *packs_head; *packs_head = new_pack; return 0; @@ -2565,7 +2581,8 @@ struct http_pack_request *new_direct_http_pack_request( 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"); if (!preq->packfile) { error("Unable to open local file %s for pack", @@ -445,6 +445,7 @@ int prepare_midx_pack(struct repository *r, struct multi_pack_index *m, uint32_t pack_int_id) { struct strbuf pack_name = STRBUF_INIT; + struct strbuf key = STRBUF_INIT; struct packed_git *p; 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, 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(&key); if (!p) return 1; p->multi_pack_index = 1; m->packs[pack_int_id] = p; - install_packed_git(r, p); - list_add_tail(&p->mru, &r->objects->packed_git_mru); return 0; } @@ -973,7 +987,7 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag } 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) midx_report(_("incorrect object offset for oid[%d] = %s: %"PRIx64" != %"PRIx64), diff --git a/pack-bitmap.c b/pack-bitmap.c index 32b222a7af..4fa9dfc771 100644 --- a/pack-bitmap.c +++ b/pack-bitmap.c @@ -935,7 +935,7 @@ static inline int bitmap_position_packfile(struct bitmap_index *bitmap_git, const struct object_id *oid) { 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) 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)) return 1; } 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; } } diff --git a/packfile.c b/packfile.c index df4ba67719..9560f0a33c 100644 --- a/packfile.c +++ b/packfile.c @@ -35,18 +35,6 @@ char *odb_pack_name(struct strbuf *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_mmap_calls; static unsigned int peak_pack_open_windows; @@ -237,13 +225,22 @@ static struct packed_git *alloc_packed_git(int extra) 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) { - const char *path = sha1_pack_name(sha1); + char *path = pack_path_from_idx(idx_path); size_t alloc = st_add(strlen(path), 1); struct packed_git *p = alloc_packed_git(alloc); memcpy(p->pack_name, path, alloc); /* includes NUL */ + free(path); hashcpy(p->hash, sha1, the_repository->hash_algo); if (check_packed_git_idx(idx_path, p)) { free(p); @@ -1242,7 +1239,9 @@ off_t get_delta_base(struct packed_git *p, *curpos += used; } else if (type == OBJ_REF_DELTA) { /* 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; } else 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, - struct packed_git *p) +off_t find_pack_entry_one(const struct object_id *oid, + struct packed_git *p) { const unsigned char *index = p->index_data; - struct object_id oid; uint32_t result; if (!index) { @@ -1986,8 +1984,7 @@ off_t find_pack_entry_one(const unsigned char *sha1, 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 0; } @@ -2013,13 +2010,13 @@ int is_pack_valid(struct packed_git *p) return !open_packed_git(p); } -struct packed_git *find_sha1_pack(const unsigned char *sha1, - struct packed_git *packs) +struct packed_git *find_oid_pack(const struct object_id *oid, + struct packed_git *packs) { struct packed_git *p; for (p = packs; p; p = p->next) { - if (find_pack_entry_one(sha1, p)) + if (find_pack_entry_one(oid, p)) return p; } return NULL; @@ -2036,7 +2033,7 @@ static int fill_pack_entry(const struct object_id *oid, oidset_contains(&p->bad_objects, oid)) return 0; - offset = find_pack_entry_one(oid->hash, p); + offset = find_pack_entry_one(oid, p); if (!offset) 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); } -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, each_packed_object_fn cb, void *data, enum for_each_object_flags flags) diff --git a/packfile.h b/packfile.h index 0f78658229..08f88a7ff5 100644 --- a/packfile.h +++ b/packfile.h @@ -32,25 +32,20 @@ struct pack_entry { 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 * (e.g., "pack-1234abcd[...].pack"). */ 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); 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); -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); @@ -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); /* - * 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. */ -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 *); 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_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 * 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 * 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, size_t idx_size, struct packed_git *p); diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c index 14b2b0c12c..85a69a4e55 100644 --- a/t/helper/test-find-pack.c +++ b/t/helper/test-find-pack.c @@ -40,7 +40,7 @@ int cmd__find_pack(int argc, const char **argv) die("cannot parse %s as an object name", argv[0]); 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); actual_count++; } diff --git a/t/t5200-update-server-info.sh b/t/t5200-update-server-info.sh index ed9dfd624c..cc51c73986 100755 --- a/t/t5200-update-server-info.sh +++ b/t/t5200-update-server-info.sh @@ -39,4 +39,12 @@ test_expect_success 'info/refs updates when changes are made' ' ! 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 diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 3c873de17e..5115b8dc23 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -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' ' git checkout --orphan branch1 && 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 --git-dir="$HTTPD_DOCUMENT_ROOT_PATH"/repo_packed_branches.git repack -d && 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 --git-dir=clone_packed_branches.git fetch "$HTTPD_URL"/dumb/repo_packed_branches.git branch2:branch2 + GIT_TRACE_CURL=$PWD/one.trace git --git-dir=clone_packed_branches.git \ + 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' ' @@ -507,4 +521,14 @@ test_expect_success 'fetching via http alternates works' ' 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 @@ -157,7 +157,7 @@ static int process(struct walker *walker, struct object *obj) else { if (obj->flags & COMPLETE) return 0; - walker->prefetch(walker, obj->oid.hash); + walker->prefetch(walker, &obj->oid); } 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. */ if (! (obj->flags & TO_SCAN)) { - if (walker->fetch(walker, obj->oid.hash)) { + if (walker->fetch(walker, &obj->oid)) { stop_progress(&progress); report_missing(obj); return -1; @@ -6,8 +6,8 @@ struct walker { void *data; int (*fetch_ref)(struct walker *, struct ref *ref); - void (*prefetch)(struct walker *, unsigned char *sha1); - int (*fetch)(struct walker *, unsigned char *sha1); + void (*prefetch)(struct walker *, const struct object_id *oid); + int (*fetch)(struct walker *, const struct object_id *oid); void (*cleanup)(struct walker *); int get_verbosely; int get_progress; |