#include "editor/SpineEditorLocator.hpp" #include #include #include namespace dts { namespace fs = std::filesystem; namespace { void addUnique(std::vector& paths, const fs::path& candidate) { std::error_code error; if (!fs::is_regular_file(candidate, error)) { return; } const auto canonical = fs::weakly_canonical(candidate, error); const auto value = error ? candidate.lexically_normal() : canonical; if (std::find(paths.begin(), paths.end(), value) == paths.end()) { paths.push_back(value); } } } // namespace std::vector SpineEditorLocator::discover() const { std::vector results; #if defined(__APPLE__) addUnique(results, "/Applications/Spine.app/Contents/MacOS/Spine"); if (const char* userHome = std::getenv("HOME")) { addUnique(results, fs::path(userHome) / "Applications/Spine.app/Contents/MacOS/Spine"); } #elif defined(_WIN32) const auto addFromRoot = [&results](const char* variable) { if (const char* root = std::getenv(variable)) { addUnique(results, fs::path(root) / "Spine/Spine.com"); } }; addFromRoot("ProgramFiles"); addFromRoot("ProgramFiles(x86)"); #endif return results; } std::optional SpineEditorLocator::normalize(const fs::path& userPath) const { std::error_code error; auto candidate = userPath; #if defined(__APPLE__) if (candidate.extension() == ".app") { candidate /= "Contents/MacOS/Spine"; } else if (fs::is_directory(candidate, error)) { const auto appCandidate = candidate / "Spine.app/Contents/MacOS/Spine"; if (fs::is_regular_file(appCandidate, error)) { candidate = appCandidate; } } #elif defined(_WIN32) if (fs::is_directory(candidate, error)) { candidate /= "Spine.com"; } else if (candidate.extension() == ".exe") { auto commandCandidate = candidate; commandCandidate.replace_extension(".com"); if (fs::is_regular_file(commandCandidate, error)) { candidate = commandCandidate; } } #endif if (!fs::is_regular_file(candidate, error)) { return std::nullopt; } const auto canonical = fs::weakly_canonical(candidate, error); return error ? std::optional(candidate.lexically_normal()) : std::optional(canonical); } } // namespace dts