Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge branch 'message-rework'
Vsevolod Stakhov committed 10 years ago
commit 631ae917cf5fc27ec21d39d531bbd60aeaae50da
parent 1c387b8
14 files changed +252 -32
modified libpkg/libpkg.ver
@@ -51,6 +51,7 @@ global:
	pkg_has_dir;
	pkg_has_file;
	pkg_has_message;
+
	pkg_need_message;
	pkg_ini;
	pkg_init;
	pkg_initialized;
modified libpkg/pkg.c
@@ -195,7 +195,7 @@ pkg_vget(const struct pkg * restrict pkg, va_list ap)
			*va_arg(ap, const char **) = NULL;
			break;
		case PKG_MESSAGE:
-
			*va_arg(ap, const char **) = pkg->message;
+
			*va_arg(ap, const char **) = pkg->message ? pkg->message->str : NULL;
			break;
		case PKG_ARCH:
			*va_arg(ap, const char **) = pkg->arch;
@@ -329,7 +329,8 @@ pkg_vset(struct pkg *pkg, va_list ap)
			break;
		case PKG_MESSAGE:
			free(pkg->message);
-
			pkg->message = strdup(va_arg(ap, const char *));
+
			pkg->message = calloc(1, sizeof(*pkg->message));
+
			pkg->message->str = strdup(va_arg(ap, const char *));
			break;
		case PKG_ARCH:
			free(pkg->arch);
@@ -1608,6 +1609,25 @@ pkg_is_installed(struct pkgdb *db, const char *name)
}

bool
+
pkg_need_message(struct pkg *p, struct pkg *old)
+
{
+
	bool ret = true;
+

+
	if (old != NULL) {
+
		if (p->message->maximum_version) {
+
			ret = (pkg_version_cmp(old->version, p->message->maximum_version)
+
					<= 0);
+
		}
+
		if (ret && p->message->minimum_version) {
+
			ret = (pkg_version_cmp(old->version, p->message->maximum_version)
+
								>= 0);
+
		}
+
	}
+

+
	return (ret);
+
}
+

+
bool
pkg_has_message(struct pkg *p)
{
	return (p->message != NULL);
@@ -1685,3 +1705,118 @@ pkg_open_root_fd(struct pkg *pkg)

	return (EPKG_FATAL);
}
+

+
int
+
pkg_message_from_ucl(struct pkg *pkg, const ucl_object_t *obj)
+
{
+
	struct pkg_message *msg;
+
	const ucl_object_t *elt;
+

+
	msg = calloc(1, sizeof(*msg));
+

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

+
	if (ucl_object_type(obj) == UCL_STRING) {
+
		msg->str = strdup(ucl_object_tostring(obj));
+
	}
+
	else if (ucl_object_type(obj) == UCL_OBJECT) {
+
		/* New format of pkg message */
+
		elt = ucl_object_find_key(obj, "message");
+

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

+
			return (EPKG_FATAL);
+
		}
+

+
		msg->str = strdup(ucl_object_tostring(elt));
+
		elt = ucl_object_find_key(obj, "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");
+

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

+
	pkg->message = msg;
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_message_from_str(struct pkg *pkg, const char *str, size_t len)
+
{
+
	struct ucl_parser *parser;
+
	ucl_object_t *obj;
+
	int ret = EPKG_FATAL;
+

+
	assert(str != NULL);
+

+
	if (len == 0) {
+
		len = strlen(str);
+
	}
+

+
	parser = ucl_parser_new(0);
+

+
	if (ucl_parser_add_chunk(parser, (const unsigned char*)str, len)) {
+
		obj = ucl_parser_get_object(parser);
+
		ucl_parser_free(parser);
+

+
		ret = pkg_message_from_ucl(pkg, obj);
+
		ucl_object_unref(obj);
+

+
		return (ret);
+
	}
+

+
	ucl_parser_free (parser);
+

+
	return (ret);
+
}
+

+
ucl_object_t*
+
pkg_message_to_ucl(struct pkg *pkg)
+
{
+
	ucl_object_t *obj;
+

+
	obj = ucl_object_typed_new (UCL_OBJECT);
+

+
	ucl_object_insert_key(obj, ucl_object_fromstring(pkg->message->str),
+
			"message", 0, false);
+

+
	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);
+
	}
+

+
	return (obj);
+
}
+

