Skip to content

Commit 146c7ed

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 146c7ed

File tree

5 files changed

+480
-18
lines changed

5 files changed

+480
-18
lines changed

object-name.c

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "packfile.h"
2121
#include "pretty.h"
2222
#include "object-file.h"
23+
#include "odb/source.h"
2324
#include "read-cache-ll.h"
2425
#include "repo-settings.h"
2526
#include "repository.h"
@@ -111,13 +112,28 @@ static enum cb_next match_prefix(const struct object_id *oid, void *arg)
111112
return ds->ambiguous ? CB_BREAK : CB_CONTINUE;
112113
}
113114

115+
static int disambiguate_cb(const struct object_id *oid,
116+
struct object_info *oi UNUSED, void *data)
117+
{
118+
struct disambiguate_state *ds = data;
119+
update_candidates(ds, oid);
120+
return ds->ambiguous ? 1 : 0;
121+
}
122+
114123
static void find_short_object_filename(struct disambiguate_state *ds)
115124
{
116125
struct odb_source *source;
117126

118-
for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next)
119-
oidtree_each(odb_source_loose_cache(source, &ds->bin_pfx),
120-
&ds->bin_pfx, ds->len, match_prefix, ds);
127+
for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
128+
if (source->for_each_unique_abbrev) {
129+
odb_source_for_each_unique_abbrev(
130+
source, &ds->bin_pfx, ds->len,
131+
disambiguate_cb, ds);
132+
} else {
133+
oidtree_each(odb_source_loose_cache(source, &ds->bin_pfx),
134+
&ds->bin_pfx, ds->len, match_prefix, ds);
135+
}
136+
}
121137
}
122138

123139
static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
@@ -208,15 +224,23 @@ static void find_short_packed_object(struct disambiguate_state *ds)
208224

209225
odb_prepare_alternates(ds->repo->objects);
210226
for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
211-
struct multi_pack_index *m = get_multi_pack_index(source);
212-
if (m)
213-
unique_in_midx(m, ds);
227+
if (source->for_each_unique_abbrev) {
228+
odb_source_for_each_unique_abbrev(
229+
source, &ds->bin_pfx, ds->len,
230+
disambiguate_cb, ds);
231+
} else {
232+
struct multi_pack_index *m = get_multi_pack_index(source);
233+
if (m)
234+
unique_in_midx(m, ds);
235+
}
214236
}
215237

216-
repo_for_each_pack(ds->repo, p) {
217-
if (ds->ambiguous)
218-
break;
219-
unique_in_pack(p, ds);
238+
if (!ds->repo->objects->sources->for_each_unique_abbrev) {
239+
repo_for_each_pack(ds->repo, p) {
240+
if (ds->ambiguous)
241+
break;
242+
unique_in_pack(p, ds);
243+
}
220244
}
221245
}
222246

@@ -796,19 +820,38 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
796820
mad->init_len = mad->cur_len;
797821
}
798822

799-
static void find_abbrev_len_packed(struct min_abbrev_data *mad)
823+
static int abbrev_len_cb(const struct object_id *oid,
824+
struct object_info *oi UNUSED, void *data)
800825
{
801-
struct packed_git *p;
826+
struct min_abbrev_data *mad = data;
827+
extend_abbrev_len(oid, mad);
828+
return 0;
829+
}
802830

831+
static void find_abbrev_len_packed(struct min_abbrev_data *mad)
832+
{
803833
odb_prepare_alternates(mad->repo->objects);
804-
for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) {
805-
struct multi_pack_index *m = get_multi_pack_index(source);
806-
if (m)
807-
find_abbrev_len_for_midx(m, mad);
834+
835+
for (struct odb_source *source = mad->repo->objects->sources;
836+
source; source = source->next) {
837+
if (source->for_each_unique_abbrev) {
838+
mad->init_len = 0;
839+
odb_source_for_each_unique_abbrev(
840+
source, mad->oid, mad->cur_len,
841+
abbrev_len_cb, mad);
842+
mad->init_len = mad->cur_len;
843+
} else {
844+
struct multi_pack_index *m = get_multi_pack_index(source);
845+
if (m)
846+
find_abbrev_len_for_midx(m, mad);
847+
}
808848
}
809849

810-
repo_for_each_pack(mad->repo, p)
811-
find_abbrev_len_for_pack(p, mad);
850+
if (!mad->repo->objects->sources->for_each_unique_abbrev) {
851+
struct packed_git *p;
852+
repo_for_each_pack(mad->repo, p)
853+
find_abbrev_len_for_pack(p, mad);
854+
}
812855
}
813856

814857
void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,

odb.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,32 @@ int odb_write_object_stream(struct object_database *odb,
981981
return odb_source_write_object_stream(odb->sources, stream, len, oid);
982982
}
983983

984+
int odb_write_packfile(struct object_database *odb,
985+
int pack_fd,
986+
struct odb_write_packfile_options *opts)
987+
{
988+
return odb_source_write_packfile(odb->sources, pack_fd, opts);
989+
}
990+
991+
int odb_for_each_unique_abbrev(struct object_database *odb,
992+
const struct object_id *oid_prefix,
993+
unsigned int prefix_len,
994+
odb_for_each_object_cb cb,
995+
void *cb_data)
996+
{
997+
int ret;
998+
999+
odb_prepare_alternates(odb);
1000+
for (struct odb_source *source = odb->sources; source; source = source->next) {
1001+
ret = odb_source_for_each_unique_abbrev(source, oid_prefix,
1002+
prefix_len, cb, cb_data);
1003+
if (ret)
1004+
return ret;
1005+
}
1006+
1007+
return 0;
1008+
}
1009+
9841010
struct object_database *odb_new(struct repository *repo,
9851011
const char *primary_source,
9861012
const char *secondary_sources)

odb.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,13 @@ enum object_info_flags {
374374
* clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK.
375375
*/
376376
OBJECT_INFO_FOR_PREFETCH = (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK),
377+
378+
/*
379+
* Only consider objects marked as "kept" (surviving GC). Used by
380+
* helper backends that track kept status per object. Backends that
381+
* do not support kept tracking should return -1 (not found).
382+
*/
383+
OBJECT_INFO_KEPT_ONLY = (1 << 5),
377384
};
378385

379386
/*
@@ -570,6 +577,25 @@ int odb_write_object_stream(struct object_database *odb,
570577
struct odb_write_stream *stream, size_t len,
571578
struct object_id *oid);
572579

580+
/*
581+
* Ingest a pack from a file descriptor into the primary source.
582+
* Returns 0 on success, a negative error code otherwise.
583+
*/
584+
struct odb_write_packfile_options;
585+
int odb_write_packfile(struct object_database *odb,
586+
int pack_fd,
587+
struct odb_write_packfile_options *opts);
588+
589+
/*
590+
* Iterate over all objects across all sources whose ID starts with
591+
* the given prefix. Used for object name disambiguation.
592+
*/
593+
int odb_for_each_unique_abbrev(struct object_database *odb,
594+
const struct object_id *oid_prefix,
595+
unsigned int prefix_len,
596+
odb_for_each_object_cb cb,
597+
void *cb_data);
598+
573599
void parse_alternates(const char *string,
574600
int sep,
575601
const char *relative_base,

0 commit comments

Comments
 (0)