Commit 35e9ba5d1cb044ee42c15d31ff663c7d16b25daf

Stefan Sperling 2018-06-21T19:41:20

introduce got_object_blob_dump_to_file()

diff --git a/include/got_object.h b/include/got_object.h
index 6687d7a..60c0249 100644
--- a/include/got_object.h
+++ b/include/got_object.h
@@ -179,6 +179,14 @@ const uint8_t *got_object_blob_get_read_buf(struct got_blob_object *);
 const struct got_error *got_object_blob_read_block(size_t *,
     struct got_blob_object *);
 
+/*
+ * Read the entire content of a blob and write it to the specified file.
+ * Flush and rewind the file as well, and indicate the amount of bytes
+ * written in the size_t output argument.
+ */
+const struct got_error *got_object_blob_dump_to_file(size_t *, FILE *,
+    struct got_blob_object *);
+
 const struct got_error *
 got_object_open_as_commit(struct got_commit_object **,
     struct got_repository *, struct got_object_id *);
diff --git a/lib/diff.c b/lib/diff.c
index 94feecd..2fb482f 100644
--- a/lib/diff.c
+++ b/lib/diff.c
@@ -44,7 +44,6 @@ got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
 	char hex1[SHA1_DIGEST_STRING_LENGTH];
 	char hex2[SHA1_DIGEST_STRING_LENGTH];
 	char *idstr1 = NULL, *idstr2 = NULL;
-	size_t len, hdrlen;
 	size_t size1, size2;
 	int res, flags = 0;
 
@@ -67,50 +66,21 @@ got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
 	size1 = 0;
 	if (blob1) {
 		idstr1 = got_object_blob_id_str(blob1, hex1, sizeof(hex1));
-		hdrlen = got_object_blob_get_hdrlen(blob1);
-		do {
-			err = got_object_blob_read_block(&len, blob1);
-			if (err)
-				goto done;
-			if (len == 0)
-				break;
-			size1 += len;
-			/* Skip blob object header first time around. */
-			fwrite(got_object_blob_get_read_buf(blob1) + hdrlen,
-			    len - hdrlen, 1, f1);
-			hdrlen = 0;
-		} while (len != 0);
+		err = got_object_blob_dump_to_file(&size1, f1, blob1);
+		if (err)
+			goto done;
 	} else
 		idstr1 = "/dev/null";
 
 	size2 = 0;
 	if (blob2) {
 		idstr2 = got_object_blob_id_str(blob2, hex2, sizeof(hex2));
-		hdrlen = got_object_blob_get_hdrlen(blob2);
-		do {
-			err = got_object_blob_read_block(&len, blob2);
-			if (err)
-				goto done;
-			if (len == 0)
-				break;
-			size2 += len;
-			/* Skip blob object header first time around. */
-			fwrite(got_object_blob_get_read_buf(blob2) + hdrlen,
-			    len - hdrlen, 1, f2);
-			hdrlen = 0;
-		} while (len != 0);
+		err = got_object_blob_dump_to_file(&size2, f2, blob2);
+		if (err)
+			goto done;
 	} else
 		idstr2 = "/dev/null";
 
-	if (f1) {
-		fflush(f1);
-		rewind(f1);
-	}
-	if (f2) {
-		fflush(f2);
-		rewind(f2);
-	}
-
 	memset(&ds, 0, sizeof(ds));
 	/* XXX should stat buffers be passed in args instead of ds? */
 	ds.stb1.st_mode = S_IFREG;
diff --git a/lib/object.c b/lib/object.c
index 7e037bb..559dc54 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -1358,6 +1358,34 @@ got_object_blob_read_block(size_t *outlenp, struct got_blob_object *blob)
 	return NULL;
 }
 
+const struct got_error *
+got_object_blob_dump_to_file(size_t *total_len, FILE *outfile,
+    struct got_blob_object *blob)
+{
+	const struct got_error *err = NULL;
+	size_t len, hdrlen;
+
+	*total_len = 0;
+	hdrlen = got_object_blob_get_hdrlen(blob);
+	do {
+		err = got_object_blob_read_block(&len, blob);
+		if (err)
+			return err;
+		if (len == 0)
+			break;
+		*total_len += len;
+		/* Skip blob object header first time around. */
+		fwrite(got_object_blob_get_read_buf(blob) + hdrlen,
+		    len - hdrlen, 1, outfile);
+		hdrlen = 0;
+	} while (len != 0);
+
+	fflush(outfile);
+	rewind(outfile);
+
+	return NULL;
+}
+
 static struct got_tree_entry *
 find_entry_by_name(struct got_tree_object *tree, const char *name)
 {