+
char*
+
pkg_message_to_str(struct pkg *pkg)
+
{
+
	ucl_object_t *obj;
+
	char *ret = NULL;
+

+
	if (pkg->message == NULL) {
+
		return (NULL);
+
	}
+

+
	obj = pkg_message_to_ucl(pkg);
+
	ret = ucl_object_emit(obj, UCL_EMIT_JSON_COMPACT);
+
	ucl_object_unref(obj);
+

+
	return (ret);
+
}
modified libpkg/pkg.h.in
@@ -1311,6 +1311,7 @@ struct pkg_event {
		} e_install_begin;
		struct {
			struct pkg *pkg;
+
      struct pkg *old;
		} e_install_finished;
		struct {
			struct pkg *pkg;
@@ -1598,6 +1599,7 @@ struct sbuf *pkg_sbuf_vprintf(struct sbuf * restrict sbuf,
	const char * restrict format, va_list ap);

bool pkg_has_message(struct pkg *p);
+
bool pkg_need_message(struct pkg *p, struct pkg *old);
bool pkg_is_locked(const struct pkg * restrict p);


modified libpkg/pkg_add.c
@@ -688,12 +688,12 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags,

	if (retcode == EPKG_OK) {
		if ((flags & PKG_ADD_UPGRADE) == 0)
-
			pkg_emit_install_finished(pkg);
+
			pkg_emit_install_finished(pkg, local);
		else {
			if (local != NULL)
				pkg_emit_upgrade_finished(pkg, local);
			else
-
				pkg_emit_install_finished(pkg);
+
				pkg_emit_install_finished(pkg, local);
		}
	}

modified libpkg/pkg_create.c
@@ -283,6 +283,43 @@ pkg_load_from_file(int fd, struct pkg *pkg, pkg_attr attr, const char *path)
	}
}

+
static int
+
pkg_load_message_from_file(int fd, struct pkg *pkg, const char *path, bool is_ucl)
+
{
+
	char *buf = NULL;
+
	off_t size = 0;
+
	int ret;
+
	ucl_object_t *obj;
+

+
	assert(pkg != NULL);
+
	assert(path != NULL);
+

+
	if (faccessat(fd, path, F_OK, 0) == 0) {
+
		pkg_debug(1, "Reading message: '%s'", path);
+

+
		if ((ret = file_to_bufferat(fd, path, &buf, &size)) != EPKG_OK) {
+
			return (ret);
+
		}
+

+
		if (is_ucl) {
+
			ret = pkg_message_from_str(pkg, buf, size);
+
			free(buf);
+

+
			return (ret);
+
		}
+
		else {
+
			obj = ucl_object_fromlstring(buf, size);
+
			ret = pkg_message_from_ucl(pkg, obj);
+
			ucl_object_unref(obj);
+
			free(buf);
+

+
			return (ret);
+
		}
+
	}
+

+
	return (EPKG_FATAL);
+
}
+

int
pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
    const char *md_dir, char *plist)
@@ -325,8 +362,13 @@ pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
		pkg_load_from_file(mfd, pkg, PKG_DESC, "+DESC");

	/* if no message try to get it from a file */
-
	if (pkg->message == NULL)
-
		pkg_load_from_file(mfd, pkg, PKG_MESSAGE, "+DISPLAY");
+
	if (pkg->message == NULL) {
+
		/* Try ucl version first */
+
		if (pkg_load_message_from_file(mfd, pkg, "+DISPLAY.ucl", true)
+
				!= EPKG_OK) {
+
			pkg_load_message_from_file(mfd, pkg, "+DISPLAY", false);
+
		}
+
	}

	/* if no arch autodetermine it */
	if (pkg->abi == NULL) {
modified libpkg/pkg_event.c
@@ -158,7 +158,9 @@ pipeevent(struct pkg_event *ev)
		    "}}",
		    ev->e_install_finished.pkg,
		    ev->e_install_finished.pkg,
-
		    sbuf_json_escape(buf, ev->e_install_finished.pkg->message));
+
			ev->e_install_finished.pkg->message ?
+
				sbuf_json_escape(buf, ev->e_install_finished.pkg->message->str) :
+
				"");
		break;
	case PKG_EVENT_INTEGRITYCHECK_BEGIN:
		sbuf_printf(msg, "{ \"type\": \"INFO_INTEGRITYCHECK_BEGIN\", "
@@ -537,13 +539,14 @@ pkg_emit_install_begin(struct pkg *p)
}

