83 lines
3.0 KiB
C++
83 lines
3.0 KiB
C++
#include "editor/SpineOutputParser.hpp"
|
|
|
|
#include <regex>
|
|
|
|
namespace dts {
|
|
namespace {
|
|
|
|
std::optional<SpineVersion> firstVersion(
|
|
const std::string& text,
|
|
const std::regex& expression,
|
|
std::string* trailing = nullptr) {
|
|
std::smatch match;
|
|
if (!std::regex_search(text, match, expression)) {
|
|
return std::nullopt;
|
|
}
|
|
if (trailing && match.size() > 2) {
|
|
*trailing = match[2].str();
|
|
}
|
|
return SpineVersion::parse(match[1].str());
|
|
}
|
|
|
|
} // namespace
|
|
|
|
EditorProbeResult SpineOutputParser::parse(
|
|
const std::filesystem::path& executable,
|
|
const ProcessResult& process) const {
|
|
EditorProbeResult result;
|
|
result.executable = executable;
|
|
result.timedOut = process.timedOut;
|
|
result.exitCode = process.exitCode;
|
|
result.output = process.output;
|
|
|
|
if (!process.started) {
|
|
result.status = EditorProbeStatus::LaunchFailed;
|
|
result.message = process.error.empty() ? "Spine process could not be started." : process.error;
|
|
return result;
|
|
}
|
|
|
|
static const std::regex launcher(R"(Spine Launcher\s+(\d+\.\d+(?:\.\d+)?))");
|
|
static const std::regex launching(
|
|
R"((?:Launching:|Starting:)\s*Spine\s+(\d+\.\d+(?:\.\d+)?)(?:\s+([^\r\n]+))?)");
|
|
// MSVC's std::regex does not implement std::regex_constants::multiline,
|
|
// so instead of relying on the '^' line anchor with the multiline flag,
|
|
// search for "Spine <version>" anywhere (regex_search scans the whole text).
|
|
static const std::regex directEditor(
|
|
R"(Spine\s+(\d+\.\d+(?:\.\d+)?)(?:\s+([^\r\n]+))?)");
|
|
|
|
result.launcherVersion = firstVersion(process.output, launcher);
|
|
result.editorVersion = firstVersion(process.output, launching, &result.edition);
|
|
if (!result.editorVersion) {
|
|
result.editorVersion = firstVersion(process.output, directEditor, &result.edition);
|
|
}
|
|
|
|
if (!result.launcherVersion && !result.editorVersion) {
|
|
result.status = EditorProbeStatus::UnrecognizedOutput;
|
|
result.message = "Process started, but its output was not recognized as Spine.";
|
|
} else if (process.timedOut) {
|
|
result.status = EditorProbeStatus::ObservedButTimedOut;
|
|
result.message = "Spine was detected, but the version probe timed out.";
|
|
} else if (process.exitCode == 0) {
|
|
result.status = EditorProbeStatus::Available;
|
|
result.message = "Spine CLI probe succeeded.";
|
|
} else {
|
|
result.status = EditorProbeStatus::LaunchFailed;
|
|
result.message = "Spine was detected, but the process returned a failure code.";
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::string toString(EditorProbeStatus status) {
|
|
switch (status) {
|
|
case EditorProbeStatus::Available: return "available";
|
|
case EditorProbeStatus::ObservedButTimedOut: return "observed-but-timed-out";
|
|
case EditorProbeStatus::PathMissing: return "path-missing";
|
|
case EditorProbeStatus::LaunchFailed: return "launch-failed";
|
|
case EditorProbeStatus::UnrecognizedOutput: return "unrecognized-output";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
} // namespace dts
|
|
|