commit 3350156242bb705818218fc29cebbf2798228b94 from: Stefan Sperling date: Wed Mar 18 16:11:30 2020 UTC prepare for providing refs we already have in fetch request imsg currently we always send and expect an empty list commit - 14778466f9e410d616fa844c9576ad0d4d1eb84f commit + 3350156242bb705818218fc29cebbf2798228b94 blob - 910dea7f0ad927dbaa23003995c60934b1a6014a blob + 4016f649d26812603b825e73b9cf0839b6ca3d8c --- lib/fetch.c +++ lib/fetch.c @@ -310,11 +310,14 @@ got_fetch_pack(struct got_object_id **pack_hash, struc char *tmppackpath = NULL, *tmpidxpath = NULL; char *packpath = NULL, *idxpath = NULL, *id_str = NULL; const char *repo_path = got_repo_get_path(repo); + struct got_pathlist_head have_refs; struct got_pathlist_entry *pe; char *path; *pack_hash = NULL; + TAILQ_INIT(&have_refs); + if (asprintf(&path, "%s/%s/fetching.pack", repo_path, GOT_OBJECTS_PACK_DIR) == -1) { err = got_error_from_errno("asprintf"); @@ -368,7 +371,7 @@ got_fetch_pack(struct got_object_id **pack_hash, struc err = got_error_from_errno("dup"); goto done; } - err = got_privsep_send_fetch_req(&ibuf, nfetchfd); + err = got_privsep_send_fetch_req(&ibuf, nfetchfd, &have_refs); if (err != NULL) goto done; nfetchfd = -1; blob - 2e254be89b81d4bebe1a43f8e7f6c95a9d69d77e blob + 05435e3e27eea7688d03567a8c5ec462c53976ac --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -233,6 +233,17 @@ struct got_imsg_tag_object { * one or more GOT_IMSG_TAG_TAGMSG messages. */ } __attribute__((__packed__)); + +/* Structures for GOT_IMSG_FETCH_REQUEST data. */ +struct got_imsg_fetch_have_ref { + uint8_t id[SHA1_DIGEST_LENGTH]; + size_t name_len; + /* Followed by name_len data bytes. */ +}; +struct got_imsg_fetch_have_refs { + size_t n_have_refs; + /* Followed by n_have_refs times of got_imsg_fetch_have_ref data. */ +}; /* Structures for GOT_IMSG_FETCH_SYMREFS data. */ struct got_imsg_fetch_symref { @@ -339,7 +350,8 @@ const struct got_error *got_privsep_send_index_pack_re struct got_object_id *); const struct got_error *got_privsep_send_index_pack_done(struct imsgbuf *); const struct got_error *got_privsep_wait_index_pack_done(struct imsgbuf *); -const struct got_error *got_privsep_send_fetch_req(struct imsgbuf *, int); +const struct got_error *got_privsep_send_fetch_req(struct imsgbuf *, int, + struct got_pathlist_head *); const struct got_error *got_privsep_send_fetch_symrefs(struct imsgbuf *, struct got_pathlist_head *); const struct got_error *got_privsep_send_fetch_progress(struct imsgbuf *, blob - 23b8318e31fac27d4a29d740ed4be0b84cdfbceb blob + 6bd3dc90e688d5c8b9f5684562599a13ede9032c --- lib/privsep.c +++ lib/privsep.c @@ -405,16 +405,68 @@ got_privsep_send_obj(struct imsgbuf *ibuf, struct got_ } const struct got_error * -got_privsep_send_fetch_req(struct imsgbuf *ibuf, int fd) +got_privsep_send_fetch_req(struct imsgbuf *ibuf, int fd, + struct got_pathlist_head *have_refs) { const struct got_error *err = NULL; + struct ibuf *wbuf; + size_t len, n_have_refs = 0; + struct got_pathlist_entry *pe; - if (imsg_compose(ibuf, GOT_IMSG_FETCH_REQUEST, 0, 0, fd, - NULL, 0) == -1) { - err = got_error_from_errno("imsg_compose FETCH_REQUEST"); + len = sizeof(struct got_imsg_fetch_symrefs); + TAILQ_FOREACH(pe, have_refs, entry) { + struct got_object_id *id = pe->data; + len += sizeof(struct got_imsg_fetch_have_ref) + + pe->path_len + sizeof(id->sha1); + n_have_refs++; + } + if (len >= MAX_IMSGSIZE - IMSG_HEADER_SIZE) { + close(fd); + return got_error(GOT_ERR_NO_SPACE); + } + + wbuf = imsg_create(ibuf, GOT_IMSG_FETCH_REQUEST, 0, 0, len); + if (wbuf == NULL) { + close(fd); + return got_error_from_errno("imsg_create FETCH_REQUEST"); + } + + /* Keep in sync with struct got_imsg_fetch_have_refs definition! */ + if (imsg_add(wbuf, &n_have_refs, sizeof(n_have_refs)) == -1) { + err = got_error_from_errno("imsg_add FETCH_REQUEST"); + ibuf_free(wbuf); close(fd); return err; } + + TAILQ_FOREACH(pe, have_refs, entry) { + const char *name = pe->path; + size_t name_len = pe->path_len; + struct got_object_id *id = pe->data; + + /* Keep in sync with struct got_imsg_fetch_have_ref! */ + if (imsg_add(wbuf, id->sha1, sizeof(id->sha1)) == -1) { + err = got_error_from_errno("imsg_add FETCH_REQUEST"); + ibuf_free(wbuf); + close(fd); + return err; + } + if (imsg_add(wbuf, &name_len, sizeof(name_len)) == -1) { + err = got_error_from_errno("imsg_add FETCH_REQUEST"); + ibuf_free(wbuf); + close(fd); + return err; + } + if (imsg_add(wbuf, name, name_len) == -1) { + err = got_error_from_errno("imsg_add FETCH_REQUEST"); + ibuf_free(wbuf); + close(fd); + return err; + } + } + + wbuf->fd = fd; + imsg_close(ibuf, wbuf); return flush_imsg(ibuf); } blob - 507b79d036a9965abbb57d877bfe59dec7b2798e blob + 0bdfc1bbd351d96517b0f716cbfebdbd855a98ce --- libexec/got-fetch-pack/got-fetch-pack.c +++ libexec/got-fetch-pack/got-fetch-pack.c @@ -55,7 +55,6 @@ struct got_object *indexed; static int chattygit; static char *fetchbranch; -static char *upstream = "origin"; static struct got_object_id zhash = {.sha1={0}}; int @@ -137,47 +136,22 @@ writepkt(int fd, char *buf, int nbuf) return 0; } -/* TODO: This should not access the file system! */ -int -got_resolve_remote_ref(struct got_object_id *id, char *ref) +static const struct got_error * +match_remote_ref(struct got_pathlist_head *have_refs, struct got_object_id *id, + char *refname, char *id_str) { - char buf[128], *s; - int r, f; + struct got_pathlist_entry *pe; - if (!got_parse_sha1_digest(id->sha1, ref)) - return 0; + memset(id, 0, sizeof(*id)); - /* Slightly special handling: translate remote refs to local ones. */ - if (strcmp(ref, "HEAD") == 0) { - if (snprintf(buf, sizeof(buf), ".git/HEAD") >= sizeof(buf)) - return -1; - } else if (strstr(ref, "refs/heads") == ref) { - ref += strlen("refs/heads"); - if (snprintf(buf, sizeof(buf), - ".git/refs/remotes/%s/%s", upstream, ref) >= sizeof(buf)) - return -1; - } else if (strstr(ref, "refs/tags") == ref) { - ref += strlen("refs/tags"); - if (snprintf(buf, sizeof(buf), - ".git/refs/tags/%s/%s", upstream, ref) >= sizeof(buf)) - return -1; - } else { - return -1; + TAILQ_FOREACH(pe, have_refs, entry) { + if (strcmp(pe->path, refname) == 0) { + if (!got_parse_sha1_digest(id->sha1, id_str)) + return got_error(GOT_ERR_BAD_OBJ_ID_STR); + break; + } } - - r = -1; - s = buf; - if ((f = open(s, O_RDONLY)) == -1) - goto err; - if (readn(f, buf, sizeof(buf)) < 40) - goto err; - if (!got_parse_sha1_digest(id->sha1, buf)) - goto err; -err: - close(f); - if (r == -1 && strstr(buf, "ref:") == buf) - return got_resolve_remote_ref(id, buf + strlen("ref:")); - return r; + return NULL; } static int @@ -399,7 +373,7 @@ match_capabilities(char **my_capabilities, struct got_ static const struct got_error * fetch_pack(int fd, int packfd, struct got_object_id *packid, - struct imsgbuf *ibuf) + struct got_pathlist_head *have_refs, struct imsgbuf *ibuf) { const struct got_error *err = NULL; char buf[GOT_PKTMAX], *sp[3]; @@ -485,8 +459,10 @@ fetch_pack(int fd, int packfd, struct got_object_id *p goto done; } - if (got_resolve_remote_ref(&have[nref], sp[1]) == -1) - memset(&have[nref], 0, sizeof(have[nref])); + err = match_remote_ref(have_refs, &have[nref], sp[0], sp[1]); + if (err) + goto done; + err = got_privsep_send_fetch_progress(ibuf, &want[nref], sp[1]); if (err) goto done; @@ -597,6 +573,11 @@ main(int argc, char **argv) struct got_object_id packid; struct imsgbuf ibuf; struct imsg imsg; + struct got_pathlist_head have_refs; + struct got_imsg_fetch_have_refs *fetch_have_refs = NULL; + size_t datalen; + + TAILQ_INIT(&have_refs); if (getenv("GOT_DEBUG") != NULL) { fprintf(stderr, "fetch-pack being chatty!\n"); @@ -615,10 +596,23 @@ main(int argc, char **argv) err = got_error(GOT_ERR_PRIVSEP_MSG); goto done; } - if (imsg.hdr.len - IMSG_HEADER_SIZE != 0) { + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (datalen < sizeof(struct got_imsg_fetch_have_refs)) { err = got_error(GOT_ERR_PRIVSEP_LEN); goto done; } + fetch_have_refs = (struct got_imsg_fetch_have_refs *)imsg.data; + if (datalen != sizeof(struct got_imsg_fetch_have_refs) + + sizeof(struct got_imsg_fetch_have_ref) * + fetch_have_refs->n_have_refs) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + goto done; + } + if (fetch_have_refs->n_have_refs != 0) { + /* TODO: Incremental fetch support */ + err = got_error(GOT_ERR_NOT_IMPL); + goto done; + } fetchfd = imsg.fd; if ((err = got_privsep_recv_imsg(&imsg, &ibuf, 0)) != 0) { @@ -638,7 +632,7 @@ main(int argc, char **argv) } packfd = imsg.fd; - err = fetch_pack(fetchfd, packfd, &packid, &ibuf); + err = fetch_pack(fetchfd, packfd, &packid, &have_refs, &ibuf); if (err) goto done; done: