[Cmake-commits] CMake branch, master, updated. v3.9.0-rc6-330-gfc4f352

Kitware Robot kwrobot at kitware.com
Tue Jul 18 11:15:05 EDT 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  fc4f3525133270ccc33ccda6acff6f85006ab457 (commit)
       via  407c7415f41fc27578bb0ab2c831e767de575531 (commit)
       via  b10d919de763000801cbffd4f58cbd0c4a1ad7a0 (commit)
       via  787017451c437713b05a2ffc6fe609ea7da5f95b (commit)
       via  8eb1cb3ff1938f4c216d08860f7cf8e07ec71537 (commit)
       via  d89e10cd58e5f9e21cbd466e56a1890e2811bee0 (commit)
       via  c4de0a25ac8b7bb94205e24b5557331ed80d79b8 (commit)
       via  c4647d84321f4a7b52301237394087065f5df33c (commit)
       via  cf0ae55dcb9224b92a95166f17452c56ba5b6213 (commit)
       via  5ddfb6a472539c3a01a6f8e6d8fa1cb1013fc4f9 (commit)
       via  d4f5d35ca491ede92003b26a7d0eb06aea3a2bbb (commit)
       via  501a4feea8d0d007ce292defec1c97d6eb702409 (commit)
       via  5acbf08bff643ec6779464c840bfe2f02a4e65ae (commit)
      from  ec049641c46eb788b25713e5d96ff32c89f0e819 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fc4f3525133270ccc33ccda6acff6f85006ab457
commit fc4f3525133270ccc33ccda6acff6f85006ab457
Merge: 407c741 cf0ae55
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jul 18 15:13:46 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jul 18 11:14:02 2017 -0400

    Merge topic 'server-refactor'
    
    cf0ae55d server: Add support for connections that aren't event based
    5ddfb6a4 server: Add connection as part of a request
    d4f5d35c server: Refactor to make the event loop owned by server object
    5acbf08b Tests: Teach Server test to forward exit code from server process
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !552

diff --cc Source/cmServer.cxx
index 5283dfc,1d5f3f6..ccb9af6
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@@ -30,13 -46,12 +46,12 @@@ public
    uint64_t StartTime;
  };
  
- cmServer::cmServer(cmServerConnection* conn, bool supportExperimental)
-   : Connection(conn)
+ cmServer::cmServer(cmConnection* conn, bool supportExperimental)
+   : cmServerBase(conn)
    , SupportExperimental(supportExperimental)
  {
-   this->Connection->SetServer(this);
    // Register supported protocols:
 -  this->RegisterProtocol(new cmServerProtocol1_0);
 +  this->RegisterProtocol(new cmServerProtocol1);
  }
  
  cmServer::~cmServer()

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=407c7415f41fc27578bb0ab2c831e767de575531
commit 407c7415f41fc27578bb0ab2c831e767de575531
Merge: b10d919 c4de0a2
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jul 18 15:12:36 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jul 18 11:12:57 2017 -0400

    Merge topic 'cmake-E-sha'
    
    c4de0a25 Add sha1sum, sha224sum, sha256sum, sha384sum and sha512sum to command mode
    c4647d84 Change ComputeFileMD5 to ComputeFileHash
    501a4fee Add some unit tests for md5sum
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1021


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b10d919de763000801cbffd4f58cbd0c4a1ad7a0
commit b10d919de763000801cbffd4f58cbd0c4a1ad7a0
Merge: 7870174 8eb1cb3
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jul 18 15:12:16 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jul 18 11:12:33 2017 -0400

    Merge topic 'GHS_int_detection'
    
    8eb1cb3f GHS: Correct the regex for the intXXXX directory detection.
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1062


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=787017451c437713b05a2ffc6fe609ea7da5f95b
commit 787017451c437713b05a2ffc6fe609ea7da5f95b
Merge: ec04964 d89e10c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jul 18 15:11:37 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jul 18 11:12:00 2017 -0400

    Merge topic 'objlib-own-target-objs'
    
    d89e10cd Diagnose object library self-reference
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1053


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8eb1cb3ff1938f4c216d08860f7cf8e07ec71537
commit 8eb1cb3ff1938f4c216d08860f7cf8e07ec71537
Author:     Roman Wüger <roman.wueger at gmx.at>
AuthorDate: Mon Jul 17 11:30:04 2017 +0200
Commit:     Roman Wüger <roman.wueger at gmx.at>
CommitDate: Mon Jul 17 11:30:04 2017 +0200

    GHS: Correct the regex for the intXXXX directory detection.
    
    The int directory does not only need to contain digits.
    E.g. C:\GHS\int409a is a valid Green Hills installation

diff --git a/Modules/Platform/GHS-MULTI-Initialize.cmake b/Modules/Platform/GHS-MULTI-Initialize.cmake
index fcda6f6..bf61d7b 100644
--- a/Modules/Platform/GHS-MULTI-Initialize.cmake
+++ b/Modules/Platform/GHS-MULTI-Initialize.cmake
@@ -10,7 +10,7 @@ if (NOT GHS_INT_DIRECTORY)
   if (EXISTS ${GHS_EXPECTED_ROOT})
     FILE(GLOB GHS_CANDIDATE_INT_DIRS RELATIVE
       ${GHS_EXPECTED_ROOT} ${GHS_EXPECTED_ROOT}/*)
-    string(REGEX MATCHALL  "int[0-9][0-9][0-9][0-9]" GHS_CANDIDATE_INT_DIRS
+    string(REGEX MATCHALL  "int[0-9][0-9][0-9][0-9a-z]" GHS_CANDIDATE_INT_DIRS
       ${GHS_CANDIDATE_INT_DIRS})
     if (GHS_CANDIDATE_INT_DIRS)
       list(SORT GHS_CANDIDATE_INT_DIRS)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d89e10cd58e5f9e21cbd466e56a1890e2811bee0
commit d89e10cd58e5f9e21cbd466e56a1890e2811bee0
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Jul 14 13:52:53 2017 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Jul 14 14:05:22 2017 -0400

    Diagnose object library self-reference
    
    The code
    
        add_library(A OBJECT a.c)
        target_sources(A PRIVATE $<TARGET_OBJECTS:A>)
    
    used to crash CMake via infinite recursion while evaluating the
    generator expression.  Then the change in commit v3.9.0-rc1~266^2~1
    (cmGeneratorTarget: Replace source classifier implementation,
    2017-04-07) avoided the infinite recursion because GetKindedSources now
    creates a map entry and initializes it once.  If it is called again on
    the same target during that initialization, the partially computed
    results are returned.  This is still wrong but does not crash.
    Detect and diagnose this case instead.
    
    Co-Author: Ben Boeckel <ben.boeckel at kitware.com>
    Fixes: #16578

diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index b93442d..e8ecac4 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1025,12 +1025,23 @@ cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
   std::string const key = cmSystemTools::UpperCase(config);
   KindedSourcesMapType::iterator it = this->KindedSourcesMap.find(key);
   if (it != this->KindedSourcesMap.end()) {
+    if (!it->second.Initialized) {
+      std::ostringstream e;
+      e << "The SOURCES of \"" << this->GetName()
+        << "\" use a generator expression that depends on the "
+           "SOURCES themselves.";
+      this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
+        cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
+      static KindedSources empty;
+      return empty;
+    }
     return it->second;
   }
 
   // Add an entry to the map for this configuration.
   KindedSources& files = this->KindedSourcesMap[key];
   this->ComputeKindedSources(files, config);
+  files.Initialized = true;
   return files;
 }
 
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index c04d62b..52147e3 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -107,6 +107,11 @@ public:
     std::set<std::string> ExpectedResxHeaders;
     std::set<std::string> ExpectedXamlHeaders;
     std::set<std::string> ExpectedXamlSources;
+    bool Initialized;
+    KindedSources()
+      : Initialized(false)
+    {
+    }
   };
 
   /** Get all sources needed for a configuration with kinds assigned.  */
diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
new file mode 100644
index 0000000..40d650e
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at OwnSources.cmake:[0-9]+ \(add_library\):
+  The SOURCES of "A" use a generator expression that depends on the SOURCES
+  themselves.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources.cmake b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake
new file mode 100644
index 0000000..e7bdf8d
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake
@@ -0,0 +1,2 @@
+add_library(A OBJECT a.c)
+target_sources(A PRIVATE $<TARGET_OBJECTS:A>)
diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
index fe708ce..b8eed73 100644
--- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -19,6 +19,7 @@ run_cmake(LinkObjRHS1)
 run_cmake(LinkObjRHS2)
 run_cmake(MissingSource)
 run_cmake(ObjWithObj)
+run_cmake(OwnSources)
 run_cmake(PostBuild)
 run_cmake(PreBuild)
 run_cmake(PreLink)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c4de0a25ac8b7bb94205e24b5557331ed80d79b8
commit c4de0a25ac8b7bb94205e24b5557331ed80d79b8
Author:     André Klitzing <aklitzing at gmail.com>
AuthorDate: Sat Jul 8 22:57:45 2017 +0200
Commit:     André Klitzing <aklitzing at gmail.com>
CommitDate: Fri Jul 14 19:49:45 2017 +0200

    Add sha1sum, sha224sum, sha256sum, sha384sum and sha512sum to command mode

diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index ba925e8..8aece23 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -262,6 +262,36 @@ Available commands are:
      351abe79cd3800b38cdfb25d45015a15  file1.txt
      052f86c15bbde68af55c7f7b340ab639  file2.txt
 
+``sha1sum <file>...``
+  Create SHA1 checksum of files in ``sha1sum`` compatible format::
+
+     4bb7932a29e6f73c97bb9272f2bdc393122f86e0  file1.txt
+     1df4c8f318665f9a5f2ed38f55adadb7ef9f559c  file2.txt
+
+``sha224sum <file>...``
+  Create SHA224 checksum of files in ``sha224sum`` compatible format::
+
+     b9b9346bc8437bbda630b0b7ddfc5ea9ca157546dbbf4c613192f930  file1.txt
+     6dfbe55f4d2edc5fe5c9197bca51ceaaf824e48eba0cc453088aee24  file2.txt
+
+``sha256sum <file>...``
+  Create SHA256 checksum of files in ``sha256sum`` compatible format::
+
+     76713b23615d31680afeb0e9efe94d47d3d4229191198bb46d7485f9cb191acc  file1.txt
+     15b682ead6c12dedb1baf91231e1e89cfc7974b3787c1e2e01b986bffadae0ea  file2.txt
+
+``sha384sum <file>...``
+  Create SHA384 checksum of files in ``sha384sum`` compatible format::
+
+     acc049fedc091a22f5f2ce39a43b9057fd93c910e9afd76a6411a28a8f2b8a12c73d7129e292f94fc0329c309df49434  file1.txt
+     668ddeb108710d271ee21c0f3acbd6a7517e2b78f9181c6a2ff3b8943af92b0195dcb7cce48aa3e17893173c0a39e23d  file2.txt
+
+``sha512sum <file>...``
+  Create SHA512 checksum of files in ``sha512sum`` compatible format::
+
+     2a78d7a6c5328cfb1467c63beac8ff21794213901eaadafd48e7800289afbc08e5fb3e86aa31116c945ee3d7bf2a6194489ec6101051083d1108defc8e1dba89  file1.txt
+     7a0b54896fe5e70cca6dd643ad6f672614b189bf26f8153061c4d219474b05dad08c4e729af9f4b009f1a1a280cb625454bf587c690f4617c27e3aebdf3b7a2d  file2.txt
+
 ``remove [-f] <file>...``
   Remove the file(s). If any of the listed files already do not
   exist, the command returns a non-zero exit code, but no message
diff --git a/Help/release/dev/cmake-command-mode-shasum.rst b/Help/release/dev/cmake-command-mode-shasum.rst
new file mode 100644
index 0000000..681e0c0
--- /dev/null
+++ b/Help/release/dev/cmake-command-mode-shasum.rst
@@ -0,0 +1,5 @@
+cmake-command-mode-shasum
+-------------------------
+
+* Added sha1sum, sha224sum, sha256sum, sha384sum and sha512sum
+  as an equivalent to existing md5sum to cmake command mode.
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 70ebd83..10889eb 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -3,7 +3,6 @@
 #include "cmcmd.h"
 
 #include "cmAlgorithms.h"
-#include "cmCryptoHash.h"
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
@@ -89,6 +88,11 @@ void CMakeCommandUsage(const char* program)
     << "  environment               - display the current environment\n"
     << "  make_directory <dir>...   - create parent and <dir> directories\n"
     << "  md5sum <file>...          - create MD5 checksum of files\n"
+    << "  sha1sum <file>...         - create SHA1 checksum of files\n"
+    << "  sha224sum <file>...       - create SHA224 checksum of files\n"
+    << "  sha256sum <file>...       - create SHA256 checksum of files\n"
+    << "  sha384sum <file>...       - create SHA384 checksum of files\n"
+    << "  sha512sum <file>...       - create SHA512 checksum of files\n"
     << "  remove [-f] <file>...     - remove the file(s), use -f to force "
        "it\n"
     << "  remove_directory dir      - remove a directory and its contents\n"
@@ -642,27 +646,28 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
 
     // Command to calculate the md5sum of a file
     if (args[1] == "md5sum" && args.size() >= 3) {
-      int retval = 0;
-      for (std::string::size_type cc = 2; cc < args.size(); cc++) {
-        const char* filename = args[cc].c_str();
-        // Cannot compute md5sum of a directory
-        if (cmSystemTools::FileIsDirectory(filename)) {
-          std::cerr << "Error: " << filename << " is a directory" << std::endl;
-          retval++;
-        } else {
-          std::string value =
-            cmSystemTools::ComputeFileHash(filename, cmCryptoHash::AlgoMD5);
-          if (value.empty()) {
-            // To mimic "md5sum" behavior in a shell:
-            std::cerr << filename << ": No such file or directory"
-                      << std::endl;
-            retval++;
-          } else {
-            std::cout << value << "  " << filename << std::endl;
-          }
-        }
-      }
-      return retval;
+      return HashSumFile(args, cmCryptoHash::AlgoMD5);
+    }
+
+    // Command to calculate the sha1sum of a file
+    if (args[1] == "sha1sum" && args.size() >= 3) {
+      return HashSumFile(args, cmCryptoHash::AlgoSHA1);
+    }
+
+    if (args[1] == "sha224sum" && args.size() >= 3) {
+      return HashSumFile(args, cmCryptoHash::AlgoSHA224);
+    }
+
+    if (args[1] == "sha256sum" && args.size() >= 3) {
+      return HashSumFile(args, cmCryptoHash::AlgoSHA256);
+    }
+
+    if (args[1] == "sha384sum" && args.size() >= 3) {
+      return HashSumFile(args, cmCryptoHash::AlgoSHA384);
+    }
+
+    if (args[1] == "sha512sum" && args.size() >= 3) {
+      return HashSumFile(args, cmCryptoHash::AlgoSHA512);
     }
 
     // Command to change directory and run a program.
@@ -1078,6 +1083,33 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
   return 1;
 }
 
