Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Rework messages to be fully context aware
Baptiste Daroussin committed 10 years ago
commit 9ec411c64ad7c5f8da7a5409e21d252ac46f6a32
parent 628d555
16 files changed +323 -103
modified libpkg/pkg.c
@@ -1751,74 +1751,75 @@ int
pkg_message_from_ucl(struct pkg *pkg, const ucl_object_t *obj)
{
	struct pkg_message *msg = NULL;
-
	const ucl_object_t *elt;
-

+
	const ucl_object_t *elt, *cur;
+
	ucl_object_iter_t it = NULL;

	if (ucl_object_type(obj) == UCL_STRING) {
-
		if (pkg->message == NULL) {
-
			msg = calloc(1, sizeof(*msg));
+
		msg = calloc(1, sizeof(*msg));

-
			if (msg == NULL) {
-
				pkg_emit_errno("malloc", "struct pkg_message");
-
				return (EPKG_FATAL);
-
			}
-
			msg->str = strdup(ucl_object_tostring(obj));
-
			msg->legacy = true;
-
		}
-
		else {
-
			/* Do no rewrite message with legacy message */
-
			return (EPKG_OK);
+
		if (msg == NULL) {
+
			pkg_emit_errno("malloc", "struct pkg_message");
+
			return (EPKG_FATAL);
		}
-

+
		msg->str = strdup(ucl_object_tostring(obj));
+
		msg->type = PKG_MESSAGE_ALWAYS;
+
		LL_APPEND(pkg->message, msg);
+
		return (EPKG_OK);
	}
-
	else {
-
		/* New format of pkg message */

-
		elt = ucl_object_find_key(obj, "message");
+
	/* New format of pkg message */
+
	if (ucl_object_type(obj) != UCL_ARRAY)
+
		pkg_emit_error("package message badly formatted, an array was"
+
		    " expected");
+

+
	while ((cur = ucl_iterate_object(obj, &it, true))) {
+
		elt = ucl_object_find_key(cur, "message");

		if (elt == NULL || ucl_object_type(elt) != UCL_STRING) {
-
			pkg_emit_error("package message lacks 'message' key that is required");
+
			pkg_emit_error("package message lacks 'message' key"
+
			    " that is required");

			return (EPKG_FATAL);
		}

-
		if (pkg->message != NULL) {
-
			if (pkg->message->legacy) {
-
				/* We can re-use legacy message */
-
				msg = pkg->message;
-
				msg->legacy = false;
-
				free(msg->str);
-
				msg->str = NULL;
-
			}
-
			else {
-
				pkg_emit_error("trying to rewrite message in a package");
-

-
				return (EPKG_FATAL);
-
			}
-
		}
-
		else {
-
			msg = calloc(1, sizeof(*msg));
+
		msg = calloc(1, sizeof(*msg));

-
			if (msg == NULL) {
-
				pkg_emit_errno("malloc", "struct pkg_message");
-
				return (EPKG_FATAL);
-
			}
+
		if (msg == NULL) {
+
			pkg_emit_errno("malloc", "struct pkg_message");
+
			return (EPKG_FATAL);
		}

		msg->str = strdup(ucl_object_tostring(elt));
-
		elt = ucl_object_find_key(obj, "minimum_version");
+
		msg->type = PKG_MESSAGE_ALWAYS;
+
		elt = ucl_object_find_key(cur, "type");
+
		if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
+
			if (strcasecmp(ucl_object_tostring(elt), "install") == 0)
+
				msg->type = PKG_MESSAGE_INSTALL;
+
			else if (strcasecmp(ucl_object_tostring(elt), "remove") == 0)
+
				msg->type = PKG_MESSAGE_REMOVE;
+
			else if (strcasecmp(ucl_object_tostring(elt), "upgrade") == 0)
+
				msg->type = PKG_MESSAGE_UPGRADE;
+
			else
+
				pkg_emit_error("Unknown message type,"
+
				    " message will always be printed");
+
		}
+
		if (msg->type != PKG_MESSAGE_UPGRADE) {
+
			LL_APPEND(pkg->message, msg);
+
			continue;
+
		}

+
		elt = ucl_object_find_key(cur, "minimum_version");
		if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
			msg->minimum_version = strdup(ucl_object_tostring(elt));
		}
-
		elt = ucl_object_find_key(obj, "maximum_version");

+
		elt = ucl_object_find_key(cur, "maximum_version");
		if (elt != NULL && ucl_object_type(elt) == UCL_STRING) {
			msg->maximum_version = strdup(ucl_object_tostring(elt));
		}
-
	}

-
	pkg->message = msg;
+
		LL_APPEND(pkg->message, msg);
+
	}

	return (EPKG_OK);
}
@@ -1856,27 +1857,52 @@ pkg_message_from_str(struct pkg *pkg, const char *str, size_t len)
ucl_object_t*
pkg_message_to_ucl(struct pkg *pkg)
{
+
	struct pkg_message *msg;
+
	ucl_object_t *array;
	ucl_object_t *obj;

-
	obj = ucl_object_typed_new (UCL_OBJECT);
-

-
	ucl_object_insert_key(obj,
-
			ucl_object_fromstring_common(pkg->message->str, 0,
-
					UCL_STRING_RAW|UCL_STRING_TRIM),
-
			"message", 0, false);
+
	array = ucl_object_typed_new(UCL_ARRAY);
+
	LL_FOREACH(pkg->message, msg) {
+
		obj = ucl_object_typed_new (UCL_OBJECT);

-
	if (pkg->message->maximum_version) {
-
		ucl_object_insert_key(obj,
-
				ucl_object_fromstring(pkg->message->maximum_version),
-
				"maximum_version", 0, false);
-
	}
-
	if (pkg->message->minimum_version) {
		ucl_object_insert_key(obj,
-
				ucl_object_fromstring(pkg->message->minimum_version),
-
				"minimum_version", 0, false);
+
		    ucl_object_fromstring_common(msg->str, 0,
+
		    UCL_STRING_RAW|UCL_STRING_TRIM),
+
		    "message", 0, false);
+

+
		switch (msg->type) {
+
		case PKG_MESSAGE_ALWAYS:
+
			break;
+
		case PKG_MESSAGE_INSTALL:
+
			ucl_object_insert_key(obj,
+
			    ucl_object_fromstring("install"),
+
			    "type", 0, false);
+
			break;
+
		case PKG_MESSAGE_UPGRADE:
+
			ucl_object_insert_key(obj,
+
			    ucl_object_fromstring("upgrade"),
+
			    "type", 0, false);
+
			break;
+
		case PKG_MESSAGE_REMOVE:
+
			ucl_object_insert_key(obj,
+
			    ucl_object_fromstring("remove"),
+
			    "type", 0, false);
+
			break;
+
		}
+
		if (msg->maximum_version) {
+
			ucl_object_insert_key(obj,
+
			    ucl_object_fromstring(msg->maximum_version),
+
			    "maximum_version", 0, false);
+
		}
+
		if (msg->minimum_version) {
+
			ucl_object_insert_key(obj,
+
			    ucl_object_fromstring(msg->minimum_version),
+
			    "minimum_version", 0, false);
+
		}
+
		ucl_array_append(array, obj);
	}

-
	return (obj);
+
	return (array);
}

char*
modified libpkg/pkg.h.in
@@ -1284,6 +1284,7 @@ typedef enum {
	PKG_EVENT_PLUGIN_INFO,
	PKG_EVENT_NOT_FOUND,
	PKG_EVENT_NEW_ACTION,
+
	PKG_EVENT_MESSAGE,
} pkg_event_t;

struct pkg_event {
@@ -1433,6 +1434,9 @@ struct pkg_event {
			int64_t current;
			int64_t total;
		} e_progress_tick;
+
		struct {
+
			const char *msg;
+
		} e_pkg_message;
	};
};

modified libpkg/pkg_add.c
@@ -383,7 +383,7 @@ pkg_globmatch(char *pattern, const char *name)
			path = g.gl_pathv[i];
			continue;
		}
-
		if (pkg_version_cmp(path, g.gl_pathv[i]) == '>')
+
		if (pkg_version_cmp(path, g.gl_pathv[i]) == 1)
			path = g.gl_pathv[i];
	}
	path = strdup(path);
@@ -565,15 +565,17 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,
    struct pkg_manifest_key *keys, const char *reloc, struct pkg *remote,
    struct pkg *local)
{
-
	struct archive	*a;
-
	struct archive_entry *ae;
-
	struct pkg	*pkg = NULL;
-
	const char	*location;
-
	bool		 extract = true;
-
	bool		 handle_rc = false;
-
	int		 retcode = EPKG_OK;
-
	int		 ret;
-
	int nfiles;
+
	struct archive		*a;
+
	struct archive_entry	*ae;
+
	struct pkg		*pkg = NULL;
+
	struct sbuf		*message;
+
	struct pkg_message	*msg;
+
	const char		*location, *msgstr;
+
	bool			 extract = true;
+
	bool			 handle_rc = false;
+
	int			 retcode = EPKG_OK;
+
	int			 ret;
+
	int			 nfiles;

	assert(path != NULL);

@@ -717,6 +719,49 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,
			else
				pkg_emit_install_finished(pkg, local);
		}
+

+
		if (pkg->message != NULL)
+
			message = sbuf_new_auto();
+
		LL_FOREACH(pkg->message, msg) {
+
			msgstr = NULL;
+
			if (msg->type == PKG_MESSAGE_ALWAYS) {
+
				msgstr = msg->str;
+
			} else if (local != NULL &&
+
			     msg->type == PKG_MESSAGE_UPGRADE) {
+
				if (msg->maximum_version == NULL &&
+
				    msg->minimum_version == NULL) {
+
					msgstr = msg->str;
+
				} else if (msg->maximum_version == NULL) {
+
					if (pkg_version_cmp(local->version, msg->minimum_version) == 1) {
+
						msgstr = msg->str;
+
					}
+
				} else if (msg->minimum_version == NULL) {
+
					if (pkg_version_cmp(local->version, msg->maximum_version) == -1) {
+
						msgstr = msg->str;
+
					}
+
				} else if (pkg_version_cmp(local->version, msg->maximum_version) == -1 &&
+
					    pkg_version_cmp(local->version, msg->minimum_version) == 1) {
+
					msgstr = msg->str;
+
				}
+
			} else if (local == NULL &&
+
			    msg->type == PKG_MESSAGE_INSTALL) {
+
				msgstr = msg->str;
+
			}
+
			if (msgstr != NULL) {
+
				if (sbuf_len(message) == 0) {
+
					pkg_sbuf_printf(message, "Message from "
+
					    "%n-%v:\n", pkg, pkg);
+
				}
+
				sbuf_printf(message, "%s\n", msgstr);
+
			}
+
		}
+
		if (pkg->message != NULL) {
+
			if (sbuf_len(message) > 0) {
+
				sbuf_finish(message);
+
				pkg_emit_message(sbuf_data(message));
+
			}
+
			sbuf_delete(message);
+
		}
	}

	cleanup:
modified libpkg/pkg_delete.c
@@ -56,6 +56,8 @@
int
pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags)
{
+
	struct pkg_message	*msg;
+
	struct sbuf	*message;
	int		 ret;
	bool		 handle_rc = false;
	const unsigned load_flags = PKG_LOAD_RDEPS|PKG_LOAD_FILES|PKG_LOAD_DIRS|
@@ -112,8 +114,28 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags)
	if (ret != EPKG_OK)
		return (ret);

-
	if ((flags & PKG_DELETE_UPGRADE) == 0)
