Skip to content

Commit e03f501

Browse files
committed
odb: add write_packfile, for_each_unique_abbrev, convert_object_id
Add three vtable methods to odb_source that were not part of the recent ps/odb-sources and ps/object-counting series: - write_packfile: ingest a pack from a file descriptor. The files backend chooses between index-pack (large packs) and unpack-objects (small packs below fetch.unpackLimit). Options cover thin-pack fixing, promisor marking, fsck, lockfile capture, and shallow file passing. - for_each_unique_abbrev: iterate objects matching a hex prefix for disambiguation. Searches loose objects via oidtree, then multi-pack indices, then non-MIDX packs. - convert_object_id: translate between hash algorithms using the loose object map. Used during SHA-1 to SHA-256 migration. Also add ODB_SOURCE_HELPER to the source type enum, preparing for the helper backend in the next commit. The write_packfile vtable method replaces the pattern where callers spawn index-pack/unpack-objects directly. fast-import already uses odb_write_packfile() and this allows non-files backends to handle pack ingestion through their own mechanism. Signed-off-by: Aaron Paterson <apaterson@pm.me>
1 parent 41688c1 commit e03f501

File tree

12 files changed

+647
-136
lines changed

12 files changed

+647
-136
lines changed

builtin/cat-file.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "object-file.h"
2525
#include "object-name.h"
2626
#include "odb.h"
27+
#include "odb/source.h"
2728
#include "odb/streaming.h"
2829
#include "replace-object.h"
2930
#include "promisor-remote.h"
@@ -859,8 +860,17 @@ static void batch_each_object(struct batch_options *opt,
859860
*/
860861
odb_prepare_alternates(the_repository->objects);
861862
for (source = the_repository->objects->sources; source; source = source->next) {
862-
int ret = odb_source_loose_for_each_object(source, NULL, batch_one_object_oi,
863-
&payload, flags);
863+
int ret;
864+
if (!source->packed) {
865+
/*
866+
* Non-files source: dispatch through vtable.
867+
*/
868+
ret = odb_source_for_each_object(source, NULL,
869+
batch_one_object_oi, &payload, flags);
870+
} else {
871+
ret = odb_source_loose_for_each_object(source, NULL,
872+
batch_one_object_oi, &payload, flags);
873+
}
864874
if (ret)
865875
break;
866876
}
@@ -882,11 +892,14 @@ static void batch_each_object(struct batch_options *opt,
882892
struct object_info oi = { 0 };
883893

884894
for (source = the_repository->objects->sources; source; source = source->next) {
885-
struct odb_source_files *files = odb_source_files_downcast(source);
886-
int ret = packfile_store_for_each_object(files->packed, &oi,
887-
batch_one_object_oi, &payload, flags);
888-
if (ret)
889-
break;
895+
if (!source->packed)
896+
continue;
897+
{
898+
int ret = packfile_store_for_each_object(source->packed, &oi,
899+
batch_one_object_oi, &payload, flags);
900+
if (ret)
901+
break;
902+
}
890903
}
891904
}
892905

builtin/fsck.c

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "object-file.h"
1818
#include "object-name.h"
1919
#include "odb.h"
20+
#include "odb/source.h"
2021
#include "odb/streaming.h"
2122
#include "path.h"
2223
#include "read-cache-ll.h"
@@ -769,24 +770,56 @@ static int fsck_subdir(unsigned int nr, const char *path UNUSED, void *data)
769770
return 0;
770771
}
771772

773+
static int fsck_vtable_object(const struct object_id *oid,
774+
struct object_info *oi UNUSED,
775+
void *data UNUSED)
776+
{
777+
struct object *obj;
778+
779+
obj = parse_object(the_repository, oid);
780+
if (!obj) {
781+
errors_found |= ERROR_OBJECT;
782+
error(_("%s: object missing"),
783+
describe_object(oid));
784+
return 0;
785+
}
786+
obj->flags |= HAS_OBJ;
787+
if (fsck_obj(obj, NULL, 0))
788+
errors_found |= ERROR_OBJECT;
789+
return 0;
790+
}
791+
772792
static void fsck_source(struct odb_source *source)
773793
{
774794
struct progress *progress = NULL;
775-
struct for_each_loose_cb cb_data = {
776-
.progress = progress,
777-
};
778795

779796
if (verbose)
780797
fprintf_ln(stderr, _("Checking object directory"));
781798

782-
if (show_progress)
783-
progress = start_progress(the_repository,
784-
_("Checking object directories"), 256);
799+
if (!source->packed) {
800+
/*
801+
* Non-files source: iterate objects through the vtable
802+
* and fsck each one.
803+
*/
804+
odb_source_for_each_object(source, NULL,
805+
fsck_vtable_object, NULL, 0);
806+
return;
807+
}
785808

786-
for_each_loose_file_in_source(source, fsck_loose,
787-
fsck_cruft, fsck_subdir, &cb_data);
788-
display_progress(progress, 256);
789-
stop_progress(&progress);
809+
{
810+
struct for_each_loose_cb cb_data = {
811+
.progress = progress,
812+
};
813+
814+
if (show_progress)
815+
progress = start_progress(the_repository,
816+
_("Checking object directories"), 256);
817+
818+
for_each_loose_file_in_source(source, fsck_loose,
819+
fsck_cruft, fsck_subdir, &cb_data);
820+
display_progress(progress, 256);
821+
stop_progress(&progress);
822+
}
790823
}
791824

