From 6b815e58baa037335fb0008f6d0345fa29931e08 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Fri, 7 Jun 2019 11:01:43 -0400
Subject: fileapi: Factor out helper to construct a version object

---
 Source/cmFileAPI.cxx | 31 +++++++++++++++++--------------
 Source/cmFileAPI.h   |  2 ++
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index 34b6b33..9cb484c 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -413,6 +413,14 @@ std::string cmFileAPI::ObjectName(Object const& o)
   return name;
 }
 
+Json::Value cmFileAPI::BuildVersion(unsigned int major, unsigned int minor)
+{
+  Json::Value version;
+  version["major"] = major;
+  version["minor"] = minor;
+  return version;
+}
+
 Json::Value cmFileAPI::BuildObject(Object const& object)
 {
   Json::Value value;
@@ -680,10 +688,9 @@ Json::Value cmFileAPI::BuildCodeModel(Object const& object)
   Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version);
   codemodel["kind"] = this->ObjectKindName(object.Kind);
 
-  Json::Value& version = codemodel["version"] = Json::objectValue;
+  Json::Value& version = codemodel["version"];
   if (object.Version == 2) {
-    version["major"] = 2;
-    version["minor"] = CodeModelV2Minor;
+    version = BuildVersion(2, CodeModelV2Minor);
   } else {
     return codemodel; // should be unreachable
   }
@@ -716,10 +723,9 @@ Json::Value cmFileAPI::BuildCache(Object const& object)
   Json::Value cache = cmFileAPICacheDump(*this, object.Version);
   cache["kind"] = this->ObjectKindName(object.Kind);
 
-  Json::Value& version = cache["version"] = Json::objectValue;
+  Json::Value& version = cache["version"];
   if (object.Version == 2) {
-    version["major"] = 2;
-    version["minor"] = CacheV2Minor;
+    version = BuildVersion(2, CacheV2Minor);
   } else {
     return cache; // should be unreachable
   }
@@ -752,10 +758,9 @@ Json::Value cmFileAPI::BuildCMakeFiles(Object const& object)
   Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version);
   cmakeFiles["kind"] = this->ObjectKindName(object.Kind);
 
-  Json::Value& version = cmakeFiles["version"] = Json::objectValue;
+  Json::Value& version = cmakeFiles["version"];
   if (object.Version == 1) {
-    version["major"] = 1;
-    version["minor"] = CMakeFilesV1Minor;
+    version = BuildVersion(1, CMakeFilesV1Minor);
   } else {
     return cmakeFiles; // should be unreachable
   }
@@ -788,13 +793,11 @@ Json::Value cmFileAPI::BuildInternalTest(Object const& object)
 {
   Json::Value test = Json::objectValue;
   test["kind"] = this->ObjectKindName(object.Kind);
-  Json::Value& version = test["version"] = Json::objectValue;
+  Json::Value& version = test["version"];
   if (object.Version == 2) {
-    version["major"] = 2;
-    version["minor"] = InternalTestV2Minor;
+    version = BuildVersion(2, InternalTestV2Minor);
   } else {
-    version["major"] = 1;
-    version["minor"] = InternalTestV1Minor;
+    version = BuildVersion(1, InternalTestV1Minor);
   }
   return test;
 }
diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h
index 341b072..1315532 100644
--- a/Source/cmFileAPI.h
+++ b/Source/cmFileAPI.h
@@ -162,6 +162,8 @@ private:
   static const char* ObjectKindName(ObjectKind kind);
   static std::string ObjectName(Object const& o);
 
+  static Json::Value BuildVersion(unsigned int major, unsigned int minor);
+
   Json::Value BuildObject(Object const& object);
 
   ClientRequests BuildClientRequests(Json::Value const& requests);
-- 
cgit v0.12


From 6696855f72adebbb40d475c39dace1e9f855ca2a Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Fri, 7 Jun 2019 09:33:11 -0400
Subject: cmake: Simplify implementation of -E capabilities

The `cmake -E capabilities` command-line tool is implemented only in a
full-featured (non-bootstrap) CMake, and server mode is now always
available in this case.
---
 Source/cmServerProtocol.cxx | 2 +-
 Source/cmake.cxx            | 8 ++++----
 Source/cmake.h              | 4 ++--
 Source/cmcmd.cxx            | 6 +-----
 4 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index dad8821..558391f 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -630,7 +630,7 @@ cmServerResponse cmServerProtocol1::ProcessGlobalSettings(
   Json::Value obj = Json::objectValue;
 
   // Capabilities information:
-  obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson(true);
+  obj[kCAPABILITIES_KEY] = cm->ReportCapabilitiesJson();
 
   obj[kDEBUG_OUTPUT_KEY] = cm->GetDebugOutput();
   obj[kTRACE_KEY] = cm->GetTrace();
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index f0b53f4..0dca578 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -248,7 +248,7 @@ Json::Value cmake::ReportVersionJson() const
   return version;
 }
 
-Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
+Json::Value cmake::ReportCapabilitiesJson() const
 {
   Json::Value obj = Json::objectValue;
 
@@ -284,18 +284,18 @@ Json::Value cmake::ReportCapabilitiesJson(bool haveServerMode) const
     generators.append(i.second);
   }
   obj["generators"] = generators;
-  obj["serverMode"] = haveServerMode;
+  obj["serverMode"] = true;
 
   return obj;
 }
 #endif
 