+
	if ((flags & PKG_DELETE_UPGRADE) == 0) {
		pkg_emit_deinstall_finished(pkg);
+
		if (pkg->message != NULL)
+
			message = sbuf_new_auto();
+
		LL_FOREACH(pkg->message, msg) {
+
			if (msg->type == PKG_MESSAGE_REMOVE) {
+
				if (sbuf_len(message) == 0) {
+
					pkg_sbuf_printf(message, "Message from "
+
					    "%n-%v:\n", pkg, pkg);
+
				}
+
				sbuf_printf(message, "%s\n", msg->str);
+
			}
+
		}
+
		if (pkg->message != NULL) {
+
			if (sbuf_len(message) > 0) {
+
				sbuf_finish(message);
+
				pkg_emit_message(sbuf_data(message));
+
			}
+
			sbuf_delete(message);
+
		}
+

+
	}

	return (pkgdb_unregister_pkg(db, pkg->id));
}
modified libpkg/pkg_event.c
@@ -1014,3 +1014,13 @@ pkg_emit_new_action(void)

	pkg_emit_event(&ev);
}
+

+
void
+
pkg_emit_message(const char *message)
+
{
+
	struct pkg_event ev;
+

+
	ev.type = PKG_EVENT_MESSAGE;
+
	ev.e_pkg_message.msg = message;
+
	pkg_emit_event(&ev);
+
}
modified libpkg/pkg_manifest.c
@@ -141,11 +141,11 @@ static struct pkg_manifest_key {
	{ "maintainer",          offsetof(struct pkg, maintainer),
			TYPE_SHIFT(UCL_STRING), pkg_string},

-
	{ "message_new",             PKG_MESSAGE_NEW,
-
			TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_OBJECT), pkg_message},
+
	{ "messages",            PKG_MESSAGE_NEW,
+
			TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_ARRAY), pkg_message},

	{ "message",             PKG_MESSAGE_LEGACY,
-
			TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_OBJECT), pkg_message},
+
			TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_ARRAY), pkg_message},

	{ "name",                offsetof(struct pkg, name),
			TYPE_SHIFT(UCL_STRING)|TYPE_SHIFT(UCL_INT), pkg_string},
@@ -1229,11 +1229,7 @@ pkg_emit_object(struct pkg *pkg, short flags)
	if (pkg->message != NULL) {
		ucl_object_insert_key(top,
			pkg_message_to_ucl(pkg),
-
			"message_new", sizeof("message_new") - 1, false);
-
		ucl_object_insert_key(top,
-
			ucl_object_fromstring_common(pkg->message->str, 0,
-
					UCL_STRING_RAW|UCL_STRING_TRIM),
-
			"message", sizeof("message") - 1, false);
+
			"messages", sizeof("messages") - 1, false);
	}

	return (top);
modified libpkg/pkg_ports.c
@@ -1290,6 +1290,8 @@ pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path,
{
	const char *location;
	int rc = EPKG_OK;
+
	struct sbuf *message;
+
	struct pkg_message *msg;

	location = reloc;
	if (pkg_rootdir != NULL)
@@ -1317,8 +1319,24 @@ pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path,
		pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL);
	}

-
	if (rc == EPKG_OK)
+
	if (rc == EPKG_OK) {
		pkg_emit_install_finished(pkg, NULL);
+
		if (pkg->message != NULL)
+
			message = sbuf_new_auto();
+
		LL_FOREACH(pkg->message, msg) {
+
			if (msg->type == PKG_MESSAGE_ALWAYS ||
+
			    msg->type == PKG_MESSAGE_INSTALL) {
+
				sbuf_printf(message, "%s\n", msg->str);
+
			}
+
		}
+
		if (pkg->message != NULL) {
+
			if (sbuf_len(message) > 0) {
+
				sbuf_finish(message);
+
				pkg_emit_message(sbuf_data(message));
+
			}
+
			sbuf_delete(message);
+
		}
+
	}

cleanup:
	pkgdb_register_finale(db, rc);