+int cmcmd::HashSumFile(std::vector<std::string>& args, cmCryptoHash::Algo algo)
+{
+  if (args.size() < 3) {
+    return -1;
+  }
+  int retval = 0;
+
+  for (std::string::size_type cc = 2; cc < args.size(); cc++) {
+    const char* filename = args[cc].c_str();
+    // Cannot compute sum of a directory
+    if (cmSystemTools::FileIsDirectory(filename)) {
+      std::cerr << "Error: " << filename << " is a directory" << std::endl;
+      retval++;
+    } else {
+      std::string value = cmSystemTools::ComputeFileHash(filename, algo);
+      if (value.empty()) {
+        // To mimic "md5sum/shasum" behavior in a shell:
+        std::cerr << filename << ": No such file or directory" << std::endl;
+        retval++;
+      } else {
+        std::cout << value << "  " << filename << std::endl;
+      }
+    }
+  }
+  return retval;
+}
+
 int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
 {
   int result = 0;
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
index 929f1ae..faac1d2 100644
--- a/Source/cmcmd.h
+++ b/Source/cmcmd.h
@@ -4,6 +4,7 @@
 #define cmcmd_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
+#include "cmCryptoHash.h"
 
 #include <string>
 #include <vector>
@@ -18,6 +19,8 @@ public:
   static int ExecuteCMakeCommand(std::vector<std::string>&);
 
 protected:
+  static int HashSumFile(std::vector<std::string>& args,
+                         cmCryptoHash::Algo algo);
   static int SymlinkLibrary(std::vector<std::string>& args);
   static int SymlinkExecutable(std::vector<std::string>& args);
   static bool SymlinkInternal(std::string const& file,
diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha1sum-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha1sum-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha1sum-dir-stderr.txt
new file mode 100644
index 0000000..061fd64
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha1sum-dir-stderr.txt
@@ -0,0 +1 @@
+Error: . is a directory
diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-stderr.txt
new file mode 100644
index 0000000..732e8c4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-stderr.txt
@@ -0,0 +1 @@
+nonexisting: No such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-result.txt b/Tests/RunCMake/CommandLine/E_sha1sum-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha1sum-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt
new file mode 100644
index 0000000..689b85b
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt
@@ -0,0 +1 @@
+829c3804401b0727f70f73d4415e162400cbe57b  ../dummy
diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha224sum-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha224sum-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha224sum-dir-stderr.txt
new file mode 100644
index 0000000..061fd64
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha224sum-dir-stderr.txt
@@ -0,0 +1 @@
+Error: . is a directory
diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-stderr.txt
new file mode 100644
index 0000000..732e8c4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-stderr.txt
@@ -0,0 +1 @@
+nonexisting: No such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-result.txt b/Tests/RunCMake/CommandLine/E_sha224sum-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha224sum-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt
new file mode 100644
index 0000000..5b3e217
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt
@@ -0,0 +1 @@
+37d32c6dbabed711cb1d4620b64090fef0ef63ab16a4a51d668259e6  ../dummy
diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha256sum-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha256sum-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha256sum-dir-stderr.txt
new file mode 100644
index 0000000..061fd64
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha256sum-dir-stderr.txt
@@ -0,0 +1 @@
+Error: . is a directory
diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-stderr.txt
new file mode 100644
index 0000000..732e8c4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-stderr.txt
@@ -0,0 +1 @@
+nonexisting: No such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-result.txt b/Tests/RunCMake/CommandLine/E_sha256sum-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha256sum-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt
new file mode 100644
index 0000000..9a18770
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt
@@ -0,0 +1 @@
+b5a2c96250612366ea272ffac6d9744aaf4b45aacd96aa7cfcb931ee3b558259  ../dummy
diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha384sum-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha384sum-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha384sum-dir-stderr.txt
new file mode 100644
index 0000000..061fd64
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha384sum-dir-stderr.txt
@@ -0,0 +1 @@
+Error: . is a directory
diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-stderr.txt
new file mode 100644
index 0000000..732e8c4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-stderr.txt
@@ -0,0 +1 @@
+nonexisting: No such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-result.txt b/Tests/RunCMake/CommandLine/E_sha384sum-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha384sum-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt
new file mode 100644
index 0000000..b706ac5
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt
@@ -0,0 +1 @@
+43c1835ceba2e29596f05e3859d4fe2b6d124a181ed670f68e914bd3ed251b02b4be609608a13f23ec3d98da6c4eb8cd  ../dummy
diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha512sum-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha512sum-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha512sum-dir-stderr.txt
new file mode 100644
index 0000000..061fd64
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha512sum-dir-stderr.txt
@@ -0,0 +1 @@
+Error: . is a directory
diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-stderr.txt
new file mode 100644
index 0000000..732e8c4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-stderr.txt
@@ -0,0 +1 @@
+nonexisting: No such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-result.txt b/Tests/RunCMake/CommandLine/E_sha512sum-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha512sum-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt
new file mode 100644
index 0000000..4305383
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt
@@ -0,0 +1 @@
+1692526aab84461a8aebcefddcba2b33fb5897ab180c53e8b345ae125484d0aaa35baf60487050be21ed8909a48eace93851bf139087ce1f7a87d97b6120a651  ../dummy
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 6f5298e..6efcc12 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -173,10 +173,27 @@ run_cmake_command(E_env-set   ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND
 run_cmake_command(E_env-unset ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -E env --unset=TEST_ENV ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake)
 
 run_cmake_command(E_md5sum-dir ${CMAKE_COMMAND} -E md5sum .)
+run_cmake_command(E_sha1sum-dir ${CMAKE_COMMAND} -E sha1sum .)
+run_cmake_command(E_sha224sum-dir ${CMAKE_COMMAND} -E sha224sum .)
+run_cmake_command(E_sha256sum-dir ${CMAKE_COMMAND} -E sha256sum .)
+run_cmake_command(E_sha384sum-dir ${CMAKE_COMMAND} -E sha384sum .)
+run_cmake_command(E_sha512sum-dir ${CMAKE_COMMAND} -E sha512sum .)
+
 run_cmake_command(E_md5sum-no-file ${CMAKE_COMMAND} -E md5sum nonexisting)
+run_cmake_command(E_sha1sum-no-file ${CMAKE_COMMAND} -E sha1sum nonexisting)
+run_cmake_command(E_sha224sum-no-file ${CMAKE_COMMAND} -E sha224sum nonexisting)
+run_cmake_command(E_sha256sum-no-file ${CMAKE_COMMAND} -E sha256sum nonexisting)
+run_cmake_command(E_sha384sum-no-file ${CMAKE_COMMAND} -E sha384sum nonexisting)
+run_cmake_command(E_sha512sum-no-file ${CMAKE_COMMAND} -E sha512sum nonexisting)
+
 file(WRITE "${RunCMake_BINARY_DIR}/dummy" "dummy")
 run_cmake_command(E_md5sum ${CMAKE_COMMAND} -E md5sum ../dummy)
 run_cmake_command(E_md5sum-mixed ${CMAKE_COMMAND} -E md5sum . ../dummy nonexisting)
+run_cmake_command(E_sha1sum ${CMAKE_COMMAND} -E sha1sum ../dummy)
+run_cmake_command(E_sha224sum ${CMAKE_COMMAND} -E sha224sum ../dummy)
+run_cmake_command(E_sha256sum ${CMAKE_COMMAND} -E sha256sum ../dummy)
+run_cmake_command(E_sha384sum ${CMAKE_COMMAND} -E sha384sum ../dummy)
+run_cmake_command(E_sha512sum ${CMAKE_COMMAND} -E sha512sum ../dummy)
 file(REMOVE "${RunCMake_BINARY_DIR}/dummy")
 
 set(RunCMake_DEFAULT_stderr ".")

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c4647d84321f4a7b52301237394087065f5df33c
commit c4647d84321f4a7b52301237394087065f5df33c
Author:     André Klitzing <aklitzing at gmail.com>
AuthorDate: Sat Jul 8 18:42:02 2017 +0200
Commit:     André Klitzing <aklitzing at gmail.com>
CommitDate: Fri Jul 14 08:57:17 2017 +0200

    Change ComputeFileMD5 to ComputeFileHash
    
    * Use a parameter to select hash algorithm
    * Return a std::string as result or an empty
      string if it fails
    * Avoids unnecessary copy of hash value

diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 00d017e..0705460 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -6,6 +6,7 @@
 #include "cmCPackComponentGroup.h"
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
+#include "cmCryptoHash.h"
 #include "cmGeneratedFileStream.h"
 #include "cmSystemTools.h"
 #include "cm_sys_stat.h"
@@ -527,15 +528,13 @@ int cmCPackDebGenerator::createDeb()
         continue;
       }
 
-      char md5sum[33];
-      if (!cmSystemTools::ComputeFileMD5(*fileIt, md5sum)) {
+      std::string output =
+        cmSystemTools::ComputeFileHash(*fileIt, cmCryptoHash::AlgoMD5);
+      if (output.empty()) {
         cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem computing the md5 of "
                         << *fileIt << std::endl);
       }
 
-      md5sum[32] = 0;
-
-      std::string output(md5sum);
       output += "  " + *fileIt + "\n";
       // debian md5sums entries are like this:
       // 014f3604694729f3bf19263bac599765  usr/bin/ccmake
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 8d62fa1..689668d 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -13,6 +13,7 @@
 #include "cmCTest.h"
 #include "cmCTestCurl.h"
 #include "cmCTestScriptHandler.h"
+#include "cmCryptoHash.h"
 #include "cmCurl.h"
 #include "cmGeneratedFileStream.h"
 #include "cmProcessOutput.h"
@@ -428,10 +429,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
       if (cmSystemTools::IsOn(this->GetOption("InternalTest"))) {
         upload_as += "bad_md5sum";
       } else {
-        char md5[33];
-        cmSystemTools::ComputeFileMD5(local_file, md5);
-        md5[32] = 0;
-        upload_as += md5;
+        upload_as +=
+          cmSystemTools::ComputeFileHash(local_file, cmCryptoHash::AlgoMD5);
       }
 
       if (!cmSystemTools::FileExists(local_file.c_str())) {
@@ -1058,9 +1057,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
     }
   }
 
-  char md5sum[33];
-  md5sum[32] = 0;
-  cmSystemTools::ComputeFileMD5(file, md5sum);
+  std::string md5sum =
+    cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5);
   // 1. request the buildid and check to see if the file
   //    has already been uploaded
   // TODO I added support for subproject. You would need to add
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index f7192e0..9f214c3 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -934,19 +934,17 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
 #endif
 }
 
