git: 5c341fe5123d - main - pkg(7): support configuration overwrite like pkg(8)

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Wed, 15 Jan 2025 08:21:30 UTC
The branch main has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=5c341fe5123d4aa6961066542de63dd4431d004d

commit 5c341fe5123d4aa6961066542de63dd4431d004d
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2025-01-15 08:18:46 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2025-01-15 08:21:19 +0000

    pkg(7): support configuration overwrite like pkg(8)
    
    with pkg(8) it is possible to overwrite a configuration like adding
    FreeBSD {
            enabled: false
    }
    
    in /usr/local/etc/pkg/repo/overwrite.conf which allows to change any
    value which can have been reviously configured in anything in
    /etc/pkg/*.conf
    
    now the bootstrap supports the same
    
    MFC After:      3 weeks
---
 usr.sbin/pkg/config.c | 55 +++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 42 insertions(+), 13 deletions(-)

diff --git a/usr.sbin/pkg/config.c b/usr.sbin/pkg/config.c
index 3aaa7a7815e8..2ad6c8a93756 100644
--- a/usr.sbin/pkg/config.c
+++ b/usr.sbin/pkg/config.c
@@ -353,51 +353,79 @@ parse_signature_type(struct repository *repo, const char *st)
 	else {
 		warnx("Signature type %s is not supported for bootstrapping,"
 		    " ignoring repository %s", st, repo->name);
-		repo_free(repo);
-		return false;
+		return (false);
 	}
 	return (true);
 }
 
+static struct repository *
+find_repository(const char *name)
+{
+	struct repository *repo;
+	STAILQ_FOREACH(repo, &repositories, next) {
+		if (strcmp(repo->name, name) == 0)
+			return (repo);
+	}
+	return (NULL);
+}
+
 static void
 parse_repo(const ucl_object_t *o)
 {
 	const ucl_object_t *cur;
-	const char *key;
+	const char *key, *reponame;
 	ucl_object_iter_t it = NULL;
+	bool newrepo = false;
+	struct repository *repo;
+
+	reponame = ucl_object_key(o);
+	repo = find_repository(reponame);
+	if (repo == NULL) {
+		repo = calloc(1, sizeof(struct repository));
+		if (repo == NULL)
+			err(EXIT_FAILURE, "calloc");
 
-	struct repository *repo = calloc(1, sizeof(struct repository));
-	if (repo == NULL)
-		err(EXIT_FAILURE, "calloc");
-
-	repo->name = strdup(ucl_object_key(o));
-	if (repo->name == NULL)
-		err(EXIT_FAILURE, "strdup");
+		repo->name = strdup(reponame);
+		if (repo->name == NULL)
+			err(EXIT_FAILURE, "strdup");
+		newrepo = true;
+	}
 	while ((cur = ucl_iterate_object(o, &it, true))) {
 		key = ucl_object_key(cur);
 		if (key == NULL)
 			continue;
 		if (strcasecmp(key, "url") == 0) {
+			free(repo->url);
 			repo->url = strdup(ucl_object_tostring(cur));
 			if (repo->url == NULL)
 				err(EXIT_FAILURE, "strdup");
 		} else if (strcasecmp(key, "mirror_type") == 0) {
 			parse_mirror_type(repo, ucl_object_tostring(cur));
 		} else if (strcasecmp(key, "signature_type") == 0) {
-			if (!parse_signature_type(repo, ucl_object_tostring(cur)))
+			if (!parse_signature_type(repo, ucl_object_tostring(cur))) {
+				if (newrepo)
+					repo_free(repo);
+				else
+					STAILQ_REMOVE(&repositories, repo, repository, next);
 				return;
+			}
 		} else if (strcasecmp(key, "fingerprints") == 0) {
+			free(repo->fingerprints);
 			repo->fingerprints = strdup(ucl_object_tostring(cur));
 			if (repo->fingerprints == NULL)
 				err(EXIT_FAILURE, "strdup");
 		} else if (strcasecmp(key, "pubkey") == 0) {
+			free(repo->pubkey);
 			repo->pubkey = strdup(ucl_object_tostring(cur));
 			if (repo->pubkey == NULL)
 				err(EXIT_FAILURE, "strdup");
 		} else if (strcasecmp(key, "enabled") == 0) {
 			if ((cur->type != UCL_BOOLEAN) ||
 			    !ucl_object_toboolean(cur)) {
-				repo_free(repo);
+				if (newrepo)
+					repo_free(repo);
+				else
+					STAILQ_REMOVE(&repositories, repo, repository, next);
 				return;
 			}
 		}
@@ -407,7 +435,8 @@ parse_repo(const ucl_object_t *o)
 		repo_free(repo);
 		return;
 	}
-	STAILQ_INSERT_TAIL(&repositories, repo, next);
+	if (newrepo)
+		STAILQ_INSERT_TAIL(&repositories, repo, next);
 	return;
 }