modified libpkg/pkgdb_iterator.c
@@ -819,7 +819,7 @@ populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg) {
				msg = sqlite3_column_text(stmt, icol);
				if (msg) {
					/* A stupid logic to detect legacy pkg message */
-
					if (msg[0] == '{') {
+
					if (msg[0] == '[') {
						pkg_message_from_str(pkg, msg, 0);
					}
					else {
modified libpkg/private/event.h
@@ -77,5 +77,6 @@ void pkg_emit_extract_finished(struct pkg *p);
void pkg_emit_delete_files_begin(struct pkg *p);
void pkg_emit_delete_files_finished(struct pkg *p);
void pkg_emit_new_action(void);
+
void pkg_emit_message(const char *msg);

#endif
modified libpkg/private/pkg.h
@@ -276,11 +276,19 @@ struct pkg_dep {
	bool		 locked;
};

+
typedef enum {
+
	PKG_MESSAGE_ALWAYS = 0,
+
	PKG_MESSAGE_INSTALL,
+
	PKG_MESSAGE_REMOVE,
+
	PKG_MESSAGE_UPGRADE,
+
} pkg_message_t;
+

struct pkg_message {
-
	char		*str;
-
	char		*minimum_version;
-
	char		*maximum_version;
-
	bool		legacy;
+
	char			*str;
+
	char			*minimum_version;
+
	char			*maximum_version;
+
	pkg_message_t		 type;
+
	struct pkg_message	*next;
};

enum pkg_conflict_type {
modified src/delete.c
@@ -222,6 +222,10 @@ exec_delete(int argc, char **argv)
	if (!rc || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK)
		goto cleanup;

+
	if (messages != NULL) {
+
		sbuf_finish(messages);
+
		printf("%s", sbuf_data(messages));
+
	}
	pkgdb_compact(db);

	retcode = EX_OK;
modified src/event.c
@@ -627,15 +627,6 @@ event_callback(void *data, struct pkg_event *ev)
		if (quiet)
			break;
		pkg = ev->e_install_finished.pkg;
-
		if (pkg_has_message(pkg)) {
-

-
			if (pkg_need_message(pkg, ev->e_install_finished.old)) {
-
				if (messages == NULL)
-
					messages = sbuf_new_auto();
-
				pkg_sbuf_printf(messages, "Message for %n-%v:\n%M\n",
-
						pkg, pkg, pkg);
-
			}
-
		}
		break;
	case PKG_EVENT_EXTRACT_BEGIN:
		if (quiet)
@@ -737,15 +728,6 @@ event_callback(void *data, struct pkg_event *ev)
		if (quiet)
			break;
		pkg_new = ev->e_upgrade_finished.n;
-
		if (pkg_has_message(pkg_new)) {
-

-
			if (pkg_need_message(pkg_new, ev->e_upgrade_finished.o)) {
-
				if (messages == NULL)
-
					messages = sbuf_new_auto();
-
				pkg_sbuf_printf(messages, "Message for %n-%v:\n%M\n",
-
						pkg_new, pkg_new, pkg_new);
-
			}
-
		}
		break;
	case PKG_EVENT_LOCKED:
		pkg = ev->e_locked.pkg;
@@ -858,6 +840,11 @@ event_callback(void *data, struct pkg_event *ev)
	case PKG_EVENT_NEW_ACTION:
		nbdone++;
		break;
+
	case PKG_EVENT_MESSAGE:
+
		if (messages == NULL)
+
			messages = sbuf_new_auto();
+
		sbuf_cat(messages, ev->e_pkg_message.msg);
+
		break;
	default:
		break;
	}
modified src/register.c
@@ -331,8 +331,10 @@ exec_register(int argc, char **argv)

	retcode = pkg_add_port(db, pkg, input_path, location, testing_mode);

-
	if (!legacy && retcode == EPKG_OK && pkg_has_message(pkg))
-
		pkg_printf("%M\n", pkg);
+
	if (!legacy && retcode == EPKG_OK && messages != NULL) {
+
		sbuf_finish(messages);
+
		printf("%s\n", sbuf_data(messages));
+
	}

	pkg_free(pkg);

modified tests/Makefile.am
@@ -85,6 +85,7 @@ tests_scripts= \
		frontend/create.sh \
		frontend/delete.sh \
		frontend/lock.sh \
+
		frontend/messages.sh \
		frontend/packagesplit.sh \
		frontend/php-pr.sh \
		frontend/pubkey.sh \
modified tests/frontend/Kyuafile.in
@@ -11,6 +11,7 @@ atf_test_program{name='conflicts-multirepo'}
atf_test_program{name='create'}
atf_test_program{name='delete'}
atf_test_program{name='lock'}
+
atf_test_program{name='messages'}
atf_test_program{name='packagesplit'}
atf_test_program{name='php-pr'}
atf_test_program{name='pkg'}
added tests/frontend/messages.sh
@@ -0,0 +1,95 @@
+
#! /usr/bin/env atf-sh
+

+
. $(atf_get_srcdir)/test_environment.sh
+

+
tests_init \
+
	messages
+

+
messages_body() {
+
	cat > test.ucl << EOF
+
name: "test"
+
origin: "test"
+
version: "5.20_3"
+
arch: "*"
+
maintainer: "none"
+
prefix: "/usr/local"
+
www: "unknown"
+
comment: "need one"
+
desc: "also need one"
+
message: [
+
	{ message: "Always print" },
+
	{ message: "package being removed", type: remove },
+
	{ message: "package being installed", type: install },
+
	{ message: "package is being upgraded", type: upgrade },
+
	{ message: "Upgrading from lower than 1.0", maximum_version: "1.0", type: upgrade },
+
	{ message: "Upgrading from higher than 1.0", minimum_version: "1.0", type: upgrade  },
+
	{ message: "Upgrading from >1.0 < 3.0", maximum_version: "3.0", minimum_version: "1.0", type: upgrade  }
+
]
+
EOF
+
	atf_check \
+
		-o match:".*Installing.*" \
+
		-o match:"^Always print.*" \
+
		-o match:"^package being installed.*" \
+
		pkg register -M test.ucl
+
	atf_check \
+
		-o match:"^package being removed.*" \
+
		pkg delete -y test
+

+
	cat << EOF > repo1.conf
+
local1: {
+
	url: file://${TMPDIR},
+
	enabled: true
+
}
+
EOF
+
	cat > test2.ucl << EOF
+
name: "test"
+
origin: "test"
+
version: "0.20_3"
+
arch: "*"
+
maintainer: "none"
+
prefix: "/usr/local"
+
www: "unknown"
+
comment: "need one"
+
desc: "also need one"
+
EOF
+
	atf_check -o ignore pkg register -M test2.ucl
+
	atf_check -o ignore pkg create -M test.ucl
+
	atf_check -o ignore pkg repo .
+
	atf_check -o match:"^Upgrading from lower than 1.0.*" \
+
	    pkg -o REPOS_DIR="${TMPDIR}" -o PKG_CACHEDIR="${TMPDIR}" upgrade -y
+
	atf_check -o ignore pkg delete -y test
+

+
	cat > test2.ucl << EOF
+
name: "test"
+
origin: "test"
+
version: "4.20_3"
+
arch: "*"
+
maintainer: "none"
+
prefix: "/usr/local"
+
www: "unknown"
+
comment: "need one"
+
desc: "also need one"
+
EOF
+
	atf_check -o ignore pkg register -M test2.ucl
+
	atf_check \
+
		-o match:"^Upgrading from higher than 1.0.*" \
+
	    pkg -o REPOS_DIR="${TMPDIR}" -o PKG_CACHEDIR="${TMPDIR}" upgrade -y
+
	atf_check -o ignore pkg delete -y test
+

+
	cat > test2.ucl << EOF
+
name: "test"
+
origin: "test"
+
version: "2.20_3"
+
arch: "*"
+
maintainer: "none"
+
prefix: "/usr/local"
+
www: "unknown"
+
comment: "need one"
+
desc: "also need one"
+
EOF
+
	atf_check -o ignore pkg register -M test2.ucl
+
	atf_check \
+
		-o match:"^Upgrading from >1.0 < 3.0.*" \
+
		-o match:"^Upgrading from higher than 1.0.*" \
+
		pkg -o REPOS_DIR="${TMPDIR}" -o PKG_CACHEDIR="${TMPDIR}" upgrade -y
+
}