-bool cmSystemTools::ComputeFileMD5(const std::string& source, char* md5out)
+std::string cmSystemTools::ComputeFileHash(const std::string& source,
+                                           cmCryptoHash::Algo algo)
 {
 #if defined(CMAKE_BUILD_WITH_CMAKE)
-  cmCryptoHash md5(cmCryptoHash::AlgoMD5);
-  std::string const str = md5.HashFile(source);
-  strncpy(md5out, str.c_str(), 32);
-  return !str.empty();
+  cmCryptoHash hash(algo);
+  return hash.HashFile(source);
 #else
   (void)source;
-  (void)md5out;
-  cmSystemTools::Message("md5sum not supported in bootstrapping mode",
+  cmSystemTools::Message("hashsum not supported in bootstrapping mode",
                          "Error");
-  return false;
+  return std::string();
 #endif
 }
 
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 9de7967..e163c91 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h"
 
+#include "cmCryptoHash.h"
 #include "cmProcessOutput.h"
 #include "cmsys/Process.h"
 #include "cmsys/SystemTools.hxx" // IWYU pragma: export
@@ -179,8 +180,9 @@ public:
       if possible).  */
   static bool RenameFile(const char* oldname, const char* newname);
 
-  ///! Compute the md5sum of a file
-  static bool ComputeFileMD5(const std::string& source, char* md5out);
+  ///! Compute the hash of a file
+  static std::string ComputeFileHash(const std::string& source,
+                                     cmCryptoHash::Algo algo);
 
   /** Compute the md5sum of a string.  */
   static std::string ComputeStringMD5(const std::string& input);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index d5b0861..70ebd83 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -3,6 +3,7 @@
 #include "cmcmd.h"
 
 #include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
@@ -641,7 +642,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
 
     // Command to calculate the md5sum of a file
     if (args[1] == "md5sum" && args.size() >= 3) {
-      char md5out[32];
       int retval = 0;
       for (std::string::size_type cc = 2; cc < args.size(); cc++) {
         const char* filename = args[cc].c_str();
@@ -649,13 +649,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
         if (cmSystemTools::FileIsDirectory(filename)) {
           std::cerr << "Error: " << filename << " is a directory" << std::endl;
           retval++;
-        } else if (!cmSystemTools::ComputeFileMD5(filename, md5out)) {
-          // To mimic md5sum behavior in a shell:
-          std::cerr << filename << ": No such file or directory" << std::endl;
-          retval++;
         } else {
-          std::cout << std::string(md5out, 32) << "  " << filename
-                    << std::endl;
+          std::string value =
+            cmSystemTools::ComputeFileHash(filename, cmCryptoHash::AlgoMD5);
+          if (value.empty()) {
+            // To mimic "md5sum" behavior in a shell:
+            std::cerr << filename << ": No such file or directory"
+                      << std::endl;
+            retval++;
+          } else {
+            std::cout << value << "  " << filename << std::endl;
+          }
         }
       }
       return retval;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf0ae55dcb9224b92a95166f17452c56ba5b6213
commit cf0ae55dcb9224b92a95166f17452c56ba5b6213
Author:     Justin Berger <j.david.berger at gmail.com>
AuthorDate: Sat Feb 25 15:06:34 2017 -0700
Commit:     Justin Berger <j.david.berger at gmail.com>
CommitDate: Mon Jul 10 18:12:05 2017 -0600

    server: Add support for connections that aren't event based

diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx
index b25843b..00cf283 100644
--- a/Source/cmConnection.cxx
+++ b/Source/cmConnection.cxx
@@ -14,18 +14,19 @@ struct write_req_t
   uv_buf_t buf;
 };
 
-void cmConnection::on_alloc_buffer(uv_handle_t* handle, size_t suggested_size,
-                                   uv_buf_t* buf)
+void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle,
+                                             size_t suggested_size,
+                                             uv_buf_t* buf)
 {
   (void)(handle);
   char* rawBuffer = new char[suggested_size];
   *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
 }
 
-void cmConnection::on_read(uv_stream_t* stream, ssize_t nread,
-                           const uv_buf_t* buf)
+void cmEventBasedConnection::on_read(uv_stream_t* stream, ssize_t nread,
+                                     const uv_buf_t* buf)
 {
-  auto conn = reinterpret_cast<cmConnection*>(stream->data);
+  auto conn = reinterpret_cast<cmEventBasedConnection*>(stream->data);
   if (conn) {
     if (nread >= 0) {
       conn->ReadData(std::string(buf->base, buf->base + nread));
@@ -37,16 +38,16 @@ void cmConnection::on_read(uv_stream_t* stream, ssize_t nread,
   delete[](buf->base);
 }
 
-void cmConnection::on_close_delete(uv_handle_t* handle)
+void cmEventBasedConnection::on_close_delete(uv_handle_t* handle)
 {
   delete handle;
 }
 
-void cmConnection::on_close(uv_handle_t*)
+void cmEventBasedConnection::on_close(uv_handle_t* /*handle*/)
 {
 }
 
-void cmConnection::on_write(uv_write_t* req, int status)
+void cmEventBasedConnection::on_write(uv_write_t* req, int status)
 {
   (void)(status);
 
@@ -56,22 +57,22 @@ void cmConnection::on_write(uv_write_t* req, int status)
   delete wr;
 }
 
-void cmConnection::on_new_connection(uv_stream_t* stream, int status)
+void cmEventBasedConnection::on_new_connection(uv_stream_t* stream, int status)
 {
   (void)(status);
-  auto conn = reinterpret_cast<cmConnection*>(stream->data);
+  auto conn = reinterpret_cast<cmEventBasedConnection*>(stream->data);
 
   if (conn) {
     conn->Connect(stream);
   }
 }
 
-bool cmConnection::IsOpen() const
+bool cmEventBasedConnection::IsOpen() const
 {
   return this->WriteStream != CM_NULLPTR;
 }
 
-void cmConnection::WriteData(const std::string& data)
+void cmEventBasedConnection::WriteData(const std::string& data)
 {
   assert(this->WriteStream);
 
@@ -86,12 +87,7 @@ void cmConnection::WriteData(const std::string& data)
            on_write);
 }
 
-cmConnection::~cmConnection()
-{
-  OnServerShuttingDown();
-}
-
-void cmConnection::ReadData(const std::string& data)
+void cmEventBasedConnection::ReadData(const std::string& data)
 {
   this->RawReadBuffer += data;
   if (BufferStrategy) {
@@ -107,19 +103,37 @@ void cmConnection::ReadData(const std::string& data)
   }
 }
 
-void cmConnection::SetServer(cmServerBase* s)
+cmEventBasedConnection::cmEventBasedConnection(
+  cmConnectionBufferStrategy* bufferStrategy)
+  : BufferStrategy(bufferStrategy)
 {
-  Server = s;
 }
 
-cmConnection::cmConnection(cmConnectionBufferStrategy* bufferStrategy)
-  : BufferStrategy(bufferStrategy)
+void cmEventBasedConnection::Connect(uv_stream_t* server)
 {
+  (void)server;
+  Server->OnConnected(nullptr);
 }
 
-void cmConnection::Connect(uv_stream_t*)
+void cmEventBasedConnection::OnDisconnect(int onerror)
 {
-  Server->OnConnected(nullptr);
+  (void)onerror;
+  this->OnConnectionShuttingDown();
+  this->Server->OnDisconnect(this);
+}
+
+cmConnection::~cmConnection()
+{
+}
+
+bool cmConnection::OnConnectionShuttingDown()
+{
+  return true;
+}
+
+void cmConnection::SetServer(cmServerBase* s)
+{
+  Server = s;
 }
 
 void cmConnection::ProcessRequest(const std::string& request)
@@ -133,13 +147,7 @@ bool cmConnection::OnServeStart(std::string* errString)
   return true;
 }
 
-void cmConnection::OnDisconnect(int errorCode)
-{
-  (void)errorCode;
-  this->Server->OnDisconnect(this);
-}
-
-bool cmConnection::OnServerShuttingDown()
+bool cmEventBasedConnection::OnConnectionShuttingDown()
 {
   this->WriteStream->data = nullptr;
   this->ReadStream->data = nullptr;
diff --git a/Source/cmConnection.h b/Source/cmConnection.h
index e994716..4b8fcb3 100644
--- a/Source/cmConnection.h
+++ b/Source/cmConnection.h
@@ -46,43 +46,57 @@ public:
   // TODO: There should be a callback / flag set for errors
 };
 
-/***
- * Abstraction of a connection; ties in event callbacks from libuv and notifies
- * the server when appropriate
- */
 class cmConnection
 {
   CM_DISABLE_COPY(cmConnection)
 
 public:
+  cmConnection() {}
+
+  virtual void WriteData(const std::string& data) = 0;
+
   virtual ~cmConnection();
 
+  virtual bool OnConnectionShuttingDown();
+
+  virtual bool IsOpen() const = 0;
+
+  virtual void SetServer(cmServerBase* s);
+
+  virtual void ProcessRequest(const std::string& request);
+
+  virtual bool OnServeStart(std::string* pString);
+
+protected:
+  cmServerBase* Server = nullptr;
+};
+
+/***
+ * Abstraction of a connection; ties in event callbacks from libuv and notifies
+ * the server when appropriate
+ */
+class cmEventBasedConnection : public cmConnection
+{
+
+public:
   /***
    * @param bufferStrategy If no strategy is given, it will process the raw
    * chunks as they come in. The connection
    * owns the pointer given.
    */
-  cmConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr);
+  cmEventBasedConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr);
 
   virtual void Connect(uv_stream_t* server);
 
   virtual void ReadData(const std::string& data);
 
-  virtual bool OnServeStart(std::string* errString);
+  bool IsOpen() const override;
 
-  virtual bool OnServerShuttingDown();
-
-  virtual bool IsOpen() const;
-
-  virtual void WriteData(const std::string& data);
-
-  virtual void ProcessRequest(const std::string& request);
-
-  virtual void SetServer(cmServerBase* s);
+  void WriteData(const std::string& data) override;
+  bool OnConnectionShuttingDown() override;
 
   virtual void OnDisconnect(int errorCode);
   uv_stream_t* ReadStream = nullptr;
-  cmServerBase* Server = nullptr;
   uv_stream_t* WriteStream = nullptr;
 
   static void on_close(uv_handle_t* handle);
diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx
index 438719f..cc82438 100644
--- a/Source/cmPipeConnection.cxx
+++ b/Source/cmPipeConnection.cxx
@@ -7,7 +7,7 @@
 
 cmPipeConnection::cmPipeConnection(const std::string& name,
                                    cmConnectionBufferStrategy* bufferStrategy)
-  : cmConnection(bufferStrategy)
+  : cmEventBasedConnection(bufferStrategy)
   , PipeName(name)
 {
 }
@@ -26,8 +26,7 @@ void cmPipeConnection::Connect(uv_stream_t* server)
 
   this->ClientPipe = new uv_pipe_t();
   uv_pipe_init(this->Server->GetLoop(), this->ClientPipe, 0);
