From 2c96cc2a411f4e3687b16e5bb3c88f90852b141e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 2 Oct 2022 19:33:21 +0200 Subject: [PATCH] Salt package installation/uninstallation even and hooks. --- src/doc/doc/about/packages.xml | 23 +++++++++++++++++++ src/lay/lay/gsiDeclLayApplication.cc | 9 ++++++++ src/lay/lay/layApplication.cc | 10 +++++++++ src/lay/lay/layApplication.h | 10 ++++++++- src/lay/lay/laySalt.cc | 33 +++++++++++++++++++++++++++- src/lay/lay/laySaltController.cc | 13 ++++++++--- src/lay/lay/laySaltController.h | 11 ++++++++++ 7 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/doc/doc/about/packages.xml b/src/doc/doc/about/packages.xml index 2b9c3daec..a2b7dad60 100644 --- a/src/doc/doc/about/packages.xml +++ b/src/doc/doc/about/packages.xml @@ -209,4 +209,27 @@ subversion equivalent.

+

Installation Hooks

+ +

+ Scripts can register an event through which + indicates that packages have been installed or uninstalled. +

+ +

+ Packages itself can supply special scripts which are executed after a package was installed + or before a package is uninstalled: +

+ + + +

+ Both scripts need to be stored in the same location as "grain.xml" and have to use + "lym" format. This is the generic XML script format KLayout employs as an interpreter-agnostic + script representation. +

