Commit 35079f50 by Patrick Steinhardt

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.
parent 28a0741f
......@@ -182,6 +182,7 @@ typedef enum {
GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION,
GIT_OPT_GET_WINDOWS_SHAREMODE,
GIT_OPT_SET_WINDOWS_SHAREMODE,
GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION,
} git_libgit2_opt_t;
/**
......@@ -337,6 +338,13 @@ typedef enum {
* > is written to permanent storage, not simply cached. This
* > defaults to disabled.
*
* opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, int enabled)
*
* > Enable strict verification of object hashsums when reading
* > objects from disk. This may impact performance due to an
* > additional checksum calculation on each object. This defaults
* > to enabled.
*
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
......
......@@ -31,6 +31,8 @@
#define GIT_ALTERNATES_MAX_DEPTH 5
bool git_odb__strict_hash_verification = true;
typedef struct
{
git_odb_backend *backend;
......@@ -1027,6 +1029,7 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
if (!found)
return GIT_ENOTFOUND;
if (git_odb__strict_hash_verification) {
if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
goto out;
......@@ -1034,6 +1037,7 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
error = git_odb__error_mismatch(id, &hashed);
goto out;
}
}
giterr_clear();
if ((object = odb_object__alloc(id, &raw)) == NULL)
......
......@@ -20,6 +20,8 @@
#define GIT_OBJECT_DIR_MODE 0777
#define GIT_OBJECT_FILE_MODE 0444
extern bool git_odb__strict_hash_verification;
/* DO NOT EXPORT */
typedef struct {
void *data; /**< Raw, decompressed object data. */
......
......@@ -15,6 +15,7 @@
#include "cache.h"
#include "global.h"
#include "object.h"
#include "odb.h"
#include "refs.h"
#include "transports/smart.h"
......@@ -243,6 +244,10 @@ int git_libgit2_opts(int key, ...)
#endif
break;
case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
break;
default:
giterr_set(GITERR_INVALID, "invalid option key");
error = -1;
......
......@@ -111,6 +111,11 @@ void test_object_lookup__lookup_object_with_wrong_hash_returns_error(void)
/* Verify that lookup fails due to a hashsum mismatch */
cl_git_fail_with(GIT_EMISMATCH, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
/* Disable verification and try again */
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0));
cl_git_pass(git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 1));
git_buf_free(&oldpath);
git_buf_free(&newpath);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment