"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: got-read-gitconfig: send key-value pairs for extensions
To:
Omar Polo <op@omarpolo.com>
Cc:
gameoftrees@openbsd.org
Date:
Sun, 5 Feb 2023 17:36:11 +0100

Download raw body.

Thread
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 <op@omarpolo.com>
> 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)
>  
> 
> 
>