Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.

Commit c755533

Browse files
authored
Merge pull request #3 from gelly-gmod/1-relocate
1 - Relocate to an installation dir
2 parents 3f6e68c + 0f15c34 commit c755533

15 files changed

+274
-0
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.3.0] - 2025-01-03
9+
10+
### Added
11+
12+
- The installer now automatically relocates itself to the installed apps directory.
13+
- This is in preparation for the upcoming auto-update feature.
14+
- Note: Opening the installer again will launch the installed app and not the one that was previously launched.
15+
816
## [1.2.0] - 2024-12-27
917

1018
### Added

CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ add_executable(gelly_installer WIN32
5656
src/logging/log.cpp
5757
src/logging/crash-logging.cpp
5858
src/logging/crash-logging.hpp
59+
src/helpers/find-app-data.cpp
60+
src/helpers/find-app-data.hpp
61+
src/app/config.cpp
62+
src/app/config.hpp
63+
src/app/relocate-installation.cpp
64+
src/app/relocate-installation.hpp
65+
src/helpers/launch-installer.cpp
66+
src/helpers/launch-installer.hpp
67+
src/helpers/parse-version.cpp
68+
src/helpers/parse-version.hpp
5969
)
6070

6171
target_link_libraries(gelly_installer
@@ -71,6 +81,7 @@ target_link_libraries(gelly_installer
7181
target_include_directories(gelly_installer
7282
PRIVATE
7383
src
84+
${CMAKE_CURRENT_BINARY_DIR}/src
7485
vendor/SDL/include
7586
vendor/VDFParser
7687
vendor/imgui
@@ -84,7 +95,10 @@ target_compile_definitions(gelly_installer
8495
)
8596

8697
include(ExtraFiles)
98+
include(GetCurrentVersion)
8799
get_extra_files(${CMAKE_CURRENT_SOURCE_DIR})
100+
get_current_version_from_changelog(${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md)
101+
configure_file(src/version.hpp.in src/version.hpp @ONLY)
88102

89103
foreach (file ${EXTRA_FILES})
90104
add_custom_command(TARGET gelly_installer POST_BUILD
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function(get_current_version_from_changelog changelog_file)
2+
file(READ ${changelog_file} CHANGELOG)
3+
string(REGEX MATCH "## \\[([0-9]+\.[0-9]+\.[0-9]+)\\]" _ ${CHANGELOG})
4+
set(GELLY_INSTALLER_VERSION ${CMAKE_MATCH_1} PARENT_SCOPE)
5+
endfunction()

src/app/config.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include "config.hpp"
2+
3+
#include "helpers/parse-version.hpp"
4+
5+
#include <array>
6+
#include <windows.h>
7+
8+
namespace gelly {
9+
namespace {
10+
auto REGISTRY_PARENT = std::string("SOFTWARE\\") + Config::APP_NAME;
11+
auto KEY = HKEY_CURRENT_USER;
12+
13+
std::optional<std::string> FetchFromGellyRegistry(const std::string &subkey) {
14+
std::array<char, MAX_PATH> value = {};
15+
DWORD size = sizeof(value);
16+
17+
const auto path = REGISTRY_PARENT;
18+
if (RegGetValue(KEY, path.c_str(), subkey.c_str(), RRF_RT_REG_SZ, nullptr,
19+
value.data(), &size) != ERROR_SUCCESS) {
20+
return std::nullopt;
21+
}
22+
23+
std::string valueStr(value.begin(), value.begin() + (size - 1));
24+
return valueStr;
25+
}
26+
27+
void WriteToGellyRegistry(const std::string &subkey, const std::string &value) {
28+
if (RegSetKeyValue(KEY, REGISTRY_PARENT.c_str(), subkey.c_str(),
29+
RRF_RT_REG_SZ, value.data(),
30+
value.size()) != ERROR_SUCCESS) {
31+
throw std::runtime_error("Failed to write to registry");
32+
}
33+
}
34+
} // namespace
35+
36+
optional<std::filesystem::path> Config::GetAppInstallPath() {
37+
return FetchFromGellyRegistry("InstallPath");
38+
}
39+
40+
void Config::SetAppInstallPath(const std::filesystem::path &path) {
41+
WriteToGellyRegistry("InstallPath", path.string());
42+
}
43+
44+
optional<std::string> Config::GetAppVersion() {
45+
return FetchFromGellyRegistry("Version");
46+
}
47+
48+
void Config::SetAppVersion(const std::string &version) {
49+
WriteToGellyRegistry("Version", version);
50+
}
51+
52+
bool Config::IsAppInstalled() {
53+
return GetAppInstallPath().has_value() &&
54+
std::filesystem::exists(*GetAppInstallPath());
55+
}
56+
57+
bool Config::IsAppUpToDate() {
58+
return IsAppInstalled() && (GetAppVersion().has_value() &&
59+
*helpers::ParseVersion(*GetAppVersion()) >=
60+
*helpers::ParseVersion(APP_VERSION));
61+
}
62+
} // namespace gelly

src/app/config.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
#include <filesystem>
4+
#include <optional>
5+
#include <version.hpp>
6+
7+
using std::optional;
8+
9+
namespace gelly {
10+
class Config {
11+
public:
12+
static constexpr auto APP_NAME = "GellyInstaller";
13+
static constexpr auto APP_VERSION = GELLY_INSTALLER_VERSION;
14+
15+
static optional<std::filesystem::path> GetAppInstallPath();
16+
static void SetAppInstallPath(const std::filesystem::path &path);
17+
18+
static optional<std::string> GetAppVersion();
19+
static void SetAppVersion(const std::string &version);
20+
21+
static bool IsAppInstalled();
22+
static bool IsAppUpToDate();
23+
};
24+
25+
} // namespace gelly

src/app/relocate-installation.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include "relocate-installation.hpp"
2+
#include "app/config.hpp"
3+
#include "helpers/find-app-data.hpp"
4+
5+
#include <filesystem>
6+
7+
namespace gelly {
8+
std::filesystem::path RelocateInstallation() {
9+
const auto cwd = std::filesystem::current_path();
10+
const auto appData = helpers::FindAppData();
11+
if (!appData.has_value()) {
12+
throw std::runtime_error("Failed to find AppData directory");
13+
}
14+
15+
const auto newPath = appData.value() / Config::APP_NAME;
16+
if (!std::filesystem::exists(newPath)) {
17+
std::filesystem::create_directories(newPath);
18+
} else {
19+
std::filesystem::remove_all(newPath);
20+
}
21+
22+
std::filesystem::copy(cwd, newPath, std::filesystem::copy_options::recursive);
23+
return newPath;
24+
}
25+
26+
} // namespace gelly

src/app/relocate-installation.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
#include <filesystem>
3+
4+
namespace gelly {
5+
std::filesystem::path RelocateInstallation();
6+
} // namespace gelly

src/helpers/find-app-data.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "find-app-data.hpp"
2+
#include <array>
3+
#include <shlobj_core.h>
4+
#include <windows.h>
5+
6+
namespace gelly::helpers {
7+
std::optional<std::filesystem::path> FindAppData() {
8+
std::array<TCHAR, MAX_PATH> appDataPath;
9+
if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, 0,
10+
appDataPath.data()))) {
11+
return std::filesystem::path(appDataPath.data());
12+
}
13+
14+
return std::nullopt;
15+
}
16+
17+
} // namespace gelly::helpers

src/helpers/find-app-data.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#include <filesystem>
4+
#include <optional>
5+
6+
namespace gelly::helpers {
7+
std::optional<std::filesystem::path> FindAppData();
8+
}

src/helpers/launch-installer.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "launch-installer.hpp"
2+
3+
// clang-format off
4+
#include <windows.h>
5+
#include <shellapi.h>
6+
// clang-format on
7+
8+
namespace gelly::helpers {
9+
namespace {
10+
const auto INSTALLER_EXE = std::string("gelly_installer.exe");
11+
}
12+
13+
void LaunchInstaller(const std::filesystem::path &installerPath) {
14+
auto exePath = installerPath.string() + "\\" + INSTALLER_EXE;
15+
auto workingDir = installerPath.string();
16+
17+
SHELLEXECUTEINFO info = {};
18+
info.cbSize = sizeof(SHELLEXECUTEINFO);
19+
info.fMask = SEE_MASK_NOCLOSEPROCESS;
20+
info.lpFile = exePath.c_str();
21+
info.lpDirectory = workingDir.c_str();
22+
info.lpClass = ".exe";
23+
info.nShow = SW_SHOW;
24+
info.lpVerb = "open";
25+
info.hwnd = nullptr;
26+
27+
const auto result = ShellExecuteExA(&info);
28+
if (result == FALSE) {
29+
MessageBoxW(nullptr, L"Failed to launch installer", L"Error",
30+
MB_OK | MB_ICONERROR);
31+
std::exit(1);
32+
}
33+
34+
std::exit(0);
35+
}
36+
37+
} // namespace gelly::helpers

0 commit comments

Comments
 (0)