Commit Diff


commit - 4c838a52b058826b33b06295771b4cd1553100d1
commit + 1785f84a3a2f8d9dd6b73551560405f87a2e2ebb
blob - 14bd628bae7ca8d8048fca27f37f546c5aca6701
blob + c3257cfa278471697b8fe6e3e8a8cb6396d55453
--- lib/got_lib_object.h
+++ lib/got_lib_object.h
@@ -37,6 +37,7 @@ struct got_object {
 };
 
 struct got_commit_object {
+	struct got_object *obj;
 	struct got_object_id *tree_id;
 	unsigned int nparents;
 	struct got_object_id_queue parent_ids;
blob - dcc76200ee994833fb286f365a9b936071eb118e
blob + 5c3980f2f01b211568497aa87e29167f3de13b4d
--- lib/got_lib_object_parse.h
+++ lib/got_lib_object_parse.h
@@ -22,8 +22,7 @@ const struct got_error *got_object_read_header_privsep
 const struct got_error *got_object_read_blob_privsep(size_t *, int, int,
     struct got_repository *repo);
 const struct got_error *got_object_read_commit_privsep(
-    struct got_commit_object **, struct got_object *, int,
-    struct got_repository *);
+    struct got_commit_object **, int, struct got_repository *);
 const struct got_error *got_object_read_tree_privsep(struct got_tree_object **,
     struct got_object *, int, struct got_repository *);
 const struct got_error *got_object_read_tag_privsep(struct got_tag_object **,
@@ -45,9 +44,12 @@ struct got_packidx;
 const struct got_error *got_object_packed_read_privsep(struct got_object **,
     struct got_repository *, struct got_pack *, struct got_packidx *, int,
     struct got_object_id *);
-const struct got_error *got_object_read_packed_commit_privsep(
-    struct got_commit_object **, struct got_object *, struct got_pack *);
+const struct got_error *
+got_object_read_packed_commit_privsep(struct got_commit_object **,
+    struct got_pack *, struct got_packidx *, int, struct got_object_id *);
 const struct got_error *got_object_read_packed_tree_privsep(
     struct got_tree_object **, struct got_object *, struct got_pack *);
 const struct got_error *got_object_read_packed_tag_privsep(
     struct got_tag_object **, struct got_object *, struct got_pack *);
+const struct got_error *got_object_parse_header(struct got_object **, char *, size_t);
+const struct got_error *got_object_read_header(struct got_object **, int);
blob - 871454f5b88c501bfe8560503f16b0d734fafba9
blob + 6f054bf24aa9628a786b47cf1f64635dec753297
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
@@ -111,8 +111,7 @@ struct got_imsg_error {
 } __attribute__((__packed__));
 
 /*
- * Structure for GOT_IMSG_TREE_REQUEST, GOT_IMSG_COMMIT_REQUEST,
- * and GOT_IMSG_OBJECT data.
+ * Structure for GOT_IMSG_TREE_REQUEST and GOT_IMSG_OBJECT data.
  */
 struct got_imsg_object {
 	uint8_t id[SHA1_DIGEST_LENGTH];
@@ -219,6 +218,8 @@ const struct got_error *got_privsep_recv_imsg(struct i
 void got_privsep_send_error(struct imsgbuf *, const struct got_error *);
 const struct got_error *got_privsep_send_obj_req(struct imsgbuf *, int,
     struct got_object *);
+const struct got_error *got_privsep_send_commit_req(struct imsgbuf *, int,
+    struct got_object_id *, int);
 const struct got_error *got_privsep_send_blob_req(struct imsgbuf *, int);
 const struct got_error *got_privsep_send_blob_outfd(struct imsgbuf *, int);
 const struct got_error *got_privsep_send_tmpfd(struct imsgbuf *, int);
blob - 5ca1099575ba902e52bb4dda0fbe2091bb0300c1
blob + 41e5235fe66dc73bcd2f261027677ff112f16817
--- lib/object.c
+++ lib/object.c
@@ -296,12 +296,15 @@ got_object_resolve_id_str(struct got_object_id **id,
 
 static const struct got_error *
 open_commit(struct got_commit_object **commit,
-    struct got_repository *repo, struct got_object *obj, int check_cache)
+    struct got_repository *repo, struct got_object_id *id, int check_cache)
 {
 	const struct got_error *err = NULL;
+	struct got_packidx *packidx = NULL;
+	int idx;
+	char *path_packfile;
 
 	if (check_cache) {
-		*commit = got_repo_get_cached_commit(repo, &obj->id);
+		*commit = got_repo_get_cached_commit(repo, id);
 		if (*commit != NULL) {
 			(*commit)->refcnt++;
 			return NULL;
@@ -309,31 +312,36 @@ open_commit(struct got_commit_object **commit,
 	} else
 		*commit = NULL;
 
-	if (obj->type != GOT_OBJ_TYPE_COMMIT)
-		return got_error(GOT_ERR_OBJ_TYPE);
+	err = got_repo_search_packidx(&packidx, &idx, repo, id);
+	if (err == NULL) {
+		struct got_pack *pack = NULL;
 
-	if (obj->flags & GOT_OBJ_FLAG_PACKED) {
-		struct got_pack *pack;
-		pack = got_repo_get_cached_pack(repo, obj->path_packfile);
+		err = get_packfile_path(&path_packfile, packidx);
+		if (err)
+			return err;
+
+		pack = got_repo_get_cached_pack(repo, path_packfile);
 		if (pack == NULL) {
-			err = got_repo_cache_pack(&pack, repo,
-			    obj->path_packfile, NULL);
+			err = got_repo_cache_pack(&pack, repo, path_packfile,
+			    packidx);
 			if (err)
 				return err;
 		}
-		err = got_object_read_packed_commit_privsep(commit, obj, pack);
-	} else {
+		err = got_object_read_packed_commit_privsep(commit, pack,
+		    packidx, idx, id);
+	} else if (err->code == GOT_ERR_NO_OBJ) {
 		int fd;
-		err = open_loose_object(&fd, got_object_get_id(obj), repo);
+
+		err = open_loose_object(&fd, id, repo);
 		if (err)
 			return err;
-		err = got_object_read_commit_privsep(commit, obj, fd, repo);
+		err = got_object_read_commit_privsep(commit, fd, repo);
 		close(fd);
 	}
 
 	if (err == NULL) {
 		(*commit)->refcnt++;
-		err = got_repo_cache_commit(repo, &obj->id, *commit);
+		err = got_repo_cache_commit(repo, id, *commit);
 	}
 
 	return err;
@@ -343,34 +351,20 @@ const struct got_error *
 got_object_open_as_commit(struct got_commit_object **commit,
     struct got_repository *repo, struct got_object_id *id)
 {
-	const struct got_error *err;
-	struct got_object *obj;
-
 	*commit = got_repo_get_cached_commit(repo, id);
 	if (*commit != NULL) {
 		(*commit)->refcnt++;
 		return NULL;
 	}
 
-	err = got_object_open(&obj, repo, id);
-	if (err)
-		return err;
-	if (obj->type != GOT_OBJ_TYPE_COMMIT) {
-		err = got_error(GOT_ERR_OBJ_TYPE);
-		goto done;
-	}
-
-	err = open_commit(commit, repo, obj, 0);
-done:
-	got_object_close(obj);
-	return err;
+	return open_commit(commit, repo, id, 0);
 }
 
 const struct got_error *
 got_object_commit_open(struct got_commit_object **commit,
     struct got_repository *repo, struct got_object *obj)
 {
-	return open_commit(commit, repo, obj, 1);
+	return open_commit(commit, repo, got_object_get_id(obj), 1);
 }
 
 const struct got_error *
@@ -1173,48 +1167,137 @@ done:
 		pack->privsep_child = NULL;
 	} else
 		err = request_packed_object(obj, pack, idx, id);
+	return err;
+}
+
+static const struct got_error *
+receive_commit(struct got_commit_object **commit, struct imsgbuf *ibuf)
+{
+	const struct got_error *err = NULL;
+	struct got_object *obj;
+
+	err = got_privsep_recv_obj(&obj, ibuf);
+	if (err)
+		return err;
+
+	err = got_privsep_recv_commit(commit, ibuf);
+	if (err)
+		got_object_close(obj);
+	else
+		(*commit)->obj = obj; /* XXX should be embedded */
+
 	return err;
 }
 
 static const struct got_error *
 request_commit(struct got_commit_object **commit, struct got_repository *repo,
-    struct got_object *obj, int fd)
+    int fd)
 {
 	const struct got_error *err = NULL;
 	struct imsgbuf *ibuf;
 
 	ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf;
 
-	err = got_privsep_send_obj_req(ibuf, fd, obj);
+	err = got_privsep_send_commit_req(ibuf, fd, NULL, -1);
 	if (err)
 		return err;
 
-	return got_privsep_recv_commit(commit, ibuf);
+	return receive_commit(commit, ibuf);
 }
 
+static const struct got_error *
+request_packed_commit(struct got_commit_object **commit, struct got_pack *pack,
+    int pack_idx, struct got_object_id *id)
+{
+	const struct got_error *err = NULL;
+
+	err = got_privsep_send_commit_req(pack->privsep_child->ibuf, -1, id,
+	    pack_idx);
+	if (err)
+		return err;
+
+	return receive_commit(commit, pack->privsep_child->ibuf);
+}
+
 const struct got_error *
 got_object_read_packed_commit_privsep(struct got_commit_object **commit,
-    struct got_object *obj, struct got_pack *pack)
+    struct got_pack *pack, struct got_packidx *packidx, int idx,
+    struct got_object_id *id)
 {
 	const struct got_error *err = NULL;
+	int imsg_fds[2];
+	pid_t pid;
+	struct imsgbuf *ibuf;
 
-	err = got_privsep_send_obj_req(pack->privsep_child->ibuf, -1, obj);
-	if (err)
+	if (pack->privsep_child)
+		return request_packed_commit(commit, pack, idx, id);
+
+	ibuf = calloc(1, sizeof(*ibuf));
+	if (ibuf == NULL)
+		return got_error_from_errno();
+
+	pack->privsep_child = calloc(1, sizeof(*pack->privsep_child));
+	if (pack->privsep_child == NULL) {
+		err = got_error_from_errno();
+		free(ibuf);
 		return err;
+	}
 
-	return got_privsep_recv_commit(commit, pack->privsep_child->ibuf);
+	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1) {
+		err = got_error_from_errno();
+		goto done;
+	}
+
+	pid = fork();
+	if (pid == -1) {
+		err = got_error_from_errno();
+		goto done;
+	} else if (pid == 0) {
+		exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_PACK,
+		    pack->path_packfile);
+		/* not reached */
+	}
+
+	close(imsg_fds[1]);
+	pack->privsep_child->imsg_fd = imsg_fds[0];
+	pack->privsep_child->pid = pid;
+	imsg_init(ibuf, imsg_fds[0]);
+	pack->privsep_child->ibuf = ibuf;
+
+	err = got_privsep_init_pack_child(ibuf, pack, packidx);
+	if (err) {
+		const struct got_error *child_err;
+		err = got_privsep_send_stop(pack->privsep_child->imsg_fd);
+		child_err = got_privsep_wait_for_child(
+		    pack->privsep_child->pid);
+		if (child_err && err == NULL)
+			err = child_err;
+		free(ibuf);
+		free(pack->privsep_child);
+		pack->privsep_child = NULL;
+		return err;
+	}
+
+done:
+	if (err) {
+		free(ibuf);
+		free(pack->privsep_child);
+		pack->privsep_child = NULL;
+	} else
+		err = request_packed_commit(commit, pack, idx, id);
+	return err;
 }
 
 const struct got_error *
 got_object_read_commit_privsep(struct got_commit_object **commit,
-    struct got_object *obj, int obj_fd, struct got_repository *repo)
+    int obj_fd, struct got_repository *repo)
 {
 	int imsg_fds[2];
 	pid_t pid;
 	struct imsgbuf *ibuf;
 
 	if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].imsg_fd != -1)
