diff --git a/docs/pkg-keywords.5 b/docs/pkg-keywords.5 index 65ffa7cee4..84e45be873 100644 --- a/docs/pkg-keywords.5 +++ b/docs/pkg-keywords.5 @@ -96,9 +96,13 @@ Valid information by entry in the array are: .Bl -tag .It Cm message Ar string actual message to be shown to the users. -.It Cm type Op Ar upgrade | Ar remove | Ar install -defines in which contect the message should be shown to the users. -If not set, the message will always be printed +.It Cm type Op Ar upgrade | Ar remove | Ar install | Ar before +defines in which context the message should be shown to the users. +If not set, the message will always be printed, when set to +.Va before , +message will be printed before install or upgrade and +.Xr pkg 8 +will sleep for 10 seconds. .El .El .Sh SEE ALSO diff --git a/libpkg/pkg.c b/libpkg/pkg.c index 8a02085644..a432c4b11d 100644 --- a/libpkg/pkg.c +++ b/libpkg/pkg.c @@ -1735,6 +1735,12 @@ pkg_message_from_ucl(struct pkg *pkg, const ucl_object_t *obj) msg->type = PKG_MESSAGE_REMOVE; else if (strcasecmp(ucl_object_tostring(elt), "upgrade") == 0) msg->type = PKG_MESSAGE_UPGRADE; + else if (strcasecmp(ucl_object_tostring(elt), "pre-install") == 0) + msg->type = PKG_MESSAGE_PREINSTALL; + else if (strcasecmp(ucl_object_tostring(elt), "pre-remove") == 0) + msg->type = PKG_MESSAGE_PREREMOVE; + else if (strcasecmp(ucl_object_tostring(elt), "pre-upgrade") == 0) + msg->type = PKG_MESSAGE_PREUPGRADE; else pkg_emit_error("Unknown message type," " message will always be printed"); @@ -1830,6 +1836,21 @@ pkg_message_to_ucl(const struct pkg *pkg) ucl_object_fromstring("remove"), "type", 0, false); break; + case PKG_MESSAGE_PREINSTALL: + ucl_object_insert_key(obj, + ucl_object_fromstring("pre-install"), + "type", 0, false); + break; + case PKG_MESSAGE_PREUPGRADE: + ucl_object_insert_key(obj, + ucl_object_fromstring("pre-upgrade"), + "type", 0, false); + break; + case PKG_MESSAGE_PREREMOVE: + ucl_object_insert_key(obj, + ucl_object_fromstring("pre-remove"), + "type", 0, false); + break; } if (msg->maximum_version) { ucl_object_insert_key(obj, diff --git a/libpkg/pkg_add.c b/libpkg/pkg_add.c index 9a7c23c7bb..a7b20ca8ff 100644 --- a/libpkg/pkg_add.c +++ b/libpkg/pkg_add.c @@ -1029,6 +1029,65 @@ pkg_rollback_cb(void *data) pkg_rollback_pkg((struct pkg *)data); } +static void +pkg_print_message(struct pkg *pkg, struct pkg *local, struct pkg *remote, + pkg_printmessage_t prepost) +{ + xstring *message = NULL; + struct pkg_message *msg; + const char *msgstr; + + LL_FOREACH(pkg->message, msg) { + msgstr = NULL; + /* Print "always"-type only post-operation */ + if ((msg->type == PKG_MESSAGE_ALWAYS) && + (prepost == PKG_PRINTMESSAGE_POST)) { + msgstr = msg->str; + } else if (local != NULL && + msg->type == ((prepost == PKG_PRINTMESSAGE_POST) ? + PKG_MESSAGE_UPGRADE : PKG_MESSAGE_PREUPGRADE)) { + 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 == ( + (prepost == PKG_PRINTMESSAGE_POST ? + PKG_MESSAGE_INSTALL : PKG_MESSAGE_PREINSTALL))) { + msgstr = msg->str; + } + if (msgstr != NULL) { + if (message == NULL) { + message = xstring_new(); + pkg_fprintf(message->fp, "=====\nMessage from " + "%n-%v:\n\n", pkg, pkg); + } + fprintf(message->fp, "--\n%s\n", msgstr); + } + } + if (pkg->message != NULL && message != NULL) { + fflush(message->fp); + if (prepost == PKG_PRINTMESSAGE_POST) + pkg_emit_message(message->buf); + else { + pkg_emit_notice("%s", message->buf); + sleep(10); + } + xstring_free(message); + } +} + static int pkg_add_common(struct pkgdb *db, const char *path, unsigned flags, struct pkg_manifest_key *keys, const char *reloc, struct pkg *remote, @@ -1037,10 +1096,7 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags, struct archive *a; struct archive_entry *ae; struct pkg *pkg = NULL; - xstring *message = NULL; - struct pkg_message *msg; struct pkg_file *f; - const char *msgstr; bool extract = true; int retcode = EPKG_OK; int ret; @@ -1130,6 +1186,8 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags, if (retcode != EPKG_OK) goto cleanup; + pkg_print_message(pkg, local, remote, PKG_PRINTMESSAGE_PRE); + /* * Execute pre-install scripts */ @@ -1204,45 +1262,7 @@ pkg_add_common(struct pkgdb *db, const char *path, unsigned flags, pkg_emit_install_finished(pkg, local); } - 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 (message == NULL) { - message = xstring_new(); - pkg_fprintf(message->fp, "=====\nMessage from " - "%n-%v:\n\n", pkg, pkg); - } - fprintf(message->fp, "--\n%s\n", msgstr); - } - } - if (pkg->message != NULL && message != NULL) { - fflush(message->fp); - pkg_emit_message(message->buf); - xstring_free(message); - } + pkg_print_message(pkg, local, remote, PKG_PRINTMESSAGE_POST); cleanup: if (a != NULL) { diff --git a/libpkg/pkg_delete.c b/libpkg/pkg_delete.c index 20141eef9f..4b75d7416f 100644 --- a/libpkg/pkg_delete.c +++ b/libpkg/pkg_delete.c @@ -62,7 +62,6 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags) bool handle_rc = false; const unsigned load_flags = PKG_LOAD_RDEPS|PKG_LOAD_FILES|PKG_LOAD_DIRS| PKG_LOAD_SCRIPTS|PKG_LOAD_ANNOTATIONS|PKG_LOAD_LUA_SCRIPTS; - bool head = true; assert(pkg != NULL); assert(db != NULL); @@ -81,6 +80,24 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags) return (EPKG_LOCKED); } + /* Print pre-action message(s), if any */ + LL_FOREACH(pkg->message, msg) { + if (msg->type == PKG_MESSAGE_PREREMOVE) { + if (message == NULL) { + message = xstring_new(); + pkg_fprintf(message->fp, "Message from " + "%n-%v:\n", pkg, pkg); + } + fprintf(message->fp, "%s\n", msg->str); + } + } + if (pkg->message != NULL && message != NULL) { + fflush(message->fp); + pkg_emit_notice("%s", message->buf); + xstring_free(message); + message = NULL; + } + /* * stop the different related services if the users do want that * and that the service is running @@ -122,7 +139,6 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags) message = xstring_new(); pkg_fprintf(message->fp, "Message from " "%n-%v:\n", pkg, pkg); - head = false; } fprintf(message->fp, "%s\n", msg->str); } diff --git a/libpkg/pkg_ports.c b/libpkg/pkg_ports.c index 4580f0a324..8634c787d7 100644 --- a/libpkg/pkg_ports.c +++ b/libpkg/pkg_ports.c @@ -133,7 +133,7 @@ keyword_open_schema(void) " type = object;" " properties {" " message = { type = string };" - " type = { enum = [ upgrade, remove, install ] };" + " type = { enum = [ upgrade, remove, install, pre-upgrade, pre-remove, pre-install ] };" " };" " required [ message ];" " };" @@ -984,6 +984,12 @@ apply_keyword_file(ucl_object_t *obj, struct plist *p, char *line, struct file_a msg->type = PKG_MESSAGE_REMOVE; else if (strcasecmp(ucl_object_tostring(elt), "upgrade") == 0) msg->type = PKG_MESSAGE_UPGRADE; + else if (strcasecmp(ucl_object_tostring(elt), "pre-install") == 0) + msg->type = PKG_MESSAGE_PREINSTALL; + else if (strcasecmp(ucl_object_tostring(elt), "pre-remove") == 0) + msg->type = PKG_MESSAGE_PREREMOVE; + else if (strcasecmp(ucl_object_tostring(elt), "pre-upgrade") == 0) + msg->type = PKG_MESSAGE_PREUPGRADE; } DL_APPEND(p->pkg->message, msg); } diff --git a/libpkg/pkg_printf.c b/libpkg/pkg_printf.c index 83e43ee937..b3e6deb945 100644 --- a/libpkg/pkg_printf.c +++ b/libpkg/pkg_printf.c @@ -1308,6 +1308,15 @@ format_message(xstring *buffer, const void *data, struct percent_esc *p) case PKG_MESSAGE_REMOVE: fprintf(bufmsg->fp, "On remove:\n"); break; + case PKG_MESSAGE_PREINSTALL: + fprintf(bufmsg->fp, "Before install:\n"); + break; + case PKG_MESSAGE_PREREMOVE: + fprintf(bufmsg->fp, "Before remove:\n"); + break; + case PKG_MESSAGE_PREUPGRADE: + fprintf(bufmsg->fp, "Before upgrade:\n"); + break; } fprintf(bufmsg->fp, "%s\n", msg->str); } diff --git a/libpkg/private/pkg.h b/libpkg/private/pkg.h index 9bcd96fa70..63ad75353b 100644 --- a/libpkg/private/pkg.h +++ b/libpkg/private/pkg.h @@ -392,8 +392,17 @@ typedef enum { PKG_MESSAGE_INSTALL, PKG_MESSAGE_REMOVE, PKG_MESSAGE_UPGRADE, + PKG_MESSAGE_PREINSTALL, + PKG_MESSAGE_PREREMOVE, + PKG_MESSAGE_PREUPGRADE, } pkg_message_t; +typedef enum { + PKG_PRINTMESSAGE_ALWAYS = 0, + PKG_PRINTMESSAGE_PRE, + PKG_PRINTMESSAGE_POST, +} pkg_printmessage_t; + struct pkg_message { char *str; char *minimum_version; diff --git a/tests/frontend/create.sh b/tests/frontend/create.sh index 7d544ddc9d..89c7604436 100755 --- a/tests/frontend/create.sh +++ b/tests/frontend/create.sh @@ -558,8 +558,10 @@ cat << EOF > showmsg.ucl actions: [] messages: [ { message: "always" }, - { message: "on upgrade";type = "upgrade" }, + { message: "on upgrade"; type = "upgrade" }, { message: "on install"; type = "install" }, + { message: "before upgrade"; type = "pre-upgrade" }, + { message: "before install"; type = "pre-install" }, ] EOF cat << EOF > +DISPLAY @@ -579,6 +581,12 @@ on upgrade On install: on install +Before upgrade: +before upgrade + +Before install: +before install + ' atf_check pkg -o PLIST_KEYWORDS_DIR=. create -m . -r ${TMPDIR} -p test.plist atf_check -o inline:"${OUTPUT}" pkg info -D -F ./test-1.txz diff --git a/tests/frontend/messages.sh b/tests/frontend/messages.sh index 83608d2fa0..ab2b79d1cd 100755 --- a/tests/frontend/messages.sh +++ b/tests/frontend/messages.sh @@ -18,6 +18,9 @@ comment: "need one" desc: "also need one" message: [ { message: "Always print" }, + { message: "Before remove", type: pre-remove }, + { message: "Before install", type: pre-install }, + { message: "Before upgrade", type: pre-upgrade }, { message: "package being removed", type: remove }, { message: "package being installed", type: install }, { message: "package is being upgraded", type: upgrade }, @@ -97,6 +100,15 @@ OUTPUT='test-5.20_3: Always: Always print +Before remove: +Before remove + +Before install: +Before install + +Before upgrade: +Before upgrade + On remove: package being removed diff --git a/tests/frontend/register.sh b/tests/frontend/register.sh index db02c2435e..2114eebfe6 100755 --- a/tests/frontend/register.sh +++ b/tests/frontend/register.sh @@ -62,6 +62,8 @@ message { message: "hey"}, { message: "install", type = install}, { message: "remove", type = remove}, + { message: "before install", type = pre-install}, + { message: "before remove", type = pre-remove}, ] EOF OUTPUT='test2-1: @@ -74,6 +76,12 @@ install On remove: remove +Before install: +before install + +Before remove: +before remove + ' atf_check -o match:"hey" -o match:"install" -o not-match:"remove" pkg register -m . atf_check -o inline:"${OUTPUT}" pkg info -D test2