diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a025e584..8bbb081cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,414 +1,414 @@ include(ECMAddAppIcon) configure_file(config-baloo.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-baloo.h) configure_file(config-kactivities.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kactivities.h) configure_file(config-terminal.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-terminal.h) add_definitions( -DTRANSLATION_DOMAIN=\"dolphin\" ) remove_definitions( -DQT_NO_CAST_FROM_BYTEARRAY -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII ) ########################################## set(dolphinvcs_LIB_SRCS views/versioncontrol/kversioncontrolplugin.cpp ) add_library(dolphinvcs ${dolphinvcs_LIB_SRCS}) generate_export_header(dolphinvcs BASE_NAME dolphinvcs) target_link_libraries( dolphinvcs PUBLIC Qt5::Widgets ) set_target_properties(dolphinvcs PROPERTIES VERSION ${DOLPHINVCS_VERSION_STRING} SOVERSION ${DOLPHINVCS_SOVERSION} EXPORT_NAME DolphinVcs ) ecm_generate_headers(dolphinvcs_LIB_HEADERS HEADER_NAMES KVersionControlPlugin RELATIVE "views/versioncontrol" REQUIRED_HEADERS dolphinvcs_LIB_HEADERS ) install(TARGETS dolphinvcs EXPORT DolphinVcsTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES views/versioncontrol/fileviewversioncontrolplugin.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dolphinvcs_export.h DESTINATION ${KDE_INSTALL_INCLUDEDIR} COMPONENT Devel) install(FILES ${dolphinvcs_LIB_HEADERS} DESTINATION "${KDE_INSTALL_INCLUDEDIR}/Dolphin" COMPONENT Devel) ########### next target ############### set(dolphinprivate_LIB_SRCS kitemviews/kfileitemlistview.cpp kitemviews/kfileitemlistwidget.cpp kitemviews/kfileitemmodel.cpp kitemviews/kfileitemmodelrolesupdater.cpp kitemviews/kitemlistcontainer.cpp kitemviews/kitemlistcontroller.cpp kitemviews/kitemlistgroupheader.cpp kitemviews/kitemlistheader.cpp kitemviews/kitemlistselectionmanager.cpp kitemviews/kitemliststyleoption.cpp kitemviews/kitemlistview.cpp kitemviews/kitemlistviewaccessible.cpp kitemviews/kitemlistwidget.cpp kitemviews/kitemmodelbase.cpp kitemviews/kitemset.cpp kitemviews/kstandarditem.cpp kitemviews/kstandarditemlistgroupheader.cpp kitemviews/kstandarditemlistwidget.cpp kitemviews/kstandarditemlistview.cpp kitemviews/kstandarditemmodel.cpp kitemviews/private/kdirectorycontentscounter.cpp kitemviews/private/kdirectorycontentscounterworker.cpp kitemviews/private/kfileitemclipboard.cpp kitemviews/private/kfileitemmodeldirlister.cpp kitemviews/private/kfileitemmodelfilter.cpp kitemviews/private/kitemlistheaderwidget.cpp kitemviews/private/kitemlistkeyboardsearchmanager.cpp kitemviews/private/kitemlistroleeditor.cpp kitemviews/private/kitemlistrubberband.cpp kitemviews/private/kitemlistselectiontoggle.cpp kitemviews/private/kitemlistsizehintresolver.cpp kitemviews/private/kitemlistsmoothscroller.cpp kitemviews/private/kitemlistviewanimation.cpp kitemviews/private/kitemlistviewlayouter.cpp kitemviews/private/kpixmapmodifier.cpp settings/applyviewpropsjob.cpp settings/viewmodes/viewmodesettings.cpp settings/viewpropertiesdialog.cpp settings/viewpropsprogressinfo.cpp views/dolphinfileitemlistwidget.cpp views/dolphinitemlistview.cpp views/dolphinnewfilemenuobserver.cpp views/dolphinremoteencoding.cpp views/dolphinview.cpp views/dolphinviewactionhandler.cpp views/draganddrophelper.cpp views/renamedialog.cpp views/versioncontrol/updateitemstatesthread.cpp views/versioncontrol/versioncontrolobserver.cpp views/viewmodecontroller.cpp views/viewproperties.cpp views/zoomlevelinfo.cpp dolphinremoveaction.cpp middleclickactioneventfilter.cpp dolphinnewfilemenu.cpp ) ecm_qt_declare_logging_category(dolphinprivate_LIB_SRCS HEADER dolphindebug.h IDENTIFIER DolphinDebug CATEGORY_NAME org.kde.dolphin) if(HAVE_BALOO) set(dolphinprivate_LIB_SRCS ${dolphinprivate_LIB_SRCS} views/tooltips/dolphinfilemetadatawidget.cpp views/tooltips/tooltipmanager.cpp kitemviews/private/kbaloorolesprovider.cpp ) endif() kconfig_add_kcfg_files(dolphinprivate_LIB_SRCS GENERATE_MOC settings/dolphin_compactmodesettings.kcfgc settings/dolphin_directoryviewpropertysettings.kcfgc settings/dolphin_detailsmodesettings.kcfgc settings/dolphin_iconsmodesettings.kcfgc settings/dolphin_generalsettings.kcfgc settings/dolphin_versioncontrolsettings.kcfgc ) add_library(dolphinprivate ${dolphinprivate_LIB_SRCS}) generate_export_header(dolphinprivate BASE_NAME dolphin) target_link_libraries( dolphinprivate PUBLIC dolphinvcs Qt5::Concurrent Qt5::Gui KF5::I18n KF5::IconThemes KF5::KIOCore KF5::KIOWidgets KF5::KIOFileWidgets KF5::Completion KF5::TextWidgets KF5::ConfigCore KF5::NewStuff KF5::Parts KF5::WindowSystem ) if(HAVE_BALOO) target_link_libraries( dolphinprivate PUBLIC KF5::FileMetaData KF5::Baloo KF5::BalooWidgets ) endif() set_target_properties(dolphinprivate PROPERTIES VERSION ${DOLPHINPRIVATE_VERSION_STRING} SOVERSION ${DOLPHINPRIVATE_SOVERSION} ) install(TARGETS dolphinprivate ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dolphin_export.h DESTINATION ${KDE_INSTALL_INCLUDEDIR} COMPONENT Devel) ########################################## set(dolphinpart_SRCS dolphinpart.cpp dolphinpart_ext.cpp dolphindebug.cpp ) qt5_add_resources(dolphinpart_SRCS dolphinpart.qrc) add_library(dolphinpart MODULE ${dolphinpart_SRCS}) target_link_libraries(dolphinpart dolphinprivate ) install(TARGETS dolphinpart DESTINATION ${KDE_INSTALL_PLUGINDIR}) install(FILES dolphinpart.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) ########################################## set(dolphinstatic_SRCS dolphinbookmarkhandler.cpp dolphindockwidget.cpp dolphinmainwindow.cpp dolphinviewcontainer.cpp dolphincontextmenu.cpp dolphintabbar.cpp dolphinplacesmodelsingleton.cpp dolphinrecenttabsmenu.cpp dolphintabpage.cpp dolphintabwidget.cpp trash/dolphintrash.cpp filterbar/filterbar.cpp panels/places/placespanel.cpp panels/places/placesitem.cpp panels/places/placesitemlistgroupheader.cpp panels/places/placesitemlistwidget.cpp panels/places/placesitemmodel.cpp panels/places/placesitemsignalhandler.cpp panels/places/placesview.cpp panels/panel.cpp panels/folders/foldersitemlistwidget.cpp panels/folders/treeviewcontextmenu.cpp panels/folders/folderspanel.cpp panels/terminal/terminalpanel.cpp search/dolphinfacetswidget.cpp search/dolphinsearchbox.cpp settings/general/behaviorsettingspage.cpp settings/general/configurepreviewplugindialog.cpp settings/general/confirmationssettingspage.cpp settings/general/generalsettingspage.cpp settings/general/previewssettingspage.cpp settings/general/statusbarsettingspage.cpp settings/dolphinsettingsdialog.cpp settings/navigation/navigationsettingspage.cpp settings/services/servicessettingspage.cpp settings/settingspagebase.cpp settings/serviceitemdelegate.cpp settings/servicemodel.cpp settings/startup/startupsettingspage.cpp settings/trash/trashsettingspage.cpp settings/viewmodes/dolphinfontrequester.cpp settings/viewmodes/viewsettingspage.cpp settings/viewmodes/viewmodesettings.cpp settings/viewmodes/viewsettingstab.cpp statusbar/dolphinstatusbar.cpp statusbar/mountpointobserver.cpp statusbar/mountpointobservercache.cpp statusbar/spaceinfoobserver.cpp statusbar/statusbarspaceinfo.cpp views/zoomlevelinfo.cpp dolphindebug.cpp global.cpp ) if(HAVE_BALOO) set(dolphinstatic_SRCS ${dolphinstatic_SRCS} panels/information/informationpanel.cpp panels/information/informationpanelcontent.cpp panels/information/pixmapviewer.cpp panels/information/phononwidget.cpp ) endif() kconfig_add_kcfg_files(dolphinstatic_SRCS GENERATE_MOC panels/folders/dolphin_folderspanelsettings.kcfgc panels/information/dolphin_informationpanelsettings.kcfgc panels/places/dolphin_placespanelsettings.kcfgc settings/dolphin_compactmodesettings.kcfgc settings/dolphin_detailsmodesettings.kcfgc settings/dolphin_generalsettings.kcfgc settings/dolphin_iconsmodesettings.kcfgc search/dolphin_searchsettings.kcfgc settings/dolphin_versioncontrolsettings.kcfgc ) qt5_add_resources(dolphinstatic_SRCS dolphin.qrc) add_library(dolphinstatic STATIC ${dolphinstatic_SRCS}) target_include_directories(dolphinstatic SYSTEM PRIVATE ${PHONON_INCLUDES}) target_link_libraries(dolphinstatic dolphinprivate KF5::KCMUtils KF5::DBusAddons KF5::Notifications Phonon::phonon4qt5 ) if (HAVE_KACTIVITIES) target_link_libraries( dolphinstatic KF5::Activities ) endif() set(dolphin_SRCS dbusinterface.cpp main.cpp ) # Sets the icon on Windows and OSX file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*system-file-manager.png") ecm_add_app_icon(dolphin_SRCS ICONS ${ICONS_SRCS}) kf5_add_kdeinit_executable(dolphin ${dolphin_SRCS}) target_link_libraries(kdeinit_dolphin PRIVATE dolphinstatic dolphinprivate KF5::Crash ) include(DbusInterfaceMacros) generate_and_install_dbus_interface( kdeinit_dolphin dbusinterface.h org.freedesktop.FileManager1.xml OPTIONS -a ) install(TARGETS kdeinit_dolphin ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(TARGETS dolphin ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) ########################################## set(kcm_dolphinviewmodes_PART_SRCS settings/kcm/kcmdolphinviewmodes.cpp settings/viewmodes/dolphinfontrequester.cpp settings/viewmodes/viewmodesettings.cpp settings/viewmodes/viewsettingstab.cpp views/zoomlevelinfo.cpp) set(kcm_dolphinnavigation_PART_SRCS settings/kcm/kcmdolphinnavigation.cpp settings/navigation/navigationsettingspage.cpp settings/settingspagebase.cpp) set(kcm_dolphinservices_PART_SRCS settings/kcm/kcmdolphinservices.cpp settings/services/servicessettingspage.cpp settings/settingspagebase.cpp settings/serviceitemdelegate.cpp settings/servicemodel.cpp) set(kcm_dolphingeneral_PART_SRCS settings/kcm/kcmdolphingeneral.cpp settings/general/behaviorsettingspage.cpp settings/general/previewssettingspage.cpp settings/general/configurepreviewplugindialog.cpp settings/general/confirmationssettingspage.cpp settings/settingspagebase.cpp settings/serviceitemdelegate.cpp settings/servicemodel.cpp) kconfig_add_kcfg_files(kcm_dolphinviewmodes_PART_SRCS settings/dolphin_compactmodesettings.kcfgc settings/dolphin_directoryviewpropertysettings.kcfgc settings/dolphin_detailsmodesettings.kcfgc settings/dolphin_iconsmodesettings.kcfgc settings/dolphin_generalsettings.kcfgc settings/dolphin_versioncontrolsettings.kcfgc ) kconfig_add_kcfg_files(kcm_dolphinnavigation_PART_SRCS settings/dolphin_generalsettings.kcfgc) kconfig_add_kcfg_files(kcm_dolphinservices_PART_SRCS settings/dolphin_generalsettings.kcfgc settings/dolphin_versioncontrolsettings.kcfgc) kconfig_add_kcfg_files(kcm_dolphingeneral_PART_SRCS settings/dolphin_generalsettings.kcfgc) add_library(kcm_dolphinviewmodes MODULE ${kcm_dolphinviewmodes_PART_SRCS}) add_library(kcm_dolphinnavigation MODULE ${kcm_dolphinnavigation_PART_SRCS}) add_library(kcm_dolphinservices MODULE ${kcm_dolphinservices_PART_SRCS}) add_library(kcm_dolphingeneral MODULE ${kcm_dolphingeneral_PART_SRCS}) target_link_libraries(kcm_dolphinviewmodes dolphinprivate) target_link_libraries(kcm_dolphinnavigation dolphinprivate) target_link_libraries(kcm_dolphinservices dolphinprivate) target_link_libraries(kcm_dolphingeneral dolphinprivate) install(TARGETS kcm_dolphinviewmodes DESTINATION ${KDE_INSTALL_PLUGINDIR} ) install(TARGETS kcm_dolphinnavigation DESTINATION ${KDE_INSTALL_PLUGINDIR} ) 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} ) install( DIRECTORY DESTINATION "${KDE_INSTALL_FULL_DATAROOTDIR}/kglobalaccel" ) install( CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink \"${KDE_INSTALL_FULL_APPDIR}/org.kde.dolphin.desktop\" \"\$ENV{DESTDIR}${KDE_INSTALL_FULL_DATAROOTDIR}/kglobalaccel/org.kde.dolphin.desktop\")" ) install( FILES settings/dolphin_directoryviewpropertysettings.kcfg settings/dolphin_generalsettings.kcfg settings/dolphin_compactmodesettings.kcfg settings/dolphin_iconsmodesettings.kcfg settings/dolphin_detailsmodesettings.kcfg settings/dolphin_versioncontrolsettings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR} ) install( FILES org.kde.dolphin.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR} ) install( FILES settings/kcm/kcmdolphinviewmodes.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) install( FILES settings/kcm/kcmdolphinnavigation.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) 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) add_subdirectory(tests) endif() diff --git a/src/settings/services/servicemenu.knsrc b/src/settings/services/servicemenu.knsrc index 021a97543..0d1c103f6 100644 --- a/src/settings/services/servicemenu.knsrc +++ b/src/settings/services/servicemenu.knsrc @@ -1,9 +1,9 @@ [KNewStuff2] ProvidersUrl=https://download.kde.org/ocs/providers.xml Categories=Dolphin Service Menus ChecksumPolicy=ifpossible 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 index 9e090e2cd..000000000 --- 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 index e2d42bfbf..000000000 --- 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 index 000000000..b5591cad7 --- /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 index 000000000..5012eead6 --- /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 index 000000000..9c614a8d3 --- /dev/null +++ b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp @@ -0,0 +1,387 @@ +/*************************************************************************** + * 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 +Q_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; + const auto basenames1 = QStringList{"install-it.sh", "install-it"}; + for (const auto &basename : qAsConst(basenames1)) { + 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; + const auto basenames2 = QStringList{"installKDE4.sh", "installKDE4", "install.sh", "install"}; + for (const auto &basename : qAsConst(basenames2)) { + 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; + const auto basenames1 = QStringList{"deinstall.sh", "deinstall"}; + for (const auto &basename : qAsConst(basenames1)) { + 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; + const auto basenames2 = QStringList{"install-it.sh", "install-it", "installKDE4.sh", + "installKDE4", "install.sh", "install"}; + for (const auto &basename : qAsConst(basenames2)) { + 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 index 2b3514a65..1c9856d94 100644 --- a/src/settings/services/test/service_menu_deinstallation_test.rb +++ b/src/settings/services/test/service_menu_deinstallation_test.rb @@ -1,121 +1,121 @@ #!/usr/bin/env ruby # 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_relative 'test_helper' require 'tmpdir' class ServiceMenuDeinstallationTest < Test::Unit::TestCase def setup @tmpdir = Dir.mktmpdir("dolphintest-#{self.class.to_s.tr(':', '_')}") @pwdir = Dir.pwd Dir.chdir(@tmpdir) ENV['XDG_DATA_HOME'] = File.join(@tmpdir, 'data') end def teardown Dir.chdir(@pwdir) FileUtils.rm_rf(@tmpdir) ENV.delete('XDG_DATA_HOME') end def test_run_deinstall service_dir = File.join(Dir.pwd, 'share/servicemenu-download') archive_base = "#{service_dir}/foo.zip" archive_dir = "#{archive_base}-dir/foo-1.1/" FileUtils.mkpath(archive_dir) File.write("#{archive_dir}/deinstall.sh", <<-DEINSTALL_SH) #!/bin/sh touch #{@tmpdir}/deinstall.sh-run DEINSTALL_SH File.write("#{archive_dir}/install.sh", <<-INSTALL_SH) #!/bin/sh 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 # archive_dir should have been correctly removed assert_path_exist('deinstall.sh-run') assert_path_not_exist('install.sh-run') assert_path_not_exist(archive_dir) end def test_run_install_with_arg service_dir = File.join(Dir.pwd, 'share/servicemenu-download') archive_base = "#{service_dir}/foo.zip" archive_dir = "#{archive_base}-dir/foo-1.1/" FileUtils.mkpath(archive_dir) File.write("#{archive_dir}/install.sh", <<-INSTALL_SH) #!/bin/sh if [ "$@" = "--uninstall" ]; then touch #{@tmpdir}/install.sh-run exit 0 fi 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') assert_path_not_exist(archive_dir) end # no scripts in sight def test_run_fail service_dir = File.join(Dir.pwd, 'share/servicemenu-download') archive_base = "#{service_dir}/foo.zip" 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 # - sitter, 2019 assert_path_exist(archive_dir) end # For desktop files things are a bit special. There is one in .local/share/servicemenu-download # and another in the actual ServiceMenus dir. The latter gets removed by the # script, the former by KNS. def test_run_desktop service_dir = File.join(Dir.pwd, 'share/servicemenu-download') downloaded_file = "#{service_dir}/foo.desktop" FileUtils.mkpath(service_dir) FileUtils.touch(downloaded_file) menu_dir = "#{ENV['XDG_DATA_HOME']}/kservices5/ServiceMenus/" installed_file = "#{menu_dir}/foo.desktop" 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) end end diff --git a/src/settings/services/test/service_menu_installation_test.rb b/src/settings/services/test/service_menu_installation_test.rb index 43f594969..01bf65b23 100644 --- a/src/settings/services/test/service_menu_installation_test.rb +++ b/src/settings/services/test/service_menu_installation_test.rb @@ -1,119 +1,119 @@ #!/usr/bin/env ruby # 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_relative 'test_helper' require 'tmpdir' class ServiceMenuInstallationTest < Test::Unit::TestCase def setup @tmpdir = Dir.mktmpdir("dolphintest-#{self.class.to_s.tr(':', '_')}") @pwdir = Dir.pwd Dir.chdir(@tmpdir) ENV['XDG_DATA_HOME'] = File.join(@tmpdir, 'data') end def teardown Dir.chdir(@pwdir) FileUtils.rm_rf(@tmpdir) ENV.delete('XDG_DATA_HOME') end def test_run_install service_dir = File.join(Dir.pwd, 'share/servicemenu-download') FileUtils.mkpath(service_dir) archive = "#{service_dir}/foo.tar" archive_dir = 'foo' # relative so tar cf is relative without fuzz FileUtils.mkpath(archive_dir) File.write("#{archive_dir}/install-it.sh", <<-INSTALL_IT_SH) #!/bin/sh touch #{@tmpdir}/install-it.sh-run INSTALL_IT_SH File.write("#{archive_dir}/install.sh", <<-INSTALL_SH) #!/bin/sh touch #{@tmpdir}/install.sh-run 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" assert_path_exist(tar_dir) assert_path_exist(tar_extract_dir) assert_path_exist("#{tar_extract_dir}/install-it.sh") assert_path_exist("#{tar_extract_dir}/install.sh") end def test_run_install_with_arg service_dir = File.join(Dir.pwd, 'share/servicemenu-download') FileUtils.mkpath(service_dir) archive = "#{service_dir}/foo.tar" archive_dir = 'foo' # relative so tar cf is relative without fuzz FileUtils.mkpath(archive_dir) File.write("#{archive_dir}/install.sh", <<-INSTALL_SH) #!/bin/sh if [ "$@" = "--install" ]; then touch #{@tmpdir}/install.sh-run exit 0 fi exit 1 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" assert_path_exist(tar_dir) assert_path_exist(tar_extract_dir) assert_path_not_exist("#{tar_extract_dir}/install-it.sh") assert_path_exist("#{tar_extract_dir}/install.sh") end def test_run_fail service_dir = File.join(Dir.pwd, 'share/servicemenu-download') FileUtils.mkpath(service_dir) archive = "#{service_dir}/foo.tar" archive_dir = 'foo' # relative so tar cf is relative without fuzz 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 service_dir = File.join(Dir.pwd, 'share/servicemenu-download') downloaded_file = "#{service_dir}/foo.desktop" FileUtils.mkpath(service_dir) FileUtils.touch(downloaded_file) 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) end end diff --git a/src/settings/services/test/test_helper.rb b/src/settings/services/test/test_helper.rb index 9da5cf3c3..35b5d19eb 100644 --- a/src/settings/services/test/test_helper.rb +++ b/src/settings/services/test/test_helper.rb @@ -1,100 +1,31 @@ # 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 -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__ return @method_name if defined?(:@method_name) index = 0 caller = '' until caller.start_with?('test_') caller = caller_locations(index, 1)[0].label index += 1 end 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 index f60eabd3f..a0c9bbf38 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1,87 +1,81 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) find_package(Qt5Test CONFIG REQUIRED) include(ECMAddTests) include(FindGem) find_gem(test-unit REQUIRED) 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) # KItemRangeTest ecm_add_test(kitemrangetest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test) # KItemListSelectionManagerTest ecm_add_test(kitemlistselectionmanagertest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test) # KItemListControllerTest ecm_add_test(kitemlistcontrollertest.cpp testdir.cpp TEST_NAME kitemlistcontrollertest LINK_LIBRARIES dolphinprivate Qt5::Test) # KFileItemListViewTest ecm_add_test(kfileitemlistviewtest.cpp testdir.cpp TEST_NAME kfileitemlistviewtest LINK_LIBRARIES dolphinprivate Qt5::Test) # KFileItemModelTest ecm_add_test(kfileitemmodeltest.cpp testdir.cpp TEST_NAME kfileitemmodeltest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) # KFileItemModelBenchmark ecm_add_test(kfileitemmodelbenchmark.cpp testdir.cpp TEST_NAME kfileitemmodelbenchmark LINK_LIBRARIES dolphinprivate Qt5::Test) # KItemListKeyboardSearchManagerTest ecm_add_test(kitemlistkeyboardsearchmanagertest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test) # DolphinSearchBox if (KF5Baloo_FOUND) ecm_add_test(dolphinsearchboxtest.cpp TEST_NAME dolphinsearchboxtest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) endif() # KStandardItemModelTest ecm_add_test(kstandarditemmodeltest.cpp TEST_NAME kstandarditemmodeltest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) # ViewPropertiesTest ecm_add_test(viewpropertiestest.cpp testdir.cpp TEST_NAME viewpropertiestest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) # DolphinMainWindowTest set(dolphinmainwindowtest_SRCS dolphinmainwindowtest.cpp) qt5_add_resources(dolphinmainwindowtest_SRCS ${CMAKE_SOURCE_DIR}/src/dolphin.qrc) ecm_add_test(${dolphinmainwindowtest_SRCS} TEST_NAME dolphinmainwindowtest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) # DragAndDropHelperTest ecm_add_test(draganddrophelpertest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test) # PlacesItemModelTest if (KIO_VERSION VERSION_GREATER_EQUAL "5.60.0") ecm_add_test(placesitemmodeltest.cpp TEST_NAME placesitemmodeltest LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test) endif() add_test(NAME servicemenutest COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../settings/services/test/test_run.rb)