-		return request_commit(commit, repo, obj, obj_fd);
+		return request_commit(commit, repo, obj_fd);
 
 	ibuf = calloc(1, sizeof(*ibuf));
 	if (ibuf == NULL)
@@ -1239,7 +1322,7 @@ got_object_read_commit_privsep(struct got_commit_objec
 	imsg_init(ibuf, imsg_fds[0]);
 	repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf = ibuf;
 
-	return request_commit(commit, repo, obj, obj_fd);
+	return request_commit(commit, repo, obj_fd);
 }
 
 static const struct got_error *
blob - 21d3471c2b584757cf15d68aad56eb7edd8d3d02
blob + b98b1784a35735c7c85b744968f43221f3a449a3
--- lib/object_parse.c
+++ lib/object_parse.c
@@ -140,6 +140,111 @@ got_object_qid_free(struct got_object_qid *qid)
 {
 	free(qid->id);
 	free(qid);
+}
+
+const struct got_error *
+got_object_parse_header(struct got_object **obj, char *buf, size_t len)
+{
+	const char *obj_tags[] = {
+		GOT_OBJ_TAG_COMMIT,
+		GOT_OBJ_TAG_TREE,
+		GOT_OBJ_TAG_BLOB,
+		GOT_OBJ_TAG_TAG,
+	};
+	const int obj_types[] = {
+		GOT_OBJ_TYPE_COMMIT,
+		GOT_OBJ_TYPE_TREE,
+		GOT_OBJ_TYPE_BLOB,
+		GOT_OBJ_TYPE_TAG,
+	};
+	int type = 0;
+	size_t size = 0, hdrlen = 0;
+	int i;
+	char *p = strchr(buf, '\0');
+
+	*obj = NULL;
+
+	if (p == NULL)
+		return got_error(GOT_ERR_BAD_OBJ_HDR);
+
+	hdrlen = strlen(buf) + 1 /* '\0' */;
+
+	for (i = 0; i < nitems(obj_tags); i++) {
+		const char *tag = obj_tags[i];
+		size_t tlen = strlen(tag);
+		const char *errstr;
+
+		if (strncmp(buf, tag, tlen) != 0)
+			continue;
+
+		type = obj_types[i];
+		if (len <= tlen)
+			return got_error(GOT_ERR_BAD_OBJ_HDR);
+		size = strtonum(buf + tlen, 0, LONG_MAX, &errstr);
+		if (errstr != NULL)
+			return got_error(GOT_ERR_BAD_OBJ_HDR);
+		break;
+	}
+
+	if (type == 0)
+		return got_error(GOT_ERR_BAD_OBJ_HDR);
+
+	*obj = calloc(1, sizeof(**obj));
+	if (*obj == NULL)
+		return got_error_from_errno();
+	(*obj)->type = type;
+	(*obj)->hdrlen = hdrlen;
+	(*obj)->size = size;
+	return NULL;
+}
+
+const struct got_error *
+got_object_read_header(struct got_object **obj, int fd)
+{
+	const struct got_error *err;
+	struct got_zstream_buf zb;
+	char *buf;
+	const size_t zbsize = 64;
+	size_t outlen, totlen;
+	int nbuf = 1;
+
+	*obj = NULL;
+
+	buf = malloc(zbsize);
+	if (buf == NULL)
+		return got_error_from_errno();
+
+	err = got_inflate_init(&zb, buf, zbsize);
+	if (err)
+		return err;
+
+	totlen = 0;
+	do {
+		err = got_inflate_read_fd(&zb, fd, &outlen);
+		if (err)
+			goto done;
+		if (outlen == 0)
+			break;
+		totlen += outlen;
+		if (strchr(zb.outbuf, '\0') == NULL) {
+			char *newbuf;
+			nbuf++;
+			newbuf = recallocarray(buf, nbuf - 1, nbuf, zbsize);
+			if (newbuf == NULL) {
+				err = got_error_from_errno();
+				goto done;
+			}
+			buf = newbuf;
+			zb.outbuf = newbuf + totlen;
+			zb.outlen = (nbuf * zbsize) - totlen;
+		}
+	} while (strchr(zb.outbuf, '\0') == NULL);
+
+	err = got_object_parse_header(obj, buf, totlen);
+done:
+	free(buf);
+	got_inflate_end(&zb);
+	return err;
 }
 
 struct got_commit_object *