-  this->ClientPipe->data = static_cast<cmConnection*>(this);
-
+  this->ClientPipe->data = static_cast<cmEventBasedConnection*>(this);
   auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe);
   if (uv_accept(server, client) != 0) {
     uv_close(reinterpret_cast<uv_handle_t*>(client), &on_close_delete);
@@ -45,7 +44,7 @@ bool cmPipeConnection::OnServeStart(std::string* errorMessage)
 {
   this->ServerPipe = new uv_pipe_t();
   uv_pipe_init(this->Server->GetLoop(), this->ServerPipe, 0);
-  this->ServerPipe->data = static_cast<cmConnection*>(this);
+  this->ServerPipe->data = static_cast<cmEventBasedConnection*>(this);
 
   int r;
   if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
@@ -63,7 +62,7 @@ bool cmPipeConnection::OnServeStart(std::string* errorMessage)
   return cmConnection::OnServeStart(errorMessage);
 }
 
-bool cmPipeConnection::OnServerShuttingDown()
+bool cmPipeConnection::OnConnectionShuttingDown()
 {
   if (this->ClientPipe) {
     uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe),
@@ -77,5 +76,5 @@ bool cmPipeConnection::OnServerShuttingDown()
   this->WriteStream = nullptr;
   this->ReadStream = nullptr;
 
-  return cmConnection::OnServerShuttingDown();
+  return cmConnection::OnConnectionShuttingDown();
 }
diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h
index 3d3d52c..fea85b5 100644
--- a/Source/cmPipeConnection.h
+++ b/Source/cmPipeConnection.h
@@ -9,7 +9,7 @@
 
 #include <string>
 
-class cmPipeConnection : public cmConnection
+class cmPipeConnection : public cmEventBasedConnection
 {
 public:
   cmPipeConnection(const std::string& name,
@@ -17,7 +17,7 @@ public:
 
   bool OnServeStart(std::string* pString) override;
 
-  bool OnServerShuttingDown() override;
+  bool OnConnectionShuttingDown() override;
 
   void Connect(uv_stream_t* server) override;
 
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index 61ebba3..1d5f3f6 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -28,7 +28,7 @@ static void on_walk_to_shutdown(uv_handle_t* handle, void* arg)
 {
   (void)arg;
   if (!uv_is_closing(handle)) {
-    uv_close(handle, &cmConnection::on_close);
+    uv_close(handle, &cmEventBasedConnection::on_close);
   }
 }
 
@@ -478,7 +478,7 @@ void cmServerBase::StartShutDown()
   }
 
   for (auto& connection : Connections) {
-    connection->OnServerShuttingDown();
+    connection->OnConnectionShuttingDown();
   }
   Connections.clear();
 
diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx
index 3cc7722..4891131 100644
--- a/Source/cmServerConnection.cxx
+++ b/Source/cmServerConnection.cxx
@@ -7,7 +7,7 @@
 
 cmStdIoConnection::cmStdIoConnection(
   cmConnectionBufferStrategy* bufferStrategy)
-  : cmConnection(bufferStrategy)
+  : cmEventBasedConnection(bufferStrategy)
   , Input()
   , Output()
 {
@@ -23,13 +23,13 @@ void cmStdIoConnection::SetServer(cmServerBase* s)
     this->Input.tty = new uv_tty_t();
     uv_tty_init(this->Server->GetLoop(), this->Input.tty, 0, 1);
     uv_tty_set_mode(this->Input.tty, UV_TTY_MODE_NORMAL);
-    this->Input.tty->data = static_cast<cmConnection*>(this);
+    this->Input.tty->data = static_cast<cmEventBasedConnection*>(this);
     this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.tty);
 
     this->Output.tty = new uv_tty_t();
     uv_tty_init(this->Server->GetLoop(), this->Output.tty, 1, 0);
     uv_tty_set_mode(this->Output.tty, UV_TTY_MODE_NORMAL);
-    this->Output.tty->data = static_cast<cmConnection*>(this);
+    this->Output.tty->data = static_cast<cmEventBasedConnection*>(this);
     this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.tty);
   } else {
     usesTty = false;
@@ -37,13 +37,13 @@ void cmStdIoConnection::SetServer(cmServerBase* s)
     this->Input.pipe = new uv_pipe_t();
     uv_pipe_init(this->Server->GetLoop(), this->Input.pipe, 0);
     uv_pipe_open(this->Input.pipe, 0);
-    this->Input.pipe->data = static_cast<cmConnection*>(this);
+    this->Input.pipe->data = static_cast<cmEventBasedConnection*>(this);
     this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.pipe);
 
     this->Output.pipe = new uv_pipe_t();
     uv_pipe_init(this->Server->GetLoop(), this->Output.pipe, 0);
     uv_pipe_open(this->Output.pipe, 1);
-    this->Output.pipe->data = static_cast<cmConnection*>(this);
+    this->Output.pipe->data = static_cast<cmEventBasedConnection*>(this);
     this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.pipe);
   }
 }
@@ -55,9 +55,9 @@ bool cmStdIoConnection::OnServeStart(std::string* pString)
   return cmConnection::OnServeStart(pString);
 }
 
-bool cmStdIoConnection::OnServerShuttingDown()
+bool cmStdIoConnection::OnConnectionShuttingDown()
 {
-  cmConnection::OnServerShuttingDown();
+  cmEventBasedConnection::OnConnectionShuttingDown();
 
   if (usesTty) {
     uv_read_stop(reinterpret_cast<uv_stream_t*>(this->Input.tty));
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
index 8865480..0804f0e 100644
--- a/Source/cmServerConnection.h
+++ b/Source/cmServerConnection.h
@@ -32,14 +32,14 @@ private:
 /***
  * Generic connection over std io interfaces -- tty
  */
-class cmStdIoConnection : public cmConnection
+class cmStdIoConnection : public cmEventBasedConnection
 {
 public:
   cmStdIoConnection(cmConnectionBufferStrategy* bufferStrategy);
 
   void SetServer(cmServerBase* s) override;
 
-  bool OnServerShuttingDown() override;
+  bool OnConnectionShuttingDown() override;
 
   bool OnServeStart(std::string* pString) override;
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5ddfb6a472539c3a01a6f8e6d8fa1cb1013fc4f9
commit 5ddfb6a472539c3a01a6f8e6d8fa1cb1013fc4f9
Author:     Justin Berger <j.david.berger at gmail.com>
AuthorDate: Fri Mar 24 21:57:04 2017 -0600
Commit:     Justin Berger <j.david.berger at gmail.com>
CommitDate: Mon Jul 10 18:11:33 2017 -0600

    server: Add connection as part of a request

diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index 03e0115..61ebba3 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -83,7 +83,7 @@ void cmServer::ProcessRequest(cmConnection* connection,
     debug->PrintStatistics = debugValue["showStats"].asBool();
   }
 
-  const cmServerRequest request(this, value[kTYPE_KEY].asString(),
+  const cmServerRequest request(this, connection, value[kTYPE_KEY].asString(),
                                 value[kCOOKIE_KEY].asString(), value);
 
   if (request.Type == "") {
@@ -323,7 +323,7 @@ void cmServer::WriteProgress(const cmServerRequest& request, int min,
   obj[kPROGRESS_MAXIMUM_KEY] = max;
   obj[kPROGRESS_CURRENT_KEY] = current;
 
-  this->WriteJsonObject(obj, nullptr);
+  this->WriteJsonObject(request.Connection, obj, nullptr);
 }
 
 void cmServer::WriteMessage(const cmServerRequest& request,
@@ -343,7 +343,7 @@ void cmServer::WriteMessage(const cmServerRequest& request,
     obj[kTITLE_KEY] = title;
   }
 
-  WriteJsonObject(obj, nullptr);
+  WriteJsonObject(request.Connection, obj, nullptr);
 }
 
 void cmServer::WriteParseError(cmConnection* connection,
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index defba77..ed1abe7 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -125,11 +125,13 @@ void getCMakeInputs(const cmGlobalGenerator* gg, const std::string& sourceDir,
 
 } // namespace
 
-cmServerRequest::cmServerRequest(cmServer* server, const std::string& t,
-                                 const std::string& c, const Json::Value& d)
+cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection,
+                                 const std::string& t, const std::string& c,
+                                 const Json::Value& d)
   : Type(t)
   , Cookie(c)
   , Data(d)
+  , Connection(connection)
   , m_Server(server)
 {
 }
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index 83b3d58..9902dfb 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <utility>
 
+class cmConnection;
 class cmFileMonitor;
 class cmServer;
 class cmServerRequest;
@@ -52,9 +53,11 @@ public:
   const std::string Type;
   const std::string Cookie;
   const Json::Value Data;
+  cmConnection* Connection;
 
 private:
-  cmServerRequest(cmServer* server, const std::string& t, const std::string& c,
+  cmServerRequest(cmServer* server, cmConnection* connection,
+                  const std::string& t, const std::string& c,
                   const Json::Value& d);
 
   void ReportProgress(int min, int current, int max,

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d4f5d35ca491ede92003b26a7d0eb06aea3a2bbb
commit d4f5d35ca491ede92003b26a7d0eb06aea3a2bbb
Author:     Justin Berger <j.david.berger at gmail.com>
AuthorDate: Fri Mar 24 21:38:52 2017 -0600
Commit:     Justin Berger <j.david.berger at gmail.com>
CommitDate: Mon Jul 10 18:11:27 2017 -0600

    server: Refactor to make the event loop owned by server object

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 40403ca..d41d514 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -976,7 +976,9 @@ target_link_libraries(cmake CMakeLib)
 
 if(CMake_ENABLE_SERVER_MODE)
   add_library(CMakeServerLib
+    cmConnection.h cmConnection.cxx
     cmFileMonitor.cxx cmFileMonitor.h
+    cmPipeConnection.cxx cmPipeConnection.h
     cmServer.cxx cmServer.h
     cmServerConnection.cxx cmServerConnection.h
     cmServerProtocol.cxx cmServerProtocol.h
diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx
new file mode 100644
index 0000000..b25843b
--- /dev/null
+++ b/Source/cmConnection.cxx
@@ -0,0 +1,150 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmConnection.h"
+
+#include "cmServer.h"
+#include "cm_uv.h"
+
+#include <cassert>
+#include <cstring>
+
+struct write_req_t
+{
+  uv_write_t req;
+  uv_buf_t buf;
+};
+
+void cmConnection::on_alloc_buffer(uv_handle_t* handle, size_t suggested_size,
+                                   uv_buf_t* buf)
+{
+  (void)(handle);
+  char* rawBuffer = new char[suggested_size];
+  *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
+}
+
+void cmConnection::on_read(uv_stream_t* stream, ssize_t nread,
+                           const uv_buf_t* buf)
+{
+  auto conn = reinterpret_cast<cmConnection*>(stream->data);
+  if (conn) {
+    if (nread >= 0) {
+      conn->ReadData(std::string(buf->base, buf->base + nread));
+    } else {
+      conn->OnDisconnect((int)nread);
+    }
+  }
+
+  delete[](buf->base);
+}
+
+void cmConnection::on_close_delete(uv_handle_t* handle)
+{
+  delete handle;
+}
+
+void cmConnection::on_close(uv_handle_t*)
+{
+}
+
+void cmConnection::on_write(uv_write_t* req, int status)
+{
+  (void)(status);
+
+  // Free req and buffer
+  write_req_t* wr = reinterpret_cast<write_req_t*>(req);
+  delete[](wr->buf.base);
+  delete wr;
+}
+
+void cmConnection::on_new_connection(uv_stream_t* stream, int status)
+{
+  (void)(status);
+  auto conn = reinterpret_cast<cmConnection*>(stream->data);
+
+  if (conn) {
+    conn->Connect(stream);
+  }
+}
+
+bool cmConnection::IsOpen() const
+{
+  return this->WriteStream != CM_NULLPTR;
+}
+
+void cmConnection::WriteData(const std::string& data)
+{
+  assert(this->WriteStream);
+
+  auto ds = data.size();
+
+  write_req_t* req = new write_req_t;
+  req->req.data = this;
+  req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds));
+  memcpy(req->buf.base, data.c_str(), ds);
+  uv_write(reinterpret_cast<uv_write_t*>(req),
+           static_cast<uv_stream_t*>(this->WriteStream), &req->buf, 1,
+           on_write);
+}
+
+cmConnection::~cmConnection()
+{
+  OnServerShuttingDown();
+}
+
+void cmConnection::ReadData(const std::string& data)
+{
+  this->RawReadBuffer += data;
+  if (BufferStrategy) {
+    std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
+    do {
+      ProcessRequest(packet);
+      packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
+    } while (!packet.empty());
+
+  } else {
+    ProcessRequest(this->RawReadBuffer);
+    this->RawReadBuffer.clear();
+  }
+}
+
+void cmConnection::SetServer(cmServerBase* s)
+{
+  Server = s;
+}
+
+cmConnection::cmConnection(cmConnectionBufferStrategy* bufferStrategy)
+  : BufferStrategy(bufferStrategy)
+{
+}
+
+void cmConnection::Connect(uv_stream_t*)
+{
+  Server->OnConnected(nullptr);
+}
+
+void cmConnection::ProcessRequest(const std::string& request)
+{
+  Server->ProcessRequest(this, request);
+}
+
+bool cmConnection::OnServeStart(std::string* errString)
+{
+  (void)errString;
+  return true;
+}
+
+void cmConnection::OnDisconnect(int errorCode)
+{
+  (void)errorCode;
+  this->Server->OnDisconnect(this);
+}
+
+bool cmConnection::OnServerShuttingDown()
+{
+  this->WriteStream->data = nullptr;
+  this->ReadStream->data = nullptr;
+
+  this->ReadStream = nullptr;
+  this->WriteStream = nullptr;
+  return true;
+}
diff --git a/Source/cmConnection.h b/Source/cmConnection.h
new file mode 100644
index 0000000..e994716
--- /dev/null
+++ b/Source/cmConnection.h
@@ -0,0 +1,104 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#pragma once
+
+#include "cmConfigure.h"
+
+#include "cm_uv.h"
+
+#include <cstddef>
+#include <memory>
+#include <string>
+
+class cmServerBase;
+
+/***
+ * Given a sequence of bytes with any kind of buffering, instances of this
+ * class arrange logical chunks according to whatever the use case is for
+ * the connection.
+ */
+class cmConnectionBufferStrategy
+{
+public:
+  virtual ~cmConnectionBufferStrategy();
+
+  /***
+   * Called whenever with an active raw buffer. If a logical chunk
+   * becomes available, that chunk is returned and that portion is
+   * removed from the rawBuffer
+   *
+   * @param rawBuffer in/out parameter. Receive buffer; the buffer strategy is
+   * free to manipulate this buffer anyway it needs to.
+   *
+   * @return Next chunk from the stream. Returns the empty string if a chunk
+   * isn't ready yet. Users of this interface should repeatedly call this
+   * function until an empty string is returned since its entirely possible
+   * multiple chunks come in a single raw buffer.
+   */
+  virtual std::string BufferMessage(std::string& rawBuffer) = 0;
+
+  /***
+   * Resets the internal state of the buffering
+   */
+  virtual void clear();
+
+  // TODO: There should be a callback / flag set for errors
+};
+
+/***
+ * Abstraction of a connection; ties in event callbacks from libuv and notifies
+ * the server when appropriate
+ */
+class cmConnection
+{
+  CM_DISABLE_COPY(cmConnection)
+
+public:
+  virtual ~cmConnection();
+
+  /***
+   * @param bufferStrategy If no strategy is given, it will process the raw
+   * chunks as they come in. The connection
+   * owns the pointer given.
+   */
+  cmConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr);
+
+  virtual void Connect(uv_stream_t* server);
+
+  virtual void ReadData(const std::string& data);
+
+  virtual bool OnServeStart(std::string* errString);
+
+  virtual bool OnServerShuttingDown();
+
+  virtual bool IsOpen() const;
+
+  virtual void WriteData(const std::string& data);
+
+  virtual void ProcessRequest(const std::string& request);
+
+  virtual void SetServer(cmServerBase* s);
+
+  virtual void OnDisconnect(int errorCode);
+  uv_stream_t* ReadStream = nullptr;
+  cmServerBase* Server = nullptr;
+  uv_stream_t* WriteStream = nullptr;
+
+  static void on_close(uv_handle_t* handle);
+  static void on_close_delete(uv_handle_t* handle);
+
+protected:
+  std::string RawReadBuffer;
+
+  std::unique_ptr<cmConnectionBufferStrategy> BufferStrategy;
+
+  static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
+
+  static void on_write(uv_write_t* req, int status);
+
+  static void on_new_connection(uv_stream_t* stream, int status);
+
+  static void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size,
+                              uv_buf_t* buf);
+};
diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx
index 8027535..c0401d7 100644
--- a/Source/cmFileMonitor.cxx
+++ b/Source/cmFileMonitor.cxx
@@ -171,7 +171,9 @@ public:
   {
     if (this->Handle) {
       uv_fs_event_stop(this->Handle);
-      uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
+      if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(this->Handle))) {
+        uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close);
+      }
       this->Handle = nullptr;
     }
     cmVirtualDirectoryWatcher::StopWatching();
diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx
new file mode 100644
index 0000000..438719f
--- /dev/null
+++ b/Source/cmPipeConnection.cxx
@@ -0,0 +1,81 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmPipeConnection.h"
+
+#include "cmConfigure.h"
+#include "cmServer.h"
+
+cmPipeConnection::cmPipeConnection(const std::string& name,
+                                   cmConnectionBufferStrategy* bufferStrategy)
+  : cmConnection(bufferStrategy)
+  , PipeName(name)
+{
+}
+
+void cmPipeConnection::Connect(uv_stream_t* server)
+{
+  if (this->ClientPipe) {
+    // Accept and close all pipes but the first:
+    uv_pipe_t* rejectPipe = new uv_pipe_t();
+
+    uv_pipe_init(this->Server->GetLoop(), rejectPipe, 0);
+    uv_accept(server, reinterpret_cast<uv_stream_t*>(rejectPipe));
+    uv_close(reinterpret_cast<uv_handle_t*>(rejectPipe), &on_close_delete);
+    return;
+  }
+
+  this->ClientPipe = new uv_pipe_t();
+  uv_pipe_init(this->Server->GetLoop(), this->ClientPipe, 0);
+  this->ClientPipe->data = static_cast<cmConnection*>(this);
+
+  auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe);
+  if (uv_accept(server, client) != 0) {
+    uv_close(reinterpret_cast<uv_handle_t*>(client), &on_close_delete);
+    this->ClientPipe = CM_NULLPTR;
+    return;
+  }
+  this->ReadStream = client;
+  this->WriteStream = client;
+
+  uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
+  Server->OnConnected(this);
+}
+
+bool cmPipeConnection::OnServeStart(std::string* errorMessage)
+{
+  this->ServerPipe = new uv_pipe_t();
+  uv_pipe_init(this->Server->GetLoop(), this->ServerPipe, 0);
+  this->ServerPipe->data = static_cast<cmConnection*>(this);
+
+  int r;
+  if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
+    *errorMessage = std::string("Internal Error with ") + this->PipeName +
+      ": " + uv_err_name(r);
+    return false;
+  }
+  auto serverStream = reinterpret_cast<uv_stream_t*>(this->ServerPipe);
+  if ((r = uv_listen(serverStream, 1, on_new_connection)) != 0) {
+    *errorMessage = std::string("Internal Error listening on ") +
+      this->PipeName + ": " + uv_err_name(r);
+    return false;
+  }
+
+  return cmConnection::OnServeStart(errorMessage);
+}
+
+bool cmPipeConnection::OnServerShuttingDown()
+{
+  if (this->ClientPipe) {
+    uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe),
+             &on_close_delete);
+    this->WriteStream->data = nullptr;
+  }
+  uv_close(reinterpret_cast<uv_handle_t*>(this->ServerPipe), &on_close_delete);
+
+  this->ClientPipe = nullptr;
+  this->ServerPipe = nullptr;
+  this->WriteStream = nullptr;
+  this->ReadStream = nullptr;
+
+  return cmConnection::OnServerShuttingDown();
+}
diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h
new file mode 100644
index 0000000..3d3d52c
--- /dev/null
+++ b/Source/cmPipeConnection.h
@@ -0,0 +1,28 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#pragma once
+
+#include "cmConnection.h"
+
+#include "cm_uv.h"
+
+#include <string>
+
+class cmPipeConnection : public cmConnection
+{
+public:
+  cmPipeConnection(const std::string& name,
+                   cmConnectionBufferStrategy* bufferStrategy = nullptr);
+
+  bool OnServeStart(std::string* pString) override;
+
+  bool OnServerShuttingDown() override;
+
+  void Connect(uv_stream_t* server) override;
+
+private:
+  const std::string PipeName;
+  uv_pipe_t* ServerPipe = nullptr;
+  uv_pipe_t* ClientPipe = nullptr;
+};
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index 7fc6ed7..03e0115 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -2,7 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmServer.h"
 
