diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -382,6 +382,8 @@ install(TARGETS kcm_dolphinservices DESTINATION ${KDE_INSTALL_PLUGINDIR} ) install(TARGETS kcm_dolphingeneral DESTINATION ${KDE_INSTALL_PLUGINDIR} ) +add_subdirectory(settings/services/servicemenuinstaller) + ########### install files ############### install( PROGRAMS org.kde.dolphin.desktop DESTINATION ${KDE_INSTALL_APPDIR} ) @@ -405,8 +407,6 @@ install( FILES settings/kcm/kcmdolphinservices.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) install( FILES settings/kcm/kcmdolphingeneral.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) install( FILES settings/services/servicemenu.knsrc DESTINATION ${KDE_INSTALL_CONFDIR} ) -install( PROGRAMS settings/services/servicemenuinstallation DESTINATION ${KDE_INSTALL_BINDIR} ) -install( PROGRAMS settings/services/servicemenudeinstallation DESTINATION ${KDE_INSTALL_BINDIR} ) if(BUILD_TESTING) find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) diff --git a/src/settings/services/servicemenu.knsrc b/src/settings/services/servicemenu.knsrc --- a/src/settings/services/servicemenu.knsrc +++ b/src/settings/services/servicemenu.knsrc @@ -5,5 +5,5 @@ SignaturePolicy=ifpossible TargetDir=servicemenu-download Uncompress=never -InstallationCommand=servicemenuinstallation %f -UninstallCommand=servicemenudeinstallation %f +InstallationCommand=servicemenuinstaller install %f +UninstallCommand=servicemenuinstaller uninstall %f diff --git a/src/settings/services/servicemenudeinstallation b/src/settings/services/servicemenudeinstallation deleted file mode 100755 --- a/src/settings/services/servicemenudeinstallation +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env ruby - -# Copyright (C) 2009 Jonathan Schmidt-Dominé -# Copyright (C) 2019 Harald Sitter -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -require 'fileutils' - -ARCHIVE = ARGV[0] - -# @param log_msg [String] error that gets logged to CLI -def fail(log_msg: nil) - # FIXME: this is not translated... - msg = 'Dolphin service menu installation failed' - warn log_msg if log_msg - system('kdialog', '--passivepopup', msg, '15') - abort -end - -if ARCHIVE.end_with?('.desktop') - data_location = `qtpaths --writable-path GenericDataLocation`.strip - unless $?.success? - fail(log_msg: "Could not get GenericDataLocation #{data_location}") - end - FileUtils.rm("#{data_location}/kservices5/ServiceMenus/#{File.basename(ARCHIVE)}") - exit(0) -end -dir = "#{ARCHIVE}-dir" - -deinstaller = nil -%w[deinstall.sh deinstall].find do |script| - deinstaller = Dir.glob("#{dir}/**/#{script}")[0] -end - -installer = nil -%w[install-it.sh install-it installKDE4.sh installKDE4 install.sh install].find do |script| - installer = Dir.glob("#{dir}/**/#{script}")[0] -end - -Dir.chdir(dir) do - deinstalled = false - - [deinstaller, installer].uniq.compact.each { |f| File.chmod(0o700, f) } - - if deinstaller - puts "[servicemenudeinstallation]: Trying to run deinstaller #{deinstaller}" - deinstalled = system(deinstaller) - elsif installer - puts "[servicemenudeinstallation]: Trying to run installer #{installer}" - %w[--remove --delete --uninstall --deinstall].any? do |arg| - deinstalled = system(installer, arg) - end - end - - fail unless deinstalled -end - -FileUtils.rm_r(dir) diff --git a/src/settings/services/servicemenuinstallation b/src/settings/services/servicemenuinstallation deleted file mode 100755 --- a/src/settings/services/servicemenuinstallation +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/env ruby - -# Copyright (C) 2009 Jonathan Schmidt-Dominé -# Copyright (C) 2019 Harald Sitter -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -require 'fileutils' - -ARCHIVE_UNCOMPRESSORS = { - 'application/x-tar' => :"tar -xf %s -C %s", - 'application/tar' => :"tar -xf %s -C %s", - 'application/x-gzip' => :"tar -zxf %s -C %s", - 'application/gzip' => :"tar -zxf %s -C %s", - 'application/x-gzip-compressed-tar' => :"tar -zxf %s -C %s", - 'application/gzip-compressed-tar' => :"tar -zxf %s -C %s", - 'application/x-gzip-compressed' => :"tar -zxf %s -C %s", - 'application/gzip-compressed' => :"tar -zxf %s -C %s", - 'application/bzip' => :"tar -jxf %s -C %s", - 'application/bzip2' => :"tar -jxf %s -C %s", - 'application/x-bzip' => :"tar -jxf %s -C %s", - 'application/x-bzip2' => :"tar -jxf %s -C %s", - 'application/bzip-compressed' => :"tar -jxf %s -C %s", - 'application/bzip2-compressed' => :"tar -jxf %s -C %s", - 'application/x-bzip-compressed' => :"tar -jxf %s -C %s", - 'application/x-bzip2-compressed' => :"tar -jxf %s -C %s", - 'application/bzip-compressed-tar' => :"tar -jxf %s -C %s", - 'application/bzip2-compressed-tar' => :"tar -jxf %s -C %s", - 'application/x-bzip-compressed-tar' => :"tar -jxf %s -C %s", - 'application/x-bzip2-compressed-tar' => :"tar -jxf %s -C %s", - 'application/zip' => :"unzip %s -d %s", - 'application/x-zip' => :"unzip %s -d %s", - 'application/x-zip-compressed' => :"unzip %s -d %s", - 'multipart/x-zip' => :"unzip %s -d %s", - 'application/tgz' => :"tar -zxf %s -C %s", - 'application/x-compressed-gtar' => :"tar -zxf %s -C %s", - 'file/tgz' => :"tar -zxf %s -C %s", - 'multipart/x-tar-gz' => :"tar -zxf %s -C %s", - 'application/x-gunzip' => :"tar -zxf %s -C %s", - 'application/gzipped' => :"tar -zxf %s -C %s", - 'gzip/document' => :"tar -zxf %s -C %s", - 'application/x-bz2 ' => :"tar -jxf %s -C %s", - 'application/x-gtar' => :"tar -xf %s -C %s", - 'multipart/x-tar' => :"tar -xf %s -C %s" -} - -ARCHIVE = ARGV[0] - -# @param log_msg [String] error that gets logged to CLI -def fail(log_msg: nil) - # FIXME: this is not translated... - msg = 'Dolphin service menu installation failed' - warn log_msg if log_msg - system('kdialog', '--passivepopup', msg, '15') - abort -end - -def mime_type(filename) - ret = `xdg-mime query filetype #{filename}`.strip - return ret if $?.success? - - warn 'Failed to xdg-mime' - fail(log_msg: "Failed to xdg-mime #{filename}: #{ret}") -end - -def uncompress(filename, output) - uncompressor = ARCHIVE_UNCOMPRESSORS.fetch(mime_type(filename)).to_s - system(format(uncompressor, filename, output)) -rescue KeyError => e - # If a mimetype doesn't have an uncompressor mapped we'll get a keyerror. - # we'll log the error but visually report the failure. - fail(log_msg: "Unmapped compression format #{filename}; #{e.message}") -end - -data_location = `qtpaths --writable-path GenericDataLocation`.strip -unless $?.success? - fail(log_msg: "Could not get GenericDataLocation #{data_location}") -end -servicedir = "#{data_location}/kservices5/ServiceMenus/" - -FileUtils.mkdir_p(servicedir) unless File.exist?(servicedir) -if ARCHIVE.end_with?('.desktop') - puts 'Single-File Service-Menu' - puts ARCHIVE - puts servicedir - FileUtils.cp(ARCHIVE, servicedir) - exit -end - -dir = "#{ARCHIVE}-dir" - -FileUtils.rm_r(dir) if File.exist?(dir) -FileUtils.mkdir(dir) - -fail(log_msg: 'uncompress failed') unless uncompress(ARCHIVE, dir) - -install_it = nil -%w[install-it.sh install-it].find do |script| - install_it = Dir.glob("#{dir}/**/#{script}")[0] -end - -installer = nil -%w[installKDE4.sh installKDE4 install.sh install].find do |script| - installer = Dir.glob("#{dir}/**/#{script}")[0] -end - -Dir.chdir(dir) do - installed = false - - [install_it, installer].uniq.compact.each { |f| File.chmod(0o700, f) } - - if install_it - puts "[servicemenuinstallation]: Trying to run install_it #{install_it}" - installed = system(install_it) - elsif installer - puts "[servicemenuinstallation]: Trying to run installer #{installer}" - %w[--local --local-install --install].any? do |arg| - installed = system(installer, arg) - end - end - - fail unless installed -end diff --git a/src/settings/services/servicemenuinstaller/CMakeLists.txt b/src/settings/services/servicemenuinstaller/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/src/settings/services/servicemenuinstaller/CMakeLists.txt @@ -0,0 +1,9 @@ +remove_definitions(-DTRANSLATION_DOMAIN=\"dolphin\") +add_definitions(-DTRANSLATION_DOMAIN=\"dolphin_servicemenuinstaller\") + +add_executable(servicemenuinstaller servicemenuinstaller.cpp) +target_link_libraries(servicemenuinstaller PRIVATE + Qt5::Core + KF5::I18n +) +install(TARGETS servicemenuinstaller ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/settings/services/servicemenuinstaller/Messages.sh b/src/settings/services/servicemenuinstaller/Messages.sh new file mode 100755 --- /dev/null +++ b/src/settings/services/servicemenuinstaller/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT `find . -name \*.cpp` -o $podir/dolphin_servicemenuinstaller.pot diff --git a/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp new file mode 100644 --- /dev/null +++ b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp @@ -0,0 +1,383 @@ +/*************************************************************************** + * Copyright © 2019 Alexander Potashev * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License or (at your option) version 3 or any later version * + * accepted by the membership of KDE e.V. (or its successor approved * + * by the membership of KDE e.V.), which shall act as a proxy * + * defined in Section 14 of version 3 of the license. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +// @param msg Error that gets logged to CLI +[[noreturn]] void fail(const QString &str) +{ + qCritical() << str; + + QProcess process; + auto args = QStringList{"--passivepopup", i18n("Dolphin service menu installation failed"), "15"}; + process.start("kdialog", args, QIODevice::ReadOnly); + if (!process.waitForStarted()) { + qFatal("Failed to run kdialog"); + } + + exit(1); +} + +bool evaluateShell(const QString &program, const QStringList &arguments, QString &output, QString &errorText) +{ + QProcess process; + process.start(program, arguments, QIODevice::ReadOnly); + if (!process.waitForStarted()) { + fail(i18n("Failed to run process: %1 %2", program, arguments.join(" "))); + } + + if (!process.waitForFinished()) { + fail(i18n("Process did not finish in reasonable time: %1 %2", program, arguments.join(" "))); + } + + const auto stdoutResult = QString::fromUtf8(process.readAllStandardOutput()).trimmed(); + const auto stderrResult = QString::fromUtf8(process.readAllStandardError()).trimmed(); + + if (process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0) { + output = stdoutResult; + return true; + } else { + errorText = stderrResult + stdoutResult; + return false; + } +} + +QString mimeType(const QString &path) +{ + QString result; + QString errorText; + if (evaluateShell("xdg-mime", QStringList{"query", "filetype", path}, result, errorText)) { + return result; + } else { + fail(i18n("Failed to run xdg-mime %1: %2", path, errorText)); + } +} + +QString getServiceMenusDir() +{ + const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); + return QDir(dataLocation).absoluteFilePath("kservices5/ServiceMenus"); +} + +struct UncompressCommand +{ + QString command; + QStringList args1; + QStringList args2; +}; + +void runUncompress(const QString &inputPath, const QString &outputPath) { + QList> mimeTypeToCommand; + mimeTypeToCommand.append({QStringList{"application/x-tar", "application/tar", "application/x-gtar", + "multipart/x-tar"}, + UncompressCommand{"tar", QStringList() << "-xf", QStringList() << "-C"}}); + mimeTypeToCommand.append({QStringList{"application/x-gzip", "application/gzip", + "application/x-gzip-compressed-tar", "application/gzip-compressed-tar", + "application/x-gzip-compressed", "application/gzip-compressed", + "application/tgz", "application/x-compressed-tar", + "application/x-compressed-gtar", "file/tgz", + "multipart/x-tar-gz", "application/x-gunzip", "application/gzipped", + "gzip/document"}, + UncompressCommand{"tar", QStringList{"-zxf"}, QStringList{"-C"}}}); + mimeTypeToCommand.append({QStringList{"application/bzip", "application/bzip2", "application/x-bzip", + "application/x-bzip2", "application/bzip-compressed", + "application/bzip2-compressed", "application/x-bzip-compressed", + "application/x-bzip2-compressed", "application/bzip-compressed-tar", + "application/bzip2-compressed-tar", "application/x-bzip-compressed-tar", + "application/x-bzip2-compressed-tar", "application/x-bz2"}, + UncompressCommand{"tar", QStringList{"-jxf"}, QStringList{"-C"}}}); + mimeTypeToCommand.append({QStringList{"application/zip", "application/x-zip", "application/x-zip-compressed", + "multipart/x-zip"}, + UncompressCommand{"unzip", QStringList{}, QStringList{"-d"}}}); + + const auto mime = mimeType(inputPath); + + UncompressCommand command{}; + for (const auto &pair : mimeTypeToCommand) { + if (pair.first.contains(mime)) { + command = pair.second; + break; + } + } + + if (command.command.isEmpty()) { + fail(i18n("Unsupported archive type %1: %2", mime, inputPath)); + } + + QProcess process; + process.start( + command.command, + QStringList() << command.args1 << inputPath << command.args2 << outputPath, + QIODevice::NotOpen); + if (!process.waitForStarted()) { + fail(i18n("Failed to run uncompressor command for %1", inputPath)); + } + + if (!process.waitForFinished()) { + fail( + i18n("Process did not finish in reasonable time: %1 %2", process.program(), process.arguments().join(" "))); + } + + if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) { + fail(i18n("Failed to uncompress %1", inputPath)); + } +} + +QString findRecursive(const QString &dir, const QString &basename) +{ + QDirIterator it(dir, QStringList{basename}, QDir::Files, QDirIterator::Subdirectories); + while (it.hasNext()) { + return QFileInfo(it.next()).canonicalFilePath(); + } + + return QString(); +} + +bool runInstallerScriptOnce(const QString &path, const QStringList &args, const QString &dir) +{ + QProcess process; + process.setWorkingDirectory(dir); + process.start(path, args, QIODevice::NotOpen); + if (!process.waitForStarted()) { + fail(i18n("Failed to run installer script %1", path)); + } + + // Wait until installer exits, without timeout + if (!process.waitForFinished(-1)) { + qWarning() << "Failed to wait on installer:" << process.program() << process.arguments().join(" "); + return false; + } + + if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) { + qWarning() << "Installer script exited with error:" << process.program() << process.arguments().join(" "); + return false; + } + + return true; +} + +// If hasArgVariants is true, run "path". +// If hasArgVariants is false, run "path argVariants[i]" until successful. +bool runInstallerScript(const QString &path, bool hasArgVariants, const QStringList &argVariants, const QString &dir, + QString &errorText) +{ + QFile file(path); + if (!file.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)) { + errorText = i18n("Failed to set permissions on %1: %2", path, file.errorString()); + return false; + } + + qInfo() << "[servicemenuinstaller]: Trying to run installer/uninstaller" << path; + if (hasArgVariants) { + for (const auto &arg : argVariants) { + if (runInstallerScriptOnce(path, QStringList{arg}, dir)) { + return true; + } + } + } else { + if (runInstallerScriptOnce(path, QStringList{}, dir)) { + return true; + } + } + + errorText = i18nc( + "%1 = comma separated list of arguments", + "Installer script %1 failed, tried arguments \"%1\".", path, argVariants.join(i18nc("Separator between arguments", "\", \""))); + return false; +} + +QString generateDirPath(const QString &archive) +{ + return QStringLiteral("%1-dir").arg(archive); +} + +bool cmdInstall(const QString &archive, QString &errorText) +{ + const auto serviceDir = getServiceMenusDir(); + if (!QDir().mkpath(serviceDir)) { + // TODO Cannot get error string because of this bug: https://bugreports.qt.io/browse/QTBUG-1483 + errorText = i18n("Failed to create path %1", serviceDir); + return false; + } + + if (archive.endsWith(".desktop")) { + // Append basename to destination directory + const auto dest = QDir(serviceDir).absoluteFilePath(QFileInfo(archive).fileName()); + qInfo() << "Single-File Service-Menu" << archive << dest; + + QFile source(archive); + if (!source.copy(dest)) { + errorText = i18n("Failed to copy .desktop file %1 to %2: %3", archive, dest, source.errorString()); + return false; + } + } else { + const QString dir = generateDirPath(archive); + if (QFile::exists(dir)) { + if (!QDir(dir).removeRecursively()) { + errorText = i18n("Failed to remove directory %1", dir); + return false; + } + } + + if (QDir().mkdir(dir)) { + errorText = i18n("Failed to create directory %1", dir); + } + + runUncompress(archive, dir); + + // Try "install-it" first + QString installItPath; + for (const auto &basename : QStringList{"install-it.sh", "install-it"}) { + const auto path = findRecursive(dir, basename); + if (!path.isEmpty()) { + installItPath = path; + break; + } + } + + if (!installItPath.isEmpty()) { + return runInstallerScript(installItPath, false, QStringList{}, dir, errorText); + } + + // If "install-it" is missing, try "install" + QString installerPath; + for (const auto &basename : QStringList{"installKDE4.sh", "installKDE4", "install.sh", "install"}) { + const auto path = findRecursive(dir, basename); + if (!path.isEmpty()) { + installerPath = path; + break; + } + } + + if (!installerPath.isEmpty()) { + return runInstallerScript(installerPath, true, QStringList{"--local", "--local-install", "--install"}, dir, errorText); + } + + fail(i18n("Failed to find an installation script in %1", dir)); + } + + return true; +} + +bool cmdUninstall(const QString &archive, QString &errorText) +{ + const auto serviceDir = getServiceMenusDir(); + if (archive.endsWith(".desktop")) { + // Append basename to destination directory + const auto dest = QDir(serviceDir).absoluteFilePath(QFileInfo(archive).fileName()); + QFile file(dest); + if (!file.remove()) { + errorText = i18n("Failed to remove .desktop file %1: %2", dest, file.errorString()); + return false; + } + } else { + const QString dir = generateDirPath(archive); + + // Try "deinstall" first + QString deinstallPath; + for (const auto &basename : QStringList{"deinstall.sh", "deinstall"}) { + const auto path = findRecursive(dir, basename); + if (!path.isEmpty()) { + deinstallPath = path; + break; + } + } + + if (!deinstallPath.isEmpty()) { + bool ok = runInstallerScript(deinstallPath, false, QStringList{}, dir, errorText); + if (!ok) { + return ok; + } + } else { + // If "deinstall" is missing, try "install --uninstall" + + QString installerPath; + for (const auto &basename : QStringList{"install-it.sh", "install-it", "installKDE4.sh", + "installKDE4", "install.sh", "install"}) { + const auto path = findRecursive(dir, basename); + if (!path.isEmpty()) { + installerPath = path; + break; + } + } + + if (!installerPath.isEmpty()) { + bool ok = runInstallerScript( + installerPath, true, QStringList{"--remove", "--delete", "--uninstall", "--deinstall"}, dir, errorText); + if (!ok) { + return ok; + } + } else { + fail(i18n("Failed to find an uninstallation script in %1", dir)); + } + } + + QDir dirObject(dir); + if (!dirObject.removeRecursively()) { + errorText = i18n("Failed to remove directory %1", dir); + return false; + } + } + + return true; +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + QCommandLineParser parser; + parser.addPositionalArgument(QStringLiteral("command"), i18nc("@info:shell", "Command to execute: install or uninstall.")); + parser.addPositionalArgument(QStringLiteral("path"), i18nc("@info:shell", "Path to archive.")); + parser.process(app); + + const QStringList args = parser.positionalArguments(); + if (args.isEmpty()) { + fail(i18n("Command is required.")); + } + if (args.size() == 1) { + fail(i18n("Path to archive is required.")); + } + + const QString cmd = args[0]; + const QString archive = args[1]; + + QString errorText; + if (cmd == "install") { + if (!cmdInstall(archive, errorText)) { + fail(errorText); + } + } else if (cmd == "uninstall") { + if (!cmdUninstall(archive, errorText)) { + fail(errorText); + } + } else { + fail(i18n("Unsupported command %1", cmd)); + } + + return 0; +} diff --git a/src/settings/services/test/service_menu_deinstallation_test.rb b/src/settings/services/test/service_menu_deinstallation_test.rb --- a/src/settings/services/test/service_menu_deinstallation_test.rb +++ b/src/settings/services/test/service_menu_deinstallation_test.rb @@ -51,7 +51,7 @@ touch #{@tmpdir}/install.sh-run INSTALL_SH - assert(covered_system('servicemenudeinstallation', archive_base)) + assert(system('servicemenuinstaller', 'uninstall', archive_base)) # deinstaller should be run # installer should not be run @@ -77,7 +77,7 @@ exit 1 INSTALL_SH - assert(covered_system('servicemenudeinstallation', archive_base)) + assert(system('servicemenuinstaller', 'uninstall', archive_base)) assert_path_not_exist('deinstall.sh-run') assert_path_exist('install.sh-run') @@ -91,7 +91,7 @@ archive_dir = "#{archive_base}-dir/foo-1.1/" FileUtils.mkpath(archive_dir) - refute(covered_system('servicemenudeinstallation', archive_base)) + refute(system('servicemenuinstaller', 'uninstall', archive_base)) # I am unsure if deinstallation really should keep the files around. But # that's how it behaved originally so it's supposedly intentional @@ -113,7 +113,7 @@ FileUtils.mkpath(menu_dir) FileUtils.touch(installed_file) - assert(covered_system('servicemenudeinstallation', downloaded_file)) + assert(system('servicemenuinstaller', 'uninstall', downloaded_file)) assert_path_exist(downloaded_file) assert_path_not_exist(installed_file) diff --git a/src/settings/services/test/service_menu_installation_test.rb b/src/settings/services/test/service_menu_installation_test.rb --- a/src/settings/services/test/service_menu_installation_test.rb +++ b/src/settings/services/test/service_menu_installation_test.rb @@ -54,7 +54,7 @@ INSTALL_SH assert(system('tar', '-cf', archive, archive_dir)) - assert(covered_system('servicemenuinstallation', archive)) + assert(system('servicemenuinstaller', 'install', archive)) tar_dir = "#{service_dir}/foo.tar-dir" tar_extract_dir = "#{service_dir}/foo.tar-dir/foo" @@ -81,7 +81,7 @@ INSTALL_SH assert(system('tar', '-cf', archive, archive_dir)) - assert(covered_system('servicemenuinstallation', archive)) + assert(system('servicemenuinstaller', 'install', archive)) tar_dir = "#{service_dir}/foo.tar-dir" tar_extract_dir = "#{service_dir}/foo.tar-dir/foo" @@ -100,7 +100,7 @@ FileUtils.mkpath(archive_dir) assert(system('tar', '-cf', archive, archive_dir)) - refute(covered_system('servicemenuinstallation', archive)) + refute(system('servicemenuinstaller', 'install', archive)) end def test_run_desktop @@ -111,7 +111,7 @@ installed_file = "#{ENV['XDG_DATA_HOME']}/kservices5/ServiceMenus/foo.desktop" - assert(covered_system('servicemenuinstallation', downloaded_file)) + assert(system('servicemenuinstaller', 'install', downloaded_file)) assert_path_exist(downloaded_file) assert_path_exist(installed_file) diff --git a/src/settings/services/test/test_helper.rb b/src/settings/services/test/test_helper.rb --- a/src/settings/services/test/test_helper.rb +++ b/src/settings/services/test/test_helper.rb @@ -15,41 +15,6 @@ # Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -GLOBAL_COVERAGE_ROOT = File.dirname(__dir__) # ../ - -# Simplecov is a bit meh and expects src and coverage to be under the -# same root. Since we get run through cmake that assumption absolutely -# doesn't hold true, so we'll need to figure out the coverage_dir relative -# to the root and the root must always be the source :/ -# The relativity only works because internally the path gets expanded, this -# isn't fully reliable, but oh well... -# https://github.com/colszowka/simplecov/issues/716 -GLOBAL_COVERAGE_DIR = begin - require 'pathname' - src_path = Pathname.new(GLOBAL_COVERAGE_ROOT) - coverage_path = Pathname.new(File.join(Dir.pwd, 'coverage')) - coverage_path.relative_path_from(src_path).to_s -end - -begin - require 'simplecov' - - SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new( - [ - SimpleCov::Formatter::HTMLFormatter - ] - ) - - SimpleCov.start do - root GLOBAL_COVERAGE_ROOT - coverage_dir GLOBAL_COVERAGE_DIR - end -rescue LoadError - warn 'SimpleCov not loaded' -end - -# FIXME: add coverage report for jenkins? - $LOAD_PATH.unshift(File.absolute_path('../', __dir__)) # ../ def __test_method_name__ @@ -63,38 +28,4 @@ caller end -# system() variant which sets up merge-coverage. simplecov supports merging -# of multiple coverage sets. we use this to get coverage metrics on the -# binaries without having to refactor the script into runnable classes. -def covered_system(cmd, *argv) - pid = fork do - Kernel.module_exec do - alias_method(:real_system, :system) - define_method(:system) do |*args| - return true if args.include?('kdialog') # disable kdialog call - real_system(*args) - end - end - - begin - require 'simplecov' - SimpleCov.start do - root GLOBAL_COVERAGE_ROOT - coverage_dir GLOBAL_COVERAGE_DIR - command_name "#{cmd}_#{__test_method_name__}" - end - rescue LoadError - warn 'SimpleCov not loaded' - end - - ARGV.replace(argv) - load "#{__dir__}/../#{cmd}" - puts 'all good, fork ending!' - exit 0 - end - waitedpid, status = Process.waitpid2(pid) - assert_equal(pid, waitedpid) - status.success? # behave like system and return the success only -end - require 'test/unit' diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -9,12 +9,6 @@ set_package_properties(Gem:test-unit PROPERTIES DESCRIPTION "Ruby gem 'test-unit' required for testing of servicemenu helpers.") -if(BUILD_COVERAGE) - find_gem(simplecov) - set_package_properties(Gem:simplecov PROPERTIES - DESCRIPTION "Ruby gem 'simplecov' used for coverage statistics.") -endif() - # KItemSetTest ecm_add_test(kitemsettest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test)