@@ -272,6 +377,7 @@ got_object_commit_close(struct got_commit_object *comm
 	free(commit->author);
 	free(commit->committer);
 	free(commit->logmsg);
+	got_object_close(commit->obj);
 	free(commit);
 }
 
blob - d95f5012099136dd65c3fbc85cbf8a99a89abdf7
blob + 2a15c7e9acf60b2624a4d24a64501982eb1dbf81
--- lib/privsep.c
+++ lib/privsep.c
@@ -233,7 +233,7 @@ got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd,
 			imsg_code = GOT_IMSG_TREE_REQUEST;
 			break;
 		case GOT_OBJ_TYPE_COMMIT:
-			imsg_code = GOT_IMSG_COMMIT_REQUEST;
+			abort(); /* should not get here */
 			break;
 		case GOT_OBJ_TYPE_BLOB:
 			imsg_code = GOT_IMSG_BLOB_REQUEST;
@@ -260,6 +260,30 @@ got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd,
 	}
 
 	if (imsg_compose(ibuf, imsg_code, 0, 0, fd, iobjp, iobj_size) == -1)
+		return got_error_from_errno();
+
+	return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_send_commit_req(struct imsgbuf *ibuf, int fd,
+    struct got_object_id *id, int pack_idx)
+{
+	struct got_imsg_packed_object iobj, *iobjp;
+	size_t len;
+
+	if (id) { /* commit is packed */
+		iobj.idx = pack_idx;
+		memcpy(iobj.id, id->sha1, sizeof(iobj.id));
+		iobjp = &iobj;
+		len = sizeof(iobj);
+	} else {
+		iobjp = NULL;
+		len = 0;
+	}
+
+	if (imsg_compose(ibuf, GOT_IMSG_COMMIT_REQUEST, 0, 0, fd, iobjp, len)
+	    == -1)
 		return got_error_from_errno();
 
 	return flush_imsg(ibuf);
blob - 9ebca90a5bf3e71ea9503fc697e1aa8fa2034493
blob + eeafefcdae2da3791cde557835ec32b1b3c58c3b
--- libexec/got-read-commit/got-read-commit.c
+++ libexec/got-read-commit/got-read-commit.c
@@ -48,30 +48,41 @@ catch_sigint(int signo)
 }
 
 static const struct got_error *