-std::string cmake::ReportCapabilities(bool haveServerMode) const
+std::string cmake::ReportCapabilities() const
 {
   std::string result;
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   Json::FastWriter writer;
-  result = writer.write(this->ReportCapabilitiesJson(haveServerMode));
+  result = writer.write(this->ReportCapabilitiesJson());
 #else
   result = "Not supported";
 #endif
diff --git a/Source/cmake.h b/Source/cmake.h
index 4de9d28..fa4409a 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -136,9 +136,9 @@ public:
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   Json::Value ReportVersionJson() const;
-  Json::Value ReportCapabilitiesJson(bool haveServerMode) const;
+  Json::Value ReportCapabilitiesJson() const;
 #endif
-  std::string ReportCapabilities(bool haveServerMode) const;
+  std::string ReportCapabilities() const;
 
   //@{
   /**
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index a983d30..86082e5 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -734,11 +734,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
         return 1;
       }
       cmake cm(cmake::RoleInternal, cmState::Unknown);
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-      std::cout << cm.ReportCapabilities(true);
-#else
-      std::cout << cm.ReportCapabilities(false);
-#endif
+      std::cout << cm.ReportCapabilities();
       return 0;
     }
 
-- 
cgit v0.12


From c932f498426609beb14b9339c2a7dec3ea624998 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Fri, 7 Jun 2019 10:22:34 -0400
Subject: cmake: Teach -E capabilities to report supported fileapi requests

Fixes: #19339
---
 Help/manual/cmake-file-api.7.rst                   |  2 ++
 Help/manual/cmake.1.rst                            | 16 +++++++++++
 Source/cmFileAPI.cxx                               | 32 ++++++++++++++++++++++
 Source/cmFileAPI.h                                 |  3 ++
 Source/cmake.cxx                                   |  1 +
 .../RunCMake/CommandLine/E_capabilities-stdout.txt |  2 +-
 6 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst
index f3e0208..04b6ed2 100644
--- a/Help/manual/cmake-file-api.7.rst
+++ b/Help/manual/cmake-file-api.7.rst
@@ -379,6 +379,8 @@ finds the file missing, that means a concurrent CMake has generated
 a new reply.  The client may simply start again by reading the new
 reply index file.
 
+.. _`file-api object kinds`:
+
 Object Kinds
 ============
 
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index f1d02eb..13cba71 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -423,6 +423,22 @@ Available commands are:
       A list of strings with all the extra generators compatible with
       the generator.
 
+  ``fileApi``
+    Optional member that is present when the :manual:`cmake-file-api(7)`
+    is available.  The value is a JSON object with one member:
+
+    ``requests``
+      A JSON array containing zero or more supported file-api requests.
+      Each request is a JSON object with members:
+
+      ``kind``
+        Specifies one of the supported :ref:`file-api object kinds`.
+
+      ``version``
+        A JSON array whose elements are each a JSON object containing
+        ``major`` and ``minor`` members specifying non-negative integer
+        version components.
+
   ``serverMode``
     ``true`` if cmake supports server-mode and ``false`` otherwise.
 
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index 9cb484c..ed45398 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -801,3 +801,35 @@ Json::Value cmFileAPI::BuildInternalTest(Object const& object)
   }
   return test;
 }
+
+Json::Value cmFileAPI::ReportCapabilities()
+{
+  Json::Value capabilities = Json::objectValue;
+  Json::Value& requests = capabilities["requests"] = Json::arrayValue;
+
+  {
+    Json::Value request = Json::objectValue;
+    request["kind"] = ObjectKindName(ObjectKind::CodeModel);
+    Json::Value& versions = request["version"] = Json::arrayValue;
+    versions.append(BuildVersion(2, CodeModelV2Minor));
+    requests.append(std::move(request));
+  }
+
+  {
+    Json::Value request = Json::objectValue;
+    request["kind"] = ObjectKindName(ObjectKind::Cache);
+    Json::Value& versions = request["version"] = Json::arrayValue;
+    versions.append(BuildVersion(2, CacheV2Minor));
+    requests.append(std::move(request));
+  }
+
+  {
+    Json::Value request = Json::objectValue;
+    request["kind"] = ObjectKindName(ObjectKind::CMakeFiles);
+    Json::Value& versions = request["version"] = Json::arrayValue;
+    versions.append(BuildVersion(1, CMakeFilesV1Minor));
+    requests.append(std::move(request));
+  }
+
+  return capabilities;
+}
diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h
index 1315532..602efa8 100644
--- a/Source/cmFileAPI.h
+++ b/Source/cmFileAPI.h
@@ -36,6 +36,9 @@ public:
       and holding the original object.  Other JSON types are unchanged.  */
   Json::Value MaybeJsonFile(Json::Value in, std::string const& prefix);
 
+  /** Report file-api capabilities for cmake -E capabilities.  */
+  static Json::Value ReportCapabilities();
+
 private:
   cmake* CMakeInstance;
 
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 0dca578..3772f09 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -284,6 +284,7 @@ Json::Value cmake::ReportCapabilitiesJson() const
     generators.append(i.second);
   }
   obj["generators"] = generators;
+  obj["fileApi"] = cmFileAPI::ReportCapabilities();
   obj["serverMode"] = true;
 
   return obj;
diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
index 6c5ea44..b4b170e 100644
--- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
+++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt
@@ -1 +1 @@
-^{.*}$
+^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$
-- 
cgit v0.12