Subject: [PATCH 02/11] Factor out and export large blob writing code to arbitrary file handle

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Mon, 27 Feb 2012 14:55:06 +0700

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 cache.h |    3 +++
 entry.c |   39 ++++++++++++++++++++++++++-------------
 2 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/cache.h b/cache.h
index e12b15f..6ce691b 100644
--- a/cache.h
+++ b/cache.h
@@ -937,6 +937,9 @@ struct checkout {
 		 refresh_cache:1;
 };
 
+extern int streaming_write_sha1(int fd, int seekable, const unsigned char *sha1,
+				enum object_type exp_type,
+				struct stream_filter *filter);
 extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 
 struct cache_def {
diff --git a/entry.c b/entry.c
index 852fea1..dde0d17 100644
--- a/entry.c
+++ b/entry.c
@@ -115,26 +115,20 @@ static int fstat_output(int fd, const struct checkout *state, struct stat *st)
 	return 0;
 }
 
-static int streaming_write_entry(struct cache_entry *ce, char *path,
-				 struct stream_filter *filter,
-				 const struct checkout *state, int to_tempfile,
-				 int *fstat_done, struct stat *statbuf)
+int streaming_write_sha1(int fd, int seekable, const unsigned char *sha1,
+			 enum object_type exp_type,
+			 struct stream_filter *filter)
 {
 	struct git_istream *st;
 	enum object_type type;
 	unsigned long sz;
 	int result = -1;
 	ssize_t kept = 0;
-	int fd = -1;
 
-	st = open_istream(ce->sha1, &type, &sz, filter);
+	st = open_istream(sha1, &type, &sz, filter);
 	if (!st)
 		return -1;
-	if (type != OBJ_BLOB)
-		goto close_and_exit;
-
-	fd = open_output_fd(path, ce, to_tempfile);
-	if (fd < 0)
+	if (exp_type != OBJ_ANY && type != exp_type)
 		goto close_and_exit;
 
 	for (;;) {
@@ -144,7 +138,7 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
 
 		if (!readlen)
 			break;
-		if (sizeof(buf) == readlen) {
+		if (seekable && sizeof(buf) == readlen) {
 			for (holeto = 0; holeto < readlen; holeto++)
 				if (buf[holeto])
 					break;
@@ -166,10 +160,29 @@ static int streaming_write_entry(struct cache_entry *ce, char *path,
 	if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 ||
 		     write(fd, "", 1) != 1))
 		goto close_and_exit;
-	*fstat_done = fstat_output(fd, state, statbuf);
+	result = 0;
 
 close_and_exit:
 	close_istream(st);
+	return result;
+}
+
+static int streaming_write_entry(struct cache_entry *ce, char *path,
+				 struct stream_filter *filter,
+				 const struct checkout *state, int to_tempfile,
+				 int *fstat_done, struct stat *statbuf)
+{
+	int result = -1;
+	int fd = open_output_fd(path, ce, to_tempfile);
+	if (fd < 0)
+		goto close_and_exit;
+
+	if (streaming_write_sha1(fd, 1, ce->sha1, OBJ_BLOB, filter))
+		goto close_and_exit;
+
+	*fstat_done = fstat_output(fd, state, statbuf);
+
+close_and_exit:
 	if (0 <= fd)
 		result = close(fd);
 	if (result && 0 <= fd)
-- 
1.7.3.1.256.g2539c.dirty