-read_commit_object(struct got_commit_object **commit, struct got_object *obj,
-    FILE *f)
+read_commit_object(struct got_commit_object **commit, FILE *f)
 {
+	struct got_object *obj;
 	const struct got_error *err = NULL;
 	size_t len;
 	uint8_t *p;
 
-	if (obj->flags & GOT_OBJ_FLAG_PACKED)
-		err = got_read_file_to_mem(&p, &len, f);
-	else
-		err = got_inflate_to_mem(&p, &len, f);
+	err = got_inflate_to_mem(&p, &len, f);
 	if (err)
 		return err;
 
+	err = got_object_parse_header(&obj, p, len);
+	if (err)
+		return err;
+
 	if (len < obj->hdrlen + obj->size) {
 		err = got_error(GOT_ERR_BAD_OBJ_DATA);
 		goto done;
 	}
 
+	if (obj->type != GOT_OBJ_TYPE_COMMIT) {
+		err = got_error(GOT_ERR_OBJ_TYPE);
+		goto done;
+	}
+
 	/* Skip object header. */
 	len -= obj->hdrlen;
 	err = got_object_parse_commit(commit, p + obj->hdrlen, len);
-	free(p);
 done:
+	free(p);
+	if (err)
+		got_object_close(obj);
+	else
+		(*commit)->obj = obj; /* XXX should be embedded in struct */
+
 	return err;
 }
 