void
-
pkg_emit_install_finished(struct pkg *p)
+
pkg_emit_install_finished(struct pkg *p, struct pkg *old)
{
	struct pkg_event ev;
	bool syslog_enabled = false;

	ev.type = PKG_EVENT_INSTALL_FINISHED;
	ev.e_install_finished.pkg = p;
+
	ev.e_install_finished.old = old;

	syslog_enabled = pkg_object_bool(pkg_config_get("SYSLOG"));
	if (syslog_enabled) {
modified libpkg/pkg_manifest.c
@@ -63,6 +63,7 @@ static int pkg_string(struct pkg *, const ucl_object_t *, int);
static int pkg_obj(struct pkg *, const ucl_object_t *, int);
static int pkg_array(struct pkg *, const ucl_object_t *, int);
static int pkg_int(struct pkg *, const ucl_object_t *, int);
+
static int pkg_message(struct pkg *, const ucl_object_t *, int);
static int pkg_set_deps_from_object(struct pkg *, const ucl_object_t *);
static int pkg_set_files_from_object(struct pkg *, const ucl_object_t *);
static int pkg_set_dirs_from_object(struct pkg *, const ucl_object_t *);
@@ -94,7 +95,7 @@ static struct manifest_key {
	{ "licenselogic",        PKG_LICENSE_LOGIC,       UCL_STRING, pkg_string},
	{ "licenses",            PKG_LICENSES,            UCL_ARRAY,  pkg_array},
	{ "maintainer",          PKG_MAINTAINER,          UCL_STRING, pkg_string},
-
	{ "message",             PKG_MESSAGE,             UCL_STRING, pkg_string},
+
	{ "message",             PKG_MESSAGE,             UCL_STRING, pkg_message},
	{ "name",                PKG_NAME,                UCL_STRING, pkg_string},
	{ "name",                PKG_NAME,                UCL_INT,    pkg_string},
	{ "options",             PKG_OPTIONS,             UCL_OBJECT, pkg_obj},
@@ -302,10 +303,8 @@ pkg_string(struct pkg *pkg, const ucl_object_t *obj, int attr)
		pkg->maintainer = strdup(str);
		break;
	case PKG_MESSAGE:
-
		urldecode(str, &buf);
-
		sbuf_finish(buf);
-
		pkg->message = strdup(sbuf_data(buf));
-
		sbuf_delete(buf);
+
		/* Should no longer be handled here */
+
		assert(0);
		break;
	case PKG_NAME:
		pkg->name = strdup(str);
@@ -552,6 +551,12 @@ pkg_obj(struct pkg *pkg, const ucl_object_t *obj, int attr)
}

static int
+
pkg_message(struct pkg *pkg, const ucl_object_t *obj, int attr)
+
{
+
	return pkg_message_from_ucl(pkg, obj);
+
}
+

+
static int
pkg_set_files_from_object(struct pkg *pkg, const ucl_object_t *obj)
{
	const ucl_object_t *cur;
@@ -1212,9 +1217,8 @@ pkg_emit_object(struct pkg *pkg, short flags)

	pkg_debug(4, "Emitting message");
	if (pkg->message != NULL) {
-
		urlencode(pkg->message, &tmpsbuf);
		ucl_object_insert_key(top,
-
		    ucl_object_fromstring_common(sbuf_data(tmpsbuf), sbuf_len(tmpsbuf), UCL_STRING_TRIM),
+
			pkg_message_to_ucl(pkg),
		    "message", 7, false);
	}

modified libpkg/pkg_ports.c
@@ -1318,7 +1318,7 @@ pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *input_path,
	}

	if (rc == EPKG_OK)
-
		pkg_emit_install_finished(pkg);
+
		pkg_emit_install_finished(pkg, NULL);

cleanup:
	pkgdb_register_finale(db, rc);
modified libpkg/pkg_printf.c
@@ -1239,7 +1239,7 @@ format_message(struct sbuf *sbuf, const void *data, struct percent_esc *p)
{
	const struct pkg	*pkg = data;

-
	return (string_val(sbuf, pkg->message, p));
+
	return (string_val(sbuf, pkg->message ? pkg->message->str : NULL, p));
}

/*
modified libpkg/pkgdb.c
@@ -1668,7 +1668,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)
	struct pkg_conflict	*conflict = NULL;
	struct pkg_config_file	*cf = NULL;
	struct pkgdb_it		*it = NULL;
-
	char			*buf;
+
	char			*buf, *msg = NULL;

	sqlite3			*s;

@@ -1696,8 +1696,9 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)
	/*
	 * Insert package record
	 */
+
	msg = pkg_message_to_str(pkg);
	ret = run_prstmt(PKG, pkg->origin, pkg->name, pkg->version,
-
	    pkg->comment, pkg->desc, pkg->message, arch, pkg->maintainer,
+
	    pkg->comment, pkg->desc, msg, arch, pkg->maintainer,
	    pkg->www, pkg->prefix, pkg->flatsize, (int64_t)pkg->automatic,
	    (int64_t)pkg->licenselogic, NULL, pkg->digest, pkg->dep_formula);
	if (ret != SQLITE_DONE) {
@@ -1957,6 +1958,8 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)

	cleanup:

+
	free(msg);
+

	return (retcode);
}

@@ -2300,7 +2303,7 @@ pkgdb_register_ports(struct pkgdb *db, struct pkg *pkg)

	ret = pkgdb_register_pkg(db, pkg, 0, 0);
	if (ret == EPKG_OK)
-
		pkg_emit_install_finished(pkg);
+
		pkg_emit_install_finished(pkg, NULL);

	pkgdb_register_finale(db, ret);

modified libpkg/pkgdb_iterator.c
@@ -776,7 +776,7 @@ pkgdb_load_requires(sqlite3 *sqlite, struct pkg *pkg)
static void
populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg) {
	int		 icol = 0;
-
	const char	*colname;
+
	const char	*colname, *msg;
	char		 legacyarch[BUFSIZ];

	assert(stmt != NULL);
@@ -816,7 +816,20 @@ populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg) {
				pkg->digest = strdup(sqlite3_column_text(stmt, icol));
				break;
			case PKG_MESSAGE:
-
				pkg->message = strdup(sqlite3_column_text(stmt, icol));
+
				msg = sqlite3_column_text(stmt, icol);
+
				if (msg) {
+
					/* A stupid logic to detect legacy pkg message */
+
					if (msg[0] == '{') {
+
						pkg_message_from_str(pkg, msg, 0);
+
					}
+
					else {
+
						pkg->message = calloc(1, sizeof(*pkg->message));
+
						pkg->message->str = strdup(msg);
+
					}
+
				}
+
				else {
+
					pkg->message = NULL;
+
				}
				break;
			case PKG_NAME:
				pkg->name = strdup(sqlite3_column_text(stmt, icol));
modified libpkg/private/event.h
@@ -39,7 +39,7 @@ void pkg_emit_fetch_finished(const char *url);
void pkg_emit_update_add(int total, int done);
void pkg_emit_update_remove(int total, int done);
void pkg_emit_install_begin(struct pkg *p);
-
void pkg_emit_install_finished(struct pkg *p);
+
void pkg_emit_install_finished(struct pkg *p, struct pkg *old);
void pkg_emit_deinstall_begin(struct pkg *p);
void pkg_emit_deinstall_finished(struct pkg *p);
void pkg_emit_upgrade_begin(struct pkg *new, struct pkg *old);
modified libpkg/private/pkg.h
@@ -196,6 +196,7 @@ extern const char *pkg_rootdir;

struct pkg_repo_it;
struct pkg_repo;
+
struct pkg_message;

KHASH_MAP_INIT_STR(pkg_deps, struct pkg_dep *);
KHASH_MAP_INIT_STR(pkg_files, struct pkg_file *);
@@ -220,7 +221,7 @@ struct pkg {
	char			*uid;
	char			*digest;
	char			*old_digest;
-
	char			*message;
+
	struct pkg_message	*message;
	char			*prefix;
	char			*comment;
	char			*desc;
@@ -269,6 +270,12 @@ struct pkg_dep {
	bool		 locked;
};

+
struct pkg_message {
+
	char		*str;
+
	char		*minimum_version;
+
	char		*maximum_version;
+
};
+

enum pkg_conflict_type {
	PKG_CONFLICT_ALL = 0,
	PKG_CONFLICT_REMOTE_LOCAL,
@@ -725,5 +732,9 @@ int pkg_addoption_description(struct pkg *pkg, const char *key, const char *desc

int pkg_arch_to_legacy(const char *arch, char *dest, size_t sz);
bool pkg_is_config_file(struct pkg *p, const char *path, const struct pkg_file **file, struct pkg_config_file **cfile);
+
int pkg_message_from_ucl(struct pkg *pkg, const ucl_object_t *obj);
+
int pkg_message_from_str(struct pkg *pkg, const char *str, size_t len);
+
ucl_object_t* pkg_message_to_ucl(struct pkg *pkg);
+
char* pkg_message_to_str(struct pkg *pkg);

#endif
modified src/event.c
@@ -631,10 +631,13 @@ event_callback(void *data, struct pkg_event *ev)
			break;
		pkg = ev->e_install_finished.pkg;
		if (pkg_has_message(pkg)) {
-
			if (messages == NULL)
-
				messages = sbuf_new_auto();
-
			pkg_sbuf_printf(messages, "Message for %n-%v:\n%M\n",
-
			    pkg, pkg, 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:
@@ -740,10 +743,13 @@ event_callback(void *data, struct pkg_event *ev)
			break;
		pkg_new = ev->e_upgrade_finished.n;
		if (pkg_has_message(pkg_new)) {
-
			if (messages == NULL)
-
				messages = sbuf_new_auto();
-
			pkg_sbuf_printf(messages, "Message for %n-%v:\n %M\n",
-
				pkg_new, pkg_new, 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: