From: Stefan Sperling Subject: Re: got-read-gitconfig: send key-value pairs for extensions To: Omar Polo Cc: gameoftrees@openbsd.org Date: Sun, 5 Feb 2023 17:36:11 +0100 On Sun, Feb 05, 2023 at 04:50:51PM +0100, Omar Polo wrote: > This depends on the diff I just sent about replacing > got_repo_get_gitconfig_extensions with got_repo_has_extension. > it'll make parsing of objectformat=sha256 dead-simple :) > > ok? Yes, ok. This is a nice way of generalizing things. > ----------------------------------------------- > commit 801ecd4bd7f8dd41df43a4225a5e3c41c144c595 (main) > from: Omar Polo > date: Sun Feb 5 15:27:06 2023 UTC > > got-read-gitconfig: send key-value pairs for extensions > > Most extension allow only for a boolean value so the current behaviour > of just sending the extension with a trueish value is fine. However, > some extensions that we could eventually support (like "objectformat") > have a string value. This is a preparatory step towards that. > > diff 7c3a2af1f17dda354dd8ae31d233458143646797 801ecd4bd7f8dd41df43a4225a5e3c41c144c595 > commit - 7c3a2af1f17dda354dd8ae31d233458143646797 > commit + 801ecd4bd7f8dd41df43a4225a5e3c41c144c595 > blob - 1b4b7bc8fc2baddfd1f3353725f35bd6ac9af0cf > blob + 076cab5adad635b8e7ea46af68a14510dced4da4 > --- lib/got_lib_privsep.h > +++ lib/got_lib_privsep.h > @@ -158,6 +158,7 @@ enum got_imsg_type { > GOT_IMSG_GITCONFIG_REMOTES_REQUEST, > GOT_IMSG_GITCONFIG_INT_VAL, > GOT_IMSG_GITCONFIG_STR_VAL, > + GOT_IMSG_GITCONFIG_PAIR, > GOT_IMSG_GITCONFIG_REMOTES, > GOT_IMSG_GITCONFIG_REMOTE, > GOT_IMSG_GITCONFIG_OWNER_REQUEST, > @@ -627,6 +628,16 @@ struct got_imsg_remotes { > }; > > /* > + * Structure for GOT_IMSG_GITCONFIG_PAIR. > + */ > +struct got_imsg_gitconfig_pair { > + size_t klen; > + size_t vlen; > + /* Followed by klen data bytes of key string. */ > + /* Followed by vlen data bytes of value string. */ > +}; > + > +/* > * Structure for GOT_IMSG_PATCH data. > */ > struct got_imsg_patch { > @@ -747,6 +758,8 @@ const struct got_error *got_privsep_recv_gitconfig_int > const struct got_error *got_privsep_send_gitconfig_owner_req(struct imsgbuf *); > const struct got_error *got_privsep_recv_gitconfig_str(char **, > struct imsgbuf *); > +const struct got_error *got_privsep_recv_gitconfig_pair(char **, char **, > + struct imsgbuf *); > const struct got_error *got_privsep_recv_gitconfig_int(int *, struct imsgbuf *); > const struct got_error *got_privsep_recv_gitconfig_remotes( > struct got_remote_repo **, int *, struct imsgbuf *); > blob - b8032ffd3ffe9dab29beaf3cc57c39a6ef957859 > blob + 83d718aa029bf9afded3debb15731d617de2169c > --- lib/got_lib_repository.h > +++ lib/got_lib_repository.h > @@ -124,7 +124,8 @@ struct got_repository { > int ngitconfig_remotes; > struct got_remote_repo *gitconfig_remotes; > char *gitconfig_owner; > - char **extensions; > + char **extnames; > + char **extvals; > int nextensions; > > /* Settings read from got.conf. */ > @@ -170,7 +171,7 @@ const struct got_error *got_repo_read_gitconfig(int *, > void got_repo_unpin_pack(struct got_repository *); > > const struct got_error *got_repo_read_gitconfig(int *, char **, char **, > - struct got_remote_repo **, int *, char **, char ***, int *, > + struct got_remote_repo **, int *, char **, char ***, char ***, int *, > const char *); > > const struct got_error *got_repo_temp_fds_get(int *, int *, > blob - a54ba7c0e2d8f3fc5ac97dacc39c1d54cb028eb7 > blob + ddb1e595d753eddc725ce0bbb056d1dc8236fc07 > --- lib/privsep.c > +++ lib/privsep.c > @@ -2103,6 +2103,60 @@ got_privsep_recv_gitconfig_int(int *val, struct imsgbu > } > > const struct got_error * > +got_privsep_recv_gitconfig_pair(char **key, char **val, struct imsgbuf *ibuf) > +{ > + const struct got_error *err = NULL; > + struct got_imsg_gitconfig_pair p; > + struct imsg imsg; > + size_t datalen; > + uint8_t *data; > + > + *key = *val = NULL; > + > + err = got_privsep_recv_imsg(&imsg, ibuf, 0); > + if (err) > + return err; > + > + data = imsg.data; > + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; > + > + if (imsg.hdr.type != GOT_IMSG_GITCONFIG_PAIR) { > + err = got_error(GOT_ERR_PRIVSEP_MSG); > + goto done; > + } > + > + if (datalen < sizeof(p)) { > + err = got_error(GOT_ERR_PRIVSEP_LEN); > + goto done; > + } > + > + memcpy(&p, data, sizeof(p)); > + data += sizeof(p); > + > + if (datalen != sizeof(p) + p.klen + p.vlen) { > + err = got_error(GOT_ERR_PRIVSEP_LEN); > + goto done; > + } > + > + *key = strndup(data, p.klen); > + if (*key == NULL) { > + err = got_error_from_errno("strndup"); > + goto done; > + } > + data += p.klen; > + > + *val = strndup(data, p.vlen); > + if (*val == NULL) { > + err = got_error_from_errno("strndup"); > + goto done; > + } > + > +done: > + imsg_free(&imsg); > + return err; > +} > + > +const struct got_error * > got_privsep_recv_gitconfig_int(int *val, struct imsgbuf *ibuf) > { > const struct got_error *err = NULL; > blob - e76312afb71dc950015ded8344d412b185adb00c > blob + db996fe3996b3c638c45e65da4fbdd6fa80f02b2 > --- lib/read_gitconfig_privsep.c > +++ lib/read_gitconfig_privsep.c > @@ -47,8 +47,8 @@ got_repo_read_gitconfig(int *gitconfig_repository_form > got_repo_read_gitconfig(int *gitconfig_repository_format_version, > char **gitconfig_author_name, char **gitconfig_author_email, > struct got_remote_repo **remotes, int *nremotes, > - char **gitconfig_owner, char ***extensions, int *nextensions, > - const char *gitconfig_path) > + char **gitconfig_owner, char ***extnames, char ***extvals, > + int *nextensions, const char *gitconfig_path) > { > const struct got_error *err = NULL, *child_err = NULL; > int fd = -1; > @@ -57,8 +57,10 @@ got_repo_read_gitconfig(int *gitconfig_repository_form > struct imsgbuf *ibuf; > > *gitconfig_repository_format_version = 0; > - if (extensions) > - *extensions = NULL; > + if (extnames) > + *extnames = NULL; > + if (extvals) > + *extvals = NULL; > if (nextensions) > *nextensions = 0; > *gitconfig_author_name = NULL; > @@ -119,7 +121,7 @@ got_repo_read_gitconfig(int *gitconfig_repository_form > if (err) > goto done; > > - if (extensions && nextensions) { > + if (extnames && extvals && nextensions) { > err = got_privsep_send_gitconfig_repository_extensions_req( > ibuf); > if (err) > @@ -129,18 +131,24 @@ got_repo_read_gitconfig(int *gitconfig_repository_form > goto done; > if (*nextensions > 0) { > int i; > - *extensions = calloc(*nextensions, sizeof(char *)); > - if (*extensions == NULL) { > + *extnames = calloc(*nextensions, sizeof(char *)); > + if (*extnames == NULL) { > err = got_error_from_errno("calloc"); > goto done; > } > + *extvals = calloc(*nextensions, sizeof(char *)); > + if (*extvals == NULL) { > + err = got_error_from_errno("calloc"); > + goto done; > + } > for (i = 0; i < *nextensions; i++) { > - char *ext; > - err = got_privsep_recv_gitconfig_str(&ext, > - ibuf); > + char *ext, *val; > + err = got_privsep_recv_gitconfig_pair(&ext, > + &val, ibuf); > if (err) > goto done; > - (*extensions)[i] = ext; > + (*extnames)[i] = ext; > + (*extvals)[i] = val; > } > } > } > blob - 724a22a36f25053e940871eed29828527c813f87 > blob + 9b6bfeb03479b844dcb5ea253742cfce88a0b45f > --- lib/repository.c > +++ lib/repository.c > @@ -74,6 +74,28 @@ const char * > RB_PROTOTYPE(got_packidx_bloom_filter_tree, got_packidx_bloom_filter, entry, > got_packidx_bloom_filter_cmp); > > +static inline int > +is_boolean_val(const char *val) > +{ > + return (strcasecmp(val, "true") == 0 || > + strcasecmp(val, "false") == 0 || > + strcasecmp(val, "on") == 0 || > + strcasecmp(val, "off") == 0 || > + strcasecmp(val, "yes") == 0 || > + strcasecmp(val, "no") == 0 || > + strcasecmp(val, "1") == 0 || > + strcasecmp(val, "0") == 0); > +} > + > +static inline int > +get_boolean_val(const char *val) > +{ > + return (strcasecmp(val, "true") == 0 || > + strcasecmp(val, "on") == 0 || > + strcasecmp(val, "yes") == 0 || > + strcasecmp(val, "1") == 0); > +} > + > const char * > got_repo_get_path(struct got_repository *repo) > { > @@ -128,8 +150,8 @@ got_repo_has_extension(struct got_repository *repo, co > int i; > > for (i = 0; i < repo->nextensions; ++i) { > - if (!strcasecmp(ext, repo->extensions[i])) > - return 1; > + if (!strcasecmp(ext, repo->extnames[i])) > + return get_boolean_val(repo->extvals[i]); > } > > return 0; > @@ -598,7 +620,8 @@ read_gitconfig(struct got_repository *repo, const char > err = got_repo_read_gitconfig(&dummy_repo_version, > &repo->global_gitconfig_author_name, > &repo->global_gitconfig_author_email, > - NULL, NULL, NULL, NULL, NULL, global_gitconfig_path); > + NULL, NULL, NULL, NULL, NULL, NULL, > + global_gitconfig_path); > if (err) > return err; > } > @@ -612,8 +635,8 @@ read_gitconfig(struct got_repository *repo, const char > &repo->gitconfig_repository_format_version, > &repo->gitconfig_author_name, &repo->gitconfig_author_email, > &repo->gitconfig_remotes, &repo->ngitconfig_remotes, > - &repo->gitconfig_owner, &repo->extensions, &repo->nextensions, > - repo_gitconfig_path); > + &repo->gitconfig_owner, &repo->extnames, &repo->extvals, > + &repo->nextensions, repo_gitconfig_path); > if (err) > goto done; > > @@ -766,8 +789,18 @@ got_repo_open(struct got_repository **repop, const cha > goto done; > } > for (i = 0; i < repo->nextensions; i++) { > - char *ext = repo->extensions[i]; > + char *ext = repo->extnames[i]; > + char *val = repo->extvals[i]; > int j, supported = 0; > + > + if (!is_boolean_val(val)) { > + err = got_error_path(ext, GOT_ERR_GIT_REPO_EXT); > + goto done; > + } > + > + if (!get_boolean_val(val)) > + continue; > + > for (j = 0; j < nitems(repo_extensions); j++) { > if (strcmp(ext, repo_extensions[j]) == 0) { > supported = 1; > @@ -852,9 +885,12 @@ got_repo_close(struct got_repository *repo) > for (i = 0; i < repo->ngitconfig_remotes; i++) > got_repo_free_remote_repo_data(&repo->gitconfig_remotes[i]); > free(repo->gitconfig_remotes); > - for (i = 0; i < repo->nextensions; i++) > - free(repo->extensions[i]); > - free(repo->extensions); > + for (i = 0; i < repo->nextensions; i++) { > + free(repo->extnames[i]); > + free(repo->extvals[i]); > + } > + free(repo->extnames); > + free(repo->extvals); > > got_pathlist_free(&repo->packidx_paths, GOT_PATHLIST_FREE_PATH); > free(repo); > blob - eb2cb32cc344ddd544e7ee0c3ed70fb044acb212 > blob + 6a5a396aaacb6e0b82ba18447c97c739cd0377cb > --- libexec/got-read-gitconfig/got-read-gitconfig.c > +++ libexec/got-read-gitconfig/got-read-gitconfig.c > @@ -83,6 +83,36 @@ gitconfig_str_request(struct imsgbuf *ibuf, struct got > } > > static const struct got_error * > +send_gitconfig_pair(struct imsgbuf *ibuf, const char *key, const char *val) > +{ > + struct ibuf *wbuf; > + size_t klen = key ? strlen(key) : 0; > + size_t vlen = val ? strlen(val) : 0; > + size_t tot = sizeof(klen) + sizeof(vlen) + klen + vlen; > + > + if (tot > MAX_IMSGSIZE - IMSG_HEADER_SIZE) > + return got_error(GOT_ERR_NO_SPACE); > + > + wbuf = imsg_create(ibuf, GOT_IMSG_GITCONFIG_PAIR, 0, 0, tot); > + if (wbuf == NULL) > + return got_error_from_errno("imsg_create GITCONFIG_PAIR"); > + > + /* Keep in sync with got_imsg_gitconfig_pair */ > + if (imsg_add(wbuf, &klen, sizeof(klen)) == -1) > + return got_error_from_errno("imsg_add GITCONFIG_PAIR"); > + if (imsg_add(wbuf, &vlen, sizeof(vlen)) == -1) > + return got_error_from_errno("imsg_add GITCONFIG_PAIR"); > + if (imsg_add(wbuf, key, klen) == -1) > + return got_error_from_errno("imsg_add GITCONFIG_PAIR"); > + if (imsg_add(wbuf, val, vlen) == -1) > + return got_error_from_errno("imsg_add GITCONFIG_PAIR"); > + > + wbuf->fd = -1; > + imsg_close(ibuf, wbuf); > + return got_privsep_flush_imsg(ibuf); > +} > + > +static const struct got_error * > gitconfig_str_request(struct imsgbuf *ibuf, struct got_gitconfig *gitconfig, > const char *section, const char *tag) > { > @@ -281,12 +311,8 @@ gitconfig_extensions_request(struct imsgbuf *ibuf, > if (tags == NULL) > return send_gitconfig_int(ibuf, 0); > > - TAILQ_FOREACH(node, &tags->fields, link) { > - val = got_gitconfig_get_str(gitconfig, "extensions", > - node->field); > - if (get_boolean_val(val)) > - nextensions++; > - } > + TAILQ_FOREACH(node, &tags->fields, link) > + nextensions++; > > err = send_gitconfig_int(ibuf, nextensions); > if (err) > @@ -295,11 +321,9 @@ gitconfig_extensions_request(struct imsgbuf *ibuf, > TAILQ_FOREACH(node, &tags->fields, link) { > val = got_gitconfig_get_str(gitconfig, "extensions", > node->field); > - if (get_boolean_val(val)) { > - err = send_gitconfig_str(ibuf, node->field); > - if (err) > - goto done; > - } > + err = send_gitconfig_pair(ibuf, node->field, val); > + if (err) > + goto done; > } > done: > got_gitconfig_free_list(tags); > blob - 68e0227e67176703391ab5f32a7cd9a9d1a91bce > blob + 9403e4715c6ed077315fb8b1bcb68bccd4247176 > --- regress/cmdline/checkout.sh > +++ regress/cmdline/checkout.sh > @@ -793,7 +793,7 @@ test_checkout_repo_with_unknown_extension() { > local testroot=`test_init checkout_repo_with_unknown_extension` > > (cd $testroot/repo && > - git config --add extensions.badExtension true) > + git config --add extensions.badExtension foobar) > (cd $testroot/repo && > git config --add extensions.otherBadExtension 0) > > > >