summaryrefslogtreecommitdiff
path: root/src/managers/VersionKeeperManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/managers/VersionKeeperManager.cpp')
-rw-r--r--src/managers/VersionKeeperManager.cpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/managers/VersionKeeperManager.cpp b/src/managers/VersionKeeperManager.cpp
new file mode 100644
index 00000000..89f7823d
--- /dev/null
+++ b/src/managers/VersionKeeperManager.cpp
@@ -0,0 +1,153 @@
+#include "VersionKeeperManager.hpp"
+#include "../debug/Log.hpp"
+#include "../macros.hpp"
+#include "../version.h"
+#include "../helpers/MiscFunctions.hpp"
+#include "../helpers/varlist/VarList.hpp"
+#include "eventLoop/EventLoopManager.hpp"
+#include "../config/ConfigValue.hpp"
+
+#include <filesystem>
+#include <fstream>
+#include <hyprutils/string/String.hpp>
+#include <hyprutils/os/Process.hpp>
+
+using namespace Hyprutils::String;
+using namespace Hyprutils::OS;
+
+constexpr const char* VERSION_FILE_NAME = "lastVersion";
+
+CVersionKeeperManager::CVersionKeeperManager() {
+ static auto PNONOTIFY = CConfigValue<Hyprlang::INT>("ecosystem:no_update_news");
+
+ const auto DATAROOT = getDataHome();
+
+ if (!DATAROOT)
+ return;
+
+ const auto LASTVER = getDataLastVersion(*DATAROOT);
+
+ if (!LASTVER)
+ return;
+
+ if (!isVersionOlderThanRunning(*LASTVER)) {
+ Debug::log(LOG, "CVersionKeeperManager: Read version {} matches or is older than running.", *LASTVER);
+ return;
+ }
+
+ writeVersionToVersionFile(*DATAROOT);
+
+ if (*PNONOTIFY) {
+ Debug::log(LOG, "CVersionKeeperManager: updated, but update news is disabled in the config :(");
+ return;
+ }
+
+ if (!executableExistsInPath("hyprland-update-screen")) {
+ Debug::log(ERR, "CVersionKeeperManager: hyprland-update-screen doesn't seem to exist, skipping notif about update...");
+ return;
+ }
+
+ g_pEventLoopManager->doLater([]() {
+ CProcess proc("hyprland-update-screen", {"--new-version", HYPRLAND_VERSION});
+ proc.runAsync();
+ });
+}
+
+std::optional<std::string> CVersionKeeperManager::getDataHome() {
+ const auto DATA_HOME = getenv("XDG_DATA_HOME");
+
+ std::string dataRoot;
+
+ if (!DATA_HOME) {
+ const auto HOME = getenv("HOME");
+
+ if (!HOME) {
+ Debug::log(ERR, "CVersionKeeperManager: can't get data home: no $HOME or $XDG_DATA_HOME");
+ return std::nullopt;
+ }
+
+ dataRoot = HOME + std::string{"/.local/share/"};
+ } else
+ dataRoot = DATA_HOME + std::string{"/"};
+
+ std::error_code ec;
+ if (!std::filesystem::exists(dataRoot, ec) || ec) {
+ Debug::log(ERR, "CVersionKeeperManager: can't get data home: inaccessible / missing");
+ return std::nullopt;
+ }
+
+ dataRoot += "hyprland/";
+
+ if (!std::filesystem::exists(dataRoot, ec) || ec) {
+ Debug::log(LOG, "CVersionKeeperManager: no hyprland data home, creating.");
+ std::filesystem::create_directory(dataRoot, ec);
+ if (ec) {
+ Debug::log(ERR, "CVersionKeeperManager: can't create new data home for hyprland");
+ return std::nullopt;
+ }
+ std::filesystem::permissions(dataRoot, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | std::filesystem::perms::owner_exec, ec);
+ if (ec)
+ Debug::log(WARN, "CVersionKeeperManager: couldn't set perms on hyprland data store. Proceeding anyways.");
+ }
+
+ if (!std::filesystem::exists(dataRoot, ec) || ec) {
+ Debug::log(ERR, "CVersionKeeperManager: no hyprland data home, failed to create.");
+ return std::nullopt;
+ }
+
+ return dataRoot;
+}
+
+std::optional<std::string> CVersionKeeperManager::getDataLastVersion(const std::string& dataRoot) {
+ std::error_code ec;
+ std::string lastVerFile = dataRoot + "/" + VERSION_FILE_NAME;
+
+ if (!std::filesystem::exists(lastVerFile, ec) || ec) {
+ Debug::log(LOG, "CVersionKeeperManager: no hyprland last version file, creating.");
+ writeVersionToVersionFile(dataRoot);
+
+ return HYPRLAND_VERSION;
+ }
+
+ std::ifstream file(lastVerFile);
+ if (!file.good()) {
+ Debug::log(ERR, "CVersionKeeperManager: couldn't open an ifstream for reading the version file.");
+ return std::nullopt;
+ }
+
+ return trim(std::string((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>())));
+}
+
+void CVersionKeeperManager::writeVersionToVersionFile(const std::string& dataRoot) {
+ std::string lastVerFile = dataRoot + "/" + VERSION_FILE_NAME;
+ std::ofstream of(lastVerFile, std::ios::trunc);
+ if (!of.good()) {
+ Debug::log(ERR, "CVersionKeeperManager: couldn't open an ofstream for writing the version file.");
+ return;
+ }
+
+ of << HYPRLAND_VERSION;
+ of.close();
+}
+
+bool CVersionKeeperManager::isVersionOlderThanRunning(const std::string& ver) {
+ const CVarList verStrings(ver, 0, '.', true);
+
+ const int V1 = configStringToInt(verStrings[0]).value_or(0);
+ const int V2 = configStringToInt(verStrings[1]).value_or(0);
+ const int V3 = configStringToInt(verStrings[2]).value_or(0);
+
+ static const CVarList runningStrings(HYPRLAND_VERSION, 0, '.', true);
+
+ static const int R1 = configStringToInt(runningStrings[0]).value_or(0);
+ static const int R2 = configStringToInt(runningStrings[1]).value_or(0);
+ static const int R3 = configStringToInt(runningStrings[2]).value_or(0);
+
+ if (R1 > V1)
+ return true;
+ if (R2 > V2)
+ return true;
+ if (R3 > V3)
+ return true;
+ return false;
+}