commit 7762fe12f8608c112ccb3bbada7235a2c4208fd0 from: Stefan Sperling date: Mon Nov 05 10:46:30 2018 UTC add a mini-commit object for use by commit graph commit - b36429aba0124d4bc92ec4dd7b285ace7abfcaee commit + 7762fe12f8608c112ccb3bbada7235a2c4208fd0 blob - d0e80bc31edd85aea3d8e095d680ea7b47a23d0c blob + be5add975f075e866935ce17ed6496c3e1439b20 --- lib/commit_graph.c +++ lib/commit_graph.c @@ -163,12 +163,12 @@ is_merge_point(struct got_commit_graph_node *node) } static const struct got_error * -detect_changed_path(int *changed, struct got_commit_object *commit, +detect_changed_path(int *changed, struct got_commit_object_mini *commit, struct got_object_id *commit_id, const char *path, struct got_repository *repo) { const struct got_error *err = NULL; - struct got_commit_object *pcommit = NULL; + struct got_commit_object_mini *pcommit = NULL; struct got_tree_object *tree = NULL, *ptree = NULL; struct got_object_qid *pid; @@ -194,7 +194,7 @@ detect_changed_path(int *changed, struct got_commit_ob *changed = 1; /* The path was created in this commit. */ free(obj_id); } else { - err = got_object_open_as_commit(&pcommit, repo, pid->id); + err = got_object_open_mini_commit(&pcommit, repo, pid->id); if (err) goto done; @@ -211,7 +211,7 @@ done: if (ptree) got_object_tree_close(ptree); if (pcommit) - got_object_commit_close(pcommit); + got_object_mini_commit_close(pcommit); return err; } @@ -275,7 +275,7 @@ close_branch(struct got_commit_graph *graph, struct go static const struct got_error * advance_branch(struct got_commit_graph *graph, struct got_commit_graph_node *node, - struct got_object_id *commit_id, struct got_commit_object *commit, + struct got_object_id *commit_id, struct got_commit_object_mini *commit, struct got_repository *repo) { const struct got_error *err; @@ -382,8 +382,8 @@ free_node(struct got_commit_graph_node *node) static const struct got_error * add_node(struct got_commit_graph_node **new_node, struct got_commit_graph *graph, struct got_object_id *commit_id, - struct got_commit_object *commit, struct got_commit_graph_node *child_node, - struct got_repository *repo) + struct got_commit_object_mini *commit, + struct got_commit_graph_node *child_node, struct got_repository *repo) { const struct got_error *err = NULL; struct got_commit_graph_node *node; @@ -456,11 +456,11 @@ got_commit_graph_open(struct got_commit_graph **graph, int first_parent_traversal, struct got_repository *repo) { const struct got_error *err = NULL; - struct got_commit_object *commit; + struct got_commit_object_mini *commit; *graph = NULL; - err = got_object_open_as_commit(&commit, repo, commit_id); + err = got_object_open_mini_commit(&commit, repo, commit_id); if (err) return err; @@ -475,7 +475,7 @@ got_commit_graph_open(struct got_commit_graph **graph, *graph = alloc_graph(path); if (*graph == NULL) { - got_object_commit_close(commit); + got_object_mini_commit_close(commit); return got_error_from_errno(); } @@ -484,7 +484,7 @@ got_commit_graph_open(struct got_commit_graph **graph, err = add_node(&(*graph)->head_node, *graph, commit_id, commit, NULL, repo); - got_object_commit_close(commit); + got_object_mini_commit_close(commit); if (err) { got_commit_graph_close(*graph); *graph = NULL; @@ -547,20 +547,20 @@ fetch_commits_from_open_branches(int *ncommits, for (i = 0; i < arg.ntips; i++) { struct got_object_id *commit_id; struct got_commit_graph_node *child_node, *new_node; - struct got_commit_object *commit; + struct got_commit_object_mini *commit; int changed; commit_id = &graph->tips[i].id; child_node = graph->tips[i].node; - err = got_object_open_as_commit(&commit, repo, commit_id); + err = got_object_open_mini_commit(&commit, repo, commit_id); if (err) break; err = detect_changed_path(&changed, commit, commit_id, graph->path, repo); if (err) { - got_object_commit_close(commit); + got_object_mini_commit_close(commit); if (err->code != GOT_ERR_NO_OBJ) break; err = close_branch(graph, commit_id); @@ -572,7 +572,7 @@ fetch_commits_from_open_branches(int *ncommits, *changed_id = commit_id; err = add_node(&new_node, graph, commit_id, commit, child_node, repo); - got_object_commit_close(commit); + got_object_mini_commit_close(commit); if (err) break; if (new_node) @@ -628,21 +628,21 @@ got_commit_graph_iter_start(struct got_commit_graph *g { const struct got_error *err = NULL; struct got_commit_graph_node *start_node; - struct got_commit_object *commit; + struct got_commit_object_mini *commit; int changed; start_node = got_object_idset_get(graph->node_ids, id); if (start_node == NULL) return got_error(GOT_ERR_NO_OBJ); - err = got_object_open_as_commit(&commit, repo, &start_node->id); + err = got_object_open_mini_commit(&commit, repo, &start_node->id); if (err) return err; err = detect_changed_path(&changed, commit, &start_node->id, graph->path, repo); if (err) { - got_object_commit_close(commit); + got_object_mini_commit_close(commit); return err; } @@ -654,13 +654,13 @@ got_commit_graph_iter_start(struct got_commit_graph *g err = fetch_commits_from_open_branches(&ncommits, &changed_id, graph, repo); if (err) { - got_object_commit_close(commit); + got_object_mini_commit_close(commit); return err; } } start_node = got_object_idset_get(graph->node_ids, changed_id); } - got_object_commit_close(commit); + got_object_mini_commit_close(commit); graph->iter_node = start_node; return NULL; blob - fc8b2eef010a4a07760e360d7e9102d16791ddbd blob + 95f019e89afcbce1f16aa9d9641ca1a175c5eec1 --- lib/got_lib_object.h +++ lib/got_lib_object.h @@ -48,3 +48,16 @@ struct got_blob_object { uint8_t *read_buf; struct got_object_id id; }; + +/* Small version of got_commit_object. Used by commit graph. */ +struct got_commit_object_mini { + struct got_object_id *tree_id; + unsigned int nparents; + struct got_object_id_queue parent_ids; + struct tm tm_committer; /* UTC */ +}; + +const struct got_error * +got_object_open_mini_commit(struct got_commit_object_mini **, + struct got_repository *, struct got_object_id *); +void got_object_mini_commit_close(struct got_commit_object_mini *); blob - b427544ee597fb40d4802b61166507af2c7f124e blob + 99f5e6bdf1e4f1b801b6f3c9b5241f99b89c4231 --- lib/got_lib_object_parse.h +++ lib/got_lib_object_parse.h @@ -14,7 +14,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +const struct got_error *got_object_qid_alloc_partial(struct got_object_qid **); struct got_commit_object *got_object_commit_alloc_partial(void); +struct got_commit_object_mini *got_object_mini_commit_alloc_partial(void); +const struct got_error *got_object_commit_add_parent(struct got_commit_object *, + const char *); struct got_tree_entry *got_alloc_tree_entry_partial(void); const struct got_error *got_object_read_header_privsep(struct got_object**, struct got_repository *repo, int); @@ -23,11 +27,16 @@ const struct got_error *got_object_read_blob_privsep(s const struct got_error *got_object_read_commit_privsep( struct got_commit_object **, struct got_object *, int, struct got_repository *); +const struct got_error *got_object_read_mini_commit_privsep( + struct got_commit_object_mini **, struct got_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_parse_commit(struct got_commit_object **, char *, size_t); +const struct got_error *got_object_parse_mini_commit( + struct got_commit_object_mini **, char *, size_t); const struct got_error *got_object_parse_tree(struct got_tree_object **, uint8_t *, size_t); const struct got_error *got_read_file_to_mem(uint8_t **, size_t *, FILE *); @@ -42,5 +51,7 @@ const struct got_error *got_object_packed_read_privsep 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_mini_commit_privsep( + struct got_commit_object_mini **, 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 *); blob - b39f11fe79428dd8bc9691d9b8b2300171346459 blob + e343c376c6a64789812c5c88e965304898f5d7d4 --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -82,6 +82,8 @@ enum got_imsg_type { GOT_IMSG_COMMIT_REQUEST, GOT_IMSG_COMMIT, GOT_IMSG_COMMIT_LOGMSG, + GOT_IMSG_MINI_COMMIT_REQUEST, + GOT_IMSG_MINI_COMMIT, GOT_IMSG_TREE_REQUEST, GOT_IMSG_TREE, GOT_IMSG_TREE_ENTRY, @@ -142,7 +144,15 @@ struct got_imsg_commit_object { */ } __attribute__((__packed__)); +/* Structure for GOT_IMSG_MINI_COMMIT data. */ +struct got_imsg_commit_object_mini { + uint8_t tree_id[SHA1_DIGEST_LENGTH]; + struct tm tm_committer; + int nparents; + /* Followed by 'nparents' SHA1_DIGEST_LENGTH length strings */ +} __attribute__((__packed__)); + /* Structure for GOT_IMSG_TREE_ENTRY. */ struct got_imsg_tree_entry { char id[SHA1_DIGEST_LENGTH]; @@ -202,8 +212,12 @@ const struct got_error *got_privsep_recv_obj(struct go struct imsgbuf *); const struct got_error *got_privsep_send_commit(struct imsgbuf *, struct got_commit_object *); +const struct got_error *got_privsep_send_mini_commit(struct imsgbuf *, + struct got_commit_object_mini *); const struct got_error *got_privsep_recv_commit(struct got_commit_object **, struct imsgbuf *); +const struct got_error *got_privsep_recv_mini_commit( + struct got_commit_object_mini **, struct imsgbuf *); const struct got_error *got_privsep_recv_tree(struct got_tree_object **, struct imsgbuf *); const struct got_error *got_privsep_send_tree(struct imsgbuf *, @@ -214,4 +228,5 @@ const struct got_error *got_privsep_init_pack_child(st struct got_pack *, struct got_packidx *); const struct got_error *got_privsep_send_packed_obj_req(struct imsgbuf *, int, struct got_object_id *); -const struct got_error *got_privsep_send_pack_child_ready(struct imsgbuf *); +const struct got_error *got_privsep_send_mini_commit_req(struct imsgbuf *, int, + struct got_object *); blob - c58c241572783b631a3bb336ed0daab98750a241 blob + de22dce4277a47abcc56218844d0eb77281f29be --- lib/object.c +++ lib/object.c @@ -311,6 +311,41 @@ open_commit(struct got_commit_object **commit, if (err == NULL) { (*commit)->refcnt++; err = got_repo_cache_commit(repo, &obj->id, *commit); + } + + return err; +} + +static const struct got_error * +open_mini_commit(struct got_commit_object_mini **commit, + struct got_repository *repo, struct got_object *obj) +{ + const struct got_error *err = NULL; + + *commit = NULL; + + if (obj->type != GOT_OBJ_TYPE_COMMIT) + return got_error(GOT_ERR_OBJ_TYPE); + + if (obj->flags & GOT_OBJ_FLAG_PACKED) { + 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_mini_commit_privsep(commit, obj, + pack); + } else { + int fd; + err = open_loose_object(&fd, obj, repo); + if (err) + return err; + err = got_object_read_mini_commit_privsep(commit, obj, fd, + repo); + close(fd); } return err; @@ -348,6 +383,27 @@ got_object_commit_open(struct got_commit_object **comm struct got_repository *repo, struct got_object *obj) { return open_commit(commit, repo, obj, 1); +} + +const struct got_error * +got_object_open_mini_commit(struct got_commit_object_mini **commit, + struct got_repository *repo, struct got_object_id *id) +{ + const struct got_error *err; + struct got_object *obj; + + err = got_object_open(&obj, repo, id); + if (err) + return err; + if (got_object_get_type(obj) != GOT_OBJ_TYPE_COMMIT) { + err = got_error(GOT_ERR_OBJ_TYPE); + goto done; + } + + err = open_mini_commit(commit, repo, obj); +done: + got_object_close(obj); + return err; } const struct got_error * @@ -1074,7 +1130,6 @@ done: return err; } - static const struct got_error * request_commit(struct got_commit_object **commit, struct got_repository *repo, struct got_object *obj, int fd) @@ -1089,6 +1144,22 @@ request_commit(struct got_commit_object **commit, stru return err; return got_privsep_recv_commit(commit, ibuf); +} + +static const struct got_error * +request_mini_commit(struct got_commit_object_mini **commit, + struct got_repository *repo, struct got_object *obj, 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_mini_commit_req(ibuf, fd, obj); + if (err) + return err; + + return got_privsep_recv_mini_commit(commit, ibuf); } const struct got_error * @@ -1105,6 +1176,20 @@ got_object_read_packed_commit_privsep(struct got_commi } const struct got_error * +got_object_read_packed_mini_commit_privsep(struct got_commit_object_mini **commit, + struct got_object *obj, struct got_pack *pack) +{ + const struct got_error *err = NULL; + + err = got_privsep_send_mini_commit_req(pack->privsep_child->ibuf, -1, + obj); + if (err) + return err; + + return got_privsep_recv_mini_commit(commit, pack->privsep_child->ibuf); +} + +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) { @@ -1141,6 +1226,43 @@ got_object_read_commit_privsep(struct got_commit_objec return request_commit(commit, repo, obj, obj_fd); } +const struct got_error * +got_object_read_mini_commit_privsep(struct got_commit_object_mini **commit, + struct got_object *obj, 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_mini_commit(commit, repo, obj, obj_fd); + + ibuf = calloc(1, sizeof(*ibuf)); + if (ibuf == NULL) + return got_error_from_errno(); + + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1) + return got_error_from_errno(); + + pid = fork(); + if (pid == -1) + return got_error_from_errno(); + else if (pid == 0) { + exec_privsep_child(imsg_fds, GOT_PATH_PROG_READ_COMMIT, + repo->path); + /* not reached */ + } + + close(imsg_fds[1]); + repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].imsg_fd = + imsg_fds[0]; + repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].pid = pid; + imsg_init(ibuf, imsg_fds[0]); + repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf = ibuf; + + return request_mini_commit(commit, repo, obj, obj_fd); +} + static const struct got_error * request_tree(struct got_tree_object **tree, struct got_repository *repo, struct got_object *obj, int fd) blob - 07d52651602537e5df106ea314f3770df1ffb56f blob + ebf46135eb8eed76cb6a8e760c20294fcdb3cc06 --- lib/object_parse.c +++ lib/object_parse.c @@ -42,10 +42,10 @@ #include "got_lib_sha1.h" #include "got_lib_delta.h" -#include "got_lib_privsep.h" -#include "got_lib_pack.h" #include "got_lib_inflate.h" #include "got_lib_object.h" +#include "got_lib_privsep.h" +#include "got_lib_pack.h" #include "got_lib_object_cache.h" #include "got_lib_repository.h" @@ -102,6 +102,24 @@ got_object_close(struct got_object *obj) free(obj); } +const struct got_error * +got_object_qid_alloc_partial(struct got_object_qid **qid) +{ + const struct got_error *err = NULL; + + *qid = malloc(sizeof(**qid)); + if (*qid == NULL) + return got_error_from_errno(); + + (*qid)->id = malloc(sizeof(*((*qid)->id))); + if ((*qid)->id == NULL) { + err = got_error_from_errno(); + got_object_qid_free(*qid); + *qid = NULL; + } + return err; +} + void got_object_qid_free(struct got_object_qid *qid) { @@ -128,6 +146,25 @@ got_object_commit_alloc_partial(void) return commit; } +struct got_commit_object_mini * +got_object_mini_commit_alloc_partial(void) +{ + struct got_commit_object_mini *commit; + + commit = calloc(1, sizeof(*commit)); + if (commit == NULL) + return NULL; + commit->tree_id = calloc(1, sizeof(*commit->tree_id)); + if (commit->tree_id == NULL) { + free(commit); + return NULL; + } + + SIMPLEQ_INIT(&commit->parent_ids); + + return commit; +} + const struct got_error * got_object_commit_add_parent(struct got_commit_object *commit, const char *id_str) @@ -135,17 +172,34 @@ got_object_commit_add_parent(struct got_commit_object const struct got_error *err = NULL; struct got_object_qid *qid; - qid = malloc(sizeof(*qid)); - if (qid == NULL) - return got_error_from_errno(); - - qid->id = malloc(sizeof(*qid->id)); - if (qid->id == NULL) { - err = got_error_from_errno(); - got_object_qid_free(qid); + err = got_object_qid_alloc_partial(&qid); + if (err) return err; + + if (!got_parse_sha1_digest(qid->id->sha1, id_str)) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + free(qid->id); + free(qid); + return err; } + SIMPLEQ_INSERT_TAIL(&commit->parent_ids, qid, entry); + commit->nparents++; + + return NULL; +} + +const struct got_error * +got_object_mini_commit_add_parent(struct got_commit_object_mini *commit, + const char *id_str) +{ + const struct got_error *err = NULL; + struct got_object_qid *qid; + + err = got_object_qid_alloc_partial(&qid); + if (err) + return err; + if (!got_parse_sha1_digest(qid->id->sha1, id_str)) { err = got_error(GOT_ERR_BAD_OBJ_DATA); free(qid->id); @@ -255,14 +309,30 @@ got_object_commit_close(struct got_commit_object *comm free(commit); } +void +got_object_mini_commit_close(struct got_commit_object_mini *commit) +{ + struct got_object_qid *qid; + + while (!SIMPLEQ_EMPTY(&commit->parent_ids)) { + qid = SIMPLEQ_FIRST(&commit->parent_ids); + SIMPLEQ_REMOVE_HEAD(&commit->parent_ids, entry); + got_object_qid_free(qid); + } + + free(commit->tree_id); + free(commit); +} + const struct got_error * -got_object_parse_commit(struct got_commit_object **commit, char *buf, size_t len) +got_object_parse_commit(struct got_commit_object **commit, char *buf, + size_t len) { const struct got_error *err = NULL; char *s = buf; size_t tlen; ssize_t remain = (ssize_t)len; - + *commit = got_object_commit_alloc_partial(); if (*commit == NULL) return got_error_from_errno(); @@ -375,6 +445,109 @@ done: return err; } +const struct got_error * +got_object_parse_mini_commit(struct got_commit_object_mini **commit, char *buf, + size_t len) +{ + const struct got_error *err = NULL; + char *s = buf; + size_t tlen; + ssize_t remain = (ssize_t)len; + + *commit = got_object_mini_commit_alloc_partial(); + if (*commit == NULL) + return got_error_from_errno(); + + tlen = strlen(GOT_COMMIT_TAG_TREE); + if (strncmp(s, GOT_COMMIT_TAG_TREE, tlen) == 0) { + remain -= tlen; + if (remain < SHA1_DIGEST_STRING_LENGTH) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + s += tlen; + if (!got_parse_sha1_digest((*commit)->tree_id->sha1, s)) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + remain -= SHA1_DIGEST_STRING_LENGTH; + s += SHA1_DIGEST_STRING_LENGTH; + } else { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + + tlen = strlen(GOT_COMMIT_TAG_PARENT); + while (strncmp(s, GOT_COMMIT_TAG_PARENT, tlen) == 0) { + remain -= tlen; + if (remain < SHA1_DIGEST_STRING_LENGTH) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + s += tlen; + err = got_object_mini_commit_add_parent(*commit, s); + if (err) + goto done; + + remain -= SHA1_DIGEST_STRING_LENGTH; + s += SHA1_DIGEST_STRING_LENGTH; + } + + tlen = strlen(GOT_COMMIT_TAG_AUTHOR); + if (strncmp(s, GOT_COMMIT_TAG_AUTHOR, tlen) == 0) { + char *p; + size_t slen; + + remain -= tlen; + if (remain <= 0) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + s += tlen; + p = strchr(s, '\n'); + if (p == NULL) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + *p = '\0'; + slen = strlen(s); + s += slen + 1; + remain -= slen + 1; + } + + tlen = strlen(GOT_COMMIT_TAG_COMMITTER); + if (strncmp(s, GOT_COMMIT_TAG_COMMITTER, tlen) == 0) { + char *p; + size_t slen; + + remain -= tlen; + if (remain <= 0) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + s += tlen; + p = strchr(s, '\n'); + if (p == NULL) { + err = got_error(GOT_ERR_BAD_OBJ_DATA); + goto done; + } + *p = '\0'; + slen = strlen(s); + err = parse_commit_time(&(*commit)->tm_committer, s); + if (err) + goto done; + s += slen + 1; + remain -= slen + 1; + } + +done: + if (err) { + got_object_mini_commit_close(*commit); + *commit = NULL; + } + return err; +} + void got_object_tree_entry_close(struct got_tree_entry *te) { blob - 2429a9462a3a8c43c3d457557c231213747aec54 blob + e0d4a53bb329a1f39e987e8ef293e4e850ef4b36 --- lib/privsep.c +++ lib/privsep.c @@ -214,6 +214,20 @@ got_privsep_send_stop(int fd) return err; } +static void +init_imsg_object(struct got_imsg_object *iobj, struct got_object *obj) +{ + memcpy(iobj->id, obj->id.sha1, sizeof(iobj->id)); + iobj->type = obj->type; + iobj->flags = obj->flags; + iobj->hdrlen = obj->hdrlen; + iobj->size = obj->size; + if (iobj->flags & GOT_OBJ_FLAG_PACKED) { + iobj->pack_offset = obj->pack_offset; + iobj->pack_idx = obj->pack_idx; + } +} + const struct got_error * got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd, struct got_object *obj) { @@ -236,15 +250,7 @@ got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd, return got_error(GOT_ERR_OBJ_TYPE); } - memcpy(iobj.id, obj->id.sha1, sizeof(iobj.id)); - iobj.type = obj->type; - iobj.flags = obj->flags; - iobj.hdrlen = obj->hdrlen; - iobj.size = obj->size; - if (iobj.flags & GOT_OBJ_FLAG_PACKED) { - iobj.pack_offset = obj->pack_offset; - iobj.pack_idx = obj->pack_idx; - } + init_imsg_object(&iobj, obj); iobjp = &iobj; iobj_size = sizeof(iobj); @@ -257,6 +263,28 @@ got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd, } const struct got_error * +got_privsep_send_mini_commit_req(struct imsgbuf *ibuf, int fd, + struct got_object *obj) +{ + struct got_imsg_object iobj, *iobjp; + size_t iobj_size; + + if (obj->type != GOT_OBJ_TYPE_COMMIT) + return got_error(GOT_ERR_OBJ_TYPE); + + init_imsg_object(&iobj, obj); + + iobjp = &iobj; + iobj_size = sizeof(iobj); + + if (imsg_compose(ibuf, GOT_IMSG_MINI_COMMIT_REQUEST, 0, 0, fd, + iobjp, iobj_size) == -1) + return got_error_from_errno(); + + return flush_imsg(ibuf); +} + +const struct got_error * got_privsep_send_blob_req(struct imsgbuf *ibuf, int infd) { if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, NULL, 0) @@ -456,6 +484,46 @@ got_privsep_send_commit(struct imsgbuf *ibuf, struct g done: free(buf); return err; +} + +const struct got_error * +got_privsep_send_mini_commit(struct imsgbuf *ibuf, + struct got_commit_object_mini *commit) +{ + const struct got_error *err = NULL; + struct got_imsg_commit_object_mini icommit; + uint8_t *buf; + size_t len, total; + struct got_object_qid *qid; + + memcpy(icommit.tree_id, commit->tree_id->sha1, sizeof(icommit.tree_id)); + memcpy(&icommit.tm_committer, &commit->tm_committer, + sizeof(icommit.tm_committer)); + icommit.nparents = commit->nparents; + + total = sizeof(icommit) + icommit.nparents * SHA1_DIGEST_LENGTH; + + buf = malloc(total); + if (buf == NULL) + return got_error_from_errno(); + + len = 0; + memcpy(buf + len, &icommit, sizeof(icommit)); + len += sizeof(icommit); + SIMPLEQ_FOREACH(qid, &commit->parent_ids, entry) { + memcpy(buf + len, qid->id, SHA1_DIGEST_LENGTH); + len += SHA1_DIGEST_LENGTH; + } + + if (imsg_compose(ibuf, GOT_IMSG_MINI_COMMIT, 0, 0, -1, + buf, len) == -1) { + err = got_error_from_errno(); + } + + free(buf); + if (err) + return err; + return flush_imsg(ibuf); } const struct got_error * @@ -592,17 +660,89 @@ got_privsep_recv_commit(struct got_commit_object **com for (i = 0; i < icommit.nparents; i++) { struct got_object_qid *qid; - qid = calloc(1, sizeof(*qid)); - if (qid == NULL) { - err = got_error_from_errno(); + err = got_object_qid_alloc_partial(&qid); + if (err) break; - } - qid->id = calloc(1, sizeof(*qid->id)); - if (qid->id == NULL) { - err = got_error_from_errno(); - free(qid); + + memcpy(qid->id, data + len + i * SHA1_DIGEST_LENGTH, + sizeof(*qid->id)); + SIMPLEQ_INSERT_TAIL(&(*commit)->parent_ids, qid, entry); + (*commit)->nparents++; + } + break; + default: + err = got_error(GOT_ERR_PRIVSEP_MSG); + break; + } + + imsg_free(&imsg); + + return err; +} + +const struct got_error * +got_privsep_recv_mini_commit(struct got_commit_object_mini **commit, + struct imsgbuf *ibuf) +{ + const struct got_error *err = NULL; + struct imsg imsg; + struct got_imsg_commit_object_mini icommit; + size_t len, datalen; + int i; + const size_t min_datalen = + MIN(sizeof(struct got_imsg_error), + sizeof(struct got_imsg_commit_object_mini)); + uint8_t *data; + + *commit = NULL; + + err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen); + if (err) + return err; + + data = imsg.data; + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + len = 0; + + switch (imsg.hdr.type) { + case GOT_IMSG_ERROR: + err = recv_imsg_error(&imsg, datalen); + break; + case GOT_IMSG_MINI_COMMIT: + if (datalen < sizeof(icommit)) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + break; + } + + memcpy(&icommit, data, sizeof(icommit)); + if (datalen != sizeof(icommit) + + icommit.nparents * SHA1_DIGEST_LENGTH) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + break; + } + if (icommit.nparents < 0) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + break; + } + len += sizeof(icommit); + + *commit = got_object_mini_commit_alloc_partial(); + if (*commit == NULL) { + err = got_error_from_errno(); + break; + } + + memcpy((*commit)->tree_id->sha1, icommit.tree_id, + SHA1_DIGEST_LENGTH); + memcpy(&(*commit)->tm_committer, &icommit.tm_committer, + sizeof((*commit)->tm_committer)); + + for (i = 0; i < icommit.nparents; i++) { + struct got_object_qid *qid; + + err = got_object_qid_alloc_partial(&qid); + if (err) break; - } memcpy(qid->id, data + len + i * SHA1_DIGEST_LENGTH, sizeof(*qid->id)); blob - f6b5435605333d42433c5981a64efdc3cb4b18e6 blob + 49187ef259affaaff4c947f46d12fb23afb35738 --- libexec/got-read-commit/got-read-commit.c +++ libexec/got-read-commit/got-read-commit.c @@ -39,38 +39,67 @@ #include "got_lib_privsep.h" static const struct got_error * -read_commit_object(struct got_commit_object **commit, struct got_object *obj, - FILE *f) +read_commit_data(uint8_t **p, size_t *len, struct got_object *obj, FILE *f) { - const struct got_error *err = NULL; - size_t len; - uint8_t *p; + const struct got_error *err; if (obj->flags & GOT_OBJ_FLAG_PACKED) - err = got_read_file_to_mem(&p, &len, f); + 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; - if (len < obj->hdrlen + obj->size) { - err = got_error(GOT_ERR_BAD_OBJ_DATA); - goto done; + if (*len < obj->hdrlen + obj->size) { + free(*p); + *p = NULL; + *len = 0; + return got_error(GOT_ERR_BAD_OBJ_DATA); } /* Skip object header. */ - len -= obj->hdrlen; + *len -= obj->hdrlen; + return NULL; +} + +static const struct got_error * +read_commit_object(struct got_commit_object **commit, struct got_object *obj, + FILE *f) +{ + const struct got_error *err; + uint8_t *p; + size_t len; + + err = read_commit_data(&p, &len, obj, f); + if (err) + return err; + err = got_object_parse_commit(commit, p + obj->hdrlen, len); free(p); -done: return err; } +static const struct got_error * +read_commit_object_mini(struct got_commit_object_mini **commit, + struct got_object *obj, FILE *f) +{ + const struct got_error *err; + size_t len; + uint8_t *p; + + err = read_commit_data(&p, &len, obj, f); + if (err) + return err; + + err = got_object_parse_mini_commit(commit, p + obj->hdrlen, len); + free(p); + return err; +} + int main(int argc, char *argv[]) { const struct got_error *err = NULL; - struct got_commit_object *commit = NULL; struct imsgbuf ibuf; size_t datalen; @@ -90,6 +119,7 @@ main(int argc, char *argv[]) struct got_imsg_object iobj; FILE *f = NULL; struct got_object *obj = NULL; + int mini = 0; err = got_privsep_recv_imsg(&imsg, &ibuf, 0); if (err) { @@ -101,9 +131,16 @@ main(int argc, char *argv[]) if (imsg.hdr.type == GOT_IMSG_STOP) break; - if (imsg.hdr.type != GOT_IMSG_COMMIT_REQUEST) { - err = got_error(GOT_ERR_PRIVSEP_MSG); - goto done; + switch (imsg.hdr.type) { + case GOT_IMSG_COMMIT_REQUEST: + mini = 0; + break; + case GOT_IMSG_MINI_COMMIT_REQUEST: + mini = 1; + break; + default: + err = got_error(GOT_ERR_PRIVSEP_MSG); + goto done; } datalen = imsg.hdr.len - IMSG_HEADER_SIZE; @@ -139,11 +176,21 @@ main(int argc, char *argv[]) goto done; } - err = read_commit_object(&commit, obj, f); - if (err) - goto done; - - err = got_privsep_send_commit(&ibuf, commit); + if (mini) { + struct got_commit_object_mini *commit; + err = read_commit_object_mini(&commit, obj, f); + if (err) + goto done; + err = got_privsep_send_mini_commit(&ibuf, commit); + got_object_mini_commit_close(commit); + } else { + struct got_commit_object *commit; + err = read_commit_object(&commit, obj, f); + if (err) + goto done; + err = got_privsep_send_commit(&ibuf, commit); + got_object_commit_close(commit); + } done: if (f) fclose(f); blob - 010b14b5519db260c50522b9ffb8d93182af1675 blob + 1a4046e49b76e09595fd6cb02c2779592713c7c2 --- libexec/got-read-pack/got-read-pack.c +++ libexec/got-read-pack/got-read-pack.c @@ -134,6 +134,44 @@ commit_request(struct imsg *imsg, struct imsgbuf *ibuf if (obj) got_object_close(obj); got_object_commit_close(commit); + 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 * +mini_commit_request(struct imsg *imsg, struct imsgbuf *ibuf, + struct got_pack *pack, struct got_packidx *packidx, + struct got_object_cache *objcache) +{ + const struct got_error *err = NULL; + struct got_object *obj = NULL; + struct got_commit_object_mini *commit = NULL; + uint8_t *buf; + size_t len; + + err = get_object(&obj, imsg, ibuf, pack, packidx, objcache, + GOT_OBJ_TYPE_COMMIT); + if (err) + return err; + + err = got_packfile_extract_object_to_mem(&buf, &len, obj, pack); + if (err) + return err; + + obj->size = len; + err = got_object_parse_mini_commit(&commit, buf, len); + free(buf); + + err = got_privsep_send_mini_commit(ibuf, commit); + if (obj) + got_object_close(obj); + got_object_mini_commit_close(commit); if (err) { if (err->code == GOT_ERR_PRIVSEP_PIPE) err = NULL; @@ -464,6 +502,10 @@ main(int argc, char *argv[]) err = commit_request(&imsg, &ibuf, pack, packidx, &objcache); break; + case GOT_IMSG_MINI_COMMIT_REQUEST: + err = mini_commit_request(&imsg, &ibuf, pack, packidx, + &objcache); + break; case GOT_IMSG_TREE_REQUEST: err = tree_request(&imsg, &ibuf, pack, packidx, &objcache);