Skip to content

Commit 35079f5

Browse files
committed
odb: add option to turn off hash verification
Verifying hashsums of objects we are reading from the ODB may be costly as we have to perform an additional hashsum calculation on the object. Especially when reading large objects, the penalty can be as high as 35%, as can be seen when executing the equivalent of `git cat-file` with and without verification enabled. To mitigate for this, we add a global option for libgit2 which enables the developer to turn off the verification, e.g. when he can be reasonably sure that the objects on disk won't be corrupted.
1 parent 28a0741 commit 35079f5

File tree

5 files changed

+29
-5
lines changed

5 files changed

+29
-5
lines changed

include/git2/common.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ typedef enum {
182182
GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION,
183183
GIT_OPT_GET_WINDOWS_SHAREMODE,
184184
GIT_OPT_SET_WINDOWS_SHAREMODE,
185+
GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION,
185186
} git_libgit2_opt_t;
186187

187188
/**
@@ -337,6 +338,13 @@ typedef enum {
337338
* > is written to permanent storage, not simply cached. This
338339
* > defaults to disabled.
339340
*
341+
* opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, int enabled)
342+
*
343+
* > Enable strict verification of object hashsums when reading
344+
* > objects from disk. This may impact performance due to an
345+
* > additional checksum calculation on each object. This defaults
346+
* > to enabled.
347+
*
340348
* @param option Option key
341349
* @param ... value to set the option
342350
* @return 0 on success, <0 on failure

src/odb.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
#define GIT_ALTERNATES_MAX_DEPTH 5
3333

34+
bool git_odb__strict_hash_verification = true;
35+
3436
typedef struct
3537
{
3638
git_odb_backend *backend;
@@ -1027,12 +1029,14 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
10271029
if (!found)
10281030
return GIT_ENOTFOUND;
10291031

1030-
if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
1031-
goto out;
1032+
if (git_odb__strict_hash_verification) {
1033+
if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
1034+
goto out;
10321035

1033-
if (!git_oid_equal(id, &hashed)) {
1034-
error = git_odb__error_mismatch(id, &hashed);
1035-
goto out;
1036+
if (!git_oid_equal(id, &hashed)) {
1037+
error = git_odb__error_mismatch(id, &hashed);
1038+
goto out;
1039+
}
10361040
}
10371041

10381042
giterr_clear();

src/odb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#define GIT_OBJECT_DIR_MODE 0777
2121
#define GIT_OBJECT_FILE_MODE 0444
2222

23+
extern bool git_odb__strict_hash_verification;
24+
2325
/* DO NOT EXPORT */
2426
typedef struct {
2527
void *data; /**< Raw, decompressed object data. */

src/settings.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "cache.h"
1616
#include "global.h"
1717
#include "object.h"
18+
#include "odb.h"
1819
#include "refs.h"
1920
#include "transports/smart.h"
2021

@@ -243,6 +244,10 @@ int git_libgit2_opts(int key, ...)
243244
#endif
244245
break;
245246

247+
case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
248+
git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
249+
break;
250+
246251
default:
247252
giterr_set(GITERR_INVALID, "invalid option key");
248253
error = -1;

tests/object/lookup.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ void test_object_lookup__lookup_object_with_wrong_hash_returns_error(void)
111111
/* Verify that lookup fails due to a hashsum mismatch */
112112
cl_git_fail_with(GIT_EMISMATCH, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
113113

114+
/* Disable verification and try again */
115+
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0));
116+
cl_git_pass(git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
117+
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 1));
118+
114119
git_buf_free(&oldpath);
115120
git_buf_free(&newpath);
116121
}

0 commit comments

Comments
 (0)