commit - c945ec50da8b849eeb8e82b3836fc106bc041419
commit + f4a881ce8b200e5283247799c39abd2b578b8e75
blob - 6ba2563737d96877e4e57392d5dd8bef4a272705
blob + c24e7e0fd473d1327a88bc5c25fd0ed0963c815e
--- include/got_object.h
+++ include/got_object.h
struct got_blob_object;
struct got_tree_object;
+struct got_tag_object;
struct got_tree_entry {
SIMPLEQ_ENTRY(got_tree_entry) entry;
const struct got_error *got_object_blob_dump_to_file(size_t *, size_t *,
FILE *, struct got_blob_object *);
+/*
+ * Attempt to open a tag object in a repository.
+ * The provided object must be of type GOT_OBJ_TYPE_TAG.
+ * The caller must dispose of the tree with got_object_tag_close().
+ */
+const struct got_error *got_object_tag_open(struct got_tag_object **,
+ struct got_repository *, struct got_object *);
+
+/* Dispose of a tag object. */
+void got_object_tag_close(struct got_tag_object *);
+
const struct got_error *
got_object_open_as_commit(struct got_commit_object **,
struct got_repository *, struct got_object_id *);
const struct got_error *
got_object_open_as_blob(struct got_blob_object **,
struct got_repository *, struct got_object_id *, size_t);
+const struct got_error *got_object_open_as_tag(struct got_tag_object **,
+ struct got_repository *, struct got_object_id *);
const struct got_error *got_object_commit_add_parent(struct got_commit_object *,
const char *);
blob - fc8b2eef010a4a07760e360d7e9102d16791ddbd
blob + c2619193e47de7f03830953b4c47623aafbbd7fb
--- lib/got_lib_object.h
+++ lib/got_lib_object.h
uint8_t *read_buf;
struct got_object_id id;
};
+
+struct got_tag_object {
+ struct got_object_id id;
+ int obj_type;
+ char *tag;
+ time_t tagger_time;
+ time_t tagger_gmtoff;
+ char *tagger;
+ char *tagmsg;
+ int refcnt; /* > 0 if open and/or cached */
+};
blob - 067f6f0703d20cfe605969655056f62b9b24771b
blob + a10ff39474235e35fee9cc7454d03acf7f84bb72
--- lib/got_lib_object_cache.h
+++ lib/got_lib_object_cache.h
GOT_OBJECT_CACHE_TYPE_OBJ,
GOT_OBJECT_CACHE_TYPE_TREE,
GOT_OBJECT_CACHE_TYPE_COMMIT,
+ GOT_OBJECT_CACHE_TYPE_TAG,
};
struct got_object_cache_entry {
struct got_object *obj;
struct got_tree_object *tree;
struct got_commit_object *commit;
+ struct got_tag_object *tag;
} data;
};
blob - f53705294442da0455ee9f988a17bdd3966aaf58
blob + dcc76200ee994833fb286f365a9b936071eb118e
--- lib/got_lib_object_parse.h
+++ lib/got_lib_object_parse.h
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 **,
+ 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_tree(struct got_tree_object **,
uint8_t *, size_t);
+const struct got_error *got_object_parse_tag(struct got_tag_object **,
+ uint8_t *, size_t);
const struct got_error *got_read_file_to_mem(uint8_t **, size_t *, FILE *);
void got_object_tree_entry_close(struct got_tree_entry *);
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 *);
+const struct got_error *got_object_read_packed_tag_privsep(
+ struct got_tag_object **, struct got_object *, struct got_pack *);
blob - a396e2c12db9ff8b8e8881e7c68a292bbab832e0
blob + 871454f5b88c501bfe8560503f16b0d734fafba9
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
#define GOT_PROG_READ_TREE got-read-tree
#define GOT_PROG_READ_COMMIT got-read-commit
#define GOT_PROG_READ_BLOB got-read-blob
+#define GOT_PROG_READ_TAG got-read-tag
#define GOT_PROG_READ_PACK got-read-pack
#define GOT_STRINGIFY(x) #x
GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_COMMIT)
#define GOT_PATH_PROG_READ_BLOB \
GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_BLOB)
+#define GOT_PATH_PROG_READ_TAG \
+ GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_TAG)
#define GOT_PATH_PROG_READ_PACK \
GOT_STRINGVAL(GOT_LIBEXECDIR) "/" GOT_STRINGVAL(GOT_PROG_READ_PACK)
GOT_IMSG_BLOB_REQUEST,
GOT_IMSG_BLOB_OUTFD,
GOT_IMSG_BLOB,
+ GOT_IMSG_TAG_REQUEST,
+ GOT_IMSG_TAG,
+ GOT_IMSG_TAG_TAGMSG,
/* Messages related to pack files. */
GOT_IMSG_PACKIDX,
size_t size;
};
+/* Structure for GOT_IMSG_TAG data. */
+struct got_imsg_tag_object {
+ uint8_t id[SHA1_DIGEST_LENGTH];
+ int obj_type;
+ size_t tag_len;
+ size_t tagger_len;
+ time_t tagger_time;
+ time_t tagger_gmtoff;
+ size_t tagmsg_len;
+
+ /*
+ * Followed by tag_len + tagger_len data bytes
+ */
+
+ /*
+ * Followed by 'tagmsg_len' bytes of tag message data in
+ * one or more GOT_IMSG_TAG_TAGMSG messages.
+ */
+} __attribute__((__packed__));
+
/* Structure for GOT_IMSG_PACKIDX. */
struct got_imsg_packidx {
size_t len;
struct got_tree_object *);
const struct got_error *got_privsep_send_blob(struct imsgbuf *, size_t);
const struct got_error *got_privsep_recv_blob(size_t *, struct imsgbuf *);
+const struct got_error *got_privsep_send_tag(struct imsgbuf *,
+ struct got_tag_object *);
+const struct got_error *got_privsep_recv_tag(struct got_tag_object **,
+ struct imsgbuf *);
const struct got_error *got_privsep_init_pack_child(struct imsgbuf *,
struct got_pack *, struct got_packidx *);
const struct got_error *got_privsep_send_packed_obj_req(struct imsgbuf *, int,
blob - feabca184d20dfd1ca4c681d9ccb24e0c7717d12
blob + 4379222e6238860a7965b41526f817c2614aa6e5
--- lib/got_lib_repository.h
+++ lib/got_lib_repository.h
struct got_pack packs[GOT_PACK_CACHE_SIZE];
/* Handles to child processes for reading loose objects. */
- struct got_privsep_child privsep_children[4];
+ struct got_privsep_child privsep_children[5];
#define GOT_REPO_PRIVSEP_CHILD_OBJECT 0
#define GOT_REPO_PRIVSEP_CHILD_COMMIT 1
#define GOT_REPO_PRIVSEP_CHILD_TREE 2
#define GOT_REPO_PRIVSEP_CHILD_BLOB 3
+#define GOT_REPO_PRIVSEP_CHILD_TAG 4
/* Caches for open objects. */
struct got_object_cache objcache;
struct got_object_cache treecache;
struct got_object_cache commitcache;
+ struct got_object_cache tagcache;
};
const struct got_error*got_repo_cache_object(struct got_repository *,
struct got_object_id *, struct got_commit_object *);
struct got_commit_object *got_repo_get_cached_commit(struct got_repository *,
struct got_object_id *);
+const struct got_error*got_repo_cache_tag(struct got_repository *,
+ struct got_object_id *, struct got_tag_object *);
+struct got_tag_object *got_repo_get_cached_tag(struct got_repository *,
+ struct got_object_id *);
const struct got_error *got_repo_cache_packidx(struct got_repository *,
struct got_packidx *);
const struct got_error *got_repo_search_packidx(struct got_packidx **, int *,
blob - 6bb2eb4489271559e6ddb7579f548ba80e7d7ff0
blob + 641b24fbfac455d82e70678c29699656df2e9b22
--- lib/object.c
+++ lib/object.c
rewind(outfile);
return NULL;
+}
+
+static const struct got_error *
+open_tag(struct got_tag_object **tag,
+ struct got_repository *repo, struct got_object *obj, int check_cache)
+{
+ const struct got_error *err = NULL;
+
+ if (check_cache) {
+ *tag = got_repo_get_cached_tag(repo, &obj->id);
+ if (*tag != NULL) {
+ (*tag)->refcnt++;
+ return NULL;
+ }
+ } else
+ *tag = NULL;
+
+ if (obj->type != GOT_OBJ_TYPE_TAG)
+ 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_tag_privsep(tag, obj, pack);
+ } else {
+ int fd;
+ err = open_loose_object(&fd, obj, repo);
+ if (err)
+ return err;
+ err = got_object_read_tag_privsep(tag, obj, fd, repo);
+ close(fd);
+ }
+
+ if (err == NULL) {
+ (*tag)->refcnt++;
+ err = got_repo_cache_tag(repo, &obj->id, *tag);
+ }
+
+ return err;
+}
+
+const struct got_error *
+got_object_open_as_tag(struct got_tag_object **tag,
+ struct got_repository *repo, struct got_object_id *id)
+{
+ const struct got_error *err;
+ struct got_object *obj;
+
+ *tag = got_repo_get_cached_tag(repo, id);
+ if (*tag != NULL) {
+ (*tag)->refcnt++;
+ return NULL;
+ }
+
+ 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_tag(tag, repo, obj, 0);
+done:
+ got_object_close(obj);
+ return err;
+}
+
+const struct got_error *
+got_object_tag_open(struct got_tag_object **tag,
+ struct got_repository *repo, struct got_object *obj)
+{
+ return open_tag(tag, repo, obj, 1);
}
static struct got_tree_entry *
return err;
}
-
static const struct got_error *
request_commit(struct got_commit_object **commit, struct got_repository *repo,
struct got_object *obj, int fd)
repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].ibuf = ibuf;
return request_blob(size, outfd, infd, ibuf);
+}
+
+static const struct got_error *
+request_tag(struct got_tag_object **tag, 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_TAG].ibuf;
+
+ err = got_privsep_send_obj_req(ibuf, fd, obj);
+ if (err)
+ return err;
+
+ return got_privsep_recv_tag(tag, ibuf);
+}
+
+const struct got_error *
+got_object_read_packed_tag_privsep(struct got_tag_object **tag,
+ 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_tag(tag, pack->privsep_child->ibuf);
+}
+
+const struct got_error *
+got_object_read_tag_privsep(struct got_tag_object **tag,
+ 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_TAG].imsg_fd != -1)
+ return request_tag(tag, 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_TAG,
+ repo->path);
+ /* not reached */
+ }
+
+ close(imsg_fds[1]);
+ repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].imsg_fd =
+ imsg_fds[0];
+ repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].pid = pid;
+ imsg_init(ibuf, imsg_fds[0]);
+ repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].ibuf = ibuf;
+
+ return request_tag(tag, repo, obj, obj_fd);
}
blob - 3325c9fb156df0f75d84e0b7075b5827a4cf25cc
blob + 63b2ca2a42f301ea74c82bfe070daf1cf71508ab
--- lib/object_cache.c
+++ lib/object_cache.c
#define GOT_OBJECT_CACHE_SIZE_OBJ 256
#define GOT_OBJECT_CACHE_SIZE_TREE 256
#define GOT_OBJECT_CACHE_SIZE_COMMIT 64
+#define GOT_OBJECT_CACHE_SIZE_TAG 32
const struct got_error *
got_object_cache_init(struct got_object_cache *cache,
case GOT_OBJECT_CACHE_TYPE_COMMIT:
cache->size = GOT_OBJECT_CACHE_SIZE_COMMIT;
break;
+ case GOT_OBJECT_CACHE_TYPE_TAG:
+ cache->size = GOT_OBJECT_CACHE_SIZE_TAG;
+ break;
}
return NULL;
}
case GOT_OBJECT_CACHE_TYPE_COMMIT:
got_object_commit_close(ce->data.commit);
break;
+ case GOT_OBJECT_CACHE_TYPE_TAG:
+ got_object_tag_close(ce->data.tag);
+ break;
}
free(ce);
cache->cache_evict++;
case GOT_OBJECT_CACHE_TYPE_COMMIT:
ce->data.commit = (struct got_commit_object *)item;
break;
+ case GOT_OBJECT_CACHE_TYPE_TAG:
+ ce->data.tag = (struct got_tag_object *)item;
+ break;
}
err = got_object_idset_add(cache->idset, id, ce);
return ce->data.tree;
case GOT_OBJECT_CACHE_TYPE_COMMIT:
return ce->data.commit;
+ case GOT_OBJECT_CACHE_TYPE_TAG:
+ return ce->data.tag;
}
}
struct got_object *obj;
struct got_tree_object *tree;
struct got_commit_object *commit;
+ struct got_tag_object *tag;
char *id_str;
if (got_object_id_str(&id_str, id) != NULL)
fprintf(stderr, "commit %s has %d unclaimed references\n",
id_str, commit->refcnt - 1);
break;
+ case GOT_OBJECT_CACHE_TYPE_TAG:
+ tag = ce->data.tag;
+ if (tag->refcnt == 1)
+ break;
+ fprintf(stderr, "tag %s has %d unclaimed references\n",
+ id_str, tag->refcnt - 1);
+ break;
}
free(id_str);
return NULL;
blob - 0c8445c525924957e8cc178b0f1f868028a3699d
blob + 433a6598256a2714af7dc3ab5859a6231a30150d
--- lib/object_parse.c
+++ lib/object_parse.c
#define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
#endif
+#define GOT_OBJ_TAG_COMMIT "commit"
+#define GOT_OBJ_TAG_TREE "tree"
+#define GOT_OBJ_TAG_BLOB "blob"
+#define GOT_OBJ_TAG_TAG "tag"
+
#define GOT_COMMIT_TAG_TREE "tree "
#define GOT_COMMIT_TAG_PARENT "parent "
#define GOT_COMMIT_TAG_AUTHOR "author "
#define GOT_COMMIT_TAG_COMMITTER "committer "
+#define GOT_TAG_TAG_OBJECT "object "
+#define GOT_TAG_TAG_TYPE "type "
+#define GOT_TAG_TAG_TAG "tag "
+#define GOT_TAG_TAG_TAGGER "tagger "
+
int
got_object_id_cmp(const struct got_object_id *id1,
const struct got_object_id *id2)
return NULL;
}
+void
+got_object_tag_close(struct got_tag_object *tag)
+{
+ free(tag->tag);
+ free(tag->tagger);
+ free(tag->tagmsg);
+ free(tag);
+}
+
const struct got_error *
+got_object_parse_tag(struct got_tag_object **tag, uint8_t *buf, size_t len)
+{
+ const struct got_error *err = NULL;
+ size_t remain = len;
+ char *s = buf;
+ size_t tlen;
+
+ *tag = calloc(1, sizeof(**tag));
+ if (*tag == NULL)
+ return got_error_from_errno();
+
+ tlen = strlen(GOT_TAG_TAG_OBJECT);
+ if (strncmp(s, GOT_TAG_TAG_OBJECT, 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((*tag)->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;
+ }
+
+ if (remain <= 0) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+
+ tlen = strlen(GOT_TAG_TAG_TYPE);
+ if (strncmp(s, GOT_TAG_TAG_TYPE, tlen) == 0) {
+ remain -= tlen;
+ if (remain <= 0) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+ s += tlen;
+ if (strncmp(s, GOT_OBJ_TAG_COMMIT,
+ strlen(GOT_OBJ_TAG_COMMIT)) == 0) {
+ (*tag)->obj_type = GOT_OBJ_TYPE_COMMIT;
+ tlen = strlen(GOT_OBJ_TAG_COMMIT);
+ s += tlen;
+ remain -= tlen;
+ } else if (strncmp(s, GOT_OBJ_TAG_TREE,
+ strlen(GOT_OBJ_TAG_TREE)) == 0) {
+ (*tag)->obj_type = GOT_OBJ_TYPE_TREE;
+ tlen = strlen(GOT_OBJ_TAG_TREE);
+ s += tlen;
+ remain -= tlen;
+ } else if (strncmp(s, GOT_OBJ_TAG_BLOB,
+ strlen(GOT_OBJ_TAG_BLOB)) == 0) {
+ (*tag)->obj_type = GOT_OBJ_TYPE_BLOB;
+ tlen = strlen(GOT_OBJ_TAG_BLOB);
+ s += tlen;
+ remain -= tlen;
+ } else if (strncmp(s, GOT_OBJ_TAG_TAG,
+ strlen(GOT_OBJ_TAG_TAG)) == 0) {
+ (*tag)->obj_type = GOT_OBJ_TYPE_TAG;
+ tlen = strlen(GOT_OBJ_TAG_TAG);
+ s += tlen;
+ remain -= tlen;
+ } else {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+
+ if (remain <= 0 || *s != '\n') {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+ s++;
+ remain--;
+ if (remain <= 0) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+ } else {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+
+ tlen = strlen(GOT_TAG_TAG_TAG);
+ if (strncmp(s, GOT_TAG_TAG_TAG, 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);
+ (*tag)->tag = strndup(s, slen);
+ if ((*tag)->tag == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ s += slen + 1;
+ remain -= slen + 1;
+ if (remain <= 0) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+ } else {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+
+ tlen = strlen(GOT_TAG_TAG_TAGGER);
+ if (strncmp(s, GOT_TAG_TAG_TAGGER, 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(&(*tag)->tagger_time,
+ &(*tag)->tagger_gmtoff, s);
+ if (err)
+ goto done;
+ (*tag)->tagger = strdup(s);
+ if ((*tag)->tagger == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ s += slen + 1;
+ remain -= slen + 1;
+ if (remain <= 0) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+ } else {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+
+ (*tag)->tagmsg = strndup(s, remain);
+ if ((*tag)->tagmsg == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+done:
+ if (err) {
+ got_object_tag_close(*tag);
+ *tag = NULL;
+ }
+ return err;
+}
+
+const struct got_error *
got_read_file_to_mem(uint8_t **outbuf, size_t *outlen, FILE *f)
{
const struct got_error *err = NULL;
blob - 28b85018e0bd0857fe3c037382a2318f2f331963
blob + d95f5012099136dd65c3fbc85cbf8a99a89abdf7
--- lib/privsep.c
+++ lib/privsep.c
break;
case GOT_OBJ_TYPE_BLOB:
imsg_code = GOT_IMSG_BLOB_REQUEST;
+ break;
+ case GOT_OBJ_TYPE_TAG:
+ imsg_code = GOT_IMSG_TAG_REQUEST;
break;
default:
return got_error(GOT_ERR_OBJ_TYPE);
iblob = imsg.data;
*size = iblob->size;
/* Data has been written to file descriptor. */
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+
+ imsg_free(&imsg);
+
+ return err;
+}
+
+static const struct got_error *
+send_tagmsg(struct imsgbuf *ibuf, struct got_tag_object *tag, size_t tagmsg_len)
+{
+ const struct got_error *err = NULL;
+ size_t offset, remain;
+
+ offset = 0;
+ remain = tagmsg_len;
+ while (remain > 0) {
+ size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE, remain);
+
+ if (imsg_compose(ibuf, GOT_IMSG_TAG_TAGMSG, 0, 0, -1,
+ tag->tagmsg + offset, n) == -1) {
+ err = got_error_from_errno();
+ break;
+ }
+
+ err = flush_imsg(ibuf);
+ if (err)
+ break;
+
+ offset += n;
+ remain -= n;
+ }
+
+ return err;
+}
+
+const struct got_error *
+got_privsep_send_tag(struct imsgbuf *ibuf, struct got_tag_object *tag)
+{
+ const struct got_error *err = NULL;
+ struct got_imsg_tag_object *itag;
+ uint8_t *buf;
+ size_t len, total;
+ size_t tag_len = strlen(tag->tag);
+ size_t tagger_len = strlen(tag->tagger);
+ size_t tagmsg_len = strlen(tag->tagmsg);
+
+ total = sizeof(*itag) + tag_len + tagger_len + tagmsg_len;
+
+ buf = malloc(total);
+ if (buf == NULL)
+ return got_error_from_errno();
+
+ itag = (struct got_imsg_tag_object *)buf;
+ memcpy(itag->id, tag->id.sha1, sizeof(itag->id));
+ itag->obj_type = tag->obj_type;
+ itag->tag_len = tag_len;
+ itag->tagger_len = tagger_len;
+ itag->tagger_time = tag->tagger_time;
+ itag->tagger_gmtoff = tag->tagger_gmtoff;
+ itag->tagmsg_len = tagmsg_len;
+
+ len = sizeof(*itag);
+ memcpy(buf + len, tag->tag, tag_len);
+ len += tag_len;
+ memcpy(buf + len, tag->tagger, tagger_len);
+ len += tagger_len;
+
+ if (imsg_compose(ibuf, GOT_IMSG_TAG, 0, 0, -1, buf, len) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ if (tagmsg_len == 0 ||
+ tagmsg_len + len > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
+ err = flush_imsg(ibuf);
+ if (err)
+ goto done;
+ }
+ err = send_tagmsg(ibuf, tag, tagmsg_len);
+done:
+ free(buf);
+ return err;
+}
+
+const struct got_error *
+got_privsep_recv_tag(struct got_tag_object **tag, struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ struct got_imsg_tag_object *itag;
+ size_t len, datalen;
+ const size_t min_datalen =
+ MIN(sizeof(struct got_imsg_error),
+ sizeof(struct got_imsg_tag_object));
+
+ *tag = NULL;
+
+ err = got_privsep_recv_imsg(&imsg, ibuf, min_datalen);
+ if (err)
+ return err;
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ len = 0;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_TAG:
+ if (datalen < sizeof(*itag)) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ break;
+ }
+ itag = imsg.data;
+ if (datalen != sizeof(*itag) + itag->tag_len +
+ itag->tagger_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ break;
+ }
+ len += sizeof(*itag);
+
+ *tag = calloc(1, sizeof(**tag));
+ if (*tag == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+
+ memcpy((*tag)->id.sha1, itag->id, SHA1_DIGEST_LENGTH);
+
+ if (itag->tag_len == 0) {
+ (*tag)->tag = strdup("");
+ if ((*tag)->tag == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+ } else {
+ (*tag)->tag = malloc(itag->tag_len + 1);
+ if ((*tag)->tag == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+ memcpy((*tag)->tag, imsg.data + len,
+ itag->tag_len);
+ (*tag)->tag[itag->tag_len] = '\0';
+ }
+ len += itag->tag_len;
+
+ (*tag)->obj_type = itag->obj_type;
+ (*tag)->tagger_time = itag->tagger_time;
+ (*tag)->tagger_gmtoff = itag->tagger_gmtoff;
+
+ if (itag->tagger_len == 0) {
+ (*tag)->tagger = strdup("");
+ if ((*tag)->tagger == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+ } else {
+ (*tag)->tagger = malloc(itag->tagger_len + 1);
+ if ((*tag)->tagger == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+ memcpy((*tag)->tagger, imsg.data + len,
+ itag->tagger_len);
+ (*tag)->tagger[itag->tagger_len] = '\0';
+ }
+ len += itag->tagger_len;
+
+ if (itag->tagmsg_len == 0) {
+ (*tag)->tagmsg = strdup("");
+ if ((*tag)->tagmsg == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+ } else {
+ size_t offset = 0, remain = itag->tagmsg_len;
+
+ (*tag)->tagmsg = malloc(itag->tagmsg_len + 1);
+ if ((*tag)->tagmsg == NULL) {
+ err = got_error_from_errno();
+ break;
+ }
+ while (remain > 0) {
+ struct imsg imsg_log;
+ size_t n = MIN(MAX_IMSGSIZE - IMSG_HEADER_SIZE,
+ remain);
+
+ err = got_privsep_recv_imsg(&imsg_log, ibuf, n);
+ if (err)
+ return err;
+
+ if (imsg_log.hdr.type != GOT_IMSG_TAG_TAGMSG)
+ return got_error(GOT_ERR_PRIVSEP_MSG);
+
+ memcpy((*tag)->tagmsg + offset, imsg_log.data,
+ n);
+ imsg_free(&imsg_log);
+ offset += n;
+ remain -= n;
+ }
+ (*tag)->tagmsg[itag->tagmsg_len] = '\0';
+ }
+
break;
default:
err = got_error(GOT_ERR_PRIVSEP_MSG);
blob - 3becb1ca45ed5e33df2ffa0843361e63961071ad
blob + 941438ef7171b50941a6d4601ad0c38546dfebed
--- lib/repository.c
+++ lib/repository.c
{
return (struct got_commit_object *)got_object_cache_get(
&repo->commitcache, id);
+}
+
+const struct got_error *
+got_repo_cache_tag(struct got_repository *repo, struct got_object_id *id,
+ struct got_tag_object *tag)
+{
+#ifndef GOT_NO_OBJ_CACHE
+ const struct got_error *err = NULL;
+ err = got_object_cache_add(&repo->tagcache, id, tag);
+ if (err)
+ return err;
+ tag->refcnt++;
+#endif
+ return NULL;
+}
+
+struct got_tag_object *
+got_repo_get_cached_tag(struct got_repository *repo, struct got_object_id *id)
+{
+ return (struct got_tag_object *)got_object_cache_get(
+ &repo->tagcache, id);
}
const struct got_error *
GOT_OBJECT_CACHE_TYPE_COMMIT);
if (err)
goto done;
+ err = got_object_cache_init(&repo->tagcache,
+ GOT_OBJECT_CACHE_TYPE_TAG);
+ if (err)
+ goto done;
normpath = got_path_normalize(abspath);
if (normpath == NULL) {
got_object_cache_close(&repo->objcache);
got_object_cache_close(&repo->treecache);
got_object_cache_close(&repo->commitcache);
+ got_object_cache_close(&repo->tagcache);
for (i = 0; i < nitems(repo->privsep_children); i++) {
if (repo->privsep_children[i].imsg_fd == -1)
blob - 7738a57cd9ee8350a5e72c39a576e5b654aa263c
blob + ae3722c08c1905a6e64dee0e34ec327baf6cb82c
--- libexec/got-read-object/got-read-object.c
+++ libexec/got-read-object/got-read-object.c
#define GOT_OBJ_TAG_COMMIT "commit"
#define GOT_OBJ_TAG_TREE "tree"
#define GOT_OBJ_TAG_BLOB "blob"
+#define GOT_OBJ_TAG_TAG "tag"
static volatile sig_atomic_t sigint_received;
const char *obj_tags[] = {
GOT_OBJ_TAG_COMMIT,
GOT_OBJ_TAG_TREE,
- GOT_OBJ_TAG_BLOB
+ 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;
blob - 24f359a343b084dcfe5e2654c1b4ae57fcaa9e05
blob + e5d58ee0bb72b099f33b72f3367599d9f6fee2eb
--- libexec/got-read-pack/got-read-pack.c
+++ libexec/got-read-pack/got-read-pack.c
}
static const struct got_error *
+tag_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_tag_object *tag = NULL;
+ uint8_t *buf;
+ size_t len;
+
+ err = get_object(&obj, imsg, ibuf, pack, packidx, objcache,
+ GOT_OBJ_TYPE_TAG);
+ 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_tag(&tag, buf, len);
+ free(buf);
+
+ err = got_privsep_send_tag(ibuf, tag);
+ if (obj)
+ got_object_close(obj);
+ got_object_tag_close(tag);
+ 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 *
receive_packidx(struct got_packidx **packidx, struct imsgbuf *ibuf)
{
const struct got_error *err = NULL;
err = blob_request(&imsg, &ibuf, pack, packidx,
&objcache);
break;
+ case GOT_IMSG_TAG_REQUEST:
+ err = tag_request(&imsg, &ibuf, pack, packidx,
+ &objcache);
+ break;
default:
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;