From f71fa268fdfcb4a3f5a805c6cccef962a4b2f3d0 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 27 Jun 2019 15:36:14 -0500 Subject: [PATCH 01/17] Implement MimeInfoEditor --- .../desktop_integration/CMakeLists.txt | 2 +- .../integrator/MimeInfoEditor.cpp | 56 +++++++++++ .../integrator/MimeInfoEditor.h | 31 +++++++ .../desktop_integration/CMakeLists.txt | 1 + .../integrator/TestMimeInfoEditor.cpp | 93 +++++++++++++++++++ 5 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp create mode 100644 src/libappimage/desktop_integration/integrator/MimeInfoEditor.h create mode 100644 tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp diff --git a/src/libappimage/desktop_integration/CMakeLists.txt b/src/libappimage/desktop_integration/CMakeLists.txt index 10d4df6f..938d4712 100644 --- a/src/libappimage/desktop_integration/CMakeLists.txt +++ b/src/libappimage/desktop_integration/CMakeLists.txt @@ -4,7 +4,7 @@ set( integrator/Integrator.cpp integrator/DesktopEntryEditError.h integrator/DesktopEntryEditor.cpp -) + integrator/MimeInfoEditor.cpp integrator/MimeInfoEditor.h) if(LIBAPPIMAGE_THUMBNAILER_ENABLED) list(APPEND appimage_desktop_integration_sources "Thumbnailer.cpp") diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp new file mode 100644 index 00000000..ed05814b --- /dev/null +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp @@ -0,0 +1,56 @@ +// libraries +#include +#include +#include +#include + +// local +#include "utils/Logger.h" +#include "MimeInfoEditor.h" + +namespace appimage { + namespace desktop_integration { + namespace integrator { + MimeInfoEditor::MimeInfoEditor(std::string data, std::string deployId) + : data(std::move(data)), deployId(std::move(deployId)) {} + + std::string MimeInfoEditor::edit() { + std::stringstream in(data), out; + + try { + using boost::property_tree::ptree; + + // populate tree structure pt + ptree pt; + read_xml(in, pt); + + // traverse pt + for (auto& node: pt.get_child("mime-info")) { + if (node.first == "mime-type") { + auto& subTree = node.second; + // get original icon name from the icon entry + std::string originalName = subTree.get("icon..name", ""); + + // or fallback to the mime-type name + if (originalName.empty()) { + originalName = subTree.get(".type"); + boost::replace_all(originalName, "/", "-"); + } + + std::string newIconName = originalName + "-" + deployId; + + subTree.put("icon..name", newIconName); + } + } + + write_xml(out, pt); + } catch (const std::runtime_error& error) { + appimage::utils::Logger::warning(std::string("Unable to edit MimeInfo: ") + error.what()); + return data; + } + + return out.str(); + } + } + } +} diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h new file mode 100644 index 00000000..e8565ce5 --- /dev/null +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h @@ -0,0 +1,31 @@ +#pragma once + +// system +#include + +namespace appimage { + namespace desktop_integration { + namespace integrator { + /** + * @brief Modifies MimeInfo files to be deployed. + * + * + */ + class MimeInfoEditor { + public: + /** + * Create an editor instance to modify the + * @param data + * @param deployId + */ + MimeInfoEditor(std::string data, std::string deployId); + + std::string edit(); + + private: + std::string data; + std::string deployId; + }; + } + } +} diff --git a/tests/libappimage/desktop_integration/CMakeLists.txt b/tests/libappimage/desktop_integration/CMakeLists.txt index a5296f78..44831e86 100644 --- a/tests/libappimage/desktop_integration/CMakeLists.txt +++ b/tests/libappimage/desktop_integration/CMakeLists.txt @@ -5,6 +5,7 @@ set( integrator/TestDesktopIntegration.cpp integrator/TestDesktopEntryEditor.cpp + integrator/TestMimeInfoEditor.cpp $ $ diff --git a/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp new file mode 100644 index 00000000..791bcc6f --- /dev/null +++ b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp @@ -0,0 +1,93 @@ +//system +#include + +// library +#include +#include +#include +#include + +// local +#include +#include "utils/hashlib.h" +#include "integrator/MimeInfoEditor.h" + +using namespace appimage::desktop_integration::integrator; +using namespace appimage::utils; + +class MimeInfoEditorTests : public ::testing::Test { +protected: + std::stringstream mimeInfo; + std::stringstream mimeInfoWithIconEntry; + std::stringstream expectedMimeInfo; +protected: + + void SetUp() override { + mimeInfo << "\n" + "\n" + " \n" + " \n" + " Starbright File\n" + " \n" + " \n" + ""; + + mimeInfoWithIconEntry + << "\n" + "\n" + " \n" + " \n" + " Starbright File\n" + " \n" + " \n" + " \n" + ""; + + expectedMimeInfo + << "\n" + "\n" + " \n" + " \n" + " Starbright File\n" + " \n" + " \n" + " \n" + ""; + } +}; + +TEST_F(MimeInfoEditorTests, setIcon) { + MimeInfoEditor editor(mimeInfo.str(), "appimaged-d41d8cd98f00b204e9800998ecf8427e"); + std::string result = editor.edit(); + + + using boost::property_tree::ptree; + + std::stringstream resultStream(result); + + // populate tree structure pt + ptree resultPt, expectedPt; + read_xml(resultStream, resultPt, boost::property_tree::xml_parser::trim_whitespace); + read_xml(expectedMimeInfo, expectedPt, boost::property_tree::xml_parser::trim_whitespace); + + + ASSERT_EQ(resultPt, expectedPt); +} + +TEST_F(MimeInfoEditorTests, updateIcon) { + MimeInfoEditor editor(mimeInfoWithIconEntry.str(), "appimaged-d41d8cd98f00b204e9800998ecf8427e"); + std::string result = editor.edit(); + + + using boost::property_tree::ptree; + + std::stringstream resultStream(result); + + // populate tree structure pt + ptree resultPt, expectedPt; + read_xml(resultStream, resultPt, boost::property_tree::xml_parser::trim_whitespace); + read_xml(expectedMimeInfo, expectedPt, boost::property_tree::xml_parser::trim_whitespace); + + + ASSERT_EQ(resultPt, expectedPt); +} From 36c2c20f746358dca34be4aa6f081549cb9f2fde Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 27 Jun 2019 16:31:10 -0500 Subject: [PATCH 02/17] MimeInfoEditor::getMimeTypeIconNames --- .../integrator/MimeInfoEditor.cpp | 56 +++++++++++++++---- .../integrator/MimeInfoEditor.h | 12 +++- .../integrator/TestMimeInfoEditor.cpp | 22 +++++++- 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp index ed05814b..54571bcc 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp @@ -1,8 +1,8 @@ // libraries #include -#include #include #include +#include // local #include "utils/Logger.h" @@ -11,18 +11,21 @@ namespace appimage { namespace desktop_integration { namespace integrator { - MimeInfoEditor::MimeInfoEditor(std::string data, std::string deployId) - : data(std::move(data)), deployId(std::move(deployId)) {} - - std::string MimeInfoEditor::edit() { - std::stringstream in(data), out; - + MimeInfoEditor::MimeInfoEditor(std::string data) { try { + std::stringstream in(data); using boost::property_tree::ptree; // populate tree structure pt - ptree pt; read_xml(in, pt); + } catch (const std::runtime_error& error) { + appimage::utils::Logger::warning(std::string("Unable to read MimeInfo: ") + error.what()); + } + } + + std::string MimeInfoEditor::edit() { + try { + using boost::property_tree::ptree; // traverse pt for (auto& node: pt.get_child("mime-info")) { @@ -43,13 +46,46 @@ namespace appimage { } } + std::stringstream out; write_xml(out, pt); + return out.str(); } catch (const std::runtime_error& error) { appimage::utils::Logger::warning(std::string("Unable to edit MimeInfo: ") + error.what()); - return data; + return std::string{}; + } + } + + void MimeInfoEditor::setDeployId(const std::string& deployId) { + MimeInfoEditor::deployId = deployId; + } + + std::list MimeInfoEditor::getMimeTypeIconNames() { + std::list icons; + + try { + using boost::property_tree::ptree; + + // traverse pt + for (auto& node: pt.get_child("mime-info")) { + if (node.first == "mime-type") { + auto& subTree = node.second; + // get original icon name from the icon entry + std::string iconName = subTree.get("icon..name", ""); + + // or fallback to the mime-type name + if (iconName.empty()) { + iconName = subTree.get(".type"); + boost::replace_all(iconName, "/", "-"); + } + + icons.push_back(iconName); + } + } + } catch (const std::runtime_error& error) { + appimage::utils::Logger::warning(std::string("Unable to read MimeInfo: ") + error.what()); } - return out.str(); + return icons; } } } diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h index e8565ce5..da9f28bb 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h @@ -1,8 +1,12 @@ #pragma once // system +#include #include +// libraries +#include + namespace appimage { namespace desktop_integration { namespace integrator { @@ -18,12 +22,16 @@ namespace appimage { * @param data * @param deployId */ - MimeInfoEditor(std::string data, std::string deployId); + MimeInfoEditor(std::string data); + + void setDeployId(const std::string& deployId); std::string edit(); + std::list getMimeTypeIconNames(); + private: - std::string data; + boost::property_tree::ptree pt; std::string deployId; }; } diff --git a/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp index 791bcc6f..c20dd5b7 100644 --- a/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp +++ b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp @@ -57,7 +57,8 @@ class MimeInfoEditorTests : public ::testing::Test { }; TEST_F(MimeInfoEditorTests, setIcon) { - MimeInfoEditor editor(mimeInfo.str(), "appimaged-d41d8cd98f00b204e9800998ecf8427e"); + MimeInfoEditor editor(mimeInfo.str()); + editor.setDeployId("appimaged-d41d8cd98f00b204e9800998ecf8427e"); std::string result = editor.edit(); @@ -75,7 +76,8 @@ TEST_F(MimeInfoEditorTests, setIcon) { } TEST_F(MimeInfoEditorTests, updateIcon) { - MimeInfoEditor editor(mimeInfoWithIconEntry.str(), "appimaged-d41d8cd98f00b204e9800998ecf8427e"); + MimeInfoEditor editor(mimeInfoWithIconEntry.str()); + editor.setDeployId("appimaged-d41d8cd98f00b204e9800998ecf8427e"); std::string result = editor.edit(); @@ -91,3 +93,19 @@ TEST_F(MimeInfoEditorTests, updateIcon) { ASSERT_EQ(resultPt, expectedPt); } + +TEST_F(MimeInfoEditorTests, getIconNamesFromMimeTypeType) { + MimeInfoEditor editor(mimeInfo.str()); + std::list iconNames = editor.getMimeTypeIconNames(); + std::list expectedIconNames = {"application-x-starbright-file"}; + + ASSERT_EQ(iconNames, expectedIconNames); +} + +TEST_F(MimeInfoEditorTests, getIconNamesFromMimeTypeIconName) { + MimeInfoEditor editor(mimeInfoWithIconEntry.str()); + std::list iconNames = editor.getMimeTypeIconNames(); + std::list expectedIconNames = {"application-x-starbright-file"}; + + ASSERT_EQ(iconNames, expectedIconNames); +} From f985c1046088fe76f7e612945f24f3afdc729607 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 27 Jun 2019 22:46:59 -0500 Subject: [PATCH 03/17] Extract mimetype packages icons --- .../integrator/Integrator.cpp | 97 ++++++++++++++++--- .../integrator/MimeInfoEditor.cpp | 2 +- .../integrator/MimeInfoEditor.h | 2 +- .../ResourcesExtractor.cpp | 1 + 4 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index 86ca32b8..d224e294 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -24,6 +24,7 @@ #include "utils/IconHandle.h" #include "utils/path_utils.h" #include "DesktopEntryEditor.h" +#include "MimeInfoEditor.h" #include "Integrator.h" #include "constants.h" @@ -50,6 +51,7 @@ namespace appimage { ResourcesExtractor resourcesExtractor; DesktopEntry desktopEntry; + std::map mimeInfoFiles; Priv(const AppImage& appImage, const bf::path& xdgDataHome) : appImage(appImage), xdgDataHome(xdgDataHome), @@ -58,7 +60,16 @@ namespace appimage { if (xdgDataHome.empty()) throw DesktopIntegrationError("Invalid XDG_DATA_HOME: " + xdgDataHome.string()); - // Extract desktop entry, DesktopIntegrationError will be throw if missing + extractDesktopEntry(); + extractMimeInfoFiles(); + + appImageId = hashPath(appImage.getPath()); + } + + /** + * Extract desktop entry, DesktopIntegrationError will be throw if missing + */ + void extractDesktopEntry() { auto desktopEntryPath = resourcesExtractor.getDesktopEntryPath(); auto desktopEntryData = resourcesExtractor.extractText(desktopEntryPath); try { @@ -66,9 +77,17 @@ namespace appimage { } catch (const DesktopEntryError& error) { throw DesktopIntegrationError(std::string("Malformed desktop entry: ") + error.what()); } + } - - appImageId = hashPath(appImage.getPath()); + /** + * Extract and store mime info files to be used latter + */ + void extractMimeInfoFiles() { + std::vector mimeInfoPaths = resourcesExtractor.getMimeTypePackagesPaths(); + for (const std::string& path: mimeInfoPaths) { + std::string mimeInfoFileData = resourcesExtractor.extractText(path); + mimeInfoFiles.insert(std::make_pair(path, MimeInfoEditor(mimeInfoFileData))); + } } /** @@ -160,6 +179,11 @@ namespace appimage { * Icons at usr/share/icons will be preferred if not available the ".DirIcon" will be used. */ void deployIcons() { + deployApplicationIcon(); + deployMimeTypeIcons(); + } + + void deployApplicationIcon() const { static const std::string dirIconPath = ".DirIcon"; static const auto iconsDirPath = "usr/share/icons"; @@ -177,7 +201,7 @@ namespace appimage { try { Logger::warning("Using .DirIcon as default app icon"); auto dirIconData = resourcesExtractor.extract(dirIconPath); - deployApplicationIcon(desktopEntryIconName, dirIconData);; + deployIcon("apps", desktopEntryIconName, dirIconData);; } catch (const PayloadIteratorError& error) { Logger::error(error.what()); Logger::error("No icon was generated for: " + appImage.getPath()); @@ -192,17 +216,68 @@ namespace appimage { } } + void deployMimeTypeIcons() { + std::list mimeTypeIconNames; + for (const auto& editor : mimeInfoFiles) { + auto names = editor.second.getMimeTypeIconNames(); + mimeTypeIconNames.merge(names); + } + + std::vector mimeTypeIconPaths; + for (const auto& iconName: mimeTypeIconNames) { + auto paths = resourcesExtractor.getIconFilePaths(iconName); + mimeTypeIconPaths.insert(mimeTypeIconPaths.end(), paths.begin(), paths.end()); + } + + // Generate deploy paths + std::map mimeTypeIconsTargetPaths; + for (const auto& path: mimeTypeIconPaths) + mimeTypeIconsTargetPaths[path] = generateMimeTypeIconDeployPath(path).string(); + + resourcesExtractor.extractTo(mimeTypeIconsTargetPaths); + } + + /** + * Append vendor prefix and appImage id to the file names to identify the appImage that owns + * this file. Replace the default XDG_DATA_DIR by the one at + * + * @param path resource path + * @return path with a prefixed file name + */ + bf::path generateMimeTypeIconDeployPath(bf::path path) const { + // add appImage resource identification prefix to the filename + std::stringstream fileNameBuilder; + fileNameBuilder << path.stem() << "-" << VENDOR_PREFIX << "-" << appImageId << path.extension(); + + // build the relative parent path ignoring the default XDG_DATA_DIR prefix ("usr/share") + path.remove_filename(); + bf::path relativeParentPath; + const bf::path defaultXdgDataDirPath = "usr/share"; + + for (const auto& itr : path) { + relativeParentPath /= itr; + + if (relativeParentPath == defaultXdgDataDirPath) + relativeParentPath.clear(); + } + + bf::path newPath = xdgDataHome / relativeParentPath / fileNameBuilder.str(); + return newPath; + } + /** * Deploy as the main application icon to - * XDG_DATA_HOME/icons/hicolor//apps/__. + * XDG_DATA_HOME/icons/hicolor///__. * - * size: actual icon dimenzions, in case of vectorial image "scalable" is used + * size: actual icon dimensions, in case of vectorial image "scalable" is used * format extension: in case of vectorial image "svg" otherwise "png" * + * @param iconGroup * @param iconName * @param iconData */ - void deployApplicationIcon(const std::string& iconName, std::vector& iconData) const { + void deployIcon(const std::string& iconGroup, const std::string& iconName, + std::vector& iconData) const { try { IconHandle icon(iconData); @@ -224,14 +299,14 @@ namespace appimage { iconPath /= (iconSize + "x" + iconSize); } - iconPath /= "apps"; + iconPath /= iconGroup; iconPath /= iconNameBuilder.str(); auto deployPath = generateDeployPath(iconPath); icon.save(deployPath.string(), icon.format()); - } catch (const IconHandleError& er) { - Logger::error(er.what()); - Logger::error("No icon was generated for: " + appImage.getPath()); + } catch (const IconHandleError& error) { + Logger::error("Icon deploy failed " + iconGroup + "/" + iconName + + " from " + appImage.getPath() + " : " + error.what()); } } diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp index 54571bcc..f9a5c825 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp @@ -59,7 +59,7 @@ namespace appimage { MimeInfoEditor::deployId = deployId; } - std::list MimeInfoEditor::getMimeTypeIconNames() { + std::list MimeInfoEditor::getMimeTypeIconNames() const { std::list icons; try { diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h index da9f28bb..9b8cd765 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h @@ -28,7 +28,7 @@ namespace appimage { std::string edit(); - std::list getMimeTypeIconNames(); + std::list getMimeTypeIconNames() const; private: boost::property_tree::ptree pt; diff --git a/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp b/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp index e62894f3..dc917227 100644 --- a/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp +++ b/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp @@ -170,5 +170,6 @@ namespace appimage { throw AppImageError("Missing Desktop Entry"); } + } } From a07a2eb896816d117242f0a72c034399a5710155 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Fri, 28 Jun 2019 12:06:37 -0500 Subject: [PATCH 04/17] Deploy edited mimetype packages --- .../integrator/Integrator.cpp | 69 ++-- .../integrator/MimeInfoEditor.cpp | 2 +- .../ResourcesExtractor.cpp | 10 +- tests/CMakeLists.txt | 2 + tests/data/CMakeLists.txt | 21 ++ tests/data/squashfs-root/echo.desktop.in | 9 + .../mimetypes/application-x-custom-file.svg | 320 ++++++++++++++++++ .../usr/share/mime/packages/custom.xml | 8 + .../TestIntegrationManager.cpp | 9 +- .../integrator/TestDesktopIntegration.cpp | 32 ++ .../integrator/TestMimeInfoEditor.cpp | 6 +- 11 files changed, 435 insertions(+), 53 deletions(-) create mode 100644 tests/data/CMakeLists.txt create mode 100644 tests/data/squashfs-root/echo.desktop.in create mode 100644 tests/data/squashfs-root/usr/share/icons/hicolor/scalable/mimetypes/application-x-custom-file.svg create mode 100644 tests/data/squashfs-root/usr/share/mime/packages/custom.xml diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index d224e294..137661bc 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -232,39 +232,11 @@ namespace appimage { // Generate deploy paths std::map mimeTypeIconsTargetPaths; for (const auto& path: mimeTypeIconPaths) - mimeTypeIconsTargetPaths[path] = generateMimeTypeIconDeployPath(path).string(); + mimeTypeIconsTargetPaths[path] = generateDeployPath(path).string(); resourcesExtractor.extractTo(mimeTypeIconsTargetPaths); } - /** - * Append vendor prefix and appImage id to the file names to identify the appImage that owns - * this file. Replace the default XDG_DATA_DIR by the one at - * - * @param path resource path - * @return path with a prefixed file name - */ - bf::path generateMimeTypeIconDeployPath(bf::path path) const { - // add appImage resource identification prefix to the filename - std::stringstream fileNameBuilder; - fileNameBuilder << path.stem() << "-" << VENDOR_PREFIX << "-" << appImageId << path.extension(); - - // build the relative parent path ignoring the default XDG_DATA_DIR prefix ("usr/share") - path.remove_filename(); - bf::path relativeParentPath; - const bf::path defaultXdgDataDirPath = "usr/share"; - - for (const auto& itr : path) { - relativeParentPath /= itr; - - if (relativeParentPath == defaultXdgDataDirPath) - relativeParentPath.clear(); - } - - bf::path newPath = xdgDataHome / relativeParentPath / fileNameBuilder.str(); - return newPath; - } - /** * Deploy as the main application icon to * XDG_DATA_HOME/icons/hicolor///__. @@ -311,18 +283,29 @@ namespace appimage { } /** - * Append vendor prefix and appImage id to the file names to identify the appImage that owns + * Prepend vendor prefix and appImage id to the file names to identify the appImage that owns * this file. Replace the default XDG_DATA_DIR by the one at * * @param path resource path - * @return path with a prefixed file name + * @return //__. */ bf::path generateDeployPath(bf::path path) const { // add appImage resource identification prefix to the filename std::stringstream fileNameBuilder; fileNameBuilder << VENDOR_PREFIX << "_" << appImageId << "_" << path.filename().string(); - // build the relative parent path ignoring the default XDG_DATA_DIR prefix ("usr/share") + boost::filesystem::path relativeParentPath = generateDeployParentPath(path); + + bf::path newPath = xdgDataHome / relativeParentPath / fileNameBuilder.str(); + return newPath; + } + + /** + * Build the relative parent path ignoring the default XDG_DATA_DIR prefix ("usr/share") + * @param path + * @return + */ + boost::filesystem::path generateDeployParentPath(boost::filesystem::path& path) const { path.remove_filename(); bf::path relativeParentPath; const bf::path defaultXdgDataDirPath = "usr/share"; @@ -333,20 +316,20 @@ namespace appimage { if (relativeParentPath == defaultXdgDataDirPath) relativeParentPath.clear(); } - - bf::path newPath = xdgDataHome / relativeParentPath / fileNameBuilder.str(); - return newPath; + return relativeParentPath; } void deployMimeTypePackages() { - auto mimeTypePackagesPaths = resourcesExtractor.getMimeTypePackagesPaths(); - std::map mimeTypePackagesTargetPaths; - - // Generate deploy paths - for (const auto& path: mimeTypePackagesPaths) - mimeTypePackagesTargetPaths[path] = generateDeployPath(path).string(); - - resourcesExtractor.extractTo(mimeTypePackagesTargetPaths); + for (auto& itr: mimeInfoFiles) { + MimeInfoEditor& editor = itr.second; + editor.setDeployId(VENDOR_PREFIX + '_' + appImageId); + boost::filesystem::path deployPath = generateDeployPath(itr.first); + + create_directories(deployPath.parent_path()); + std::ofstream out(deployPath.string()); + out << editor.edit(); + out.close(); + } } void setExecutionPermission() { diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp index f9a5c825..5a5e11ce 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp @@ -40,7 +40,7 @@ namespace appimage { boost::replace_all(originalName, "/", "-"); } - std::string newIconName = originalName + "-" + deployId; + std::string newIconName = deployId + '_' + originalName; subTree.put("icon..name", newIconName); } diff --git a/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp b/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp index dc917227..32e18730 100644 --- a/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp +++ b/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp @@ -29,19 +29,23 @@ namespace appimage { PayloadEntriesCache entriesCache; + bool isFile(const std::string& fileName) const { + return appimage::core::PayloadEntryType::REGULAR == entriesCache.getEntryType(fileName) || + appimage::core::PayloadEntryType::LINK == entriesCache.getEntryType(fileName); + } bool isIconFile(const std::string& fileName) const { - return (fileName.find("usr/share/icons") != std::string::npos); + return (fileName.find("usr/share/icons") != std::string::npos) && isFile(fileName); } bool isMainDesktopFile(const std::string& fileName) const { return fileName.find(".desktop") != std::string::npos && - fileName.find('/') == std::string::npos; + fileName.find('/') == std::string::npos && isFile(fileName); } bool isMimeFile(const std::string& fileName) const { return fileName.find("usr/share/mime/packages") != std::string::npos && - fileName.find(".xml") == std::string::npos; + fileName.find(".xml") != std::string::npos && isFile(fileName); } std::vector readDataFile(std::istream& istream) const { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4594c7aa..1e49bdf1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,10 +6,12 @@ if(BUILD_TESTING) # global definitions add_definitions( -DTEST_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data/" + -DNEW_TEST_DATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data/" -DGIT_COMMIT="AppImageKit unit tests" ) + add_subdirectory(data) add_subdirectory(libappimage) if(ENABLE_COVERAGE) diff --git a/tests/data/CMakeLists.txt b/tests/data/CMakeLists.txt new file mode 100644 index 00000000..f291d879 --- /dev/null +++ b/tests/data/CMakeLists.txt @@ -0,0 +1,21 @@ +message(STATUS "Generating test data AppImage") + +# Generate Echo AppImage with custom mime type package +set(APPIMAGE_NAME "echo.with.mimetype") +set(TARGET_APPDIR ${CMAKE_CURRENT_BINARY_DIR}/${APPIMAGE_NAME}.AppDir) + +if(NOT EXISTS ${TARGET_APPDIR}) + message(STATUS "Generating ${APPIMAGE_NAME} AppDir") + + file(MAKE_DIRECTORY ${TARGET_APPDIR}) + configure_file(squashfs-root/echo.desktop.in ${TARGET_APPDIR}/echo.desktop @ONLY) + file(COPY squashfs-root/.DirIcon DESTINATION ${TARGET_APPDIR}) + file(COPY squashfs-root/AppRun DESTINATION ${TARGET_APPDIR}) + file(COPY squashfs-root/utilities-terminal.svg DESTINATION ${TARGET_APPDIR}) + file(COPY squashfs-root/usr DESTINATION ${TARGET_APPDIR}) + + message(STATUS "Creating ${APPIMAGE_NAME} AppImage") + execute_process( + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/appimagetool-x86_64.AppImage ${TARGET_APPDIR} + ${CMAKE_CURRENT_BINARY_DIR}/${APPIMAGE_NAME}.AppImage) +endif() diff --git a/tests/data/squashfs-root/echo.desktop.in b/tests/data/squashfs-root/echo.desktop.in new file mode 100644 index 00000000..2bb3824f --- /dev/null +++ b/tests/data/squashfs-root/echo.desktop.in @@ -0,0 +1,9 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=@APPIMAGE_NAME@ +Name[de]=Echo DE +Comment=Just echo. +Exec=echo %F +Icon=utilities-terminal +X-AppImage-Version=1234 diff --git a/tests/data/squashfs-root/usr/share/icons/hicolor/scalable/mimetypes/application-x-custom-file.svg b/tests/data/squashfs-root/usr/share/icons/hicolor/scalable/mimetypes/application-x-custom-file.svg new file mode 100644 index 00000000..4a0250da --- /dev/null +++ b/tests/data/squashfs-root/usr/share/icons/hicolor/scalable/mimetypes/application-x-custom-file.svg @@ -0,0 +1,320 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/data/squashfs-root/usr/share/mime/packages/custom.xml b/tests/data/squashfs-root/usr/share/mime/packages/custom.xml new file mode 100644 index 00000000..508aa35c --- /dev/null +++ b/tests/data/squashfs-root/usr/share/mime/packages/custom.xml @@ -0,0 +1,8 @@ + + + + + Custom File + + + diff --git a/tests/libappimage/desktop_integration/TestIntegrationManager.cpp b/tests/libappimage/desktop_integration/TestIntegrationManager.cpp index 54762213..f2fb5db2 100644 --- a/tests/libappimage/desktop_integration/TestIntegrationManager.cpp +++ b/tests/libappimage/desktop_integration/TestIntegrationManager.cpp @@ -74,11 +74,14 @@ TEST_F(TestIntegrationManager, shallAppImageBeRegistered) { IntegrationManager manager; ASSERT_TRUE(manager.shallAppImageBeRegistered( - appimage::core::AppImage(TEST_DATA_DIR "Echo-x86_64.AppImage"))); + appimage::core::AppImage(TEST_DATA_DIR + "Echo-x86_64.AppImage"))); ASSERT_FALSE(manager.shallAppImageBeRegistered( - appimage::core::AppImage(TEST_DATA_DIR "Echo-no-integrate-x86_64.AppImage"))); + appimage::core::AppImage(TEST_DATA_DIR + "Echo-no-integrate-x86_64.AppImage"))); ASSERT_THROW(manager.shallAppImageBeRegistered( - appimage::core::AppImage(TEST_DATA_DIR "elffile")), appimage::core::AppImageError); + appimage::core::AppImage(TEST_DATA_DIR + "elffile")), appimage::core::AppImageError); } diff --git a/tests/libappimage/desktop_integration/integrator/TestDesktopIntegration.cpp b/tests/libappimage/desktop_integration/integrator/TestDesktopIntegration.cpp index ab52417e..9fb1f067 100644 --- a/tests/libappimage/desktop_integration/integrator/TestDesktopIntegration.cpp +++ b/tests/libappimage/desktop_integration/integrator/TestDesktopIntegration.cpp @@ -1,5 +1,7 @@ // system #include +#include +#include // library headers #include @@ -9,6 +11,7 @@ // local #include "appimage/desktop_integration/exceptions.h" #include "integrator/Integrator.h" +#include "integrator/MimeInfoEditor.h" #include "utils/hashlib.h" #include "utils/path_utils.h" @@ -84,3 +87,32 @@ TEST_F(DesktopIntegrationTests, malformedDesktopEntry) { ASSERT_THROW(Integrator(appImage, userDirPath.string()), appimage::desktop_integration::DesktopIntegrationError); } + +TEST_F(DesktopIntegrationTests, integrateMimeType) { + std::string appImagePath = NEW_TEST_DATA_DIR "echo.with.mimetype.AppImage"; + appimage::core::AppImage appImage(appImagePath); + Integrator i(appImage, userDirPath.string()); + + i.integrate(); + + std::string md5 = appimage::utils::hashPath(appImagePath.c_str()); + + bf::path mimeTypeIconFilePath = + userDirPath / ("icons/hicolor/scalable/mimetypes/appimagekit_" + md5 + "_application-x-custom-file.svg"); + ASSERT_TRUE(bf::exists(mimeTypeIconFilePath)); + + bf::path mimeTypePackageFilePath = userDirPath / ("mime/packages/appimagekit_" + md5 + "_custom.xml"); + ASSERT_TRUE(bf::exists(mimeTypePackageFilePath)); + + // Read generated mime info package file + std::ifstream mimeTypePackageFile(mimeTypePackageFilePath.string()); + std::string fileData((std::istreambuf_iterator(mimeTypePackageFile)), + std::istreambuf_iterator()); + + MimeInfoEditor editor(fileData); + // Compare icon names + auto result = editor.getMimeTypeIconNames(); + std::list expected = {"appimagekit_" + md5 + "_application-x-custom-file"}; + ASSERT_EQ(result, expected); +} + diff --git a/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp index c20dd5b7..81010bea 100644 --- a/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp +++ b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp @@ -50,7 +50,7 @@ class MimeInfoEditorTests : public ::testing::Test { " \n" " Starbright File\n" " \n" - " \n" + " \n" " \n" ""; } @@ -58,7 +58,7 @@ class MimeInfoEditorTests : public ::testing::Test { TEST_F(MimeInfoEditorTests, setIcon) { MimeInfoEditor editor(mimeInfo.str()); - editor.setDeployId("appimaged-d41d8cd98f00b204e9800998ecf8427e"); + editor.setDeployId("appimaged_d41d8cd98f00b204e9800998ecf8427e"); std::string result = editor.edit(); @@ -77,7 +77,7 @@ TEST_F(MimeInfoEditorTests, setIcon) { TEST_F(MimeInfoEditorTests, updateIcon) { MimeInfoEditor editor(mimeInfoWithIconEntry.str()); - editor.setDeployId("appimaged-d41d8cd98f00b204e9800998ecf8427e"); + editor.setDeployId("appimaged_d41d8cd98f00b204e9800998ecf8427e"); std::string result = editor.edit(); From 6b1fed2937f85f01017e4c8410ded8ee868a8152 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Fri, 28 Jun 2019 13:20:41 -0500 Subject: [PATCH 05/17] Keep code style --- src/libappimage/desktop_integration/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libappimage/desktop_integration/CMakeLists.txt b/src/libappimage/desktop_integration/CMakeLists.txt index 938d4712..92539255 100644 --- a/src/libappimage/desktop_integration/CMakeLists.txt +++ b/src/libappimage/desktop_integration/CMakeLists.txt @@ -4,7 +4,8 @@ set( integrator/Integrator.cpp integrator/DesktopEntryEditError.h integrator/DesktopEntryEditor.cpp - integrator/MimeInfoEditor.cpp integrator/MimeInfoEditor.h) + integrator/MimeInfoEditor.cpp +) if(LIBAPPIMAGE_THUMBNAILER_ENABLED) list(APPEND appimage_desktop_integration_sources "Thumbnailer.cpp") From ccf5a19ac461edfe5abece7261470a1ff1d8c662 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Fri, 28 Jun 2019 13:27:17 -0500 Subject: [PATCH 06/17] Document MimeInfoEditor --- .../integrator/MimeInfoEditor.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h index 9b8cd765..ddd3a012 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h @@ -11,9 +11,7 @@ namespace appimage { namespace desktop_integration { namespace integrator { /** - * @brief Modifies MimeInfo files to be deployed. - * - * + * @brief Edit MimeInfo files to be deployed */ class MimeInfoEditor { public: @@ -24,10 +22,22 @@ namespace appimage { */ MimeInfoEditor(std::string data); + /** + * Set the deploy id to be prepended to the icon file name + * @param deployId + */ void setDeployId(const std::string& deployId); + /** + * Apply modification to the MimeInfo file + * @return modified MimeInfo + */ std::string edit(); + /** + * Extract the icon names from from the icon entry or the mime type name + * @return names of the icons related to the mime types + */ std::list getMimeTypeIconNames() const; private: From 985c927910465ab53d1e2218874c250417f36825 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Fri, 28 Jun 2019 13:28:39 -0500 Subject: [PATCH 07/17] Remove unrequired lines --- .../utils/resources_extractor/ResourcesExtractor.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp b/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp index 32e18730..ac80ecc1 100644 --- a/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp +++ b/src/libappimage/utils/resources_extractor/ResourcesExtractor.cpp @@ -24,7 +24,6 @@ namespace appimage { public: explicit Priv(const AppImage& appImage) : appImage(appImage), entriesCache(appImage) {} - core::AppImage appImage; PayloadEntriesCache entriesCache; @@ -174,6 +173,5 @@ namespace appimage { throw AppImageError("Missing Desktop Entry"); } - } } From a41791418b357ad5424e36fb2a317415c07ab812 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Fri, 28 Jun 2019 14:32:13 -0500 Subject: [PATCH 08/17] Use remote version of appimagetool --- tests/data/CMakeLists.txt | 13 ++++++++++--- tests/data/squashfs-root/echo.desktop.in | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/data/CMakeLists.txt b/tests/data/CMakeLists.txt index f291d879..6b1d89bb 100644 --- a/tests/data/CMakeLists.txt +++ b/tests/data/CMakeLists.txt @@ -1,5 +1,14 @@ message(STATUS "Generating test data AppImage") +# Get appimagetool +set(APPIMAGETOOL_BIN ${CMAKE_CURRENT_BINARY_DIR}/appimagetool) +if(NOT EXISTS ${APPIMAGETOOL_BIN}) + message(STATUS "Downloading appimagetool for ${CMAKE_SYSTEM_PROCESSOR}") + file(DOWNLOAD "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${CMAKE_SYSTEM_PROCESSOR}.AppImage" "${APPIMAGETOOL_BIN}" SHOW_PROGRESS) + execute_process(COMMAND chmod +x ${APPIMAGETOOL_BIN}) +endif() +message(STATUS "Using appimagetool: ${APPIMAGETOOL_BIN}") + # Generate Echo AppImage with custom mime type package set(APPIMAGE_NAME "echo.with.mimetype") set(TARGET_APPDIR ${CMAKE_CURRENT_BINARY_DIR}/${APPIMAGE_NAME}.AppDir) @@ -15,7 +24,5 @@ if(NOT EXISTS ${TARGET_APPDIR}) file(COPY squashfs-root/usr DESTINATION ${TARGET_APPDIR}) message(STATUS "Creating ${APPIMAGE_NAME} AppImage") - execute_process( - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/appimagetool-x86_64.AppImage ${TARGET_APPDIR} - ${CMAKE_CURRENT_BINARY_DIR}/${APPIMAGE_NAME}.AppImage) + execute_process(COMMAND ${APPIMAGETOOL_BIN} ${TARGET_APPDIR} ${CMAKE_CURRENT_BINARY_DIR}/${APPIMAGE_NAME}.AppImage) endif() diff --git a/tests/data/squashfs-root/echo.desktop.in b/tests/data/squashfs-root/echo.desktop.in index 2bb3824f..2010cde7 100644 --- a/tests/data/squashfs-root/echo.desktop.in +++ b/tests/data/squashfs-root/echo.desktop.in @@ -7,3 +7,4 @@ Comment=Just echo. Exec=echo %F Icon=utilities-terminal X-AppImage-Version=1234 +Categories=Utility; From 40a267d72a63918cc41aefe34033b5a500d2e964 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 1 Jul 2019 22:11:52 -0500 Subject: [PATCH 09/17] Use system enviroment var ARCH to decide which appimagetool bin should be downloaded --- tests/data/CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/data/CMakeLists.txt b/tests/data/CMakeLists.txt index 6b1d89bb..d61dfba6 100644 --- a/tests/data/CMakeLists.txt +++ b/tests/data/CMakeLists.txt @@ -3,8 +3,15 @@ message(STATUS "Generating test data AppImage") # Get appimagetool set(APPIMAGETOOL_BIN ${CMAKE_CURRENT_BINARY_DIR}/appimagetool) if(NOT EXISTS ${APPIMAGETOOL_BIN}) - message(STATUS "Downloading appimagetool for ${CMAKE_SYSTEM_PROCESSOR}") - file(DOWNLOAD "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${CMAKE_SYSTEM_PROCESSOR}.AppImage" "${APPIMAGETOOL_BIN}" SHOW_PROGRESS) + if(DEFINED ENV{ARCH} ) + set(APPIMAGETOOL_BIN_ARCH $ENV{ARCH}) + else() + set(APPIMAGETOOL_BIN_ARCH ${CMAKE_SYSTEM_PROCESSOR}) + endif() + + message(STATUS "Downloading appimagetool for ${APPIMAGETOOL_BIN_ARCH}") + file(DOWNLOAD "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${APPIMAGETOOL_BIN_ARCH}.AppImage" "${APPIMAGETOOL_BIN}") + execute_process(COMMAND chmod +x ${APPIMAGETOOL_BIN}) endif() message(STATUS "Using appimagetool: ${APPIMAGETOOL_BIN}") From 5744d24262316834193fce7366110d957f2afd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20L=C3=B3pez=20Zubieta?= Date: Wed, 3 Jul 2019 14:59:39 +0000 Subject: [PATCH 10/17] Update src/libappimage/desktop_integration/integrator/Integrator.cpp fix typo Co-Authored-By: TheAssassin --- src/libappimage/desktop_integration/integrator/Integrator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index 137661bc..7025727e 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -80,7 +80,7 @@ namespace appimage { } /** - * Extract and store mime info files to be used latter + * Extract and store mime info files to be used later */ void extractMimeInfoFiles() { std::vector mimeInfoPaths = resourcesExtractor.getMimeTypePackagesPaths(); From bb3a0d822537002fad5317c77594392af854b286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20L=C3=B3pez=20Zubieta?= Date: Wed, 3 Jul 2019 14:59:52 +0000 Subject: [PATCH 11/17] Update src/libappimage/desktop_integration/integrator/Integrator.cpp fix typo Co-Authored-By: TheAssassin --- src/libappimage/desktop_integration/integrator/Integrator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index 7025727e..c2103935 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -67,7 +67,7 @@ namespace appimage { } /** - * Extract desktop entry, DesktopIntegrationError will be throw if missing + * Extract desktop entry, DesktopIntegrationError will be thrown in case there is no desktop file */ void extractDesktopEntry() { auto desktopEntryPath = resourcesExtractor.getDesktopEntryPath(); From 8d0df132c297ea5fca3917c15f3dc77093ceb91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20L=C3=B3pez=20Zubieta?= Date: Wed, 3 Jul 2019 15:00:13 +0000 Subject: [PATCH 12/17] Update src/libappimage/desktop_integration/integrator/Integrator.cpp fix typo Co-Authored-By: TheAssassin --- src/libappimage/desktop_integration/integrator/Integrator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index c2103935..c41a1587 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -241,7 +241,7 @@ namespace appimage { * Deploy as the main application icon to * XDG_DATA_HOME/icons/hicolor///__. * - * size: actual icon dimensions, in case of vectorial image "scalable" is used + * size: actual icon dimensions, in case of vector image "scalable" is used * format extension: in case of vectorial image "svg" otherwise "png" * * @param iconGroup From 67629487e4fb47ba35fa4090dae49fa44242486e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20L=C3=B3pez=20Zubieta?= Date: Wed, 3 Jul 2019 15:00:36 +0000 Subject: [PATCH 13/17] Update src/libappimage/desktop_integration/integrator/Integrator.cpp use namespace alias Co-Authored-By: TheAssassin --- src/libappimage/desktop_integration/integrator/Integrator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index c41a1587..7cbf5ee7 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -323,7 +323,7 @@ namespace appimage { for (auto& itr: mimeInfoFiles) { MimeInfoEditor& editor = itr.second; editor.setDeployId(VENDOR_PREFIX + '_' + appImageId); - boost::filesystem::path deployPath = generateDeployPath(itr.first); + bf::path deployPath = generateDeployPath(itr.first); create_directories(deployPath.parent_path()); std::ofstream out(deployPath.string()); From 27113b383b809321324144a155e31ad179b338d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20L=C3=B3pez=20Zubieta?= Date: Wed, 3 Jul 2019 15:00:56 +0000 Subject: [PATCH 14/17] Update src/libappimage/desktop_integration/integrator/Integrator.cpp use namespace alias Co-Authored-By: TheAssassin --- src/libappimage/desktop_integration/integrator/Integrator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index 7cbf5ee7..e690f845 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -294,7 +294,7 @@ namespace appimage { std::stringstream fileNameBuilder; fileNameBuilder << VENDOR_PREFIX << "_" << appImageId << "_" << path.filename().string(); - boost::filesystem::path relativeParentPath = generateDeployParentPath(path); + bf::path relativeParentPath = generateDeployParentPath(path); bf::path newPath = xdgDataHome / relativeParentPath / fileNameBuilder.str(); return newPath; From 83932eafe359827ee3cda5608489d28121bb399f Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Wed, 3 Jul 2019 12:13:18 -0500 Subject: [PATCH 15/17] Use stable release of appimagetool --- tests/data/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/CMakeLists.txt b/tests/data/CMakeLists.txt index d61dfba6..7d43d91c 100644 --- a/tests/data/CMakeLists.txt +++ b/tests/data/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT EXISTS ${APPIMAGETOOL_BIN}) endif() message(STATUS "Downloading appimagetool for ${APPIMAGETOOL_BIN_ARCH}") - file(DOWNLOAD "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${APPIMAGETOOL_BIN_ARCH}.AppImage" "${APPIMAGETOOL_BIN}") + file(DOWNLOAD "https://github.com/AppImage/AppImageKit/releases/download/12/appimagetool-${APPIMAGETOOL_BIN_ARCH}.AppImage" "${APPIMAGETOOL_BIN}") execute_process(COMMAND chmod +x ${APPIMAGETOOL_BIN}) endif() From 7ef3c6198c484f2435ff0576e73a9fdc4df7a11e Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Wed, 3 Jul 2019 12:13:48 -0500 Subject: [PATCH 16/17] Improve MimeInfoEditor members naming --- .../integrator/Integrator.cpp | 6 +++-- .../integrator/MimeInfoEditor.cpp | 25 +++++++++++-------- .../integrator/MimeInfoEditor.h | 10 ++++---- .../integrator/TestMimeInfoEditor.cpp | 8 +++--- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index e690f845..cba51bd6 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -84,6 +84,7 @@ namespace appimage { */ void extractMimeInfoFiles() { std::vector mimeInfoPaths = resourcesExtractor.getMimeTypePackagesPaths(); + for (const std::string& path: mimeInfoPaths) { std::string mimeInfoFileData = resourcesExtractor.extractText(path); mimeInfoFiles.insert(std::make_pair(path, MimeInfoEditor(mimeInfoFileData))); @@ -316,18 +317,19 @@ namespace appimage { if (relativeParentPath == defaultXdgDataDirPath) relativeParentPath.clear(); } + return relativeParentPath; } void deployMimeTypePackages() { for (auto& itr: mimeInfoFiles) { MimeInfoEditor& editor = itr.second; - editor.setDeployId(VENDOR_PREFIX + '_' + appImageId); + editor.prependDeployIdToIcons(VENDOR_PREFIX + '_' + appImageId); bf::path deployPath = generateDeployPath(itr.first); create_directories(deployPath.parent_path()); std::ofstream out(deployPath.string()); - out << editor.edit(); + out << editor.getResult(); out.close(); } } diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp index 5a5e11ce..21415fb9 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.cpp @@ -23,7 +23,21 @@ namespace appimage { } } - std::string MimeInfoEditor::edit() { + std::string MimeInfoEditor::getResult() { + try { + using boost::property_tree::ptree; + std::stringstream out; + + write_xml(out, pt); + + return out.str(); + } catch (const std::runtime_error& error) { + appimage::utils::Logger::warning(std::string("Unable to edit MimeInfo: ") + error.what()); + return std::string{}; + } + } + + void MimeInfoEditor::prependDeployIdToIcons(const std::string& deployId) { try { using boost::property_tree::ptree; @@ -45,20 +59,11 @@ namespace appimage { subTree.put("icon..name", newIconName); } } - - std::stringstream out; - write_xml(out, pt); - return out.str(); } catch (const std::runtime_error& error) { appimage::utils::Logger::warning(std::string("Unable to edit MimeInfo: ") + error.what()); - return std::string{}; } } - void MimeInfoEditor::setDeployId(const std::string& deployId) { - MimeInfoEditor::deployId = deployId; - } - std::list MimeInfoEditor::getMimeTypeIconNames() const { std::list icons; diff --git a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h index ddd3a012..ef6bb898 100644 --- a/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h +++ b/src/libappimage/desktop_integration/integrator/MimeInfoEditor.h @@ -23,16 +23,17 @@ namespace appimage { MimeInfoEditor(std::string data); /** - * Set the deploy id to be prepended to the icon file name + * @brief Prepends to the icon file name + * + * * @param deployId */ - void setDeployId(const std::string& deployId); + void prependDeployIdToIcons(const std::string& deployId); /** - * Apply modification to the MimeInfo file * @return modified MimeInfo */ - std::string edit(); + std::string getResult(); /** * Extract the icon names from from the icon entry or the mime type name @@ -42,7 +43,6 @@ namespace appimage { private: boost::property_tree::ptree pt; - std::string deployId; }; } } diff --git a/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp index 81010bea..9d1a44cb 100644 --- a/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp +++ b/tests/libappimage/desktop_integration/integrator/TestMimeInfoEditor.cpp @@ -58,8 +58,8 @@ class MimeInfoEditorTests : public ::testing::Test { TEST_F(MimeInfoEditorTests, setIcon) { MimeInfoEditor editor(mimeInfo.str()); - editor.setDeployId("appimaged_d41d8cd98f00b204e9800998ecf8427e"); - std::string result = editor.edit(); + editor.prependDeployIdToIcons("appimaged_d41d8cd98f00b204e9800998ecf8427e"); + std::string result = editor.getResult(); using boost::property_tree::ptree; @@ -77,8 +77,8 @@ TEST_F(MimeInfoEditorTests, setIcon) { TEST_F(MimeInfoEditorTests, updateIcon) { MimeInfoEditor editor(mimeInfoWithIconEntry.str()); - editor.setDeployId("appimaged_d41d8cd98f00b204e9800998ecf8427e"); - std::string result = editor.edit(); + editor.prependDeployIdToIcons("appimaged_d41d8cd98f00b204e9800998ecf8427e"); + std::string result = editor.getResult(); using boost::property_tree::ptree; From 14d7726bf5182b49d90994bc72cfbea9f7cb945e Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 4 Jul 2019 11:26:59 -0500 Subject: [PATCH 17/17] Add comments --- .../desktop_integration/integrator/Integrator.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libappimage/desktop_integration/integrator/Integrator.cpp b/src/libappimage/desktop_integration/integrator/Integrator.cpp index cba51bd6..1e073c08 100644 --- a/src/libappimage/desktop_integration/integrator/Integrator.cpp +++ b/src/libappimage/desktop_integration/integrator/Integrator.cpp @@ -218,12 +218,13 @@ namespace appimage { } void deployMimeTypeIcons() { + // Resolve mime type icon names std::list mimeTypeIconNames; for (const auto& editor : mimeInfoFiles) { auto names = editor.second.getMimeTypeIconNames(); mimeTypeIconNames.merge(names); } - + // Resolve file paths for the icon names std::vector mimeTypeIconPaths; for (const auto& iconName: mimeTypeIconNames) { auto paths = resourcesExtractor.getIconFilePaths(iconName); @@ -323,11 +324,15 @@ namespace appimage { void deployMimeTypePackages() { for (auto& itr: mimeInfoFiles) { + // Prepare mime type package to be deployed MimeInfoEditor& editor = itr.second; editor.prependDeployIdToIcons(VENDOR_PREFIX + '_' + appImageId); bf::path deployPath = generateDeployPath(itr.first); + // ensure parent dir exists create_directories(deployPath.parent_path()); + + // write mime type file std::ofstream out(deployPath.string()); out << editor.getResult(); out.close();