diff --git a/debian/control b/debian/control index 70b67873..617d1184 100644 --- a/debian/control +++ b/debian/control @@ -133,7 +133,7 @@ Description: Translation files for nymead and plugins - translations Package: nymea-tests -Section: misc +Section: devel Architecture: any Multi-Arch: same Depends: nymea (= ${binary:Version}), diff --git a/libnymea-core/jsonrpc/jsonrpcserver.cpp b/libnymea-core/jsonrpc/jsonrpcserver.cpp index 5745e27b..1bea5280 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserver.cpp @@ -687,7 +687,8 @@ void JsonRPCServer::sendNotification(const QVariantMap ¶ms) Q_ASSERT_X(handler->validateParams(method.name(), params).first, "validating return value", formatAssertion(handler->name(), method.name(), QMetaMethod::Signal, handler, notification).toLatin1().data()); QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact); - qCDebug(dcJsonRpcTraffic()) << "Sending notification:" << data; + qCDebug(dcJsonRpc()) << "Sending notification:" << handler->name() + "." + method.name(); + qCDebug(dcJsonRpcTraffic()) << "Notification content:" << data; foreach (const QUuid &clientId, m_clientNotifications.keys(true)) { m_clientTransports.value(clientId)->sendData(clientId, data); diff --git a/libnymea-core/jsonrpc/jsontypes.cpp b/libnymea-core/jsonrpc/jsontypes.cpp index 08b3ab6e..e7de6f8b 100644 --- a/libnymea-core/jsonrpc/jsontypes.cpp +++ b/libnymea-core/jsonrpc/jsontypes.cpp @@ -404,6 +404,7 @@ void JsonTypes::init() s_package.insert("id", basicTypeToString(QVariant::String)); s_package.insert("displayName", basicTypeToString(QVariant::String)); + s_package.insert("summary", basicTypeToString(QVariant::String)); s_package.insert("installedVersion", basicTypeToString(QVariant::String)); s_package.insert("candidateVersion", basicTypeToString(QVariant::String)); s_package.insert("changelog", basicTypeToString(QVariant::String)); @@ -1290,6 +1291,7 @@ QVariantMap JsonTypes::packPackage(const Package &package) QVariantMap ret; ret.insert("id", package.packageId()); ret.insert("displayName", package.displayName()); + ret.insert("summary", package.summary()); ret.insert("installedVersion", package.installedVersion()); ret.insert("candidateVersion", package.candidateVersion()); ret.insert("changelog", package.changelog()); diff --git a/libnymea-core/jsonrpc/logginghandler.cpp b/libnymea-core/jsonrpc/logginghandler.cpp index c50c6e61..abbeaadf 100644 --- a/libnymea-core/jsonrpc/logginghandler.cpp +++ b/libnymea-core/jsonrpc/logginghandler.cpp @@ -118,7 +118,6 @@ QString LoggingHandler::name() const void LoggingHandler::logEntryAdded(const LogEntry &logEntry) { - qCDebug(dcJsonRpc) << "Notify \"Logging.LogEntryAdded\""; QVariantMap params; params.insert("logEntry", JsonTypes::packLogEntry(logEntry)); emit LogEntryAdded(params); @@ -126,14 +125,11 @@ void LoggingHandler::logEntryAdded(const LogEntry &logEntry) void LoggingHandler::logDatabaseUpdated() { - qCDebug(dcJsonRpc) << "Notify \"Logging.LogDatabaseUpdated\""; emit LogDatabaseUpdated(QVariantMap()); } JsonReply* LoggingHandler::GetLogEntries(const QVariantMap ¶ms) const { - qCDebug(dcJsonRpc) << "Asked for log entries" << params; - LogFilter filter = JsonTypes::unpackLogFilter(params); QVariantList entries; diff --git a/libnymea-core/jsonrpc/systemhandler.cpp b/libnymea-core/jsonrpc/systemhandler.cpp index 23b184a6..40c7e280 100644 --- a/libnymea-core/jsonrpc/systemhandler.cpp +++ b/libnymea-core/jsonrpc/systemhandler.cpp @@ -53,27 +53,63 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): setReturns("Shutdown", returns); params.clear(); returns.clear(); - setDescription("GetPackages", "Get the list of packages currently available to the system. This includes installed and available but not installed packages."); + setDescription("GetUpdateStatus", + "Get the current status of the update system. \"busy\" indicates that the system is current busy with " + "an operation regarding updates. This does not necessarily mean an actual update is running. When this " + "is true, update related functions on the client should be marked as busy and no interaction with update " + "components shall be allowed. An example for such a state is when the system queries the server if there " + "are updates available, typically after a call to CheckForUpdates. \"updateRunning\" on the other hand " + "indicates an actual update process is ongoing. The user should be informed about it, the system also " + "might restart at any point while an update is running."); + setParams("GetUpdateStatus", params); + returns.insert("busy", JsonTypes::basicTypeToString(JsonTypes::Bool)); + returns.insert("updateRunning", JsonTypes::basicTypeToString(JsonTypes::Bool)); + setReturns("GetUpdateStatus", returns); + + params.clear(); returns.clear(); + setDescription("CheckForUpdates", + "Instruct the system to poll the server for updates. Normally the system should automatically do this " + "in regular intervals, however, if the client wants to allow the user to manually check for new updates " + "now, this can be called. Returns true if the operation has been started successfully and the update " + "manager will become busy. In order to know whether there are updates available, clients should walk through " + "the list of packages retrieved from GetPackages and check whether there are packages with the updateAvailable " + "flag set to true."); + setParams("CheckForUpdates", params); + returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); + setReturns("CheckForUpdates", returns); + + params.clear(); returns.clear(); + setDescription("GetPackages", + "Get the list of packages currently available to the system. This might include installed available but " + "not installed packages. Installed packages will have the installedVersion set to a non-empty value."); setParams("GetPackages", params); returns.insert("packages", QVariantList() << JsonTypes::packageRef()); setReturns("GetPackages", returns); params.clear(); returns.clear(); - setDescription("UpdatePackages", "Starts updating/installing packages with the given ids. Returns true if the upgrade has been started successfully. Note that it might still fail later."); + setDescription("UpdatePackages", + "Starts updating/installing packages with the given ids. Returns true if the upgrade has been started " + "successfully. Note that it might still fail later. Before calling this method, clients should " + "check the packages whether they are in a state where they can either be installed (no installedVersion " + "set) or upgraded (updateAvailable set to true)."); params.insert("o:packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); setParams("UpdatePackages", params); returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); setReturns("UpdatePackages", returns); params.clear(); returns.clear(); - setDescription("RollbackPackages", "Starts a rollback. Returns true if the rollback has been started successfully."); + setDescription("RollbackPackages", + "Starts a rollback. Returns true if the rollback has been started successfully. Before calling this " + "method, clients should check whether the package can be rolled back (canRollback set to true)."); params.insert("packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); setParams("RollbackPackages", params); returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); setReturns("RollbackPackages", returns); params.clear(); returns.clear(); - setDescription("RemovePackages", "Starts removing a package. Returns true if the removal has been started successfully."); + setDescription("RemovePackages", + "Starts removing a package. Returns true if the removal has been started successfully. Before calling " + "this method, clients should check whether the package can be removed (canRemove set to true)."); params.insert("packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); setParams("RemovePackages", params); returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); @@ -103,6 +139,7 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): params.clear(); setDescription("UpdateStatusChanged", "Emitted whenever the update status changes."); + params.insert("busy", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("updateRunning", JsonTypes::basicTypeToString(JsonTypes::Bool)); setParams("UpdateStatusChanged", params); @@ -139,8 +176,15 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): connect(m_platform->systemController(), &PlatformSystemController::availableChanged, this, &SystemHandler::onCapabilitiesChanged); connect(m_platform->updateController(), &PlatformUpdateController::availableChanged, this, &SystemHandler::onCapabilitiesChanged); + connect(m_platform->updateController(), &PlatformUpdateController::busyChanged, this, [this](){ + QVariantMap params; + params.insert("busy", m_platform->updateController()->busy()); + params.insert("updateRunning", m_platform->updateController()->updateRunning()); + emit UpdateStatusChanged(params); + }); connect(m_platform->updateController(), &PlatformUpdateController::updateRunningChanged, this, [this](){ QVariantMap params; + params.insert("busy", m_platform->updateController()->busy()); params.insert("updateRunning", m_platform->updateController()->updateRunning()); emit UpdateStatusChanged(params); }); @@ -212,10 +256,20 @@ JsonReply *SystemHandler::GetUpdateStatus(const QVariantMap ¶ms) const { Q_UNUSED(params) QVariantMap ret; + ret.insert("busy", m_platform->updateController()->updateRunning()); ret.insert("updateRunning", m_platform->updateController()->updateRunning()); return createReply(ret); } +JsonReply *SystemHandler::CheckForUpdates(const QVariantMap ¶ms) const +{ + Q_UNUSED(params) + QVariantMap ret; + bool success = m_platform->updateController()->checkForUpdates(); + ret.insert("success", success); + return createReply(ret); +} + JsonReply *SystemHandler::GetPackages(const QVariantMap ¶ms) const { Q_UNUSED(params) diff --git a/libnymea-core/jsonrpc/systemhandler.h b/libnymea-core/jsonrpc/systemhandler.h index 727d4465..36dc09df 100644 --- a/libnymea-core/jsonrpc/systemhandler.h +++ b/libnymea-core/jsonrpc/systemhandler.h @@ -43,6 +43,7 @@ public: Q_INVOKABLE JsonReply *Shutdown(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *GetUpdateStatus(const QVariantMap ¶ms) const; + Q_INVOKABLE JsonReply *CheckForUpdates(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *GetPackages(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *UpdatePackages(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *RollbackPackages(const QVariantMap ¶ms) const; diff --git a/libnymea/platform/package.cpp b/libnymea/platform/package.cpp index 5b45cbfb..195205ec 100644 --- a/libnymea/platform/package.cpp +++ b/libnymea/platform/package.cpp @@ -42,6 +42,16 @@ QString Package::displayName() const return m_displayName; } +QString Package::summary() const +{ + return m_summary; +} + +void Package::setSummary(const QString &summary) +{ + m_summary = summary; +} + QString Package::installedVersion() const { return m_installedVersion; @@ -106,6 +116,7 @@ bool Package::operator==(const Package &other) const { return m_packageId == other.packageId() && m_displayName == other.displayName() && + m_summary == other.summary() && m_installedVersion == other.installedVersion() && m_candidateVersion == other.candidateVersion() && m_changeLog == other.changelog() && diff --git a/libnymea/platform/package.h b/libnymea/platform/package.h index a4f693cc..a0c90ab1 100644 --- a/libnymea/platform/package.h +++ b/libnymea/platform/package.h @@ -32,6 +32,10 @@ public: QString packageId() const; QString displayName() const; + + QString summary() const; + void setSummary(const QString &summary); + QString installedVersion() const; void setInstalledVersion(const QString &installedVersion); @@ -56,6 +60,7 @@ public: private: QString m_packageId; QString m_displayName; + QString m_summary; QString m_installedVersion; QString m_candidateVersion; QString m_changeLog; diff --git a/libnymea/platform/platformupdatecontroller.cpp b/libnymea/platform/platformupdatecontroller.cpp index 553ea2ec..00c997cc 100644 --- a/libnymea/platform/platformupdatecontroller.cpp +++ b/libnymea/platform/platformupdatecontroller.cpp @@ -27,48 +27,134 @@ PlatformUpdateController::PlatformUpdateController(QObject *parent) : QObject(pa } -/*! Override this to indicate whether update management is available. Defaults to false. - When a plugin returns true here, it is assumed that the system is capable of updating and nymea - has permissions to do so. +/*! Whether or not the update management is available. Returns true if the system is ready + to perform any upgrade tasks. When the return value is true, it is assumed that the + system is capable of updating and nymea has permissions to do so. + + A backend plugin should override this to indicate whether update management is available. Defaults to false. + If the update mechanism becomes available during runtime, \l{availableChanged()} should be emitted + to indicate the change. */ -bool PlatformUpdateController::updateManagementAvailable() +bool PlatformUpdateController::updateManagementAvailable() const { return false; } +/*! Triggers a cache update on the update system, e.g. call "apt-get update" on the system. + + A backend plugin may override this to to allow the system triggering package manager cache updates. + */ +bool PlatformUpdateController::checkForUpdates() +{ + return false; +} + +/*! Indicates whether the update system is busy. This might be the case when \l{checkForUpdates()} or + \l{enableRepository()} are called. In general, this indicates a state where the update system + is working and might not be ready to take additional requests. Clients should not perform any operations + on the upgrade system while this is true. + + A backend plugin may override this and return true when appropriate. For instance if \l{checkForUpdates()} + is a long-running task and the client should be informed about it being worked on. Additionally, + whenever the value changes \l{busyChanged()} should be emitted. + */ +bool PlatformUpdateController::busy() const +{ + return false; +} + +/*! Indicates whether an update is running. While this is true, clients should not perform + any operations on the upgrade system and in general expect the system to go down for + restart any moment. This flag can be used by clients to indicate the running update + and may restrict interaction with the system. + + A backend plugin should override this and return true when an update is running. Additionally. + whenever the value changes, \l{updateRunningChanged()} should be emitted. + */ bool PlatformUpdateController::updateRunning() const { return false; } +/*! Returns a list of packages availabe in the system. If a backend supports installation of new packages, + the list of packages may contain not installed packages. Such packages are marked by + returning an empty \l{Package::installedVersion()}. If the backend supports removal + of installed packages, uninstallable packages are marked with \l{Package::canRemove()}. + Packages that can be updated or rolled back will be marked with \l{Package::updateAvailable()} + and \l{Package::rollbackAvailable()}. + + A backend plugin should override this and return the list of all packages available in the system + filling in \l{Package} details as described above. + + */ QList PlatformUpdateController::packages() const { return {}; } +/*! Returns a list of all optional repositories available in the system. Such repositories + can be enabled or disabled in order to follow prereleases. + + A backend plugin may override this if enabling different repositories is supported. + */ QList PlatformUpdateController::repositories() const { return {}; } +/*! Starts upgrading the packages with the given \a packageIds. If \a packageIds is an empty + list, a full system upgrade will be performed. Use \l {Package::updateAvailable()} + to find packages with available upgrades. Passing packageIds for packages which are not + installed at this time will install the packages, provided the backend supports package + installation. If \l{canInstallPackages()} is false, only installed packages should + be provided for upgrades. The return value indicates whether the update has been started or not. + + A backend plugin should override this and start the system upgrades indicating success in + the return value. Additionally, once the update procedure has started, it should emit + \l {updateRunningChanged()} and \l {updateRunning()} should return true. + */ bool PlatformUpdateController::startUpdate(const QStringList &packageIds) { Q_UNUSED(packageIds) return false; } +/*! Starts a rollback of the packages with the given \a packageIds. Use \l {Package::rollbackAvailable()} + to find packages with available rollbacks. + + A backend plugin should override this and start the rollback process indicating success in + the return value. Once the rollback procedure has started, it should emit + \l {updateRunningChanged()} and \l {updateRunning()} should return true. + */ bool PlatformUpdateController::rollback(const QStringList &packageIds) { Q_UNUSED(packageIds) return false; } +/*! Starts the removal of the packages with the given \a packageIds. Use \l {Package::installedVersion()} + to find packages which are currently installed. Check \l{Package::canRemove()} to see whether a package + can be removed or not. + + A backend plugin should override this and start the removal process indicating success in + the return value. Once the removal procedure has started, it should emit + \l {updateRunningChanged()} and \l {updateRunning()} should return true. + */ bool PlatformUpdateController::removePackages(const QStringList &packageIds) { Q_UNUSED(packageIds) return false; } +/*! Enables or disables the given \l{Repository} in the system. The return value indicates whether + the request has been started successfully or not. Upon successful completion of the request, + \l{repositoryChanged()} signals should be emitted. + + A backend plugin should override this if multiple install repositories are supported (e.g. if + \l{repositories()} returns a non-empty list) and perform the requested operation. If enabling/disabling + a repository implies the immediate upgrade/downgrade of packages, \l{updateRunning()} should be + marked accordingly. + */ bool PlatformUpdateController::enableRepository(const QString &repositoryId, bool enabled) { Q_UNUSED(repositoryId) diff --git a/libnymea/platform/platformupdatecontroller.h b/libnymea/platform/platformupdatecontroller.h index 8dc5fdc5..d63a1622 100644 --- a/libnymea/platform/platformupdatecontroller.h +++ b/libnymea/platform/platformupdatecontroller.h @@ -35,8 +35,10 @@ public: explicit PlatformUpdateController(QObject *parent = nullptr); virtual ~PlatformUpdateController() = default; - virtual bool updateManagementAvailable(); + virtual bool updateManagementAvailable() const; + virtual bool checkForUpdates(); + virtual bool busy() const; virtual bool updateRunning() const; virtual QList packages() const; @@ -50,6 +52,7 @@ public: signals: void availableChanged(); + void busyChanged(); void updateRunningChanged(); void packageAdded(const Package &pacakge); void packageChanged(const Package &package); diff --git a/tests/auto/api.json b/tests/auto/api.json index e3330909..cc69dfdc 100644 --- a/tests/auto/api.json +++ b/tests/auto/api.json @@ -867,6 +867,14 @@ "o:stateType": "$ref:StateType" } }, + "System.CheckForUpdates": { + "description": "Instruct the system to poll the server for updates. Normally the system should automatically do this in regular intervals, however, if the client wants to allow the user to manually check for new updates now, this can be called. Returns true if the operation has been started successfully and the update manager will become busy. In order to know whether there are updates available, clients should walk through the list of packages retrieved from GetPackages and check whether there are packages with the updateAvailable flag set to true.", + "params": { + }, + "returns": { + "success": "Bool" + } + }, "System.EnableRepository": { "description": "Enable or disable a repository.", "params": { @@ -887,7 +895,7 @@ } }, "System.GetPackages": { - "description": "Get the list of packages currently available to the system. This includes installed and available but not installed packages.", + "description": "Get the list of packages currently available to the system. This might include installed available but not installed packages. Installed packages will have the installedVersion set to a non-empty value.", "params": { }, "returns": { @@ -906,6 +914,15 @@ ] } }, + "System.GetUpdateStatus": { + "description": "Get the current status of the update system. \"busy\" indicates that the system is current busy with an operation regarding updates. This does not necessarily mean an actual update is running. When this is true, update related functions on the client should be marked as busy and no interaction with update components shall be allowed. An example for such a state is when the system queries the server if there are updates available, typically after a call to CheckForUpdates. \"updateRunning\" on the other hand indicates an actual update process is ongoing. The user should be informed about it, the system also might restart at any point while an update is running.", + "params": { + }, + "returns": { + "busy": "Bool", + "updateRunning": "Bool" + } + }, "System.Reboot": { "description": "Initiate a reboot of the system. The return value will indicate whether the procedure has been initiated successfully.", "params": { @@ -915,7 +932,7 @@ } }, "System.RemovePackages": { - "description": "Starts removing a package. Returns true if the removal has been started successfully.", + "description": "Starts removing a package. Returns true if the removal has been started successfully. Before calling this method, clients should check whether the package can be removed (canRemove set to true).", "params": { "packageIds": [ "String" @@ -926,7 +943,7 @@ } }, "System.RollbackPackages": { - "description": "Starts a rollback. Returns true if the rollback has been started successfully.", + "description": "Starts a rollback. Returns true if the rollback has been started successfully. Before calling this method, clients should check whether the package can be rolled back (canRollback set to true).", "params": { "packageIds": [ "String" @@ -945,7 +962,7 @@ } }, "System.UpdatePackages": { - "description": "Starts updating/installing packages with the given ids. Returns true if the upgrade has been started successfully. Note that it might still fail later.", + "description": "Starts updating/installing packages with the given ids. Returns true if the upgrade has been started successfully. Note that it might still fail later. Before calling this method, clients should check the packages whether they are in a state where they can either be installed (no installedVersion set) or upgraded (updateAvailable set to true).", "params": { "o:packageIds": [ "String" @@ -1261,6 +1278,7 @@ "System.UpdateStatusChanged": { "description": "Emitted whenever the update status changes.", "params": { + "busy": "Bool", "updateRunning": "Bool" } }, @@ -1543,6 +1561,7 @@ "id": "String", "installedVersion": "String", "rollbackAvailable": "Bool", + "summary": "String", "updateAvailable": "Bool" }, "Param": {