Commit Diff


commit - 2624d1656867df76d9de1103980ebe112bd5d6a9
commit + b091c2cda94edf2935404ce50aa5bccfcced54b6
blob - d45c856b23421ee688bc12134960d91d40572e28
blob + 2493aaabc9c4744a9891d4f20798fab42941e201
--- 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_send_gitconfig_rem
 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 @@ struct got_pack *got_repo_get_pinned_pack(struct got_r
 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 - 7c89e0deea089505b7e874e3a4df2146d7da65ef
blob + 3281689195b792c0028d9a8f39b5d7be49321c83
--- lib/privsep.c
+++ lib/privsep.c
@@ -2096,8 +2096,62 @@ got_privsep_recv_gitconfig_str(char **str, struct imsg
 	default:
 		err = got_error(GOT_ERR_PRIVSEP_MSG);
 		break;
+	}
+
+	imsg_free(&imsg);
+	return err;
+}
+
+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;
 }
blob - 5522108b0b638af2088f27d7658bd2a3671def42
blob + bb395ed8acf27a029c07482c594674dc90ca0213
--- lib/read_gitconfig_privsep.c
+++ lib/read_gitconfig_privsep.c
@@ -45,8 +45,8 @@ const struct got_error *
 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;
@@ -55,8 +55,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;
@@ -117,7 +119,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)
@@ -127,18 +129,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 - c9f770d505436eed7a5216d43275ed7014742655
blob + a45339114895d53cb16168cd6dc55379e43f94d7
--- lib/repository.c
+++ lib/repository.c
@@ -68,6 +68,28 @@
 
 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)
@@ -123,8 +145,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;
@@ -593,7 +615,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;
 	}
@@ -607,8 +630,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;
 
@@ -761,8 +784,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;
@@ -847,9 +880,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 - ff3627e163f53858ed10cfa6c0860570e49ff420
blob + ec661ca8daa84e29923797dbbf72c7809c986bf8
--- libexec/got-read-gitconfig/got-read-gitconfig.c
+++ libexec/got-read-gitconfig/got-read-gitconfig.c
@@ -78,7 +78,37 @@ send_gitconfig_str(struct imsgbuf *ibuf, const char *v
 	if (imsg_compose(ibuf, GOT_IMSG_GITCONFIG_STR_VAL, 0, 0, -1,
 	    value, len) == -1)
 		return got_error_from_errno("imsg_compose GITCONFIG_STR_VAL");
+
+	return got_privsep_flush_imsg(ibuf);
+}
+
+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);
 }
 
@@ -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)