@@ -79,9 +90,7 @@ int
 main(int argc, char *argv[])
 {
 	const struct got_error *err = NULL;
-	struct got_commit_object *commit = NULL;
 	struct imsgbuf ibuf;
-	size_t datalen;
 
 	signal(SIGINT, catch_sigint);
 
@@ -98,9 +107,8 @@ main(int argc, char *argv[])
 
 	while (1) {
 		struct imsg imsg;
-		struct got_imsg_object iobj;
 		FILE *f = NULL;
-		struct got_object *obj = NULL;
+		struct got_commit_object *commit = NULL;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -122,32 +130,11 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
-		if (datalen != sizeof(iobj)) {
-			err = got_error(GOT_ERR_PRIVSEP_LEN);
-			goto done;
-		}
-
-		memcpy(&iobj, imsg.data, sizeof(iobj));
-		if (iobj.type != GOT_OBJ_TYPE_COMMIT) {
-			err = got_error(GOT_ERR_OBJ_TYPE);
-			goto done;
-		}
-
 		if (imsg.fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
 
-		obj = calloc(1, sizeof(*obj));
-		if (obj == NULL) {
-			err = got_error_from_errno();
-			goto done;
-		}
-		obj->type = iobj.type;
-		obj->hdrlen = iobj.hdrlen;
-		obj->size = iobj.size;
-
 		/* Always assume file offset zero. */
 		f = fdopen(imsg.fd, "rb");
 		if (f == NULL) {
@@ -155,10 +142,17 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		err = read_commit_object(&commit, obj, f);
+		err = read_commit_object(&commit, f);
 		if (err)
 			goto done;
 
+		/* XXX This flushes the pipe, should only fill it instead. */
+		err = got_privsep_send_obj(&ibuf, commit->obj);
+		if (err)
+			goto done;
+
+		/* XXX Assumes full imsg buf size, should take obj into
+		 * account when above flush is removed. */
 		err = got_privsep_send_commit(&ibuf, commit);
 done:
 		if (f)
@@ -166,8 +160,6 @@ done:
 		else if (imsg.fd != -1)
 			close(imsg.fd);
 		imsg_free(&imsg);
-		if (obj)
-			got_object_close(obj);
 		if (err)
 			break;
 	}
blob - ae3722c08c1905a6e64dee0e34ec327baf6cb82c
blob + e6339341b9614a7bf218a689c25d8212ef1025e2
--- libexec/got-read-object/got-read-object.c
+++ libexec/got-read-object/got-read-object.c
@@ -36,6 +36,7 @@
 #include "got_lib_delta.h"
 #include "got_lib_inflate.h"
 #include "got_lib_object.h"
+#include "got_lib_object_parse.h"
 #include "got_lib_privsep.h"
 
 #ifndef nitems
@@ -55,112 +56,6 @@ catch_sigint(int signo)
 	sigint_received = 1;
 }
 
-static const struct got_error *
-parse_object_header(struct got_object **obj, char *buf, size_t len)
-{
-	const char *obj_tags[] = {
-		GOT_OBJ_TAG_COMMIT,
-		GOT_OBJ_TAG_TREE,
-		GOT_OBJ_TAG_BLOB,
-		GOT_OBJ_TAG_TAG,
-	};
-	const int obj_types[] = {
-		GOT_OBJ_TYPE_COMMIT,
-		GOT_OBJ_TYPE_TREE,
-		GOT_OBJ_TYPE_BLOB,
-		GOT_OBJ_TYPE_TAG,
-	};
-	int type = 0;
-	size_t size = 0, hdrlen = 0;
-	int i;
-	char *p = strchr(buf, '\0');
-
-	*obj = NULL;
-
-	if (p == NULL)
-		return got_error(GOT_ERR_BAD_OBJ_HDR);
-
-	hdrlen = strlen(buf) + 1 /* '\0' */;
-
-	for (i = 0; i < nitems(obj_tags); i++) {
-		const char *tag = obj_tags[i];
-		size_t tlen = strlen(tag);
-		const char *errstr;
-
-		if (strncmp(buf, tag, tlen) != 0)
-			continue;
-
-		type = obj_types[i];
-		if (len <= tlen)
-			return got_error(GOT_ERR_BAD_OBJ_HDR);
-		size = strtonum(buf + tlen, 0, LONG_MAX, &errstr);
-		if (errstr != NULL)
-			return got_error(GOT_ERR_BAD_OBJ_HDR);
-		break;
-	}
-
-	if (type == 0)
-		return got_error(GOT_ERR_BAD_OBJ_HDR);
-
-	*obj = calloc(1, sizeof(**obj));
-	if (*obj == NULL)
-		return got_error_from_errno();
-	(*obj)->type = type;
-	(*obj)->hdrlen = hdrlen;
-	(*obj)->size = size;
-	return NULL;
-}
-
-static const struct got_error *
-read_object_header(struct got_object **obj, int fd)
-{
-	const struct got_error *err;
-	struct got_zstream_buf zb;
-	char *buf;
-	const size_t zbsize = 64;
-	size_t outlen, totlen;
-	int nbuf = 1;
-
-	*obj = NULL;
-
-	buf = malloc(zbsize);
-	if (buf == NULL)
-		return got_error_from_errno();
-
-	err = got_inflate_init(&zb, buf, zbsize);
-	if (err)
-		return err;
-
-	totlen = 0;
-	do {
-		err = got_inflate_read_fd(&zb, fd, &outlen);
-		if (err)
-			goto done;
-		if (outlen == 0)
-			break;
-		totlen += outlen;
-		if (strchr(zb.outbuf, '\0') == NULL) {
-			char *newbuf;
-			nbuf++;
-			newbuf = recallocarray(buf, nbuf - 1, nbuf, zbsize);
-			if (newbuf == NULL) {
-				err = got_error_from_errno();
-				goto done;
-			}
-			buf = newbuf;
-			zb.outbuf = newbuf + totlen;
-			zb.outlen = (nbuf * zbsize) - totlen;
-		}
-	} while (strchr(zb.outbuf, '\0') == NULL);
-
-	err = parse_object_header(obj, buf, totlen);
-done:
-	free(buf);
-	got_inflate_end(&zb);
-	return err;
-}
-
-
 int
 main(int argc, char *argv[])
 {
@@ -210,7 +105,7 @@ main(int argc, char *argv[])
 			goto done;
 		}
 
-		err = read_object_header(&obj, imsg.fd);
+		err = got_object_read_header(&obj, imsg.fd);
 		if (err)
 			goto done;
 
blob - e5d58ee0bb72b099f33b72f3367599d9f6fee2eb
blob + 92227336ac9362deae0f19afe555b42461ad7b04
--- libexec/got-read-pack/got-read-pack.c
+++ libexec/got-read-pack/got-read-pack.c
@@ -121,13 +121,21 @@ commit_request(struct imsg *imsg, struct imsgbuf *ibuf
     struct got_packidx *packidx, struct got_object_cache *objcache)
 {
 	const struct got_error *err = NULL;
-	struct got_object *obj = NULL;
+	struct got_imsg_packed_object iobj;
+	struct got_object *obj;
 	struct got_commit_object *commit = NULL;
 	uint8_t *buf;
 	size_t len;
+	struct got_object_id id;
+	size_t datalen;
 
-	err = get_object(&obj, imsg, ibuf, pack, packidx, objcache,
-	    GOT_OBJ_TYPE_COMMIT);
+	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+	if (datalen != sizeof(iobj))
+		return got_error(GOT_ERR_PRIVSEP_LEN);
+	memcpy(&iobj, imsg->data, sizeof(iobj));
+	memcpy(id.sha1, iobj.id, SHA1_DIGEST_LENGTH);
+
+	err = got_packfile_open_object(&obj, pack, packidx, iobj.idx, &id);
 	if (err)
 		return err;
 
@@ -138,10 +146,22 @@ commit_request(struct imsg *imsg, struct imsgbuf *ibuf
 	obj->size = len;
 	err = got_object_parse_commit(&commit, buf, len);
 	free(buf);
+	if (err) {
+		got_object_close(obj);
+		return err;
+	} else
+		commit->obj = obj; /* XXX should be embedded */
+
+	/* XXX This flushes the pipe, should only fill it instead. */
+	err = got_privsep_send_obj(ibuf, commit->obj);
+	if (err) {
+		got_object_commit_close(commit);
+		return err;
+	}
 
+	/* XXX Assumes full imsg buf size, should take obj into
+	 * account when above flush is removed. */
 	err = got_privsep_send_commit(ibuf, commit);
-	if (obj)
-		got_object_close(obj);
 	got_object_commit_close(commit);
 	if (err) {
 		if (err->code == GOT_ERR_PRIVSEP_PIPE)