2 #include <boost/filesystem/path.hpp>
4 #include "includes/appdir.h"
5 #include "includes/log.h"
7 #include "includes/core.h"
9 using namespace linuxdeploy::core;
10 using namespace linuxdeploy::core::log;
11 using namespace linuxdeploy::desktopfile;
12 namespace bf = boost::filesystem;
14 namespace linuxdeploy {
15 class DeployError : public std::runtime_error {
17 explicit DeployError(const std::string& what) : std::runtime_error(what) {};
21 * Resolve the 'MAIN' desktop file from all the available.
23 * @param desktopFilePaths
24 * @param deployedDesktopFiles
25 * @return the MAIN DesktopFile
26 * @throw DeployError in case of 'deployed desktop file not found'
28 desktopfile::DesktopFile getMainDesktopFile(const std::vector<std::string>& desktopFilePaths,
29 const std::vector<desktopfile::DesktopFile>& deployedDesktopFiles) {
30 if (desktopFilePaths.empty()) {
31 ldLog() << LD_WARNING << "No desktop file specified, using first desktop file found:"
32 << deployedDesktopFiles[0].path() << std::endl;
33 return deployedDesktopFiles[0];
36 auto firstDeployedDesktopFileName = boost::filesystem::path(desktopFilePaths.front()).filename().string();
38 auto desktopFileMatchingName = find_if(
39 deployedDesktopFiles.begin(),
40 deployedDesktopFiles.end(),
41 [&firstDeployedDesktopFileName](const desktopfile::DesktopFile& desktopFile) {
42 auto fileName = bf::path(desktopFile.path()).filename().string();
43 return fileName == firstDeployedDesktopFileName;
47 if (desktopFileMatchingName != deployedDesktopFiles.end()) {
48 return *desktopFileMatchingName;
50 ldLog() << LD_ERROR << "Could not find desktop file deployed earlier any more:"
51 << firstDeployedDesktopFileName << std::endl;
52 throw DeployError("Old desktop file is not reachable.");
56 bool deployAppDirRootFiles(std::vector<std::string> desktopFilePaths,
57 std::string customAppRunPath, appdir::AppDir& appDir) {
58 ldLog() << std::endl << "-- Deploying files into AppDir root directory --" << std::endl;
60 if (!customAppRunPath.empty()) {
61 ldLog() << LD_INFO << "Deploying custom AppRun: " << customAppRunPath << std::endl;
63 const auto& appRunPathInAppDir = appDir.path() / "AppRun";
64 if (bf::exists(appRunPathInAppDir)) {
65 ldLog() << LD_WARNING << "File exists, replacing with custom AppRun" << std::endl;
66 bf::remove(appRunPathInAppDir);
69 appDir.deployFile(customAppRunPath, appDir.path() / "AppRun");
70 appDir.executeDeferredOperations();
73 auto deployedDesktopFiles = appDir.deployedDesktopFiles();
74 if (deployedDesktopFiles.empty()) {
75 ldLog() << LD_WARNING << "Could not find desktop file in AppDir, cannot create links for AppRun, "
76 "desktop file and icon in AppDir root" << std::endl;
81 desktopfile::DesktopFile desktopFile = getMainDesktopFile(desktopFilePaths, deployedDesktopFiles);
82 ldLog() << "Deploying files to AppDir root using desktop file:" << desktopFile.path() << std::endl;
83 return appDir.setUpAppDirRoot(desktopFile, customAppRunPath);
84 } catch (const DeployError& er) {
89 bool addDefaultKeys(DesktopFile& desktopFile, const std::string& executableFileName) {
90 ldLog() << "Adding default values to desktop file:" << desktopFile.path() << std::endl;
94 auto setDefault = [&rv, &desktopFile](const std::string& section, const std::string& key, const std::string& value) {
95 if (desktopFile.entryExists(section, key)) {
96 DesktopFileEntry entry;
98 // this should never return false
99 auto entryExists = desktopFile.getEntry(section, key, entry);
102 ldLog() << LD_WARNING << "Key exists, not modified:" << key << "(current value:" << entry.value() << LD_NO_SPACE << ")" << std::endl;
105 auto entryOverwritten = desktopFile.setEntry(section, DesktopFileEntry(key, value));
106 assert(!entryOverwritten);
110 setDefault("Desktop Entry", "Name", executableFileName);
111 setDefault("Desktop Entry", "Exec", executableFileName);
112 setDefault("Desktop Entry", "Icon", executableFileName);
113 setDefault("Desktop Entry", "Type", "Application");
114 setDefault("Desktop Entry", "Categories", "Utility;");