diff --git a/Makefile b/Makefile index 4063e6c4a..850cf44e8 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ $(TEST_EXE): tests/%.exe: tests/%.o tests/%_main.o $(CC) -o $@ \ $(patsubst %.exe,%_main.o,$@) \ $(patsubst %.exe,%.o,$@) \ - $(T_LIB) -L. -lgit2 -lz + $(T_LIB) -L. -lgit2 -lz -lcrypto $(TEST_RUN): tests/%.run: tests/%.exe @t=trash-$( + +struct git_hash_ctx { + SHA_CTX c; +}; + +git_hash_ctx *git_hash_new_ctx(void) +{ + git_hash_ctx *ctx = malloc(sizeof(*ctx)); + + if (!ctx) + return NULL; + + SHA1_Init(&ctx->c); + + return ctx; +} + +void git_hash_free_ctx(git_hash_ctx *ctx) +{ + free(ctx); +} + +void git_hash_init(git_hash_ctx *ctx) +{ + assert(ctx); + SHA1_Init(&ctx->c); +} + +void git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + assert(ctx); + SHA1_Update(&ctx->c, data, len); +} + +void git_hash_final(git_oid *out, git_hash_ctx *ctx) +{ + assert(ctx); + SHA1_Final(out->id, &ctx->c); +} + +void git_hash_buf(git_oid *out, const void *data, size_t len) +{ + SHA_CTX c; + + SHA1_Init(&c); + SHA1_Update(&c, data, len); + SHA1_Final(out->id, &c); +} + +void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n) +{ + SHA_CTX c; + size_t i; + + SHA1_Init(&c); + for (i = 0; i < n; i++) + SHA1_Update(&c, vec[i].data, vec[i].len); + SHA1_Final(out->id, &c); +} diff --git a/src/hash.h b/src/hash.h new file mode 100644 index 000000000..b371c056b --- /dev/null +++ b/src/hash.h @@ -0,0 +1,26 @@ +/* + * hash.h + */ +#ifndef INCLUDE_hash_h__ +#define INCLUDE_hash_h__ + +#include "git/oid.h" + +typedef struct git_hash_ctx git_hash_ctx; + +typedef struct { + void *data; + size_t len; +} git_buf_vec; + +git_hash_ctx *git_hash_new_ctx(void); +void git_hash_free_ctx(git_hash_ctx *ctx); + +void git_hash_init(git_hash_ctx *c); +void git_hash_update(git_hash_ctx *c, const void *data, size_t len); +void git_hash_final(git_oid *out, git_hash_ctx *c); + +void git_hash_buf(git_oid *out, const void *data, size_t len); +void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n); + +#endif /* INCLUDE_hash_h__ */ diff --git a/tests/t0000-hash.c b/tests/t0000-hash.c new file mode 100644 index 000000000..6e9df7119 --- /dev/null +++ b/tests/t0000-hash.c @@ -0,0 +1,57 @@ +#include "test_lib.h" +#include "hash.h" +#include + +static char *hello_id = "22596363b3de40b06f981fb85d82312e8c0ed511"; +static char *hello_text = "hello world\n"; + +static char *bye_id = "ce08fe4884650f067bd5703b6a59a8b3b3c99a09"; +static char *bye_text = "bye world\n"; + +BEGIN_TEST(hash_iuf) + git_hash_ctx *ctx; + git_oid id1, id2; + + must_be_true((ctx = git_hash_new_ctx()) != NULL); + + /* should already be init'd */ + git_hash_update(ctx, hello_text, strlen(hello_text)); + git_hash_final(&id2, ctx); + must_pass(git_oid_mkstr(&id1, hello_id)); + must_be_true(git_oid_cmp(&id1, &id2) == 0); + + /* reinit should permit reuse */ + git_hash_init(ctx); + git_hash_update(ctx, bye_text, strlen(bye_text)); + git_hash_final(&id2, ctx); + must_pass(git_oid_mkstr(&id1, bye_id)); + must_be_true(git_oid_cmp(&id1, &id2) == 0); + + git_hash_free_ctx(ctx); +END_TEST + +BEGIN_TEST(hash_buf) + git_oid id1, id2; + + must_pass(git_oid_mkstr(&id1, hello_id)); + + git_hash_buf(&id2, hello_text, strlen(hello_text)); + + must_be_true(git_oid_cmp(&id1, &id2) == 0); +END_TEST + +BEGIN_TEST(hash_vec) + git_oid id1, id2; + git_buf_vec vec[2]; + + must_pass(git_oid_mkstr(&id1, hello_id)); + + vec[0].data = hello_text; + vec[0].len = 4; + vec[1].data = hello_text+4; + vec[1].len = strlen(hello_text)-4; + + git_hash_vec(&id2, vec, 2); + + must_be_true(git_oid_cmp(&id1, &id2) == 0); +END_TEST