-#include "cmServerConnection.h"
+#include "cmConnection.h"
+#include "cmFileMonitor.h"
 #include "cmServerDictionary.h"
 #include "cmServerProtocol.h"
 #include "cmSystemTools.h"
@@ -14,8 +15,23 @@
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
+#include <memory>
 #include <utility>
 
+void on_signal(uv_signal_t* signal, int signum)
+{
+  auto conn = reinterpret_cast<cmServerBase*>(signal->data);
+  conn->OnSignal(signum);
+}
+
+static void on_walk_to_shutdown(uv_handle_t* handle, void* arg)
+{
+  (void)arg;
+  if (!uv_is_closing(handle)) {
+    uv_close(handle, &cmConnection::on_close);
+  }
+}
+
 class cmServer::DebugInfo
 {
 public:
@@ -30,11 +46,10 @@ public:
   uint64_t StartTime;
 };
 
-cmServer::cmServer(cmServerConnection* conn, bool supportExperimental)
-  : Connection(conn)
+cmServer::cmServer(cmConnection* conn, bool supportExperimental)
+  : cmServerBase(conn)
   , SupportExperimental(supportExperimental)
 {
-  this->Connection->SetServer(this);
   // Register supported protocols:
   this->RegisterProtocol(new cmServerProtocol1_0);
 }
@@ -48,23 +63,15 @@ cmServer::~cmServer()
   for (cmServerProtocol* p : this->SupportedProtocols) {
     delete p;
   }
-
-  delete this->Connection;
 }
 
-void cmServer::PopOne()
+void cmServer::ProcessRequest(cmConnection* connection,
+                              const std::string& input)
 {
-  if (this->Queue.empty()) {
-    return;
-  }
-
   Json::Reader reader;
   Json::Value value;
-  const std::string input = this->Queue.front();
-  this->Queue.erase(this->Queue.begin());
-
   if (!reader.parse(input, value)) {
-    this->WriteParseError("Failed to parse JSON input.");
+    this->WriteParseError(connection, "Failed to parse JSON input.");
     return;
   }
 
@@ -82,7 +89,7 @@ void cmServer::PopOne()
   if (request.Type == "") {
     cmServerResponse response(request);
     response.SetError("No type given in request.");
-    this->WriteResponse(response, nullptr);
+    this->WriteResponse(connection, response, nullptr);
     return;
   }
 
@@ -91,9 +98,11 @@ void cmServer::PopOne()
   if (this->Protocol) {
     this->Protocol->CMakeInstance()->SetProgressCallback(
       reportProgress, const_cast<cmServerRequest*>(&request));
-    this->WriteResponse(this->Protocol->Process(request), debug.get());
+    this->WriteResponse(connection, this->Protocol->Process(request),
+                        debug.get());
   } else {
-    this->WriteResponse(this->SetProtocolVersion(request), debug.get());
+    this->WriteResponse(connection, this->SetProtocolVersion(request),
+                        debug.get());
   }
 }
 
@@ -115,7 +124,7 @@ void cmServer::RegisterProtocol(cmServerProtocol* protocol)
   }
 }
 
-void cmServer::PrintHello() const
+void cmServer::PrintHello(cmConnection* connection) const
 {
   Json::Value hello = Json::objectValue;
   hello[kTYPE_KEY] = "hello";
@@ -134,13 +143,7 @@ void cmServer::PrintHello() const
     protocolVersions.append(tmp);
   }
 
-  this->WriteJsonObject(hello, nullptr);
-}
-
-void cmServer::QueueRequest(const std::string& request)
-{
-  this->Queue.push_back(request);
-  this->PopOne();
+  this->WriteJsonObject(connection, hello, nullptr);
 }
 
 void cmServer::reportProgress(const char* msg, float progress, void* data)
@@ -232,17 +235,26 @@ bool cmServer::Serve(std::string* errorMessage)
   }
   assert(!this->Protocol);
 
-  return Connection->ProcessEvents(errorMessage);
+  return cmServerBase::Serve(errorMessage);
 }
 
 cmFileMonitor* cmServer::FileMonitor() const
 {
-  return Connection->FileMonitor();
+  return fileMonitor.get();
 }
 
 void cmServer::WriteJsonObject(const Json::Value& jsonValue,
                                const DebugInfo* debug) const
 {
+  for (auto& connection : this->Connections) {
+    WriteJsonObject(connection.get(), jsonValue, debug);
+  }
+}
+
+void cmServer::WriteJsonObject(cmConnection* connection,
+                               const Json::Value& jsonValue,
+                               const DebugInfo* debug) const
+{
   Json::FastWriter writer;
 
   auto beforeJson = uv_hrtime();
@@ -272,7 +284,7 @@ void cmServer::WriteJsonObject(const Json::Value& jsonValue,
     }
   }
 
-  Connection->WriteData(std::string("\n") + kSTART_MAGIC + std::string("\n") +
+  connection->WriteData(std::string("\n") + kSTART_MAGIC + std::string("\n") +
                         result + kEND_MAGIC + std::string("\n"));
 }
 
@@ -334,7 +346,8 @@ void cmServer::WriteMessage(const cmServerRequest& request,
   WriteJsonObject(obj, nullptr);
 }
 
