Commit Diff


commit - 30b4bb734581ef7586f4c99a6be5675153e3a6df
commit + 68482ea3f555f479c9342976a7fbacae381ffc05
blob - d13b60b4636e8d6487f381e4411f9f4167864c19
blob + b96bf6e63fbfc72d14e2b594437e9ce8b5c6ad44
--- include/got_object.h
+++ include/got_object.h
@@ -14,12 +14,23 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+struct got_zstream_buf {
+	z_stream z;
+	char *inbuf;
+	size_t inlen;
+	char *outbuf;
+	size_t outlen;
+	int flags;
+#define GOT_ZSTREAM_F_HAVE_MORE 0x01
+};
+
 struct got_object_id {
 	u_int8_t sha1[SHA1_DIGEST_LENGTH];
 };
 
 struct got_blob_object {
-	char *dummy;
+	FILE *f;
+	struct got_zstream_buf zb;
 };
 
 struct got_tree_entry {
@@ -73,3 +84,8 @@ void got_object_commit_close(struct got_commit_object 
 const struct got_error *got_object_tree_open(struct got_tree_object **,
     struct got_repository *, struct got_object *);
 void got_object_tree_close(struct got_tree_object *);
+const struct got_error *got_object_blob_open(struct got_blob_object **,
+    struct got_repository *, struct got_object *, size_t);
+void got_object_blob_close(struct got_blob_object *);
+const struct got_error *got_object_blob_read_block(struct got_blob_object *,
+    size_t *);
blob - ba716d03ea4d230704feb345266231ccd3603142
blob + a48d2da75fb713c02727e94d82ccc5cf85f6b8d4
--- lib/object.c
+++ lib/object.c
@@ -67,16 +67,6 @@ got_object_id_str(struct got_object_id *id, char *buf,
 
 	return buf;
 }
-
-struct got_zstream_buf {
-	z_stream z;
-	char *inbuf;
-	size_t inlen;
-	char *outbuf;
-	size_t outlen;
-	int flags;
-#define GOT_ZSTREAM_F_HAVE_MORE 0x01
-};
 
 static void
 inflate_end(struct got_zstream_buf *zb)
@@ -661,4 +651,58 @@ got_object_tree_close(struct got_tree_object *tree)
 	}
 
 	free(tree);
+}
+
+const struct got_error *
+got_object_blob_open(struct got_blob_object **blob,
+    struct got_repository *repo, struct got_object *obj, size_t blocksize)
+{
+	const struct got_error *err = NULL;
+	char *path;
+
+	if (obj->type != GOT_OBJ_TYPE_BLOB)
+		return got_error(GOT_ERR_OBJ_TYPE);
+
+	err = object_path(&path, &obj->id, repo);
+	if (err)
+		return err;
+
+	*blob = calloc(1, sizeof(**blob));
+	if (*blob == NULL) {
+		free(path);
+		return got_error(GOT_ERR_NO_MEM);
+	}
+
+	(*blob)->f = fopen(path, "rb");
+	if ((*blob)->f == NULL) {
+		free(*blob);
+		free(path);
+		return got_error(GOT_ERR_BAD_PATH);
+	}
+
+	err = inflate_init(&(*blob)->zb, blocksize);
+	if (err != NULL) {
+		fclose((*blob)->f);
+		free(*blob);
+		free(path);
+		return err;
+	}
+
+	free(path);
+	return err;
 }
+
+void
+got_object_blob_close(struct got_blob_object *blob)
+{
+	inflate_end(&blob->zb);
+	fclose(blob->f);
+	free(blob);
+}
+
+const struct got_error *
+got_object_blob_read_block(struct got_blob_object *blob, size_t *outlenp)
+{
+	return inflate_read(&blob->zb, blob->f, outlenp);
+}
+
blob - b299fd1c82f09e8d7eb1da05f0288b581998f571
blob + a754c2376543c040fa032dfb79ea805cf0c912a9
--- lib/refs.c
+++ lib/refs.c
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <util.h>
+#include <zlib.h>
 
 #include "got_error.h"
 #include "got_object.h"
blob - 395a24db512cb86c0510ef340e2cc9275c5dd803
blob + e5867e0a5aae93c78d3d5ba2dd7e3ade9b54f54b
--- regress/repository/repository_test.c
+++ regress/repository/repository_test.c
@@ -20,11 +20,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sha1.h>
+#include <zlib.h>
 
 #include "got_error.h"
 #include "got_object.h"
 #include "got_refs.h"
 #include "got_repository.h"
+#include "got_sha1.h"
 
 #define RUN_TEST(expr, name) \
 	if (!(expr)) { printf("test %s failed", (name)); failure = 1; }
@@ -184,6 +186,51 @@ repo_read_log(const char *repo_path)
 	return 1;
 }
 
+static int
+repo_read_blob(const char *repo_path)
+{
+	const char *blob_sha1 = "141f5fdc96126c1f4195558560a3c915e3d9b4c3";
+	const struct got_error *err;
+	struct got_repository *repo;
+	struct got_object_id id;
+	struct got_object *obj;
+	struct got_blob_object *blob;
+	char hex[SHA1_DIGEST_STRING_LENGTH];
+	int i;
+	size_t len;
+
+	if (!got_parse_sha1_digest(id.sha1, blob_sha1))
+		return 0;
+
+	err = got_repo_open(&repo, repo_path);
+	if (err != NULL || repo == NULL)
+		return 0;
+	err = got_object_open(&obj, repo, &id);
+	if (err != NULL || obj == NULL)
+		return 0;
+	if (obj->type != GOT_OBJ_TYPE_BLOB)
+		return 0;
+
+	err = got_object_blob_open(&blob, repo, obj, 64);
+	if (err != NULL)
+		return 0;
+
+	putchar('\n');
+	do {
+		err = got_object_blob_read_block(blob, &len);
+		if (err)
+			break;
+		for (i = 0; i < len; i++)
+			putchar(blob->zb.outbuf[i]);
+	} while (len != 0);
+	putchar('\n');
+
+	got_object_blob_close(blob);
+	got_object_close(obj);
+	got_repo_close(repo);
+	return (err == NULL);
+}
+
 int
 main(int argc, const char *argv[])
 {
@@ -200,6 +247,7 @@ main(int argc, const char *argv[])
 	}
 
 	RUN_TEST(repo_read_log(repo_path), "read_log");
+	RUN_TEST(repo_read_blob(repo_path), "read_blob");
 
 	return failure ? 1 : 0;
 }