Files
yaze/src/util/platform_paths.cc
scawful 7f4a0f546c refactor: Integrate PlatformPaths for configuration directory management
- Replaced direct calls to GetConfigDirectory with PlatformPaths::GetConfigDirectory across multiple files to standardize configuration directory access.
- Updated RecentFilesManager, EditorManager, and various agent components to handle potential errors when retrieving the configuration directory.
- Enhanced file loading functions to utilize the new LoadFileFromConfigDir method for improved clarity and error handling.
- Introduced new methods in file_util.h for better file management practices, leveraging std::filesystem for cross-platform consistency.
2025-10-08 20:50:49 -04:00

179 lines
4.9 KiB
C++

#include "util/platform_paths.h"
#include <cstdlib>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#ifdef _WIN32
#include <windows.h>
#include <shlobj.h>
#else
#include <unistd.h>
#include <pwd.h>
#endif
namespace yaze {
namespace util {
std::filesystem::path PlatformPaths::GetHomeDirectory() {
#ifdef _WIN32
// Windows: Use USERPROFILE environment variable
const char* userprofile = std::getenv("USERPROFILE");
if (userprofile && *userprofile) {
return std::filesystem::path(userprofile);
}
// Fallback to HOMEDRIVE + HOMEPATH
const char* homedrive = std::getenv("HOMEDRIVE");
const char* homepath = std::getenv("HOMEPATH");
if (homedrive && homepath) {
return std::filesystem::path(std::string(homedrive) + std::string(homepath));
}
// Last resort: use temp directory
return std::filesystem::temp_directory_path();
#else
// Unix/macOS: Use HOME environment variable
const char* home = std::getenv("HOME");
if (home && *home) {
return std::filesystem::path(home);
}
// Fallback: try getpwuid
struct passwd* pw = getpwuid(getuid());
if (pw && pw->pw_dir) {
return std::filesystem::path(pw->pw_dir);
}
// Last resort: current directory
return std::filesystem::current_path();
#endif
}
absl::StatusOr<std::filesystem::path> PlatformPaths::GetAppDataDirectory() {
#ifdef _WIN32
wchar_t path[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path))) {
std::filesystem::path app_data = std::filesystem::path(path) / "yaze";
auto status = EnsureDirectoryExists(app_data);
if (!status.ok()) {
return status;
}
return app_data;
}
// Fallback if SHGetFolderPathW fails
std::filesystem::path home = GetHomeDirectory();
std::filesystem::path app_data = home / "yaze_data";
auto status = EnsureDirectoryExists(app_data);
if (!status.ok()) {
return status;
}
return app_data;
#elif defined(__APPLE__)
std::filesystem::path home = GetHomeDirectory();
std::filesystem::path app_data = home / "Library" / "Application Support" / "yaze";
auto status = EnsureDirectoryExists(app_data);
if (!status.ok()) {
return status;
}
return app_data;
#else // Linux and other Unix-like systems
const char* xdg_config_home = std::getenv("XDG_CONFIG_HOME");
std::filesystem::path config_dir;
if (xdg_config_home && *xdg_config_home) {
config_dir = std::filesystem::path(xdg_config_home);
} else {
config_dir = GetHomeDirectory() / ".config";
}
std::filesystem::path app_data = config_dir / "yaze";
auto status = EnsureDirectoryExists(app_data);
if (!status.ok()) {
return status;
}
return app_data;
#endif
}
absl::StatusOr<std::filesystem::path> PlatformPaths::GetConfigDirectory() {
// For yaze, config and data directories are the same.
// This provides a semantically clearer API for config access.
return GetAppDataDirectory();
}
absl::StatusOr<std::filesystem::path> PlatformPaths::GetAppDataSubdirectory(
const std::string& subdir) {
auto app_data_result = GetAppDataDirectory();
if (!app_data_result.ok()) {
return app_data_result.status();
}
std::filesystem::path subdir_path = *app_data_result / subdir;
auto status = EnsureDirectoryExists(subdir_path);
if (!status.ok()) {
return status;
}
return subdir_path;
}
absl::Status PlatformPaths::EnsureDirectoryExists(
const std::filesystem::path& path) {
if (Exists(path)) {
return absl::OkStatus();
}
std::error_code ec;
if (!std::filesystem::create_directories(path, ec)) {
if (ec) {
return absl::InternalError(
absl::StrCat("Failed to create directory: ", path.string(),
" - Error: ", ec.message()));
}
}
return absl::OkStatus();
}
bool PlatformPaths::Exists(const std::filesystem::path& path) {
std::error_code ec;
bool exists = std::filesystem::exists(path, ec);
return exists && !ec;
}
absl::StatusOr<std::filesystem::path> PlatformPaths::GetTempDirectory() {
std::error_code ec;
std::filesystem::path temp_base = std::filesystem::temp_directory_path(ec);
if (ec) {
return absl::InternalError(
absl::StrCat("Failed to get temp directory: ", ec.message()));
}
std::filesystem::path yaze_temp = temp_base / "yaze";
auto status = EnsureDirectoryExists(yaze_temp);
if (!status.ok()) {
return status;
}
return yaze_temp;
}
std::string PlatformPaths::NormalizePathForDisplay(
const std::filesystem::path& path) {
// Convert to string and replace backslashes with forward slashes
// Forward slashes work on all platforms for display purposes
std::string path_str = path.string();
return absl::StrReplaceAll(path_str, {{"\\", "/"}});
}
std::string PlatformPaths::ToNativePath(const std::filesystem::path& path) {
// std::filesystem::path::string() already returns the native format
return path.string();
}
} // namespace util
} // namespace yaze