-void cmServer::WriteParseError(const std::string& message) const
+void cmServer::WriteParseError(cmConnection* connection,
+                               const std::string& message) const
 {
   Json::Value obj = Json::objectValue;
   obj[kTYPE_KEY] = kERROR_TYPE;
@@ -342,7 +355,7 @@ void cmServer::WriteParseError(const std::string& message) const
   obj[kREPLY_TO_KEY] = "";
   obj[kCOOKIE_KEY] = "";
 
-  this->WriteJsonObject(obj, nullptr);
+  this->WriteJsonObject(connection, obj, nullptr);
 }
 
 void cmServer::WriteSignal(const std::string& name,
@@ -358,7 +371,8 @@ void cmServer::WriteSignal(const std::string& name,
   WriteJsonObject(obj, nullptr);
 }
 
-void cmServer::WriteResponse(const cmServerResponse& response,
+void cmServer::WriteResponse(cmConnection* connection,
+                             const cmServerResponse& response,
                              const DebugInfo* debug) const
 {
   assert(response.IsComplete());
@@ -371,5 +385,161 @@ void cmServer::WriteResponse(const cmServerResponse& response,
     obj[kERROR_MESSAGE_KEY] = response.ErrorMessage();
   }
 
-  this->WriteJsonObject(obj, debug);
+  this->WriteJsonObject(connection, obj, debug);
+}
+
+void cmServer::OnConnected(cmConnection* connection)
+{
+  PrintHello(connection);
+}
+
+void cmServer::OnServeStart()
+{
+  cmServerBase::OnServeStart();
+  fileMonitor = std::make_shared<cmFileMonitor>(GetLoop());
+}
+
+void cmServer::StartShutDown()
+{
+  if (fileMonitor) {
+    fileMonitor->StopMonitoring();
+    fileMonitor.reset();
+  }
+  cmServerBase::StartShutDown();
+}
+
+static void __start_thread(void* arg)
+{
+  auto server = reinterpret_cast<cmServerBase*>(arg);
+  std::string error;
+  server->Serve(&error);
+}
+
+bool cmServerBase::StartServeThread()
+{
+  ServeThreadRunning = true;
+  uv_thread_create(&ServeThread, __start_thread, this);
+  return true;
+}
+
+bool cmServerBase::Serve(std::string* errorMessage)
+{
+  errorMessage->clear();
+
+  uv_signal_init(&Loop, &this->SIGINTHandler);
+  uv_signal_init(&Loop, &this->SIGHUPHandler);
+
+  this->SIGINTHandler.data = this;
+  this->SIGHUPHandler.data = this;
+
+  uv_signal_start(&this->SIGINTHandler, &on_signal, SIGINT);
+  uv_signal_start(&this->SIGHUPHandler, &on_signal, SIGHUP);
+
+  OnServeStart();
+
+  for (auto& connection : Connections) {
+    if (!connection->OnServeStart(errorMessage)) {
+      return false;
+    }
+  }
+
+  if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
+    *errorMessage = "Internal Error: Event loop stopped in unclean state.";
+    StartShutDown();
+    return false;
+  }
+
+  ServeThreadRunning = false;
+  return true;
+}
+
+void cmServerBase::OnConnected(cmConnection*)
+{
+}
+
+void cmServerBase::OnDisconnect()
+{
+}
+
+void cmServerBase::OnServeStart()
+{
+  uv_signal_start(&this->SIGINTHandler, &on_signal, SIGINT);
+  uv_signal_start(&this->SIGHUPHandler, &on_signal, SIGHUP);
+}
+
+void cmServerBase::StartShutDown()
+{
+  if (!uv_is_closing((const uv_handle_t*)&this->SIGINTHandler)) {
+    uv_signal_stop(&this->SIGINTHandler);
+  }
+
+  if (!uv_is_closing((const uv_handle_t*)&this->SIGHUPHandler)) {
+    uv_signal_stop(&this->SIGHUPHandler);
+  }
+
+  for (auto& connection : Connections) {
+    connection->OnServerShuttingDown();
+  }
+  Connections.clear();
+
+  uv_stop(&Loop);
+
+  uv_walk(&Loop, on_walk_to_shutdown, CM_NULLPTR);
+
+  uv_run(&Loop, UV_RUN_DEFAULT);
+}
+
+bool cmServerBase::OnSignal(int signum)
+{
+  (void)signum;
+  StartShutDown();
+  return true;
+}
+
+cmServerBase::cmServerBase(cmConnection* connection)
+{
+  uv_loop_init(&Loop);
+
+  uv_signal_init(&Loop, &this->SIGINTHandler);
+  uv_signal_init(&Loop, &this->SIGHUPHandler);
+
+  this->SIGINTHandler.data = this;
+  this->SIGHUPHandler.data = this;
+
+  AddNewConnection(connection);
+}
+
+cmServerBase::~cmServerBase()
+{
+
+  if (ServeThreadRunning) {
+    StartShutDown();
+    uv_thread_join(&ServeThread);
+  }
+
+  uv_loop_close(&Loop);
+}
+
+void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
+{
+  Connections.emplace_back(ownedConnection);
+  ownedConnection->SetServer(this);
+}
+
+uv_loop_t* cmServerBase::GetLoop()
+{
+  return &Loop;
+}
+
+void cmServerBase::OnDisconnect(cmConnection* pConnection)
+{
+  auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
+    return m.get() == pConnection;
+  };
+  Connections.erase(
+    std::remove_if(Connections.begin(), Connections.end(), pred),
+    Connections.end());
+  if (Connections.empty()) {
+    StartShutDown();
+  }
 }
diff --git a/Source/cmServer.h b/Source/cmServer.h
index b814050..0000704 100644
--- a/Source/cmServer.h
+++ b/Source/cmServer.h
@@ -7,26 +7,83 @@
 #include "cm_jsoncpp_value.h"
 #include "cm_uv.h"
 
+#include <memory> // IWYU pragma: keep
 #include <string>
 #include <vector>
 
+class cmConnection;
 class cmFileMonitor;
-class cmServerConnection;
 class cmServerProtocol;
 class cmServerRequest;
 class cmServerResponse;
 
-class cmServer
+/***
+ * This essentially hold and manages a libuv event queue and responds to
+ * messages
+ * on any of its connections.
+ */
+class cmServerBase
+{
+public:
+  cmServerBase(cmConnection* connection);
+  virtual ~cmServerBase();
+
+  virtual void AddNewConnection(cmConnection* ownedConnection);
+
+  /***
+   * The main override responsible for tailoring behavior towards
+   * whatever the given server is supposed to do
+   *
+   * This should almost always be called by the given connections
+   * directly.
+   *
+   * @param connection The connectiont the request was received on
+   * @param request The actual request
+   */
+  virtual void ProcessRequest(cmConnection* connection,
+                              const std::string& request) = 0;
+  virtual void OnConnected(cmConnection* connection);
+  virtual void OnDisconnect();
+
+  /***
+   * Start a dedicated thread. If this is used to start the server, it will
+   * join on the
+   * servers dtor.
+   */
+  virtual bool StartServeThread();
+  virtual bool Serve(std::string* errorMessage);
+
+  virtual void OnServeStart();
+  virtual void StartShutDown();
+
+  virtual bool OnSignal(int signum);
+  uv_loop_t* GetLoop();
+
+  void OnDisconnect(cmConnection* pConnection);
+
+protected:
+  std::vector<std::unique_ptr<cmConnection> > Connections;
+
+  bool ServeThreadRunning = false;
+  uv_thread_t ServeThread;
+
+  uv_loop_t Loop;
+
+  uv_signal_t SIGINTHandler;
+  uv_signal_t SIGHUPHandler;
+};
+
+class cmServer : public cmServerBase
 {
   CM_DISABLE_COPY(cmServer)
 
 public:
   class DebugInfo;
 
-  cmServer(cmServerConnection* conn, bool supportExperimental);
-  ~cmServer();
+  cmServer(cmConnection* conn, bool supportExperimental);
+  ~cmServer() override;
 
-  bool Serve(std::string* errorMessage);
+  bool Serve(std::string* errorMessage) override;
 
   cmFileMonitor* FileMonitor() const;
 
@@ -34,9 +91,20 @@ private:
   void RegisterProtocol(cmServerProtocol* protocol);
 
   // Callbacks from cmServerConnection:
-  void PopOne();
-  void QueueRequest(const std::string& request);
 
+  void ProcessRequest(cmConnection* connection,
+                      const std::string& request) override;
+  std::shared_ptr<cmFileMonitor> fileMonitor;
+
+public:
+  void OnServeStart() override;
+
+  void StartShutDown() override;
+
+public:
+  void OnConnected(cmConnection* connection) override;
+
+private:
   static void reportProgress(const char* msg, float progress, void* data);
   static void reportMessage(const char* msg, const char* title, bool& cancel,
                             void* data);
@@ -44,36 +112,37 @@ private:
   // Handle requests:
   cmServerResponse SetProtocolVersion(const cmServerRequest& request);
 
-  void PrintHello() const;
+  void PrintHello(cmConnection* connection) const;
 
   // Write responses:
   void WriteProgress(const cmServerRequest& request, int min, int current,
                      int max, const std::string& message) const;
   void WriteMessage(const cmServerRequest& request, const std::string& message,
                     const std::string& title) const;
-  void WriteResponse(const cmServerResponse& response,
+  void WriteResponse(cmConnection* connection,
+                     const cmServerResponse& response,
                      const DebugInfo* debug) const;
-  void WriteParseError(const std::string& message) const;
+  void WriteParseError(cmConnection* connection,
+                       const std::string& message) const;
   void WriteSignal(const std::string& name, const Json::Value& obj) const;
 
   void WriteJsonObject(Json::Value const& jsonValue,
                        const DebugInfo* debug) const;
 
+  void WriteJsonObject(cmConnection* connection, Json::Value const& jsonValue,
+                       const DebugInfo* debug) const;
+
   static cmServerProtocol* FindMatchingProtocol(
     const std::vector<cmServerProtocol*>& protocols, int major, int minor);
 
-  cmServerConnection* Connection = nullptr;
   const bool SupportExperimental;
 
   cmServerProtocol* Protocol = nullptr;
   std::vector<cmServerProtocol*> SupportedProtocols;
-  std::vector<std::string> Queue;
 
   std::string DataBuffer;
   std::string JsonData;
 
-  uv_loop_t* Loop = nullptr;
-
   typedef union
   {
     uv_tty_t tty;
@@ -87,7 +156,6 @@ private:
 
   mutable bool Writing = false;
 
-  friend class cmServerConnection;
   friend class cmServerProtocol;
   friend class cmServerRequest;
 };
diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx
index 36312ed..3cc7722 100644
--- a/Source/cmServerConnection.cxx
+++ b/Source/cmServerConnection.cxx
@@ -2,376 +2,123 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmServerConnection.h"
 
-#include "cmFileMonitor.h"
 #include "cmServer.h"
 #include "cmServerDictionary.h"
 
-#include <assert.h>
-#include <string.h>
-
-namespace {
-
-struct write_req_t
+cmStdIoConnection::cmStdIoConnection(
+  cmConnectionBufferStrategy* bufferStrategy)
+  : cmConnection(bufferStrategy)
+  , Input()
+  , Output()
 {
-  uv_write_t req;
-  uv_buf_t buf;
-};
-
-void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
-{
-  (void)(handle);
-  char* rawBuffer = new char[suggested_size];
-  *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size));
-}
-
-void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
-{
-  auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
-  if (nread >= 0) {
-    conn->ReadData(std::string(buf->base, buf->base + nread));
-  } else {
-    conn->TriggerShutdown();
-  }
-
-  delete[](buf->base);
 }
 
-void on_write(uv_write_t* req, int status)
+void cmStdIoConnection::SetServer(cmServerBase* s)
 {
-  (void)(status);
-  auto conn = reinterpret_cast<cmServerConnection*>(req->data);
-
-  // Free req and buffer
-  write_req_t* wr = reinterpret_cast<write_req_t*>(req);
-  delete[](wr->buf.base);
-  delete wr;
+  cmConnection::SetServer(s);
 
-  conn->ProcessNextRequest();
-}
+  if (uv_guess_handle(1) == UV_TTY) {
+    usesTty = true;
 
-void on_new_connection(uv_stream_t* stream, int status)
-{
-  (void)(status);
-  auto conn = reinterpret_cast<cmServerConnection*>(stream->data);
-  conn->Connect(stream);
-}
+    this->Input.tty = new uv_tty_t();
+    uv_tty_init(this->Server->GetLoop(), this->Input.tty, 0, 1);
+    uv_tty_set_mode(this->Input.tty, UV_TTY_MODE_NORMAL);
+    this->Input.tty->data = static_cast<cmConnection*>(this);
+    this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.tty);
 
-void on_signal(uv_signal_t* signal, int signum)
-{
-  auto conn = reinterpret_cast<cmServerConnection*>(signal->data);
-  (void)(signum);
-  conn->TriggerShutdown();
-}
+    this->Output.tty = new uv_tty_t();
+    uv_tty_init(this->Server->GetLoop(), this->Output.tty, 1, 0);
+    uv_tty_set_mode(this->Output.tty, UV_TTY_MODE_NORMAL);
+    this->Output.tty->data = static_cast<cmConnection*>(this);
+    this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.tty);
+  } else {
+    usesTty = false;
 
-void on_signal_close(uv_handle_t* handle)
-{
-  delete reinterpret_cast<uv_signal_t*>(handle);
-}
+    this->Input.pipe = new uv_pipe_t();
+    uv_pipe_init(this->Server->GetLoop(), this->Input.pipe, 0);
+    uv_pipe_open(this->Input.pipe, 0);
+    this->Input.pipe->data = static_cast<cmConnection*>(this);
+    this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.pipe);
 
-void on_pipe_close(uv_handle_t* handle)
-{
-  delete reinterpret_cast<uv_pipe_t*>(handle);
+    this->Output.pipe = new uv_pipe_t();
+    uv_pipe_init(this->Server->GetLoop(), this->Output.pipe, 0);
+    uv_pipe_open(this->Output.pipe, 1);
+    this->Output.pipe->data = static_cast<cmConnection*>(this);
+    this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.pipe);
+  }
 }
 