+ diff --git a/src/lay/lay/gsiDeclLayApplication.cc b/src/lay/lay/gsiDeclLayApplication.cc index fbf23517b..f59e77244 100644 --- a/src/lay/lay/gsiDeclLayApplication.cc +++ b/src/lay/lay/gsiDeclLayApplication.cc @@ -24,6 +24,7 @@ #include "layMainWindow.h" #include "laySignalHandler.h" #include "gsiDecl.h" +#include "gsiSignals.h" #include "tlArch.h" #if defined(HAVE_QTBINDINGS) @@ -243,6 +244,14 @@ static gsi::Methods application_methods () "\n" "There is exactly one instance of the application. This instance can be obtained with this " "method." + ) + + event ("on_salt_changed", &C::salt_changed_event, + "@brief This event is triggered when the package status changes.\n" + "\n" + "Register to this event if you are interested in package changes - i.e. installation or removal of packages or " + "package updates.\n" + "\n" + "This event has been introduced in version 0.28." ) ; } diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index 5aee10b73..707416e5a 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -672,6 +672,8 @@ ApplicationBase::init_app () } } + sc->salt_changed_event.add (this, &ApplicationBase::salt_changed); + } if (tc) { @@ -852,6 +854,14 @@ ApplicationBase::add_macro_category (const std::string &name, const std::string } } +void +ApplicationBase::salt_changed () +{ +BEGIN_PROTECTED_SILENT + salt_changed_event (); +END_PROTECTED_SILENT +} + ApplicationBase::~ApplicationBase () { tl::set_ui_exception_handlers (0, 0, 0); diff --git a/src/lay/lay/layApplication.h b/src/lay/lay/layApplication.h index 6b42e1318..79cf507fb 100644 --- a/src/lay/lay/layApplication.h +++ b/src/lay/lay/layApplication.h @@ -26,6 +26,7 @@ #include "layCommon.h" #include "layBusy.h" +#include "tlEvents.h" #include #include @@ -76,7 +77,7 @@ class LayoutView; * and one for the GUI version (derived from QApplication). */ class LAY_PUBLIC ApplicationBase - : public gsi::ObjectBase + : public gsi::ObjectBase, public tl::Object { public: /** @@ -313,6 +314,11 @@ public: */ void init_app (); + /** + * @brief An event indicating that the package collection has changed + */ + tl::Event salt_changed_event; + /** * @brief Gets the QApplication object * This method will return non-null only if a GUI-enabled application is present. @@ -376,6 +382,8 @@ private: // in order to maintain a valid MainWindow reference for ruby scripts and Ruby's GC all the time. gsi::Interpreter *mp_ruby_interpreter; gsi::Interpreter *mp_python_interpreter; + + void salt_changed (); }; /** diff --git a/src/lay/lay/laySalt.cc b/src/lay/lay/laySalt.cc index 6c47c949b..45313074d 100644 --- a/src/lay/lay/laySalt.cc +++ b/src/lay/lay/laySalt.cc @@ -26,6 +26,7 @@ #include "tlLog.h" #include "tlInternational.h" #include "tlWebDAV.h" +#include "lymMacro.h" #include #include @@ -281,6 +282,21 @@ Salt::remove_grain (const SaltGrain &grain) QString name = tl::to_qstring (grain.name ()); tl::info << QObject::tr ("Removing package '%1' ..").arg (name); + + // Execute "_uninstall.lym" if it exists + try { + QFile uninstall_lym (QDir (tl::to_qstring (grain.path ())).absoluteFilePath (tl::to_qstring ("_uninstall.lym"))); + if (uninstall_lym.exists ()) { + lym::Macro uninstall; + uninstall.load_from (tl::to_string (uninstall_lym.fileName ())); + uninstall.set_file_path (tl::to_string (uninstall_lym.fileName ())); + uninstall.run (); + } + } catch (tl::Exception &ex) { + // Errors in the uninstallation script are only logged, but do not prevent uninstallation + tl::error << ex.msg (); + } + bool res = remove_from_collection (m_root, grain.name ()); if (res) { tl::info << QObject::tr ("Package '%1' removed.").arg (name); @@ -493,10 +509,25 @@ Salt::create_grain (const SaltGrain &templ, SaltGrain &target, double timeout, t if (res) { - tl::info << QObject::tr ("Package '%1' installed").arg (tl::to_qstring (target.name ())); target.set_installed_time (QDateTime::currentDateTime ()); target.save (); + // Execute "_install.lym" if it exists + try { + QFile install_lym (QDir (tl::to_qstring (target.path ())).absoluteFilePath (tl::to_qstring ("_install.lym"))); + if (install_lym.exists ()) { + lym::Macro install; + install.load_from (tl::to_string (install_lym.fileName ())); + install.set_file_path (tl::to_string (install_lym.fileName ())); + install.run (); + } + } catch (tl::Exception &ex) { + // Errors in the installation script are only logged, but do not prevent installation + tl::error << ex.msg (); + } + + tl::info << QObject::tr ("Package '%1' installed").arg (tl::to_qstring (target.name ())); + // NOTE: this is a bit brute force .. we could as well try to insert the new grain into the existing structure refresh (); diff --git a/src/lay/lay/laySaltController.cc b/src/lay/lay/laySaltController.cc index bfc5af1b2..17967733e 100644 --- a/src/lay/lay/laySaltController.cc +++ b/src/lay/lay/laySaltController.cc @@ -58,13 +58,13 @@ SaltController::initialized (lay::Dispatcher * /*root*/) connect (m_file_watcher, SIGNAL (fileRemoved (const QString &)), this, SLOT (file_watcher_triggered ())); } - connect (&m_salt, SIGNAL (collections_changed ()), this, SIGNAL (salt_changed ())); + connect (&m_salt, SIGNAL (collections_changed ()), this, SLOT (emit_salt_changed ())); } void SaltController::uninitialize (lay::Dispatcher * /*root*/) { - disconnect (&m_salt, SIGNAL (collections_changed ()), this, SIGNAL (salt_changed ())); + disconnect (&m_salt, SIGNAL (collections_changed ()), this, SLOT (emit_salt_changed ())); if (m_file_watcher) { disconnect (m_file_watcher, SIGNAL (fileChanged (const QString &)), this, SLOT (file_watcher_triggered ())); @@ -168,7 +168,7 @@ void SaltController::sync_files () { tl::log << tl::to_string (tr ("Detected file system change in packages - updating")); - emit salt_changed (); + emit_salt_changed (); } bool @@ -242,6 +242,13 @@ SaltController::file_watcher_triggered () dm_sync_files (); } +void +SaltController::emit_salt_changed () +{ + salt_changed_event (); + emit salt_changed (); +} + void SaltController::set_salt_mine_url (const std::string &url) { diff --git a/src/lay/lay/laySaltController.h b/src/lay/lay/laySaltController.h index f660039a6..e2a9fa0fb 100644 --- a/src/lay/lay/laySaltController.h +++ b/src/lay/lay/laySaltController.h @@ -29,6 +29,7 @@ #include "laySalt.h" #include "tlFileSystemWatcher.h" #include "tlDeferredExecution.h" +#include "tlEvents.h" #include #include @@ -171,6 +172,11 @@ public: return m_salt; } + /** + * @brief Event-style version of "salt_changed" + */ + tl::Event salt_changed_event; + /** * @brief Gets the singleton instance for this object */ @@ -182,6 +188,11 @@ private slots: */ void file_watcher_triggered (); + /** + * @brief Emits a salt_changed event + signal + */ + void emit_salt_changed (); + signals: /** * @brief This signal is emitted if the salt changed