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:
+
+
+
+ - _install.lym: if present, this script is executed after the package is installed.
+ - _uninstall.lym: if present, this script is executed before the 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