792825
static int fsck_cache_tree(struct cache_tree *it, const char *index_path)

builtin/pack-objects.c

Lines changed: 28 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "packfile.h"
3333
#include "object-file.h"
3434
#include "odb.h"
35+
#include "odb/source.h"
3536
#include "odb/streaming.h"
3637
#include "replace-object.h"
3738
#include "dir.h"
@@ -1541,57 +1542,15 @@ static int have_duplicate_entry(const struct object_id *oid,
15411542

15421543
static int want_cruft_object_mtime(struct repository *r,
15431544
const struct object_id *oid,
1544-
unsigned flags, uint32_t mtime)
1545+
unsigned flags UNUSED, uint32_t mtime UNUSED)
15451546
{
1546-
struct odb_source *source;
1547-
1548-
for (source = r->objects->sources; source; source = source->next) {
1549-
struct odb_source_files *files = odb_source_files_downcast(source);
1550-
struct packed_git **cache = packfile_store_get_kept_pack_cache(files->packed, flags);
1551-
1552-
for (; *cache; cache++) {
1553-
struct packed_git *p = *cache;
1554-
off_t ofs;
1555-
uint32_t candidate_mtime;
1556-
1557-
ofs = find_pack_entry_one(oid, p);
1558-
if (!ofs)
1559-
continue;
1560-
1561-
/*
1562-
* We have a copy of the object 'oid' in a non-cruft
1563-
* pack. We can avoid packing an additional copy
1564-
* regardless of what the existing copy's mtime is since
1565-
* it is outside of a cruft pack.
1566-
*/
1567-
if (!p->is_cruft)
1568-
return 0;
1569-
1570-
/*
1571-
* If we have a copy of the object 'oid' in a cruft
1572-
* pack, then either read the cruft pack's mtime for
1573-
* that object, or, if that can't be loaded, assume the
1574-
* pack's mtime itself.
1575-
*/
1576-
if (!load_pack_mtimes(p)) {
1577-
uint32_t pos;
1578-
if (offset_to_pack_pos(p, ofs, &pos) < 0)
1579-
continue;
1580-
candidate_mtime = nth_packed_mtime(p, pos);
1581-
} else {
1582-
candidate_mtime = p->mtime;
1583-
}
1584-
1585-
/*
1586-
* We have a surviving copy of the object in a cruft
1587-
* pack whose mtime is greater than or equal to the one
1588-
* we are considering. We can thus avoid packing an
1589-
* additional copy of that object.
1590-
*/
1591-
if (mtime <= candidate_mtime)
1592-
return 0;
1593-
}
1594-
}
1547+
/*
1548+
* Check if the object exists in a kept source. Dispatches through
1549+
* the vtable: files backends check kept packs, non-files backends
1550+
* check their own kept tracking via OBJECT_INFO_KEPT_ONLY.
1551+
*/
1552+
if (odb_has_object_kept(r->objects, oid))
1553+
return 0;
15951554

15961555
return -1;
15971556
}
@@ -1657,7 +1616,7 @@ static int want_found_object(const struct object_id *oid, int exclude,
16571616
return 0;
16581617
if (ignore_packed_keep_in_core && p->pack_keep_in_core)
16591618
return 0;
1660-
if (has_object_kept_pack(p->repo, oid, flags))
1619+
if (odb_has_object_kept(p->repo->objects, oid))
16611620
return 0;
16621621
} else {
16631622
/*
@@ -1726,8 +1685,6 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
17261685
uint32_t found_mtime)
17271686
{
17281687
int want;
1729-
struct packfile_list_entry *e;
1730-
struct odb_source *source;
17311688

17321689
if (!exclude && local) {
17331690
/*
@@ -1757,25 +1714,18 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
17571714

17581715
odb_prepare_alternates(the_repository->objects);
17591716

1760-
for (source = the_repository->objects->sources; source; source = source->next) {
1761-
struct multi_pack_index *m = get_multi_pack_index(source);
1762-
struct pack_entry e;
1763-
1764-
if (m && fill_midx_entry(m, oid, &e)) {
1765-
want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime);
1766-
if (want != -1)
1767-
return want;
1768-
}
1769-
}
1770-
1771-
for (source = the_repository->objects->sources; source; source = source->next) {
1772-
struct odb_source_files *files = odb_source_files_downcast(source);
1717+
{
1718+
struct object_info oi = OBJECT_INFO_INIT;
17731719

1774-
for (e = files->packed->packs.head; e; e = e->next) {
1775-
struct packed_git *p = e->pack;
1776-
want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
1777-
if (!exclude && want > 0)
1778-
packfile_list_prepend(&files->packed->packs, p);
1720+
if (!odb_read_object_info_extended(the_repository->objects,
1721+
oid, &oi,
1722+
OBJECT_INFO_QUICK) &&
1723+
oi.whence == OI_PACKED) {
1724+
struct packed_git *p = oi.u.packed.pack;
1725+
want = want_object_in_pack_one(p, oid, exclude,
1726+
found_pack,
1727+
found_offset,
1728+
found_mtime);
17791729
if (want != -1)
17801730
return want;
17811731
}
@@ -4065,7 +4015,7 @@ static void show_cruft_commit(struct commit *commit, void *data)
40654015

40664016
static int cruft_include_check_obj(struct object *obj, void *data UNUSED)
40674017
{
4068-
return !has_object_kept_pack(to_pack.repo, &obj->oid, KEPT_PACK_IN_CORE);
4018+
return !odb_has_object_kept(to_pack.repo->objects, &obj->oid);
40694019
}
40704020

40714021
static int cruft_include_check(struct commit *commit, void *data)
@@ -4365,17 +4315,15 @@ static void add_objects_in_unpacked_packs(void)
43654315

43664316
odb_prepare_alternates(to_pack.repo->objects);
43674317
for (source = to_pack.repo->objects->sources; source; source = source->next) {
4368-
struct odb_source_files *files = odb_source_files_downcast(source);
4369-
43704318
if (!source->local)
43714319
continue;
43724320

4373-
if (packfile_store_for_each_object(files->packed, &oi,
4374-
add_object_in_unpacked_pack, NULL,
4375-
ODB_FOR_EACH_OBJECT_PACK_ORDER |
4376-
ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
4377-
ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS |
4378-
ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS))
4321+
if (odb_source_for_each_object(source, &oi,
4322+
add_object_in_unpacked_pack, NULL,
4323+
ODB_FOR_EACH_OBJECT_PACK_ORDER |
4324+
ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
4325+
ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS |
4326+
ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS))
43794327
die(_("cannot open pack index"));
43804328
}
43814329
}

loose.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,17 @@ int repo_read_loose_object_map(struct repository *repo)
128128

129129
int repo_write_loose_object_map(struct repository *repo)
130130
{
131-
struct odb_source_files *files = odb_source_files_downcast(repo->objects->sources);
132-
kh_oid_map_t *map = files->loose->map->to_compat;
131+
struct odb_source *source = repo->objects->sources;
132+
kh_oid_map_t *map;
133133
struct lock_file lock;
134134
int fd;
135135
khiter_t iter;
136136
struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
137137

138+
if (!source->loose || !source->loose->map)
139+
return 0;
140+
map = source->loose->map->to_compat;
141+
138142
if (!should_use_loose_object_map(repo))
139143
return 0;
140144

@@ -235,8 +239,10 @@ int repo_loose_object_map_oid(struct repository *repo,
235239
khiter_t pos;
236240

237241
for (source = repo->objects->sources; source; source = source->next) {
238-
struct odb_source_files *files = odb_source_files_downcast(source);
239-
struct loose_object_map *loose_map = files->loose->map;
242+
struct loose_object_map *loose_map;
243+
if (!source->loose)
244+
continue;
245+
loose_map = source->loose->map;
240246
if (!loose_map)
241247
continue;
242248
map = (to == repo->compat_hash_algo) ?

midx.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,10 @@ static int midx_read_object_offsets(const unsigned char *chunk_start,
101101

102102
struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
103103
{
104-
struct odb_source_files *files = odb_source_files_downcast(source);
105-
packfile_store_prepare(files->packed);
106-
return files->packed->midx;
104+
if (!source->packed)
105+
return NULL;
106+
packfile_store_prepare(source->packed);
107+
return source->packed->midx;
107108
}
108109

109110
static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *source,

0 commit comments

Comments
 (0)