-void on_tty_close(uv_handle_t* handle)
+bool cmStdIoConnection::OnServeStart(std::string* pString)
 {
-  delete reinterpret_cast<uv_tty_t*>(handle);
+  uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
+  Server->OnConnected(this);
+  return cmConnection::OnServeStart(pString);
 }
 
-} // namespace
-
-class LoopGuard
+bool cmStdIoConnection::OnServerShuttingDown()
 {
-public:
-  LoopGuard(cmServerConnection* connection)
-    : Connection(connection)
-  {
-    this->Connection->mLoop = uv_default_loop();
-    if (!this->Connection->mLoop) {
-      return;
-    }
-    this->Connection->mFileMonitor =
-      new cmFileMonitor(this->Connection->mLoop);
-  }
-
-  ~LoopGuard()
-  {
-    if (!this->Connection->mLoop) {
-      return;
-    }
+  cmConnection::OnServerShuttingDown();
 
-    if (this->Connection->mFileMonitor) {
-      delete this->Connection->mFileMonitor;
-    }
-    uv_loop_close(this->Connection->mLoop);
-    this->Connection->mLoop = nullptr;
+  if (usesTty) {
+    uv_read_stop(reinterpret_cast<uv_stream_t*>(this->Input.tty));
+    uv_close(reinterpret_cast<uv_handle_t*>(this->Input.tty),
+             &on_close_delete);
+    uv_close(reinterpret_cast<uv_handle_t*>(this->Output.tty),
+             &on_close_delete);
+  } else {
+    uv_close(reinterpret_cast<uv_handle_t*>(this->Input.pipe),
+             &on_close_delete);
+    uv_close(reinterpret_cast<uv_handle_t*>(this->Output.pipe),
+             &on_close_delete);
   }
 
-private:
-  cmServerConnection* Connection;
-};
+  return true;
+}
 
-cmServerConnection::cmServerConnection()
+cmServerPipeConnection::cmServerPipeConnection(const std::string& name)
+  : cmPipeConnection(name, new cmServerBufferStrategy)
 {
 }
 
-cmServerConnection::~cmServerConnection()
+cmServerStdIoConnection::cmServerStdIoConnection()
+  : cmStdIoConnection(new cmServerBufferStrategy)
 {
 }
 
-void cmServerConnection::SetServer(cmServer* s)
+cmConnectionBufferStrategy::~cmConnectionBufferStrategy()
 {
-  this->Server = s;
 }
 
-bool cmServerConnection::ProcessEvents(std::string* errorMessage)
+void cmConnectionBufferStrategy::clear()
 {
-  assert(this->Server);
-  errorMessage->clear();
-
-  this->RawReadBuffer.clear();
-  this->RequestBuffer.clear();
-
-  LoopGuard guard(this);
-  (void)(guard);
-  if (!this->mLoop) {
-    *errorMessage = "Internal Error: Failed to create event loop.";
-    return false;
-  }
-
-  this->SIGINTHandler = new uv_signal_t;
-  uv_signal_init(this->mLoop, this->SIGINTHandler);
-  this->SIGINTHandler->data = static_cast<void*>(this);
-  uv_signal_start(this->SIGINTHandler, &on_signal, SIGINT);
-
-  this->SIGHUPHandler = new uv_signal_t;
-  uv_signal_init(this->mLoop, this->SIGHUPHandler);
-  this->SIGHUPHandler->data = static_cast<void*>(this);
-  uv_signal_start(this->SIGHUPHandler, &on_signal, SIGHUP);
-
-  if (!DoSetup(errorMessage)) {
-    return false;
-  }
-
-  if (uv_run(this->mLoop, UV_RUN_DEFAULT) != 0) {
-    *errorMessage = "Internal Error: Event loop stopped in unclean state.";
-    return false;
-  }
-
-  // These need to be cleaned up by now:
-  assert(!this->ReadStream);
-  assert(!this->WriteStream);
-
-  this->RawReadBuffer.clear();
-  this->RequestBuffer.clear();
-
-  return true;
 }
 
-void cmServerConnection::ReadData(const std::string& data)
+std::string cmServerBufferStrategy::BufferMessage(std::string& RawReadBuffer)
 {
-  this->RawReadBuffer += data;
-
   for (;;) {
-    auto needle = this->RawReadBuffer.find('\n');
+    auto needle = RawReadBuffer.find('\n');
 
     if (needle == std::string::npos) {
-      return;
+      return "";
     }
-    std::string line = this->RawReadBuffer.substr(0, needle);
+    std::string line = RawReadBuffer.substr(0, needle);
     const auto ls = line.size();
     if (ls > 1 && line.at(ls - 1) == '\r') {
       line.erase(ls - 1, 1);
     }
-    this->RawReadBuffer.erase(this->RawReadBuffer.begin(),
-                              this->RawReadBuffer.begin() +
-                                static_cast<long>(needle) + 1);
+    RawReadBuffer.erase(RawReadBuffer.begin(),
+                        RawReadBuffer.begin() + static_cast<long>(needle) + 1);
     if (line == kSTART_MAGIC) {
-      this->RequestBuffer.clear();
+      RequestBuffer.clear();
       continue;
     }
     if (line == kEND_MAGIC) {
-      this->Server->QueueRequest(this->RequestBuffer);
-      this->RequestBuffer.clear();
-    } else {
-      this->RequestBuffer += line;
-      this->RequestBuffer += "\n";
+      std::string rtn;
+      rtn.swap(this->RequestBuffer);
+      return rtn;
     }
-  }
-}
 
-void cmServerConnection::TriggerShutdown()
-{
-  this->FileMonitor()->StopMonitoring();
-
-  uv_signal_stop(this->SIGINTHandler);
-  uv_signal_stop(this->SIGHUPHandler);
-
-  uv_close(reinterpret_cast<uv_handle_t*>(this->SIGINTHandler),
-           &on_signal_close); // delete handle
-  uv_close(reinterpret_cast<uv_handle_t*>(this->SIGHUPHandler),
-           &on_signal_close); // delete handle
-
-  this->SIGINTHandler = nullptr;
-  this->SIGHUPHandler = nullptr;
-
-  this->TearDown();
-}
-
-void cmServerConnection::WriteData(const std::string& data)
-{
-  assert(this->WriteStream);
-
-  auto ds = data.size();
-
-  write_req_t* req = new write_req_t;
-  req->req.data = this;
-  req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds));
-  memcpy(req->buf.base, data.c_str(), ds);
-
-  uv_write(reinterpret_cast<uv_write_t*>(req),
-           static_cast<uv_stream_t*>(this->WriteStream), &req->buf, 1,
-           on_write);
-}
-
-void cmServerConnection::ProcessNextRequest()
-{
-  Server->PopOne();
-}
-
-void cmServerConnection::SendGreetings()
-{
-  Server->PrintHello();
-}
-
-cmServerStdIoConnection::cmServerStdIoConnection()
-{
-  this->Input.tty = nullptr;
-  this->Output.tty = nullptr;
-}
-
-bool cmServerStdIoConnection::DoSetup(std::string* errorMessage)
-{
-  (void)(errorMessage);
-
-  if (uv_guess_handle(1) == UV_TTY) {
-    usesTty = true;
-    this->Input.tty = new uv_tty_t;
-    uv_tty_init(this->Loop(), this->Input.tty, 0, 1);
-    uv_tty_set_mode(this->Input.tty, UV_TTY_MODE_NORMAL);
-    Input.tty->data = this;
-    this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.tty);
-
-    this->Output.tty = new uv_tty_t;
-    uv_tty_init(this->Loop(), this->Output.tty, 1, 0);
-    uv_tty_set_mode(this->Output.tty, UV_TTY_MODE_NORMAL);
-    Output.tty->data = this;
-    this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.tty);
-  } else {
-    usesTty = false;
-    this->Input.pipe = new uv_pipe_t;
-    uv_pipe_init(this->Loop(), this->Input.pipe, 0);
-    uv_pipe_open(this->Input.pipe, 0);
-    Input.pipe->data = this;
-    this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.pipe);
-
-    this->Output.pipe = new uv_pipe_t;
-    uv_pipe_init(this->Loop(), this->Output.pipe, 0);
-    uv_pipe_open(this->Output.pipe, 1);
-    Output.pipe->data = this;
-    this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.pipe);
+    this->RequestBuffer += line;
+    this->RequestBuffer += "\n";
   }
-
-  SendGreetings();
-  uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
-
-  return true;
-}
-
-void cmServerStdIoConnection::TearDown()
-{
-  if (usesTty) {
-    uv_close(reinterpret_cast<uv_handle_t*>(this->Input.tty), &on_tty_close);
-    uv_close(reinterpret_cast<uv_handle_t*>(this->Output.tty), &on_tty_close);
-    this->Input.tty = nullptr;
-    this->Output.tty = nullptr;
-  } else {
-    uv_close(reinterpret_cast<uv_handle_t*>(this->Input.pipe), &on_pipe_close);
-    uv_close(reinterpret_cast<uv_handle_t*>(this->Output.pipe),
-             &on_pipe_close);
-    this->Input.pipe = nullptr;
-    this->Input.pipe = nullptr;
-  }
-  this->ReadStream = nullptr;
-  this->WriteStream = nullptr;
-}
-
-cmServerPipeConnection::cmServerPipeConnection(const std::string& name)
-  : PipeName(name)
-{
-}
-
-bool cmServerPipeConnection::DoSetup(std::string* errorMessage)
-{
-  this->ServerPipe = new uv_pipe_t;
-  uv_pipe_init(this->Loop(), this->ServerPipe, 0);
-  this->ServerPipe->data = this;
-
-  int r;
-  if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
-    *errorMessage = std::string("Internal Error with ") + this->PipeName +
-      ": " + uv_err_name(r);
-    return false;
-  }
-  auto serverStream = reinterpret_cast<uv_stream_t*>(this->ServerPipe);
-  if ((r = uv_listen(serverStream, 1, on_new_connection)) != 0) {
-    *errorMessage = std::string("Internal Error listening on ") +
-      this->PipeName + ": " + uv_err_name(r);
-    return false;
-  }
-
-  return true;
-}
-
-void cmServerPipeConnection::TearDown()
-{
-  if (this->ClientPipe) {
-    uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe), &on_pipe_close);
-    this->WriteStream->data = nullptr;
-  }
-  uv_close(reinterpret_cast<uv_handle_t*>(this->ServerPipe), &on_pipe_close);
-
-  this->ClientPipe = nullptr;
-  this->ServerPipe = nullptr;
-  this->WriteStream = nullptr;
-  this->ReadStream = nullptr;
-}
-
-void cmServerPipeConnection::Connect(uv_stream_t* server)
-{
-  if (this->ClientPipe) {
-    // Accept and close all pipes but the first:
-    uv_pipe_t* rejectPipe = new uv_pipe_t;
-
-    uv_pipe_init(this->Loop(), rejectPipe, 0);
-    auto rejecter = reinterpret_cast<uv_stream_t*>(rejectPipe);
-    uv_accept(server, rejecter);
-    uv_close(reinterpret_cast<uv_handle_t*>(rejecter), &on_pipe_close);
-    return;
-  }
-
-  this->ClientPipe = new uv_pipe_t;
-  uv_pipe_init(this->Loop(), this->ClientPipe, 0);
-  this->ClientPipe->data = this;
-  auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe);
-  if (uv_accept(server, client) != 0) {
-    uv_close(reinterpret_cast<uv_handle_t*>(client), nullptr);
-    return;
-  }
-  this->ReadStream = client;
-  this->WriteStream = client;
-
-  uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
-
-  this->SendGreetings();
 }
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
index b96bf3c..8865480 100644
--- a/Source/cmServerConnection.h
+++ b/Source/cmServerConnection.h
@@ -2,68 +2,46 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #pragma once
 
-#include "cmConfigure.h"
+#include "cmConnection.h"
 
+#include "cmPipeConnection.h"
 #include "cm_uv.h"
 
 #include <string>
 
-class cmFileMonitor;
-class cmServer;
+class cmServerBase;
 
-class cmServerConnection
+/***
+ * This connection buffer strategy accepts messages in the form of
+ * [== "CMake Server" ==[
+{
+  ... some JSON message ...
+}
+]== "CMake Server" ==]
+ * and only passes on the core json; it discards the envelope.
+ */
+class cmServerBufferStrategy : public cmConnectionBufferStrategy
 {
-  CM_DISABLE_COPY(cmServerConnection)
-
 public:
-  cmServerConnection();
-  virtual ~cmServerConnection();
-
-  void SetServer(cmServer* s);
-
-  bool ProcessEvents(std::string* errorMessage);
-
-  void ReadData(const std::string& data);
-  void TriggerShutdown();
-  void WriteData(const std::string& data);
-  void ProcessNextRequest();
-
-  virtual void Connect(uv_stream_t* server) { (void)(server); }
-
-  cmFileMonitor* FileMonitor() const { return this->mFileMonitor; }
-
-protected:
-  virtual bool DoSetup(std::string* errorMessage) = 0;
-  virtual void TearDown() = 0;
-
-  void SendGreetings();
-
-  uv_loop_t* Loop() const { return mLoop; }
-
-protected:
-  std::string RawReadBuffer;
-  std::string RequestBuffer;
-
-  uv_stream_t* ReadStream = nullptr;
-  uv_stream_t* WriteStream = nullptr;
+  std::string BufferMessage(std::string& rawBuffer) override;
 
 private:
-  uv_loop_t* mLoop = nullptr;
-  cmFileMonitor* mFileMonitor = nullptr;
-  cmServer* Server = nullptr;
-  uv_signal_t* SIGINTHandler = nullptr;
-  uv_signal_t* SIGHUPHandler = nullptr;
-
-  friend class LoopGuard;
+  std::string RequestBuffer;
 };
 
