Commit 8380b39a6761efa360398279083a65064d6770d3

Carlos Martín Nieto 2013-08-15T14:29:39

odb: perform the stream hashing in the frontend Hash the data as it's coming into the stream and tell the backend what its name is when finalizing the write. This makes it consistent with the way a plain git_odb_write() performs the write.

diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h
index af1e3e5..d004238 100644
--- a/include/git2/odb_backend.h
+++ b/include/git2/odb_backend.h
@@ -65,10 +65,13 @@ typedef enum {
 	GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY),
 } git_odb_stream_t;
 
+typedef struct git_hash_ctx git_hash_ctx;
+
 /** A stream to read/write from a backend */
 struct git_odb_stream {
 	git_odb_backend *backend;
 	unsigned int mode;
+	git_hash_ctx *hash_ctx;
 
 	int (*read)(git_odb_stream *stream, char *buffer, size_t len);
 	int (*write)(git_odb_stream *stream, const char *buffer, size_t len);
diff --git a/src/odb.c b/src/odb.c
index 1581596..b7f64df 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -871,11 +871,21 @@ int git_odb_write(
 	return error;
 }
 
+static void hash_header(git_hash_ctx *ctx, size_t size, git_otype type)
+{
+	char header[64];
+	int hdrlen;
+
+	hdrlen = git_odb__format_object_header(header, sizeof(header), size, type);
+	git_hash_update(ctx, header, hdrlen);
+}
+
 int git_odb_open_wstream(
 	git_odb_stream **stream, git_odb *db, size_t size, git_otype type)
 {
 	size_t i, writes = 0;
 	int error = GIT_ERROR;
+	git_hash_ctx *ctx;
 
 	assert(stream && db);
 
@@ -901,16 +911,26 @@ int git_odb_open_wstream(
 	if (error < 0 && !writes)
 		error = git_odb__error_unsupported_in_backend("write object");
 
+	ctx = git__malloc(sizeof(git_hash_ctx));
+	GITERR_CHECK_ALLOC(ctx);
+
+
+	git_hash_ctx_init(ctx);
+	hash_header(ctx, size, type);
+	(*stream)->hash_ctx = ctx;
+
 	return error;
 }
 
 int git_odb_stream_write(git_odb_stream *stream, const char *buffer, size_t len)
 {
+	git_hash_update(stream->hash_ctx, buffer, len);
 	return stream->write(stream, buffer, len);
 }
 
 int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
 {
+	git_hash_final(out, stream->hash_ctx);
 	return stream->finalize_write(out, stream);
 }
 
@@ -921,6 +941,7 @@ int git_odb_stream_read(git_odb_stream *stream, char *buffer, size_t len)
 
 void git_odb_stream_free(git_odb_stream *stream)
 {
+	git__free(stream->hash_ctx);
 	stream->free(stream);
 }
 
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 76ed8e2..a0c2c8c 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -776,8 +776,7 @@ static int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
 	git_buf final_path = GIT_BUF_INIT;
 	int error = 0;
 
-	if (git_filebuf_hash(oid, &stream->fbuf) < 0 ||
-		object_file_name(&final_path, backend, oid) < 0 ||
+	if (object_file_name(&final_path, backend, oid) < 0 ||
 		object_mkdir(&final_path, backend) < 0)
 		error = -1;
 	/*
@@ -848,7 +847,6 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
 
 	if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
 		git_filebuf_open(&stream->fbuf, tmp_path.ptr,
-			GIT_FILEBUF_HASH_CONTENTS |
 			GIT_FILEBUF_TEMPORARY |
 			(backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT)) < 0 ||
 		stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)