Merge topic 'cmake-server-signals'
e22d30e2
server-mode: Allow for sending signalscc576c2c
server-mode: Pass server into cmServerProtocol277ffa28
server-mode: Move constants for server mode into its own file
This commit is contained in:
commit
aec5bf8edb
|
@ -186,6 +186,14 @@ Example::
|
||||||
]== CMake Server ==]
|
]== CMake Server ==]
|
||||||
|
|
||||||
|
|
||||||
|
Type "signal"
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The server can send signals when it detects changes in the system state. Signals
|
||||||
|
are of type "signal", have an empty "cookie" and "inReplyTo" field and always
|
||||||
|
have a "name" set to show which signal was sent.
|
||||||
|
|
||||||
|
|
||||||
Specific Message Types
|
Specific Message Types
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "cmServer.h"
|
#include "cmServer.h"
|
||||||
|
|
||||||
#include "cmServerConnection.h"
|
#include "cmServerConnection.h"
|
||||||
|
#include "cmServerDictionary.h"
|
||||||
#include "cmServerProtocol.h"
|
#include "cmServerProtocol.h"
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
#include "cmVersionMacros.h"
|
#include "cmVersionMacros.h"
|
||||||
|
@ -28,19 +29,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
static const std::string kTYPE_KEY = "type";
|
|
||||||
static const std::string kCOOKIE_KEY = "cookie";
|
|
||||||
static const std::string kREPLY_TO_KEY = "inReplyTo";
|
|
||||||
static const std::string kERROR_MESSAGE_KEY = "errorMessage";
|
|
||||||
|
|
||||||
static const std::string kERROR_TYPE = "error";
|
|
||||||
static const std::string kREPLY_TYPE = "reply";
|
|
||||||
static const std::string kPROGRESS_TYPE = "progress";
|
|
||||||
static const std::string kMESSAGE_TYPE = "message";
|
|
||||||
|
|
||||||
static const std::string kSTART_MAGIC = "[== CMake Server ==[";
|
|
||||||
static const std::string kEND_MAGIC = "]== CMake Server ==]";
|
|
||||||
|
|
||||||
class cmServer::DebugInfo
|
class cmServer::DebugInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -144,16 +132,16 @@ void cmServer::PrintHello() const
|
||||||
Json::Value hello = Json::objectValue;
|
Json::Value hello = Json::objectValue;
|
||||||
hello[kTYPE_KEY] = "hello";
|
hello[kTYPE_KEY] = "hello";
|
||||||
|
|
||||||
Json::Value& protocolVersions = hello["supportedProtocolVersions"] =
|
Json::Value& protocolVersions = hello[kSUPPORTED_PROTOCOL_VERSIONS] =
|
||||||
Json::arrayValue;
|
Json::arrayValue;
|
||||||
|
|
||||||
for (auto const& proto : this->SupportedProtocols) {
|
for (auto const& proto : this->SupportedProtocols) {
|
||||||
auto version = proto->ProtocolVersion();
|
auto version = proto->ProtocolVersion();
|
||||||
Json::Value tmp = Json::objectValue;
|
Json::Value tmp = Json::objectValue;
|
||||||
tmp["major"] = version.first;
|
tmp[kMAJOR_KEY] = version.first;
|
||||||
tmp["minor"] = version.second;
|
tmp[kMINOR_KEY] = version.second;
|
||||||
if (proto->IsExperimental()) {
|
if (proto->IsExperimental()) {
|
||||||
tmp["experimental"] = true;
|
tmp[kIS_EXPERIMENTAL_KEY] = true;
|
||||||
}
|
}
|
||||||
protocolVersions.append(tmp);
|
protocolVersions.append(tmp);
|
||||||
}
|
}
|
||||||
|
@ -193,31 +181,37 @@ void cmServer::reportMessage(const char* msg, const char* title,
|
||||||
|
|
||||||
cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
|
cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
|
||||||
{
|
{
|
||||||
if (request.Type != "handshake")
|
if (request.Type != kHANDSHAKE_TYPE)
|
||||||
return request.ReportError("Waiting for type \"handshake\".");
|
return request.ReportError("Waiting for type \"" + kHANDSHAKE_TYPE +
|
||||||
|
"\".");
|
||||||
|
|
||||||
Json::Value requestedProtocolVersion = request.Data["protocolVersion"];
|
Json::Value requestedProtocolVersion = request.Data[kPROTOCOL_VERSION_KEY];
|
||||||
if (requestedProtocolVersion.isNull())
|
if (requestedProtocolVersion.isNull())
|
||||||
return request.ReportError(
|
return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
|
||||||
"\"protocolVersion\" is required for \"handshake\".");
|
"\" is required for \"" + kHANDSHAKE_TYPE +
|
||||||
|
"\".");
|
||||||
|
|
||||||
if (!requestedProtocolVersion.isObject())
|
if (!requestedProtocolVersion.isObject())
|
||||||
return request.ReportError("\"protocolVersion\" must be a JSON object.");
|
return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
|
||||||
|
"\" must be a JSON object.");
|
||||||
|
|
||||||
Json::Value majorValue = requestedProtocolVersion["major"];
|
Json::Value majorValue = requestedProtocolVersion[kMAJOR_KEY];
|
||||||
if (!majorValue.isInt())
|
if (!majorValue.isInt())
|
||||||
return request.ReportError("\"major\" must be set and an integer.");
|
return request.ReportError("\"" + kMAJOR_KEY +
|
||||||
|
"\" must be set and an integer.");
|
||||||
|
|
||||||
Json::Value minorValue = requestedProtocolVersion["minor"];
|
Json::Value minorValue = requestedProtocolVersion[kMINOR_KEY];
|
||||||
if (!minorValue.isNull() && !minorValue.isInt())
|
if (!minorValue.isNull() && !minorValue.isInt())
|
||||||
return request.ReportError("\"minor\" must be unset or an integer.");
|
return request.ReportError("\"" + kMINOR_KEY +
|
||||||
|
"\" must be unset or an integer.");
|
||||||
|
|
||||||
const int major = majorValue.asInt();
|
const int major = majorValue.asInt();
|
||||||
const int minor = minorValue.isNull() ? -1 : minorValue.asInt();
|
const int minor = minorValue.isNull() ? -1 : minorValue.asInt();
|
||||||
if (major < 0)
|
if (major < 0)
|
||||||
return request.ReportError("\"major\" must be >= 0.");
|
return request.ReportError("\"" + kMAJOR_KEY + "\" must be >= 0.");
|
||||||
if (!minorValue.isNull() && minor < 0)
|
if (!minorValue.isNull() && minor < 0)
|
||||||
return request.ReportError("\"minor\" must be >= 0 when set.");
|
return request.ReportError("\"" + kMINOR_KEY +
|
||||||
|
"\" must be >= 0 when set.");
|
||||||
|
|
||||||
this->Protocol =
|
this->Protocol =
|
||||||
this->FindMatchingProtocol(this->SupportedProtocols, major, minor);
|
this->FindMatchingProtocol(this->SupportedProtocols, major, minor);
|
||||||
|
@ -226,7 +220,7 @@ cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string errorMessage;
|
std::string errorMessage;
|
||||||
if (!this->Protocol->Activate(request, &errorMessage)) {
|
if (!this->Protocol->Activate(this, request, &errorMessage)) {
|
||||||
this->Protocol = CM_NULLPTR;
|
this->Protocol = CM_NULLPTR;
|
||||||
return request.ReportError("Failed to activate protocol version: " +
|
return request.ReportError("Failed to activate protocol version: " +
|
||||||
errorMessage);
|
errorMessage);
|
||||||
|
@ -311,10 +305,10 @@ void cmServer::WriteProgress(const cmServerRequest& request, int min,
|
||||||
obj[kTYPE_KEY] = kPROGRESS_TYPE;
|
obj[kTYPE_KEY] = kPROGRESS_TYPE;
|
||||||
obj[kREPLY_TO_KEY] = request.Type;
|
obj[kREPLY_TO_KEY] = request.Type;
|
||||||
obj[kCOOKIE_KEY] = request.Cookie;
|
obj[kCOOKIE_KEY] = request.Cookie;
|
||||||
obj["progressMessage"] = message;
|
obj[kPROGRESS_MESSAGE_KEY] = message;
|
||||||
obj["progressMinimum"] = min;
|
obj[kPROGRESS_MINIMUM_KEY] = min;
|
||||||
obj["progressMaximum"] = max;
|
obj[kPROGRESS_MAXIMUM_KEY] = max;
|
||||||
obj["progressCurrent"] = current;
|
obj[kPROGRESS_CURRENT_KEY] = current;
|
||||||
|
|
||||||
this->WriteJsonObject(obj, nullptr);
|
this->WriteJsonObject(obj, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -330,9 +324,9 @@ void cmServer::WriteMessage(const cmServerRequest& request,
|
||||||
obj[kTYPE_KEY] = kMESSAGE_TYPE;
|
obj[kTYPE_KEY] = kMESSAGE_TYPE;
|
||||||
obj[kREPLY_TO_KEY] = request.Type;
|
obj[kREPLY_TO_KEY] = request.Type;
|
||||||
obj[kCOOKIE_KEY] = request.Cookie;
|
obj[kCOOKIE_KEY] = request.Cookie;
|
||||||
obj["message"] = message;
|
obj[kMESSAGE_KEY] = message;
|
||||||
if (!title.empty()) {
|
if (!title.empty()) {
|
||||||
obj["title"] = title;
|
obj[kTITLE_KEY] = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteJsonObject(obj, nullptr);
|
WriteJsonObject(obj, nullptr);
|
||||||
|
@ -349,6 +343,19 @@ void cmServer::WriteParseError(const std::string& message) const
|
||||||
this->WriteJsonObject(obj, nullptr);
|
this->WriteJsonObject(obj, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmServer::WriteSignal(const std::string& name,
|
||||||
|
const Json::Value& data) const
|
||||||
|
{
|
||||||
|
assert(data.isObject());
|
||||||
|
Json::Value obj = data;
|
||||||
|
obj[kTYPE_KEY] = kSIGNAL_TYPE;
|
||||||
|
obj[kREPLY_TO_KEY] = "";
|
||||||
|
obj[kCOOKIE_KEY] = "";
|
||||||
|
obj[kNAME_KEY] = name;
|
||||||
|
|
||||||
|
WriteJsonObject(obj, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void cmServer::WriteResponse(const cmServerResponse& response,
|
void cmServer::WriteResponse(const cmServerResponse& response,
|
||||||
const DebugInfo* debug) const
|
const DebugInfo* debug) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,6 +63,7 @@ private:
|
||||||
void WriteResponse(const cmServerResponse& response,
|
void WriteResponse(const cmServerResponse& response,
|
||||||
const DebugInfo* debug) const;
|
const DebugInfo* debug) const;
|
||||||
void WriteParseError(const std::string& message) const;
|
void WriteParseError(const std::string& message) const;
|
||||||
|
void WriteSignal(const std::string& name, const Json::Value& obj) const;
|
||||||
|
|
||||||
void WriteJsonObject(Json::Value const& jsonValue,
|
void WriteJsonObject(Json::Value const& jsonValue,
|
||||||
const DebugInfo* debug) const;
|
const DebugInfo* debug) const;
|
||||||
|
@ -95,6 +96,7 @@ private:
|
||||||
|
|
||||||
mutable bool Writing = false;
|
mutable bool Writing = false;
|
||||||
|
|
||||||
friend class cmServerRequest;
|
|
||||||
friend class cmServerConnection;
|
friend class cmServerConnection;
|
||||||
|
friend class cmServerProtocol;
|
||||||
|
friend class cmServerRequest;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,15 +13,14 @@
|
||||||
|
|
||||||
#include "cmServerConnection.h"
|
#include "cmServerConnection.h"
|
||||||
|
|
||||||
|
#include "cmServerDictionary.h"
|
||||||
|
|
||||||
#include <cmServer.h>
|
#include <cmServer.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static const std::string kSTART_MAGIC = "[== CMake Server ==[";
|
|
||||||
static const std::string kEND_MAGIC = "]== CMake Server ==]";
|
|
||||||
|
|
||||||
struct write_req_t
|
struct write_req_t
|
||||||
{
|
{
|
||||||
uv_write_t req;
|
uv_write_t req;
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*============================================================================
|
||||||
|
CMake - Cross Platform Makefile Generator
|
||||||
|
Copyright 2016 Tobias Hunger <tobias.hunger@qt.io>
|
||||||
|
|
||||||
|
Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
see accompanying file Copyright.txt for details.
|
||||||
|
|
||||||
|
This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the License for more information.
|
||||||
|
============================================================================*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Vocabulary:
|
||||||
|
|
||||||
|
static const std::string kERROR_TYPE = "error";
|
||||||
|
static const std::string kHANDSHAKE_TYPE = "handshake";
|
||||||
|
static const std::string kMESSAGE_TYPE = "message";
|
||||||
|
static const std::string kPROGRESS_TYPE = "progress";
|
||||||
|
static const std::string kREPLY_TYPE = "reply";
|
||||||
|
static const std::string kSIGNAL_TYPE = "signal";
|
||||||
|
|
||||||
|
static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
|
||||||
|
static const std::string kCOOKIE_KEY = "cookie";
|
||||||
|
static const std::string kERROR_MESSAGE_KEY = "errorMessage";
|
||||||
|
static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator";
|
||||||
|
static const std::string kGENERATOR_KEY = "generator";
|
||||||
|
static const std::string kIS_EXPERIMENTAL_KEY = "isExperimental";
|
||||||
|
static const std::string kMAJOR_KEY = "major";
|
||||||
|
static const std::string kMESSAGE_KEY = "message";
|
||||||
|
static const std::string kMINOR_KEY = "minor";
|
||||||
|
static const std::string kNAME_KEY = "name";
|
||||||
|
static const std::string kPROGRESS_CURRENT_KEY = "progressCurrent";
|
||||||
|
static const std::string kPROGRESS_MAXIMUM_KEY = "progressMaximum";
|
||||||
|
static const std::string kPROGRESS_MESSAGE_KEY = "progressMessage";
|
||||||
|
static const std::string kPROGRESS_MINIMUM_KEY = "progressMinimum";
|
||||||
|
static const std::string kPROTOCOL_VERSION_KEY = "protocolVersion";
|
||||||
|
static const std::string kREPLY_TO_KEY = "inReplyTo";
|
||||||
|
static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
|
||||||
|
static const std::string kSUPPORTED_PROTOCOL_VERSIONS =
|
||||||
|
"supportedProtocolVersions";
|
||||||
|
static const std::string kTITLE_KEY = "title";
|
||||||
|
static const std::string kTYPE_KEY = "type";
|
||||||
|
|
||||||
|
static const std::string kSTART_MAGIC = "[== CMake Server ==[";
|
||||||
|
static const std::string kEND_MAGIC = "]== CMake Server ==]";
|
|
@ -14,23 +14,17 @@
|
||||||
|
|
||||||
#include "cmExternalMakefileProjectGenerator.h"
|
#include "cmExternalMakefileProjectGenerator.h"
|
||||||
#include "cmServer.h"
|
#include "cmServer.h"
|
||||||
|
#include "cmServerDictionary.h"
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
#include "cmake.h"
|
#include "cmake.h"
|
||||||
|
|
||||||
|
#include "cmServerDictionary.h"
|
||||||
|
|
||||||
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
||||||
#include "cm_jsoncpp_reader.h"
|
#include "cm_jsoncpp_reader.h"
|
||||||
#include "cm_jsoncpp_value.h"
|
#include "cm_jsoncpp_value.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Vocabulary:
|
|
||||||
|
|
||||||
static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
|
|
||||||
static const std::string kCOOKIE_KEY = "cookie";
|
|
||||||
static const std::string kEXTRA_GENERATOR_KEY = "extraGenerator";
|
|
||||||
static const std::string kGENERATOR_KEY = "generator";
|
|
||||||
static const std::string kSOURCE_DIRECTORY_KEY = "sourceDirectory";
|
|
||||||
static const std::string kTYPE_KEY = "type";
|
|
||||||
|
|
||||||
cmServerRequest::cmServerRequest(cmServer* server, const std::string& t,
|
cmServerRequest::cmServerRequest(cmServer* server, const std::string& t,
|
||||||
const std::string& c, const Json::Value& d)
|
const std::string& c, const Json::Value& d)
|
||||||
: Type(t)
|
: Type(t)
|
||||||
|
@ -115,9 +109,12 @@ Json::Value cmServerResponse::Data() const
|
||||||
return this->m_Data;
|
return this->m_Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmServerProtocol::Activate(const cmServerRequest& request,
|
bool cmServerProtocol::Activate(cmServer* server,
|
||||||
|
const cmServerRequest& request,
|
||||||
std::string* errorMessage)
|
std::string* errorMessage)
|
||||||
{
|
{
|
||||||
|
assert(server);
|
||||||
|
this->m_Server = server;
|
||||||
this->m_CMakeInstance = std::make_unique<cmake>();
|
this->m_CMakeInstance = std::make_unique<cmake>();
|
||||||
const bool result = this->DoActivate(request, errorMessage);
|
const bool result = this->DoActivate(request, errorMessage);
|
||||||
if (!result)
|
if (!result)
|
||||||
|
@ -125,6 +122,13 @@ bool cmServerProtocol::Activate(const cmServerRequest& request,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmServerProtocol::SendSignal(const std::string& name,
|
||||||
|
const Json::Value& data) const
|
||||||
|
{
|
||||||
|
if (this->m_Server)
|
||||||
|
this->m_Server->WriteSignal(name, data);
|
||||||
|
}
|
||||||
|
|
||||||
cmake* cmServerProtocol::CMakeInstance() const
|
cmake* cmServerProtocol::CMakeInstance() const
|
||||||
{
|
{
|
||||||
return this->m_CMakeInstance.get();
|
return this->m_CMakeInstance.get();
|
||||||
|
|
|
@ -87,7 +87,10 @@ public:
|
||||||
virtual bool IsExperimental() const = 0;
|
virtual bool IsExperimental() const = 0;
|
||||||
virtual const cmServerResponse Process(const cmServerRequest& request) = 0;
|
virtual const cmServerResponse Process(const cmServerRequest& request) = 0;
|
||||||
|
|
||||||
bool Activate(const cmServerRequest& request, std::string* errorMessage);
|
bool Activate(cmServer* server, const cmServerRequest& request,
|
||||||
|
std::string* errorMessage);
|
||||||
|
|
||||||
|
void SendSignal(const std::string& name, const Json::Value& data) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
cmake* CMakeInstance() const;
|
cmake* CMakeInstance() const;
|
||||||
|
@ -97,6 +100,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<cmake> m_CMakeInstance;
|
std::unique_ptr<cmake> m_CMakeInstance;
|
||||||
|
cmServer* m_Server = nullptr; // not owned!
|
||||||
|
|
||||||
friend class cmServer;
|
friend class cmServer;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue