diff --git a/.reuse/dep5 b/.reuse/dep5 index 0290a03..8284358 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -23,6 +23,11 @@ Files: *.qrc Copyright: None License: CC0-1.0 +# polkit policy +Files: polkit-1/actions/*.policy +Copyright: None +License: CC0-1.0 + # translations Files: translations/*.ts Copyright: UnionTech Software Technology Co., Ltd. diff --git a/CMakeLists.txt b/CMakeLists.txt index be8bef7..54356f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,5 +72,7 @@ target_link_libraries(${BIN_NAME} PRIVATE ) install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}) +install(FILES scripts/dde-appwiz-uninstaller.sh DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}) +install(FILES polkit-1/actions/org.deepin.dde.appwiz.uninstall.policy DESTINATION ${CMAKE_INSTALL_DATADIR}/polkit-1/actions) install(FILES polkit-1/rules.d/org.deepin.dde.application-wizard.rules DESTINATION ${CMAKE_INSTALL_DATADIR}/polkit-1/rules.d) install(FILES ${TRANSLATED_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/dde-application-wizard/translations) diff --git a/dbus/launcher1compat.cpp b/dbus/launcher1compat.cpp index 8c9ec99..a8dec3e 100644 --- a/dbus/launcher1compat.cpp +++ b/dbus/launcher1compat.cpp @@ -92,31 +92,26 @@ void Launcher1Compat::uninstallPackageKitPackage(const QString & pkgDisplayName, }); } -void Launcher1Compat::onHandleLastoreUninstall(const QDBusMessage &message) +void Launcher1Compat::uninstallPackageByScript(const QString & pkgDisplayName, const QString & packageDesktopFilePath) { - QList arguments = message.arguments(); - - if (3 != arguments.count()) - return; + // call `/usr/libexec/dde-appwiz-uninstaller.sh ` and check the return code. + qDebug() << "Calling dde-appwiz-uninstaller.sh to uninstall" << pkgDisplayName << packageDesktopFilePath << "via script"; + QProcess process; + process.start("/usr/libexec/dde-appwiz-uninstaller.sh", QStringList{packageDesktopFilePath}); + process.waitForFinished(); - QVariantMap changedProps = qdbus_cast(arguments.at(1).value()); - const QStringList keys = changedProps.keys(); + QString standardOutput = process.readAllStandardOutput(); + QString standardError = process.readAllStandardError(); + qDebug() << "stdout:" << standardOutput; + qDebug() << "stderr:" << standardError; - QString status; - if (keys.contains("Status")) { - status = changedProps["Status"].toString(); - } - -#ifdef QT_DEBUG - qInfo() << "changedProps: " << changedProps << ", status: " << status; -#endif - if (status == "succeed" || status == "end") { + if (process.exitCode() != 0) { + sendNotification(pkgDisplayName, false); + } else { + sendNotification(pkgDisplayName, true); QFileInfo fi(m_desktopFilePath); // FIXME: THIS IS NOT DESKTOP ID postUninstallCleanUp(fi.fileName()); - emit UninstallSuccess(m_desktopFilePath); - } else if (status == "failed") { - emit UninstallFailed(m_desktopFilePath, QString()); } } @@ -129,19 +124,13 @@ void Launcher1Compat::RequestUninstall(const QString & desktop, bool unused) // Thus this checking will be no longer necessary. We still need this check since we are // still using lastore to uninstall package if it exists. QString servicePid = QString::number(QDBusConnection::sessionBus().interface()->servicePid(message().service())); - QString procfs = QLatin1String("/proc/%1/cmdline").arg(servicePid); - QFile procfile(procfs); - if (!procfile.exists() || !procfile.open(QFile::ReadOnly)) { - qDebug() << "Cannot verify caller"; - return; - } - QString cmdline(procfile.readAll()); - procfile.close(); - qDebug() << cmdline; + QString procfs = QLatin1String("/proc/%1/exe").arg(servicePid); + QFileInfo procfile(procfs); + QString realPath = procfile.canonicalFilePath(); #ifndef QT_DEBUG - if (!QString(cmdline).endsWith(BINDIR_PREFIX + QStringLiteral("dde-shell")) && - !QString(cmdline).endsWith(BINDIR_PREFIX + QStringLiteral("dde-launchpad"))) { - qWarning() << cmdline << " has no right to uninstall " << desktop; + if (!realPath.endsWith(BINDIR_PREFIX + QStringLiteral("dde-shell")) && + !realPath.endsWith(BINDIR_PREFIX + QStringLiteral("dde-launchpad"))) { + qWarning() << realPath << " has no right to uninstall " << desktop; return; } #endif // !QT_DEBUG @@ -177,22 +166,28 @@ void Launcher1Compat::RequestUninstall(const QString & desktop, bool unused) emit UninstallSuccess(desktopFilePath); sendNotification(desktopEntry.name(), true); } + // TODO: check if it's a flatpak or snap bundle and do the uninstallation? } else { m_packageDisplayName = desktopEntry.name(); - // TODO: check if it's a flatpak or snap bundle and do the uninstallation? + // Uninstall regular package via PackageKit or deepin-store - PKUtils::searchFiles(desktopFilePath, PackageKit::Transaction::FilterInstalled).then([this](const PKUtils::PkPackages packages) { - if (packages.size() == 0) { - qDebug() << "No matching package found"; - return; - } - for (const PKUtils::PkPackage & pkg : packages) { - QString pkgId; - std::tie(std::ignore, pkgId, std::ignore) = pkg; - uninstallPackageKitPackage(m_packageDisplayName, pkgId); - } - }, [](const std::exception & e){ - PKUtils::PkError::printException(e); - }); + if (QFile::exists("/run/ostree-booted")) { + uninstallPackageByScript(m_packageDisplayName, desktopFilePath); + } else { + // call PackageKit to uninstall + PKUtils::searchFiles(desktopFilePath, PackageKit::Transaction::FilterInstalled).then([this](const PKUtils::PkPackages packages) { + if (packages.size() == 0) { + qDebug() << "No matching package found"; + return; + } + for (const PKUtils::PkPackage & pkg : packages) { + QString pkgId; + std::tie(std::ignore, pkgId, std::ignore) = pkg; + uninstallPackageKitPackage(m_packageDisplayName, pkgId); + } + }, [](const std::exception & e){ + PKUtils::PkError::printException(e); + }); + } } } diff --git a/dbus/launcher1compat.h b/dbus/launcher1compat.h index 372f394..d5218d2 100644 --- a/dbus/launcher1compat.h +++ b/dbus/launcher1compat.h @@ -32,7 +32,7 @@ class Launcher1Compat : public QObject, protected QDBusContext explicit Launcher1Compat(QObject *parent = nullptr); void uninstallPackageKitPackage(const QString & pkgDisplayName, const QString & pkPackageId); - void onHandleLastoreUninstall(const QDBusMessage &message); + void uninstallPackageByScript(const QString & pkgDisplayName, const QString & packageDesktopFilePath); Launcher1Adaptor * m_daemonLauncher1Adapter; diff --git a/debian/changelog b/debian/changelog index 889df44..3c12128 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +dde-application-wizard (0.1.11) unstable; urgency=medium + + * Fix uninstall on ostree-booted environment + + -- Wang Zichong Tue, 14 Jan 2025 21:00:00 +0800 + dde-application-wizard (0.1.10) unstable; urgency=medium * Revert "feat: Adapt to uninstall of applications patched by deepin-deb-fix" diff --git a/polkit-1/actions/org.deepin.dde.appwiz.uninstall.policy b/polkit-1/actions/org.deepin.dde.appwiz.uninstall.policy new file mode 100644 index 0000000..11b03c5 --- /dev/null +++ b/polkit-1/actions/org.deepin.dde.appwiz.uninstall.policy @@ -0,0 +1,15 @@ + + + + + Uninstall a package associated with a .desktop file + Authentication is required to uninstall a package. + + auth_admin + auth_admin + auth_admin + + /usr/libexec/dde-appwiz-uninstaller.sh + true + + diff --git a/scripts/dde-appwiz-uninstaller.sh b/scripts/dde-appwiz-uninstaller.sh new file mode 100755 index 0000000..9e42d89 --- /dev/null +++ b/scripts/dde-appwiz-uninstaller.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +# Check if the path to the .desktop file is provided +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +DESKTOP_FILE_PATH="$1" + +# Check if the .desktop file exists +if [ ! -f "$DESKTOP_FILE_PATH" ]; then + echo "Error: File '$DESKTOP_FILE_PATH' does not exist." + exit 1 +fi + +# Use dpkg to find the associated package name +PACKAGE_NAME=$(dpkg -S "$DESKTOP_FILE_PATH" 2>/dev/null | awk -F: '{print $1}' | head -n 1) + +# Check if a package was found +if [ -z "$PACKAGE_NAME" ]; then + echo "Error: No package found for the file '$DESKTOP_FILE_PATH'." + exit 1 +fi + +# Use pkexec to uninstall the package +if pkexec apt purge -y "$PACKAGE_NAME"; then + echo "Package '$PACKAGE_NAME' has been successfully uninstalled." +else + echo "Error: Failed to uninstall the package '$PACKAGE_NAME'." + exit 1 +fi