Skip to content

Commit dbccfc2

Browse files
committed
odb: accept an oid type in options
Allow the object database to take an oid type that it supports. This oid type will be used to validate the objects that the backends provide.
1 parent 3eba918 commit dbccfc2

File tree

4 files changed

+33
-16
lines changed

4 files changed

+33
-16
lines changed

include/git2/odb.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ typedef int GIT_CALLBACK(git_odb_foreach_cb)(const git_oid *id, void *payload);
4141
/** Options for configuring a loose object backend. */
4242
typedef struct {
4343
unsigned int version; /**< version for the struct */
44+
45+
/**
46+
* Type of object IDs to use for this object database, or
47+
* 0 for default (currently SHA1).
48+
*/
49+
git_oid_t oid_type;
4450
} git_odb_options;
4551

4652
/* The current version of the diff options structure */

include/git2/odb_backend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ struct git_odb_stream {
8787
unsigned int mode;
8888
void *hash_ctx;
8989

90+
git_oid_t oid_type;
91+
9092
git_object_size_t declared_size;
9193
git_object_size_t received_bytes;
9294

src/libgit2/odb.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,9 @@ static void normalize_options(
485485
memcpy(opts, given_opts, sizeof(git_odb_options));
486486
else
487487
memcpy(opts, &init, sizeof(git_odb_options));
488+
489+
if (!opts->oid_type)
490+
opts->oid_type = GIT_OID_DEFAULT;
488491
}
489492

490493
int git_odb_new(git_odb **out, const git_odb_options *opts)
@@ -1023,7 +1026,7 @@ int git_odb_exists_prefix(
10231026
if (len < GIT_OID_MINPREFIXLEN)
10241027
return git_odb__error_ambiguous("prefix length too short");
10251028

1026-
if (len >= GIT_OID_SHA1_HEXSIZE) {
1029+
if (len >= git_oid_hexsize(db->options.oid_type)) {
10271030
if (git_odb_exists(db, short_id)) {
10281031
if (out)
10291032
git_oid_cpy(out, short_id);
@@ -1052,11 +1055,13 @@ int git_odb_expand_ids(
10521055
git_odb_expand_id *ids,
10531056
size_t count)
10541057
{
1055-
size_t i;
1058+
size_t hex_size, i;
10561059

10571060
GIT_ASSERT_ARG(db);
10581061
GIT_ASSERT_ARG(ids);
10591062

1063+
hex_size = git_oid_hexsize(db->options.oid_type);
1064+
10601065
for (i = 0; i < count; i++) {
10611066
git_odb_expand_id *query = &ids[i];
10621067
int error = GIT_EAMBIGUOUS;
@@ -1065,21 +1070,21 @@ int git_odb_expand_ids(
10651070
query->type = GIT_OBJECT_ANY;
10661071

10671072
/* if we have a short OID, expand it first */
1068-
if (query->length >= GIT_OID_MINPREFIXLEN && query->length < GIT_OID_SHA1_HEXSIZE) {
1073+
if (query->length >= GIT_OID_MINPREFIXLEN && query->length < hex_size) {
10691074
git_oid actual_id;
10701075

10711076
error = odb_exists_prefix_1(&actual_id, db, &query->id, query->length, false);
10721077
if (!error) {
10731078
git_oid_cpy(&query->id, &actual_id);
1074-
query->length = GIT_OID_SHA1_HEXSIZE;
1079+
query->length = (unsigned short)hex_size;
10751080
}
10761081
}
10771082

10781083
/*
10791084
* now we ought to have a 40-char OID, either because we've expanded it
10801085
* or because the user passed a full OID. Ensure its type is right.
10811086
*/
1082-
if (query->length >= GIT_OID_SHA1_HEXSIZE) {
1087+
if (query->length >= hex_size) {
10831088
git_object_t actual_type;
10841089

10851090
error = odb_otype_fast(&actual_type, db, &query->id);
@@ -1099,7 +1104,7 @@ int git_odb_expand_ids(
10991104
/* the object is missing or ambiguous */
11001105
case GIT_ENOTFOUND:
11011106
case GIT_EAMBIGUOUS:
1102-
git_oid_clear(&query->id, GIT_OID_SHA1);
1107+
git_oid_clear(&query->id, db->options.oid_type);
11031108
query->length = 0;
11041109
query->type = 0;
11051110
break;
@@ -1207,7 +1212,7 @@ int git_odb__read_header_or_object(
12071212
error = odb_read_header_1(len_p, type_p, db, id, true);
12081213

12091214
if (error == GIT_ENOTFOUND)
1210-
return git_odb__error_notfound("cannot read header for", id, GIT_OID_SHA1_HEXSIZE);
1215+
return git_odb__error_notfound("cannot read header for", id, git_oid_hexsize(db->options.oid_type));
12111216

12121217
/* we found the header; return early */
12131218
if (!error)
@@ -1277,7 +1282,7 @@ static int odb_read_1(
12771282
return GIT_ENOTFOUND;
12781283

12791284
if (git_odb__strict_hash_verification) {
1280-
if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type, GIT_OID_SHA1)) < 0)
1285+
if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type, db->options.oid_type)) < 0)
12811286
goto out;
12821287

12831288
if (!git_oid_equal(id, &hashed)) {
@@ -1321,7 +1326,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
13211326
error = odb_read_1(out, db, id, true);
13221327

13231328
if (error == GIT_ENOTFOUND)
1324-
return git_odb__error_notfound("no match for id", id, GIT_OID_SHA1_HEXSIZE);
1329+
return git_odb__error_notfound("no match for id", id, git_oid_hexsize(id->type));
13251330

13261331
return error;
13271332
}
@@ -1418,7 +1423,7 @@ static int read_prefix_1(git_odb_object **out, git_odb *db,
14181423
if (git_odb__strict_hash_verification) {
14191424
git_oid hash;
14201425

1421-
if ((error = git_odb_hash(&hash, raw.data, raw.len, raw.type, GIT_OID_SHA1)) < 0)
1426+
if ((error = git_odb_hash(&hash, raw.data, raw.len, raw.type, db->options.oid_type)) < 0)
14221427
goto out;
14231428

14241429
if (!git_oid_equal(&found_full_oid, &hash)) {
@@ -1451,13 +1456,15 @@ int git_odb_read_prefix(
14511456
GIT_ASSERT_ARG(out);
14521457
GIT_ASSERT_ARG(db);
14531458

1459+
hex_size = git_oid_hexsize(db->options.oid_type);
1460+
14541461
if (len < GIT_OID_MINPREFIXLEN)
14551462
return git_odb__error_ambiguous("prefix length too short");
14561463

1457-
if (len > GIT_OID_SHA1_HEXSIZE)
1458-
len = GIT_OID_SHA1_HEXSIZE;
1464+
if (len > hex_size)
1465+
len = hex_size;
14591466

1460-
if (len == GIT_OID_SHA1_HEXSIZE) {
1467+
if (len == hex_size) {
14611468
*out = git_cache_get_raw(odb_cache(db), short_id);
14621469
if (*out != NULL)
14631470
return 0;
@@ -1517,7 +1524,7 @@ int git_odb_write(
15171524
GIT_ASSERT_ARG(oid);
15181525
GIT_ASSERT_ARG(db);
15191526

1520-
if ((error = git_odb_hash(oid, data, len, type, GIT_OID_SHA1)) < 0)
1527+
if ((error = git_odb_hash(oid, data, len, type, db->options.oid_type)) < 0)
15211528
return error;
15221529

15231530
if (git_oid_is_zero(oid))
@@ -1618,10 +1625,11 @@ int git_odb_open_wstream(
16181625
ctx = git__malloc(sizeof(git_hash_ctx));
16191626
GIT_ERROR_CHECK_ALLOC(ctx);
16201627

1621-
if ((error = git_hash_ctx_init(ctx, GIT_HASH_ALGORITHM_SHA1)) < 0 ||
1628+
if ((error = git_hash_ctx_init(ctx, git_oid_algorithm(db->options.oid_type))) < 0 ||
16221629
(error = hash_header(ctx, size, type)) < 0)
16231630
goto done;
16241631

1632+
(*stream)->oid_type = db->options.oid_type;
16251633
(*stream)->hash_ctx = ctx;
16261634
(*stream)->declared_size = size;
16271635
(*stream)->received_bytes = 0;
@@ -1665,7 +1673,7 @@ int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
16651673
"stream_finalize_write()");
16661674

16671675
git_hash_final(out->id, stream->hash_ctx);
1668-
out->type = GIT_OID_SHA1;
1676+
out->type = stream->oid_type;
16691677

16701678
if (git_odb__freshen(stream->backend->odb, out))
16711679
return 0;

src/libgit2/oid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b)
122122
GIT_INLINE(void) git_oid__cpy_prefix(
123123
git_oid *out, const git_oid *id, size_t len)
124124
{
125+
out->type = id->type;
125126
memcpy(&out->id, id->id, (len + 1) / 2);
126127

127128
if (len & 1)

0 commit comments

Comments
 (0)