Git fork

packfile: introduce function to load and add packfiles

We have a recurring pattern where we essentially perform an upsert of a
packfile in case it isn't yet known by the packfile store. The logic to
do so is non-trivial as we have to reconstruct the packfile's key, check
the map of packfiles, then create the new packfile and finally add it to
the store.

Introduce a new function that does this dance for us. Refactor callsites
to use it.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
d67530f6 f6f236d9

+48 -41
+2 -2
builtin/fast-import.c
··· 897 897 idx_name = keep_pack(create_index()); 898 898 899 899 /* Register the packfile with core git's machinery. */ 900 - new_p = add_packed_git(pack_data->repo, idx_name, strlen(idx_name), 1); 900 + new_p = packfile_store_load_pack(pack_data->repo->objects->packfiles, 901 + idx_name, 1); 901 902 if (!new_p) 902 903 die("core git rejected index %s", idx_name); 903 904 all_packs[pack_id] = new_p; 904 - packfile_store_add_pack(the_repository->objects->packfiles, new_p); 905 905 free(idx_name); 906 906 907 907 /* Print the boundary */
+3 -7
builtin/index-pack.c
··· 1640 1640 rename_tmp_packfile(&final_index_name, curr_index_name, &index_name, 1641 1641 hash, "idx", 1); 1642 1642 1643 - if (do_fsck_object) { 1644 - struct packed_git *p; 1645 - p = add_packed_git(the_repository, final_index_name, 1646 - strlen(final_index_name), 0); 1647 - if (p) 1648 - packfile_store_add_pack(the_repository->objects->packfiles, p); 1649 - } 1643 + if (do_fsck_object) 1644 + packfile_store_load_pack(the_repository->objects->packfiles, 1645 + final_index_name, 0); 1650 1646 1651 1647 if (!from_stdin) { 1652 1648 printf("%s\n", hash_to_hex(hash));
+4 -19
midx.c
··· 443 443 { 444 444 struct repository *r = m->source->odb->repo; 445 445 struct strbuf pack_name = STRBUF_INIT; 446 - struct strbuf key = STRBUF_INIT; 447 446 struct packed_git *p; 448 447 449 448 pack_int_id = midx_for_pack(&m, pack_int_id); ··· 455 454 456 455 strbuf_addf(&pack_name, "%s/pack/%s", m->source->path, 457 456 m->pack_names[pack_int_id]); 458 - 459 - /* pack_map holds the ".pack" name, but we have the .idx */ 460 - strbuf_addbuf(&key, &pack_name); 461 - strbuf_strip_suffix(&key, ".idx"); 462 - strbuf_addstr(&key, ".pack"); 463 - p = hashmap_get_entry_from_hash(&r->objects->packfiles->map, 464 - strhash(key.buf), key.buf, 465 - struct packed_git, packmap_ent); 466 - if (!p) { 467 - p = add_packed_git(r, pack_name.buf, pack_name.len, 468 - m->source->local); 469 - if (p) { 470 - packfile_store_add_pack(r->objects->packfiles, p); 471 - list_add_tail(&p->mru, &r->objects->packfiles->mru); 472 - } 473 - } 474 - 457 + p = packfile_store_load_pack(r->objects->packfiles, 458 + pack_name.buf, m->source->local); 459 + if (p) 460 + list_add_tail(&p->mru, &r->objects->packfiles->mru); 475 461 strbuf_release(&pack_name); 476 - strbuf_release(&key); 477 462 478 463 if (!p) { 479 464 m->packs[pack_int_id] = MIDX_PACK_ERROR;
+31 -13
packfile.c
··· 792 792 hashmap_add(&store->map, &pack->packmap_ent); 793 793 } 794 794 795 + struct packed_git *packfile_store_load_pack(struct packfile_store *store, 796 + const char *idx_path, int local) 797 + { 798 + struct strbuf key = STRBUF_INIT; 799 + struct packed_git *p; 800 + 801 + /* 802 + * We're being called with the path to the index file, but `pack_map` 803 + * holds the path to the packfile itself. 804 + */ 805 + strbuf_addstr(&key, idx_path); 806 + strbuf_strip_suffix(&key, ".idx"); 807 + strbuf_addstr(&key, ".pack"); 808 + 809 + p = hashmap_get_entry_from_hash(&store->map, strhash(key.buf), key.buf, 810 + struct packed_git, packmap_ent); 811 + if (!p) { 812 + p = add_packed_git(store->odb->repo, idx_path, 813 + strlen(idx_path), local); 814 + if (p) 815 + packfile_store_add_pack(store, p); 816 + } 817 + 818 + strbuf_release(&key); 819 + return p; 820 + } 821 + 795 822 void (*report_garbage)(unsigned seen_bits, const char *path); 796 823 797 824 static void report_helper(const struct string_list *list, ··· 891 918 const char *file_name, void *_data) 892 919 { 893 920 struct prepare_pack_data *data = (struct prepare_pack_data *)_data; 894 - struct packed_git *p; 895 921 size_t base_len = full_name_len; 896 922 897 923 if (strip_suffix_mem(full_name, &base_len, ".idx") && 898 924 !(data->m && midx_contains_pack(data->m, file_name))) { 899 - struct hashmap_entry hent; 900 - char *pack_name = xstrfmt("%.*s.pack", (int)base_len, full_name); 901 - unsigned int hash = strhash(pack_name); 902 - hashmap_entry_init(&hent, hash); 903 - 904 - /* Don't reopen a pack we already have. */ 905 - if (!hashmap_get(&data->r->objects->packfiles->map, &hent, pack_name)) { 906 - p = add_packed_git(data->r, full_name, full_name_len, data->local); 907 - if (p) 908 - packfile_store_add_pack(data->r->objects->packfiles, p); 909 - } 910 - free(pack_name); 925 + char *trimmed_path = xstrndup(full_name, full_name_len); 926 + packfile_store_load_pack(data->r->objects->packfiles, 927 + trimmed_path, data->local); 928 + free(trimmed_path); 911 929 } 912 930 913 931 if (!report_garbage)
+8
packfile.h
··· 127 127 void packfile_store_add_pack(struct packfile_store *store, 128 128 struct packed_git *pack); 129 129 130 + /* 131 + * Open the packfile and add it to the store if it isn't yet known. Returns 132 + * either the newly opened packfile or the preexisting packfile. Returns a 133 + * `NULL` pointer in case the packfile could not be opened. 134 + */ 135 + struct packed_git *packfile_store_load_pack(struct packfile_store *store, 136 + const char *idx_path, int local); 137 + 130 138 struct pack_window { 131 139 struct pack_window *next; 132 140 unsigned char *base;