Merge pull request #41 from linuxdeploy/integration_test

Improve AppDir root files deployment
This commit is contained in:
TheAssassin
2018-11-06 15:48:05 +01:00
committed by GitHub
6 changed files with 233 additions and 55 deletions

View File

@@ -45,7 +45,7 @@ add_subdirectory(util)
add_subdirectory(plugin)
add_subdirectory(core)
add_executable(linuxdeploy main.cpp)
add_executable(linuxdeploy main.cpp core.cpp)
target_link_libraries(linuxdeploy linuxdeploy_core args)
set_target_properties(linuxdeploy PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")

88
src/core.cpp Normal file
View File

@@ -0,0 +1,88 @@
#include <iostream>
#include <boost/filesystem/path.hpp>
#include <linuxdeploy/core/appdir.h>
#include <linuxdeploy/core/log.h>
#include "core.h"
using namespace linuxdeploy::core;
using namespace linuxdeploy::core::log;
namespace bf = boost::filesystem;
namespace linuxdeploy {
class DeployError : public std::runtime_error {
public:
explicit DeployError(const std::string& what) : std::runtime_error(what) {};
};
/**
* Resolve the 'MAIN' desktop file from all the available.
*
* @param desktopFilePaths
* @param deployedDesktopFiles
* @return the MAIN DesktopFile
* @throw DeployError in case of 'deployed desktop file not found'
*/
desktopfile::DesktopFile getMainDesktopFile(const std::vector<std::string>& desktopFilePaths,
const std::vector<desktopfile::DesktopFile>& deployedDesktopFiles) {
if (desktopFilePaths.empty()) {
ldLog() << LD_WARNING << "No desktop file specified, using first desktop file found:"
<< deployedDesktopFiles[0].path() << std::endl;
return deployedDesktopFiles[0];
}
auto firstDeployedDesktopFileName = boost::filesystem::path(
desktopFilePaths.front()).filename().string();
auto desktopFileMatchingName = find_if(
deployedDesktopFiles.begin(),
deployedDesktopFiles.end(),
[&firstDeployedDesktopFileName](const desktopfile::DesktopFile& desktopFile) {
auto fileName = desktopFile.path().filename().string();
return fileName == firstDeployedDesktopFileName;
}
);
if (desktopFileMatchingName != deployedDesktopFiles.end()) {
return *desktopFileMatchingName;
} else {
ldLog() << LD_ERROR << "Could not find desktop file deployed earlier any more:"
<< firstDeployedDesktopFileName << std::endl;
throw DeployError("Old desktop file is not reachable.");
}
}
bool deployAppDirRootFiles(std::vector<std::string> desktopFilePaths,
std::string customAppRunPath, appdir::AppDir& appDir) {
ldLog() << std::endl << "-- Deploying files into AppDir root directory --" << std::endl;
if (!customAppRunPath.empty()) {
ldLog() << LD_INFO << "Deploying custom AppRun: " << customAppRunPath << std::endl;
const auto& appRunPathInAppDir = appDir.path() / "AppRun";
if (bf::exists(appRunPathInAppDir)) {
ldLog() << LD_WARNING << "File exists, replacing with custom AppRun" << std::endl;
bf::remove(appRunPathInAppDir);
}
appDir.deployFile(customAppRunPath, appDir.path() / "AppRun");
appDir.executeDeferredOperations();
}
auto deployedDesktopFiles = appDir.deployedDesktopFiles();
if (deployedDesktopFiles.empty()) {
ldLog() << LD_WARNING << "Could not find desktop file in AppDir, cannot create links for AppRun, "
"desktop file and icon in AppDir root" << std::endl;
return true;
}
try {
desktopfile::DesktopFile desktopFile = getMainDesktopFile(desktopFilePaths, deployedDesktopFiles);
ldLog() << "Deploying desktop file:" << desktopFile.path() << std::endl;
return appDir.createLinksInAppDirRoot(desktopFile, customAppRunPath);
} catch (const DeployError& er) {
return false;
}
}
}

20
src/core.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include <iostream>
#include <boost/filesystem/path.hpp>
#include "linuxdeploy/core/appdir.h"
namespace linuxdeploy {
/**
* Deploy the application ".deskop", icon, and runnable files in the AppDir root path. According to the
* AppDir spec at: https://docs.appimage.org/reference/appdir.html
*
* @param desktopFilePaths to be deployed in the AppDir root
* @param customAppRunPath AppRun to be used, if empty the application executable will be used instead
* @param appDir
* @return true on success otherwise false
*/
bool deployAppDirRootFiles(std::vector<std::string> desktopFilePaths, std::string customAppRunPath,
linuxdeploy::core::appdir::AppDir& appDir);
}

View File

@@ -12,6 +12,7 @@
#include "linuxdeploy/core/log.h"
#include "linuxdeploy/plugin/plugin.h"
#include "linuxdeploy/util/util.h"
#include "core.h"
using namespace linuxdeploy::core;
using namespace linuxdeploy::core::log;
@@ -253,60 +254,8 @@ int main(int argc, char** argv) {
return 1;
}
}
// search for desktop file and deploy it to AppDir root
ldLog() << std::endl << "-- Deploying files into AppDir root directory --" << std::endl;
if (bf::is_regular_file(appDir.path() / "AppRun")) {
if (customAppRunPath)
ldLog() << LD_WARNING << "AppRun exists but custom AppRun specified, overwriting existing AppRun" << std::endl;
else
ldLog() << LD_WARNING << "AppRun exists, skipping deployment" << std::endl;
} else {
auto deployedDesktopFiles = appDir.deployedDesktopFiles();
desktopfile::DesktopFile desktopFile;
if (deployedDesktopFiles.empty()) {
ldLog() << LD_WARNING << "Could not find desktop file in AppDir, cannot create links for AppRun, desktop file and icon in AppDir root" << std::endl;
} else {
if (!desktopFilePaths.Get().empty()) {
auto firstDeployedDesktopFileName = bf::path(desktopFilePaths.Get().front()).filename().string();
auto desktopFileMatchingName = std::find_if(
deployedDesktopFiles.begin(),
deployedDesktopFiles.end(),
[&firstDeployedDesktopFileName](const desktopfile::DesktopFile& desktopFile) {
auto fileName = desktopFile.path().filename().string();
return fileName == firstDeployedDesktopFileName;
}
);
if (desktopFileMatchingName != deployedDesktopFiles.end()) {
desktopFile = *desktopFileMatchingName;
} else {
ldLog() << LD_ERROR << "Could not find desktop file deployed earlier any more:" << firstDeployedDesktopFileName << std::endl;
return 1;
}
} else {
desktopFile = deployedDesktopFiles[0];
ldLog() << LD_WARNING << "No desktop file specified, using first desktop file found:" << desktopFile.path() << std::endl;
}
ldLog() << "Deploying desktop file:" << desktopFile.path() << std::endl;
bool rv;
if (customAppRunPath) {
rv = appDir.createLinksInAppDirRoot(desktopFile, customAppRunPath.Get());
} else {
rv = appDir.createLinksInAppDirRoot(desktopFile);
}
if (!rv)
return 1;
}
}
if (!linuxdeploy::deployAppDirRootFiles(desktopFilePaths.Get(), customAppRunPath.Get(), appDir))
return 1;
if (outputPlugins) {
for (const auto& pluginName : outputPlugins.Get()) {
@@ -342,3 +291,4 @@ int main(int argc, char** argv) {
return 0;
}

View File

@@ -16,3 +16,24 @@ add_test(test_appdir test_appdir)
# make sure library and executable are built before test_appdir
add_dependencies(test_appdir simple_library simple_executable)
add_executable(test_linuxdeploy test_linuxdeploy.cpp ../../src/core.cpp)
target_link_libraries(test_linuxdeploy PRIVATE linuxdeploy_core args gtest gtest_main)
target_include_directories(test_linuxdeploy PRIVATE ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/src)
# calculate paths to resources using CMake and hardcode them in the test binary
target_compile_definitions(test_linuxdeploy PRIVATE
-DSIMPLE_LIBRARY_PATH="$<TARGET_FILE:simple_library>"
-DSIMPLE_EXECUTABLE_PATH="$<TARGET_FILE:simple_executable>"
-DSIMPLE_DESKTOP_ENTRY_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../data/simple_app.desktop"
-DSIMPLE_ICON_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../data/simple_icon.svg"
-DSIMPLE_FILE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../data/simple_file.txt"
)
# register in CTest
add_test(test_linuxdeploy test_linuxdeploy)
# make sure library and executable are built before test_appdir
add_dependencies(test_linuxdeploy simple_library simple_executable)

View File

@@ -0,0 +1,99 @@
#include "gtest/gtest.h"
#include "core.h"
using namespace std;
namespace bf = boost::filesystem;
namespace LinuxDeployTest {
class LinuxDeployTestsFixture : public ::testing::Test {
public:
bf::path tmpAppDir;
bf::path source_executable_path;
bf::path target_executable_path;
bf::path source_desktop_path;
bf::path target_desktop_path;
bf::path source_icon_path;
bf::path target_icon_path;
bf::path source_apprun_path;
bf::path target_apprun_path;
void SetUp() override {
tmpAppDir = bf::temp_directory_path() / bf::unique_path("linuxdeploy-tests-%%%%-%%%%-%%%%");
source_executable_path = SIMPLE_EXECUTABLE_PATH;
target_executable_path = tmpAppDir / "usr/bin" / source_executable_path.filename();
source_desktop_path = SIMPLE_DESKTOP_ENTRY_PATH;
target_desktop_path = tmpAppDir / "usr/share/applications" / source_desktop_path.filename();
source_icon_path = SIMPLE_ICON_PATH;
target_icon_path = tmpAppDir / "usr/share/icons/hicolor/scalable/apps" / source_icon_path.filename();
source_apprun_path = SIMPLE_FILE_PATH;
target_apprun_path = tmpAppDir / "AppRun";
create_directories(tmpAppDir);
}
void TearDown() override {
remove_all(tmpAppDir);
}
~LinuxDeployTestsFixture() override = default;
void listDeployedFiles() {
std::cout << "Files deployed in AppDir:" << std::endl;
bf::recursive_directory_iterator end_itr; // default construction yields past-the-end
for (bf::recursive_directory_iterator itr(tmpAppDir); itr != end_itr; itr++) {
std::cout << relative(itr->path(), tmpAppDir).string() << std::endl;
}
}
void fillRegularAppDir() {
add_executable();
add_desktop();
add_icon();
}
bf::path add_executable() const {
create_directories(target_executable_path.parent_path());
copy_file(source_executable_path, target_executable_path);
return target_executable_path;
}
void add_desktop() const {
create_directories(target_desktop_path.parent_path());
copy_file(source_desktop_path, target_desktop_path);
}
void add_icon() const {
create_directories(target_icon_path.parent_path());
copy_file(source_icon_path, target_icon_path);
}
void add_apprun() const {
copy_file(source_apprun_path, target_apprun_path);
}
};
TEST_F(LinuxDeployTestsFixture, deployAppDirRootFilesWithExistentAppRun) {
fillRegularAppDir();
add_apprun();
linuxdeploy::core::appdir::AppDir appDir(tmpAppDir);
linuxdeploy::deployAppDirRootFiles({}, "", appDir);
ASSERT_TRUE(exists(tmpAppDir / source_desktop_path.filename()));
ASSERT_TRUE(exists(tmpAppDir / source_icon_path.filename()));
ASSERT_TRUE(exists(target_apprun_path));
}
TEST_F(LinuxDeployTestsFixture, deployAppDirRootFilesWithCustomAppRun) {
linuxdeploy::core::appdir::AppDir appDir(tmpAppDir);
linuxdeploy::deployAppDirRootFiles({}, source_apprun_path.string(), appDir);
ASSERT_TRUE(exists(target_apprun_path));
}
}