diff options
-rw-r--r-- | hyprpm/src/core/PluginManager.cpp | 135 | ||||
-rw-r--r-- | hyprpm/src/core/PluginManager.hpp | 5 |
2 files changed, 87 insertions, 53 deletions
diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 6ac5445e..14b93d3e 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -12,6 +12,10 @@ #include <algorithm> #include <format> +#include <sys/types.h> +#include <sys/stat.h> +#include <pwd.h> + #include <toml++/toml.hpp> static std::string removeBeginEndSpacesTabs(std::string str) { @@ -92,6 +96,22 @@ SHyprlandVersion CPluginManager::getHyprlandVersion() { return ver; } +bool CPluginManager::createSafeDirectory(const std::string& path) { + if (path.empty() || !path.starts_with("/tmp")) + return false; + + if (std::filesystem::exists(path)) + std::filesystem::remove_all(path); + + if (std::filesystem::exists(path)) + return false; + + if (mkdir(path.c_str(), S_IRWXU) < 0) + return false; + + return true; +} + bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& rev) { const auto HLVER = getHyprlandVersion(); @@ -137,24 +157,31 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& if (!std::filesystem::exists("/tmp/hyprpm")) { std::filesystem::create_directory("/tmp/hyprpm"); std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); + } else if (!std::filesystem::is_directory("/tmp/hyprpm")) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hyprpm\n"; + return false; } - if (std::filesystem::exists("/tmp/hyprpm/new")) { - progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old plugin repo build files found in temp directory, removing."); - std::filesystem::remove_all("/tmp/hyprpm/new"); + const std::string USERNAME = getpwuid(getuid())->pw_name; + + m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; + + if (!createSafeDirectory(m_szWorkingPluginDirectory)) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for repo\n"; + return false; } progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " new"); + std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " " + USERNAME); - if (!std::filesystem::exists("/tmp/hyprpm/new")) { + if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n"; return false; } if (!rev.empty()) { - std::string ret = execAndGet("git -C /tmp/hyprpm/new reset --hard --recurse-submodules " + rev); + std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + rev); if (ret.compare(0, 6, "fatal:") == 0) { std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n"; return false; @@ -168,12 +195,12 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::unique_ptr<CManifest> pManifest; - if (std::filesystem::exists("/tmp/hyprpm/new/hyprpm.toml")) { + if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) { progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); - pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, "/tmp/hyprpm/new/hyprpm.toml"); - } else if (std::filesystem::exists("/tmp/hyprpm/new/hyprload.toml")) { + pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml"); + } else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) { progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); - pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, "/tmp/hyprpm/new/hyprload.toml"); + pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml"); } if (!pManifest) { @@ -212,7 +239,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); - execAndGet("cd /tmp/hyprpm/new/ && git reset --hard --recurse-submodules " + plugin); + execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin); } } @@ -243,14 +270,14 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); for (auto& bs : p.buildSteps) { - std::string cmd = std::format("cd /tmp/hyprpm/new && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs); + std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } if (m_bVerbose) std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; - if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) { + if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n" + " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update " "first.\n Try re-running with -v to see " @@ -270,7 +297,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& // add repo toml to DataState SPluginRepository repo; - std::string repohash = execAndGet("cd /tmp/hyprpm/new/ && git rev-parse HEAD"); + std::string repohash = execAndGet("cd " + m_szWorkingPluginDirectory + " && git rev-parse HEAD"); if (repohash.length() > 0) repohash.pop_back(); repo.name = pManifest->m_sRepository.name.empty() ? url.substr(url.find_last_of('/') + 1) : pManifest->m_sRepository.name; @@ -278,7 +305,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& repo.rev = rev; repo.hash = repohash; for (auto& p : pManifest->m_vPlugins) { - repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false, p.failed}); + repo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, false, p.failed}); } DataState::addNewPluginRepo(repo); @@ -291,7 +318,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& std::cout << "\n"; // remove build files - std::filesystem::remove_all("/tmp/hyprpm/new"); + std::filesystem::remove_all(m_szWorkingPluginDirectory); return true; } @@ -404,9 +431,12 @@ bool CPluginManager::updateHeaders(bool force) { progress.m_szCurrentMessage = "Cloning the hyprland repository"; progress.print(); - if (std::filesystem::exists("/tmp/hyprpm/hyprland")) { - progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old hyprland source files found in temp directory, removing."); - std::filesystem::remove_all("/tmp/hyprpm/hyprland"); + const std::string USERNAME = getpwuid(getuid())->pw_name; + const auto WORKINGDIR = "/tmp/hyprpm/hyprland-" + USERNAME; + + if (!createSafeDirectory(WORKINGDIR)) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not prepare working dir for hl\n"; + return false; } progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment."); @@ -418,14 +448,14 @@ bool CPluginManager::updateHeaders(bool force) { if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "will shallow since: " + SHALLOW_DATE); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland --shallow-since='" + SHALLOW_DATE + "'"); + std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME + " --shallow-since='" + SHALLOW_DATE + "'"); - if (!std::filesystem::exists("/tmp/hyprpm/hyprland")) { + if (!std::filesystem::exists(WORKINGDIR)) { progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Clone failed. Retrying without shallow."); - ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland"); + ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland-" + USERNAME); } - if (!std::filesystem::exists("/tmp/hyprpm/hyprland")) { + if (!std::filesystem::exists(WORKINGDIR + "/.git")) { std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n"; return false; } @@ -435,12 +465,12 @@ bool CPluginManager::updateHeaders(bool force) { progress.m_szCurrentMessage = "Checking out sources"; progress.print(); - ret = execAndGet("cd /tmp/hyprpm/hyprland && git checkout " + HLVER.branch + " 2>&1"); + ret = execAndGet("cd " + WORKINGDIR + " && git checkout " + HLVER.branch + " 2>&1"); if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (co): " + ret); - ret = execAndGet("cd /tmp/hyprpm/hyprland && git rm subprojects/tracy && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash); + ret = execAndGet("cd " + WORKINGDIR + " && git rm subprojects/tracy && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash); if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned (rs): " + ret); @@ -455,14 +485,13 @@ bool CPluginManager::updateHeaders(bool force) { if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath()); - ret = execAndGet( - std::format("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja", - DataState::getHeadersPath())); + ret = execAndGet(std::format("cd {} && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja", WORKINGDIR, + DataState::getHeadersPath())); if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret); // le hack. Wlroots has to generate its build/include - ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots-hyprland && meson setup -Drenderers=gles2 -Dexamples=false build"); + ret = execAndGet("cd " + WORKINGDIR + "/subprojects/wlroots-hyprland && meson setup -Drenderers=gles2 -Dexamples=false build"); if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret); @@ -471,8 +500,8 @@ bool CPluginManager::updateHeaders(bool force) { progress.m_szCurrentMessage = "Installing sources"; progress.print(); - std::string cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" /tmp/hyprpm/hyprland/Makefile && cd /tmp/hyprpm/hyprland && make installheaders", - DataState::getHeadersPath()); + std::string cmd = + std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" {}/Makefile && cd {} && make installheaders", WORKINGDIR, WORKINGDIR, DataState::getHeadersPath()); if (m_bVerbose) progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd); @@ -482,7 +511,7 @@ bool CPluginManager::updateHeaders(bool force) { std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n"; // remove build files - std::filesystem::remove_all("/tmp/hyprpm/hyprland"); + std::filesystem::remove_all(WORKINGDIR); auto HEADERSVALID = headersValid(); if (HEADERSVALID == HEADERS_OK) { @@ -529,6 +558,9 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.m_szCurrentMessage = "Updating repositories"; progress.print(); + const std::string USERNAME = getpwuid(getuid())->pw_name; + m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; + for (auto& repo : REPOS) { bool update = forceUpdateAll; @@ -538,16 +570,13 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name); - if (std::filesystem::exists("/tmp/hyprpm/update")) { - progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old update build files found in temp directory, removing."); - std::filesystem::remove_all("/tmp/hyprpm/update"); - } + createSafeDirectory(m_szWorkingPluginDirectory); progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " update"); + std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " " + USERNAME); - if (!std::filesystem::exists("/tmp/hyprpm/update")) { + if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/.git")) { std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret; return false; } @@ -555,7 +584,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { if (!repo.rev.empty()) { progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev); - std::string ret = execAndGet("git -C /tmp/hyprpm/update reset --hard --recurse-submodules " + repo.rev); + std::string ret = execAndGet("git -C " + m_szWorkingPluginDirectory + " reset --hard --recurse-submodules " + repo.rev); if (ret.compare(0, 6, "fatal:") == 0) { std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not check out revision " + repo.rev + ": shell returned:\n" + ret; return false; @@ -564,7 +593,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { if (!update) { // check if git has updates - std::string hash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD"); + std::string hash = execAndGet("cd " + m_szWorkingPluginDirectory + " && git rev-parse HEAD"); if (!hash.empty()) hash.pop_back(); @@ -572,7 +601,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { } if (!update) { - std::filesystem::remove_all("/tmp/hyprpm/update"); + std::filesystem::remove_all(m_szWorkingPluginDirectory); progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " is up-to-date."); progress.m_iSteps++; progress.print(); @@ -588,12 +617,12 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { std::unique_ptr<CManifest> pManifest; - if (std::filesystem::exists("/tmp/hyprpm/update/hyprpm.toml")) { + if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprpm.toml")) { progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); - pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, "/tmp/hyprpm/update/hyprpm.toml"); - } else if (std::filesystem::exists("/tmp/hyprpm/update/hyprload.toml")) { + pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, m_szWorkingPluginDirectory + "/hyprpm.toml"); + } else if (std::filesystem::exists(m_szWorkingPluginDirectory + "/hyprload.toml")) { progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); - pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, "/tmp/hyprpm/update/hyprload.toml"); + pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, m_szWorkingPluginDirectory + "/hyprload.toml"); } if (!pManifest) { @@ -617,7 +646,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); - execAndGet("cd /tmp/hyprpm/update/ && git reset --hard --recurse-submodules " + plugin); + execAndGet("cd " + m_szWorkingPluginDirectory + " && git reset --hard --recurse-submodules " + plugin); } } @@ -633,14 +662,14 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); for (auto& bs : p.buildSteps) { - std::string cmd = std::format("cd /tmp/hyprpm/update && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs); + std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; } if (m_bVerbose) std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; - if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) { + if (!std::filesystem::exists(m_szWorkingPluginDirectory + "/" + p.output)) { std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n" << " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update first.\n Try " @@ -656,20 +685,20 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { // add repo toml to DataState SPluginRepository newrepo = repo; newrepo.plugins.clear(); - execAndGet( - "cd /tmp/hyprpm/update/ && git pull --recurse-submodules && git reset --hard --recurse-submodules"); // repo hash in the state.toml has to match head and not any pin - std::string repohash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD"); + execAndGet("cd " + m_szWorkingPluginDirectory + + " && git pull --recurse-submodules && git reset --hard --recurse-submodules"); // repo hash in the state.toml has to match head and not any pin + std::string repohash = execAndGet("cd " + m_szWorkingPluginDirectory + " && git rev-parse HEAD"); if (repohash.length() > 0) repohash.pop_back(); newrepo.hash = repohash; for (auto& p : pManifest->m_vPlugins) { const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; }); - newrepo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/update/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false}); + newrepo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false}); } DataState::removePluginRepo(newrepo.name); DataState::addNewPluginRepo(newrepo); - std::filesystem::remove_all("/tmp/hyprpm/update"); + std::filesystem::remove_all(m_szWorkingPluginDirectory); progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name); } diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp index f934d34a..a87240e3 100644 --- a/hyprpm/src/core/PluginManager.hpp +++ b/hyprpm/src/core/PluginManager.hpp @@ -60,8 +60,13 @@ class CPluginManager { bool m_bVerbose = false; + // will delete recursively if exists!! + bool createSafeDirectory(const std::string& path); + private: std::string headerError(const eHeadersErrors err); + + std::string m_szWorkingPluginDirectory = ""; }; inline std::unique_ptr<CPluginManager> g_pPluginManager; |