From: Omar Polo Subject: got-read-gitconfig: send key-value pairs for extensions To: gameoftrees@openbsd.org Date: Sun, 05 Feb 2023 16:50:51 +0100 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? ----------------------------------------------- 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)