Commit e78854052d44df6460677e042f83e2bae4cb06e0

Stefan Sperling 2018-09-10T17:26:06

read packed trees with privsep

diff --git a/lib/got_lib_object_parse.h b/lib/got_lib_object_parse.h
index 901a18c..b427544 100644
--- a/lib/got_lib_object_parse.h
+++ b/lib/got_lib_object_parse.h
@@ -42,3 +42,5 @@ const struct got_error *got_object_packed_read_privsep(struct got_object **,
     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_tree_privsep(
+    struct got_tree_object **, struct got_object *, struct got_pack *);
diff --git a/lib/object.c b/lib/object.c
index f98a68d..dd27607 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -328,27 +328,6 @@ got_object_qid_alloc(struct got_object_qid **qid, struct got_object_id *id)
 	return NULL;
 }
 
-static const struct got_error *
-extract_packed_object_to_mem(uint8_t **buf, size_t *len,
-    struct got_object *obj, struct got_repository *repo)
-{
-	const struct got_error *err = NULL;
-	struct got_pack *pack;
-
-	if ((obj->flags & GOT_OBJ_FLAG_PACKED) == 0)
-		return got_error(GOT_ERR_OBJ_NOT_PACKED);
-
-	pack = got_repo_get_cached_pack(repo, obj->path_packfile);
-	if (pack == NULL) {
-		err = got_repo_cache_pack(&pack, repo,
-		    obj->path_packfile, NULL);
-		if (err)
-			return err;
-	}
-
-	return got_packfile_extract_object_to_mem(buf, len, obj, pack);
-}
-
 const struct got_error *
 got_object_commit_open(struct got_commit_object **commit,
     struct got_repository *repo, struct got_object *obj)
@@ -407,14 +386,15 @@ got_object_tree_open(struct got_tree_object **tree,
 		return got_error(GOT_ERR_OBJ_TYPE);
 
 	if (obj->flags & GOT_OBJ_FLAG_PACKED) {
-		uint8_t *buf;
-		size_t len;
-		err = extract_packed_object_to_mem(&buf, &len, obj, repo);
-		if (err)
-			return err;
-		obj->size = len;
-		err = got_object_parse_tree(tree, buf, len);
-		free(buf);
+		struct got_pack *pack;
+		pack = got_repo_get_cached_pack(repo, obj->path_packfile);
+		if (pack == NULL) {
+			err = got_repo_cache_pack(&pack, repo,
+			    obj->path_packfile, NULL);
+			if (err)
+				return err;
+		}
+		err = got_object_read_packed_tree_privsep(tree, obj, pack);
 	} else {
 		int fd;
 		err = open_loose_object(&fd, obj, repo);
diff --git a/lib/object_parse.c b/lib/object_parse.c
index 823f934..ae91d51 100644
--- a/lib/object_parse.c
+++ b/lib/object_parse.c
@@ -824,6 +824,19 @@ got_object_read_tree_privsep(struct got_tree_object **tree,
 	return request_tree(tree, repo, obj, obj_fd);
 }
 
+const struct got_error *
+got_object_read_packed_tree_privsep(struct got_tree_object **tree,
+    struct got_object *obj, struct got_pack *pack)
+{
+	const struct got_error *err = NULL;
+
+	err = got_privsep_send_obj_req(pack->privsep_child->ibuf, -1, obj);
+	if (err)
+		return err;
+
+	return got_privsep_recv_tree(tree, pack->privsep_child->ibuf);
+}
+
 static const struct got_error *
 request_blob(size_t *size, int outfd, int infd, struct got_repository *repo)
 {
diff --git a/lib/privsep.c b/lib/privsep.c
index 068c8e8..faa53d4 100644
--- a/lib/privsep.c
+++ b/lib/privsep.c
@@ -278,7 +278,7 @@ got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd, struct got_object *obj)
 		iobj.flags = obj->flags;
 		iobj.hdrlen = obj->hdrlen;
 		iobj.size = obj->size;
-		iobj.ndeltas = 0;
+		iobj.ndeltas = obj->deltas.nentries;
 		if (iobj.flags & GOT_OBJ_FLAG_PACKED)
 			iobj.pack_offset = obj->pack_offset;
 
diff --git a/libexec/got-read-pack/got-read-pack.c b/libexec/got-read-pack/got-read-pack.c
index 19b70b7..8110b5f 100644
--- a/libexec/got-read-pack/got-read-pack.c
+++ b/libexec/got-read-pack/got-read-pack.c
@@ -107,7 +107,39 @@ static const struct got_error *
 tree_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
     struct got_packidx *packidx)
 {
-	return got_error(GOT_ERR_NOT_IMPL);
+	const struct got_error *err = NULL;
+	struct got_object *obj = NULL;
+	struct got_tree_object *tree = NULL;
+	uint8_t *buf;
+	size_t len;
+
+	err = got_privsep_get_imsg_obj(&obj, imsg, ibuf);
+	if (err)
+		return err;
+
+	if (obj->type != GOT_OBJ_TYPE_TREE)
+		return got_error(GOT_ERR_OBJ_TYPE);
+
+	err = got_packfile_extract_object_to_mem(&buf, &len, obj, pack);
+	if (err)
+		return err;
+
+	obj->size = len;
+	err = got_object_parse_tree(&tree, buf, len);
+	free(buf);
+
+	err = got_privsep_send_tree(ibuf, tree);
+	if (obj)
+		got_object_close(obj);
+	got_object_tree_close(tree);
+	if (err) {
+		if (err->code == GOT_ERR_PRIVSEP_PIPE)
+			err = NULL;
+		else
+			got_privsep_send_error(ibuf, err);
+	}
+
+	return err;
 }
 
 static const struct got_error *