-class cmServerStdIoConnection : public cmServerConnection
+/***
+ * Generic connection over std io interfaces -- tty
+ */
+class cmStdIoConnection : public cmConnection
 {
 public:
-  cmServerStdIoConnection();
-  bool DoSetup(std::string* errorMessage) override;
+  cmStdIoConnection(cmConnectionBufferStrategy* bufferStrategy);
+
+  void SetServer(cmServerBase* s) override;
+
+  bool OnServerShuttingDown() override;
 
-  void TearDown() override;
+  bool OnServeStart(std::string* pString) override;
 
 private:
   typedef union
@@ -78,18 +56,18 @@ private:
   InOutUnion Output;
 };
 
-class cmServerPipeConnection : public cmServerConnection
+/***
+ * These specific connections use the cmake server
+ * buffering strategy.
+ */
+class cmServerStdIoConnection : public cmStdIoConnection
 {
 public:
-  cmServerPipeConnection(const std::string& name);
-  bool DoSetup(std::string* errorMessage) override;
-
-  void TearDown() override;
-
-  void Connect(uv_stream_t* server) override;
+  cmServerStdIoConnection();
+};
 
-private:
-  const std::string PipeName;
-  uv_pipe_t* ServerPipe = nullptr;
-  uv_pipe_t* ClientPipe = nullptr;
+class cmServerPipeConnection : public cmPipeConnection
+{
+public:
+  cmServerPipeConnection(const std::string& name);
 };
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index d5b0861..8fadbb1 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -44,6 +44,8 @@
 #include <stdlib.h>
 #include <time.h>
 
+class cmConnection;
+
 int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
                               std::vector<std::string>::const_iterator argEnd);
 int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
@@ -1013,7 +1015,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
         }
       }
 #if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE
-      cmServerConnection* conn;
+      cmConnection* conn;
       if (isDebug) {
         conn = new cmServerStdIoConnection;
       } else {
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index fe0f7df..23ca091 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -21,6 +21,7 @@
   { include: [ "<wctype.h>", public, "<cwctype>", public ] },
 
   # HACK: check whether this can be removed with next iwyu release.
+  { include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] },
   { include: [ "<bits/std_function.h>", private, "<functional>", public ] },
   { include: [ "<bits/time.h>", private, "<time.h>", public ] },
   { include: [ "<bits/types/clock_t.h>", private, "<time.h>", public ] },

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=501a4feea8d0d007ce292defec1c97d6eb702409
commit 501a4feea8d0d007ce292defec1c97d6eb702409
Author:     André Klitzing <aklitzing at gmail.com>
AuthorDate: Sun Jul 9 13:18:20 2017 +0200
Commit:     André Klitzing <aklitzing at gmail.com>
CommitDate: Sun Jul 9 13:18:20 2017 +0200

    Add some unit tests for md5sum

diff --git a/Tests/RunCMake/CommandLine/E_md5sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-dir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-dir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt
new file mode 100644
index 0000000..061fd64
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt
@@ -0,0 +1 @@
+Error: . is a directory
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-mixed-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-mixed-result.txt
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-mixed-result.txt
@@ -0,0 +1 @@
+2
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-mixed-stderr.txt b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stderr.txt
new file mode 100644
index 0000000..b6b84c3
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stderr.txt
@@ -0,0 +1,2 @@
+Error: . is a directory
+nonexisting: No such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-mixed-stdout.txt b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stdout.txt
new file mode 100644
index 0000000..18e49be
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stdout.txt
@@ -0,0 +1 @@
+275876e34cf609db118f3d84b799a790  ../dummy
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-no-file-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-no-file-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_md5sum-no-file-stderr.txt
new file mode 100644
index 0000000..732e8c4
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-no-file-stderr.txt
@@ -0,0 +1 @@
+nonexisting: No such file or directory
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/CommandLine/E_md5sum-stdout.txt b/Tests/RunCMake/CommandLine/E_md5sum-stdout.txt
new file mode 100644
index 0000000..18e49be
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/E_md5sum-stdout.txt
@@ -0,0 +1 @@
+275876e34cf609db118f3d84b799a790  ../dummy
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index f94b10a..6f5298e 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -172,6 +172,13 @@ run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1)
 run_cmake_command(E_env-set   ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake)
 run_cmake_command(E_env-unset ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -E env --unset=TEST_ENV ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake)
 
+run_cmake_command(E_md5sum-dir ${CMAKE_COMMAND} -E md5sum .)
+run_cmake_command(E_md5sum-no-file ${CMAKE_COMMAND} -E md5sum nonexisting)
+file(WRITE "${RunCMake_BINARY_DIR}/dummy" "dummy")
+run_cmake_command(E_md5sum ${CMAKE_COMMAND} -E md5sum ../dummy)
+run_cmake_command(E_md5sum-mixed ${CMAKE_COMMAND} -E md5sum . ../dummy nonexisting)
+file(REMOVE "${RunCMake_BINARY_DIR}/dummy")
+
 set(RunCMake_DEFAULT_stderr ".")
 run_cmake_command(E_sleep-no-args ${CMAKE_COMMAND} -E sleep)
 unset(RunCMake_DEFAULT_stderr)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5acbf08bff643ec6779464c840bfe2f02a4e65ae
commit 5acbf08bff643ec6779464c840bfe2f02a4e65ae
Author:     Justin Berger <j.david.berger at gmail.com>
AuthorDate: Sat Feb 25 15:06:34 2017 -0700
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Jun 8 15:00:12 2017 -0400

    Tests: Teach Server test to forward exit code from server process

diff --git a/Tests/Server/server-test.py b/Tests/Server/server-test.py
index 62d9008..5621111 100644
--- a/Tests/Server/server-test.py
+++ b/Tests/Server/server-test.py
@@ -117,4 +117,4 @@ except:
     proc.terminate()
     raise
 
-sys.exit(0)
+sys.exit(proc.returncode)

-----------------------------------------------------------------------

Summary of changes:
 Help/manual/cmake.1.rst                            |   30 ++
 Help/release/dev/cmake-command-mode-shasum.rst     |    5 +
 Modules/Platform/GHS-MULTI-Initialize.cmake        |    2 +-
 Source/CMakeLists.txt                              |    2 +
 Source/CPack/cmCPackDebGenerator.cxx               |    9 +-
 Source/CTest/cmCTestSubmitHandler.cxx              |   12 +-
 Source/cmConnection.cxx                            |  158 ++++++++
 Source/cmConnection.h                              |  118 ++++++
 Source/cmFileMonitor.cxx                           |    4 +-
 Source/cmGeneratorTarget.cxx                       |   11 +
 Source/cmGeneratorTarget.h                         |    5 +
 Source/cmPipeConnection.cxx                        |   80 ++++
 Source/cmPipeConnection.h                          |   28 ++
 Source/cmServer.cxx                                |  242 ++++++++++--
 Source/cmServer.h                                  |   98 ++++-
 Source/cmServerConnection.cxx                      |  391 ++++----------------
 Source/cmServerConnection.h                        |   94 ++---
 Source/cmServerProtocol.cxx                        |    6 +-
 Source/cmServerProtocol.h                          |    5 +-
 Source/cmSystemTools.cxx                           |   14 +-
 Source/cmSystemTools.h                             |    6 +-
 Source/cmcmd.cxx                                   |   76 +++-
 Source/cmcmd.h                                     |    3 +
 .../E_md5sum-dir-result.txt}                       |    0
 Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt |    1 +
 ...r-pipe-result.txt => E_md5sum-mixed-result.txt} |    0
 .../RunCMake/CommandLine/E_md5sum-mixed-stderr.txt |    2 +
 .../RunCMake/CommandLine/E_md5sum-mixed-stdout.txt |    1 +
 .../E_md5sum-no-file-result.txt}                   |    0
 .../CommandLine/E_md5sum-no-file-stderr.txt        |    1 +
 .../E_md5sum-result.txt}                           |    0
 Tests/RunCMake/CommandLine/E_md5sum-stdout.txt     |    1 +
 .../E_sha1sum-dir-result.txt}                      |    0
 .../RunCMake/CommandLine/E_sha1sum-dir-stderr.txt  |    1 +
 .../E_sha1sum-no-file-result.txt}                  |    0
 .../CommandLine/E_sha1sum-no-file-stderr.txt       |    1 +
 .../E_sha1sum-result.txt}                          |    0
 Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt    |    1 +
 .../E_sha224sum-dir-result.txt}                    |    0
 .../CommandLine/E_sha224sum-dir-stderr.txt         |    1 +
 .../E_sha224sum-no-file-result.txt}                |    0
 .../CommandLine/E_sha224sum-no-file-stderr.txt     |    1 +
 .../E_sha224sum-result.txt}                        |    0
 Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt  |    1 +
 .../E_sha256sum-dir-result.txt}                    |    0
 .../CommandLine/E_sha256sum-dir-stderr.txt         |    1 +
 .../E_sha256sum-no-file-result.txt}                |    0
 .../CommandLine/E_sha256sum-no-file-stderr.txt     |    1 +
 .../E_sha256sum-result.txt}                        |    0
 Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt  |    1 +
 .../E_sha384sum-dir-result.txt}                    |    0
 .../CommandLine/E_sha384sum-dir-stderr.txt         |    1 +
 .../E_sha384sum-no-file-result.txt}                |    0
 .../CommandLine/E_sha384sum-no-file-stderr.txt     |    1 +
 .../E_sha384sum-result.txt}                        |    0
 Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt  |    1 +
 .../E_sha512sum-dir-result.txt}                    |    0
 .../CommandLine/E_sha512sum-dir-stderr.txt         |    1 +
 .../E_sha512sum-no-file-result.txt}                |    0
 .../CommandLine/E_sha512sum-no-file-stderr.txt     |    1 +
 .../E_sha512sum-result.txt}                        |    0
 Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt  |    1 +
 Tests/RunCMake/CommandLine/RunCMakeTest.cmake      |   24 ++
 .../OwnSources-result.txt}                         |    0
 Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt |    5 +
 Tests/RunCMake/ObjectLibrary/OwnSources.cmake      |    2 +
 Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake    |    1 +
 Tests/Server/server-test.py                        |    2 +-
 Utilities/IWYU/mapping.imp                         |    1 +
 69 files changed, 977 insertions(+), 478 deletions(-)
 create mode 100644 Help/release/dev/cmake-command-mode-shasum.rst
 create mode 100644 Source/cmConnection.cxx
 create mode 100644 Source/cmConnection.h
 create mode 100644 Source/cmPipeConnection.cxx
 create mode 100644 Source/cmPipeConnection.h
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_md5sum-dir-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt
 copy Tests/RunCMake/CommandLine/{E_server-pipe-result.txt => E_md5sum-mixed-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_md5sum-mixed-stderr.txt
 create mode 100644 Tests/RunCMake/CommandLine/E_md5sum-mixed-stdout.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_md5sum-no-file-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_md5sum-no-file-stderr.txt
 copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CommandLine/E_md5sum-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_md5sum-stdout.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha1sum-dir-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha1sum-dir-stderr.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha1sum-no-file-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha1sum-no-file-stderr.txt
 copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CommandLine/E_sha1sum-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha224sum-dir-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha224sum-dir-stderr.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha224sum-no-file-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha224sum-no-file-stderr.txt
 copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CommandLine/E_sha224sum-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha256sum-dir-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha256sum-dir-stderr.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha256sum-no-file-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha256sum-no-file-stderr.txt
 copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CommandLine/E_sha256sum-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha384sum-dir-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha384sum-dir-stderr.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha384sum-no-file-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha384sum-no-file-stderr.txt
 copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CommandLine/E_sha384sum-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha512sum-dir-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha512sum-dir-stderr.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/E_sha512sum-no-file-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha512sum-no-file-stderr.txt
 copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CommandLine/E_sha512sum-result.txt} (100%)
 create mode 100644 Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt
 copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => ObjectLibrary/OwnSources-result.txt} (100%)
 create mode 100644 Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt
 create mode 100644 Tests/RunCMake/ObjectLibrary/OwnSources.cmake


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list