From f1fdd15863150fe42e99a95362a4387333502262 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Wed, 14 Oct 2020 12:06:50 -0400
Subject: clang-format: Fix include block order in ctest.cxx and cpack.cxx

---
 Source/CPack/cpack.cxx | 18 +++++++++---------
 Source/ctest.cxx       |  9 +++++----
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 3a400b7..76e19dc 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -1,6 +1,15 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 
+#include <cstddef>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
 #include "cmsys/CommandLineArguments.hxx"
 #include "cmsys/Encoding.hxx"
 
@@ -22,15 +31,6 @@
 #  include "cmsys/ConsoleBuf.hxx"
 #endif
 
-#include <cstddef>
-#include <iostream>
-#include <map>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
 namespace {
 const char* cmDocumentationName[][2] = {
   { nullptr, "  cpack - Packaging driver provided by CMake." },
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 3b5bf8c..f06981a 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -1,6 +1,11 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+
 #include "cmsys/Encoding.hxx"
 
 #include "cmCTest.h"
@@ -12,10 +17,6 @@
 #if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
 #  include "cmsys/ConsoleBuf.hxx"
 #endif
-#include <cstring>
-#include <iostream>
-#include <string>
-#include <vector>
 
 static const char* cmDocumentationName[][2] = {
   { nullptr, "  ctest - Testing driver provided by CMake." },
-- 
cgit v0.12


From 90b39a52090e6ba52424b441d5827b2b6e11ff56 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Wed, 14 Oct 2020 10:57:46 -0400
Subject: cmConsoleBuf: Factor out cout/cerr console buffer management

---
 Source/CMakeLists.txt   |  2 ++
 Source/CPack/cpack.cxx  | 15 +++++----------
 Source/cmConsoleBuf.cxx | 23 +++++++++++++++++++++++
 Source/cmConsoleBuf.h   | 23 +++++++++++++++++++++++
 Source/cmakemain.cxx    | 14 +++++---------
 Source/cmcmd.cxx        | 10 ++--------
 Source/ctest.cxx        | 14 +++++---------
 bootstrap               |  1 +
 8 files changed, 66 insertions(+), 36 deletions(-)
 create mode 100644 Source/cmConsoleBuf.cxx
 create mode 100644 Source/cmConsoleBuf.h

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 1b6bb00..2026ab1 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -193,6 +193,8 @@ set(SRCS
   cmComputeLinkInformation.h
   cmComputeTargetDepends.h
   cmComputeTargetDepends.cxx
+  cmConsoleBuf.h
+  cmConsoleBuf.cxx
   cmCPackPropertiesGenerator.h
   cmCPackPropertiesGenerator.cxx
   cmCryptoHash.cxx
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 76e19dc..cc1ddf5 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -16,6 +16,7 @@
 #include "cmCPackGenerator.h"
 #include "cmCPackGeneratorFactory.h"
 #include "cmCPackLog.h"
+#include "cmConsoleBuf.h"
 #include "cmDocumentation.h"
 #include "cmDocumentationEntry.h"
 #include "cmDocumentationFormatter.h"
@@ -27,10 +28,6 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
-#  include "cmsys/ConsoleBuf.hxx"
-#endif
-
 namespace {
 const char* cmDocumentationName[][2] = {
   { nullptr, "  cpack - Packaging driver provided by CMake." },
@@ -103,13 +100,11 @@ void cpackProgressCallback(const std::string& message, float /*unused*/)
 int main(int argc, char const* const* argv)
 {
   cmSystemTools::EnsureStdPipes();
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+
   // Replace streambuf so we can output Unicode to console
-  cmsys::ConsoleBuf::Manager consoleOut(std::cout);
-  consoleOut.SetUTF8Pipes();
-  cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
-  consoleErr.SetUTF8Pipes();
-#endif
+  cmConsoleBuf consoleBuf;
+  consoleBuf.SetUTF8Pipes();
+
   cmsys::Encoding::CommandLineArguments args =
     cmsys::Encoding::CommandLineArguments::Main(argc, argv);
   argc = args.argc();
diff --git a/Source/cmConsoleBuf.cxx b/Source/cmConsoleBuf.cxx
new file mode 100644
index 0000000..70be481
--- /dev/null
+++ b/Source/cmConsoleBuf.cxx
@@ -0,0 +1,23 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmConsoleBuf.h"
+
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+cmConsoleBuf::cmConsoleBuf()
+  : m_ConsoleOut(std::cout)
+  , m_ConsoleErr(std::cerr, true)
+{
+}
+#else
+cmConsoleBuf::cmConsoleBuf() = default;
+#endif
+
+cmConsoleBuf::~cmConsoleBuf() = default;
+
+void cmConsoleBuf::SetUTF8Pipes()
+{
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+  m_ConsoleOut.SetUTF8Pipes();
+  m_ConsoleErr.SetUTF8Pipes();
+#endif
+}
diff --git a/Source/cmConsoleBuf.h b/Source/cmConsoleBuf.h
new file mode 100644
index 0000000..3564598
--- /dev/null
+++ b/Source/cmConsoleBuf.h
@@ -0,0 +1,23 @@
+/* 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" // IWYU pragma: keep
+
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+#  include "cmsys/ConsoleBuf.hxx"
+#endif
+
+class cmConsoleBuf
+{
+#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+  cmsys::ConsoleBuf::Manager m_ConsoleOut;
+  cmsys::ConsoleBuf::Manager m_ConsoleErr;
+#endif
+public:
+  cmConsoleBuf();
+  ~cmConsoleBuf();
+  cmConsoleBuf(cmConsoleBuf const&) = delete;
+  cmConsoleBuf& operator=(cmConsoleBuf const&) = delete;
+  void SetUTF8Pipes();
+};
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index d662a9a..eb44329 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -15,6 +15,7 @@
 
 #include <cm3p/uv.h>
 
+#include "cmConsoleBuf.h"
 #include "cmDocumentationEntry.h" // IWYU pragma: keep
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
@@ -32,9 +33,6 @@
 #endif
 
 #include "cmsys/Encoding.hxx"
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
-#  include "cmsys/ConsoleBuf.hxx"
-#endif
 
 namespace {
 #ifndef CMAKE_BOOTSTRAP
@@ -687,13 +685,11 @@ int do_open(int ac, char const* const* av)
 int main(int ac, char const* const* av)
 {
   cmSystemTools::EnsureStdPipes();
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+
   // Replace streambuf so we can output Unicode to console
-  cmsys::ConsoleBuf::Manager consoleOut(std::cout);
-  consoleOut.SetUTF8Pipes();
-  cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
-  consoleErr.SetUTF8Pipes();
-#endif
+  cmConsoleBuf consoleBuf;
+  consoleBuf.SetUTF8Pipes();
+
   cmsys::Encoding::CommandLineArguments args =
     cmsys::Encoding::CommandLineArguments::Main(ac, av);
   ac = args.argc();
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index de76d73..150fefd 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -7,6 +7,7 @@
 #include <cm3p/uv.h>
 #include <fcntl.h>
 
+#include "cmConsoleBuf.h"
 #include "cmDuration.h"
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
@@ -33,10 +34,6 @@
 #  include "bindexplib.h"
 #endif
 
-#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32)
-#  include "cmsys/ConsoleBuf.hxx"
-#endif
-
 #if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__)
 #  include "cmVisualStudioWCEPlatformParser.h"
 #endif
@@ -1863,14 +1860,11 @@ private:
 // still works.
 int cmcmd::VisualStudioLink(std::vector<std::string> const& args, int type)
 {
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
   // Replace streambuf so we output in the system codepage. CMake is set up
   // to output in Unicode (see SetUTF8Pipes) but the Visual Studio linker
   // outputs using the system codepage so we need to change behavior when
   // we run the link command.
-  cmsys::ConsoleBuf::Manager consoleOut(std::cout);
-  cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
-#endif
+  cmConsoleBuf consoleBuf;
 
   if (args.size() < 2) {
     return -1;
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index f06981a..d0bc061 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -9,14 +9,12 @@
 #include "cmsys/Encoding.hxx"
 
 #include "cmCTest.h"
+#include "cmConsoleBuf.h"
 #include "cmDocumentation.h"
 #include "cmSystemTools.h"
 
 #include "CTest/cmCTestLaunch.h"
 #include "CTest/cmCTestScriptHandler.h"
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
-#  include "cmsys/ConsoleBuf.hxx"
-#endif
 
 static const char* cmDocumentationName[][2] = {
   { nullptr, "  ctest - Testing driver provided by CMake." },
@@ -155,13 +153,11 @@ static const char* cmDocumentationOptions[][2] = {
 int main(int argc, char const* const* argv)
 {
   cmSystemTools::EnsureStdPipes();
-#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP)
+
   // Replace streambuf so we can output Unicode to console
-  cmsys::ConsoleBuf::Manager consoleOut(std::cout);
-  consoleOut.SetUTF8Pipes();
-  cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true);
-  consoleErr.SetUTF8Pipes();
-#endif
+  cmConsoleBuf consoleBuf;
+  consoleBuf.SetUTF8Pipes();
+
   cmsys::Encoding::CommandLineArguments encoding_args =
     cmsys::Encoding::CommandLineArguments::Main(argc, argv);
   argc = encoding_args.argc();
diff --git a/bootstrap b/bootstrap
index 04067dc..1362f9d 100755
--- a/bootstrap
+++ b/bootstrap
@@ -299,6 +299,7 @@ CMAKE_CXX_SOURCES="\
   cmComputeLinkDepends \
   cmComputeLinkInformation \
   cmComputeTargetDepends \
+  cmConsoleBuf \
   cmConditionEvaluator \
   cmConfigureFileCommand \
   cmContinueCommand \
-- 
cgit v0.12


From f7a5f283188c1e51b0fb549f0a78afaf1d570383 Mon Sep 17 00:00:00 2001
From: Johnny Jazeix <jazeix@gmail.com>
Date: Tue, 13 Oct 2020 23:48:12 +0200
Subject: cmake: Fix '-E cat' command for binary files on Windows

Reset `std::cout` to write in binary mode with no encoding conversions.

Co-Author: Brad King <brad.king@kitware.com>
Fixes: #21295
---
 Source/cmakemain.cxx                                      |  13 ++++++++-----
 Source/cmcmd.cxx                                          |  14 +++++++++++++-
 Source/cmcmd.h                                            |   6 +++++-
 Tests/RunCMake/CommandLine/.gitattributes                 |   2 ++
 Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj  | Bin 0 -> 124 bytes
 .../RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt | Bin 0 -> 248 bytes
 Tests/RunCMake/CommandLine/RunCMakeTest.cmake             |   3 +++
 7 files changed, 31 insertions(+), 7 deletions(-)
 create mode 100644 Tests/RunCMake/CommandLine/.gitattributes
 create mode 100644 Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj
 create mode 100644 Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt

diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index eb44329..7e589c0 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -9,8 +9,10 @@
 #include <cstring>
 #include <iostream>
 #include <string>
+#include <utility>
 #include <vector>
 
+#include <cm/memory>
 #include <cmext/algorithm>
 
 #include <cm3p/uv.h>
@@ -107,13 +109,14 @@ const char* cmDocumentationOptions[][2] = {
 
 #endif
 
-int do_command(int ac, char const* const* av)
+int do_command(int ac, char const* const* av,
+               std::unique_ptr<cmConsoleBuf> consoleBuf)
 {
   std::vector<std::string> args;
   args.reserve(ac - 1);
   args.emplace_back(av[0]);
   cm::append(args, av + 2, av + ac);
-  return cmcmd::ExecuteCMakeCommand(args);
+  return cmcmd::ExecuteCMakeCommand(args, std::move(consoleBuf));
 }
 
 cmMakefile* cmakemainGetMakefile(cmake* cm)
@@ -687,8 +690,8 @@ int main(int ac, char const* const* av)
   cmSystemTools::EnsureStdPipes();
 
   // Replace streambuf so we can output Unicode to console
-  cmConsoleBuf consoleBuf;
-  consoleBuf.SetUTF8Pipes();
+  auto consoleBuf = cm::make_unique<cmConsoleBuf>();
+  consoleBuf->SetUTF8Pipes();
 
   cmsys::Encoding::CommandLineArguments args =
     cmsys::Encoding::CommandLineArguments::Main(ac, av);
@@ -708,7 +711,7 @@ int main(int ac, char const* const* av)
       return do_open(ac, av);
     }
     if (strcmp(av[1], "-E") == 0) {
-      return do_command(ac, av);
+      return do_command(ac, av, std::move(consoleBuf));
     }
   }
   int ret = do_cmake(ac, av);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 150fefd..a1fafcb 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -48,6 +48,12 @@
 #include <sstream>
 #include <utility>
 
+#ifdef _WIN32
+#  include <fcntl.h> // for _O_BINARY
+#  include <io.h>    // for _setmode
+#  include <stdio.h> // for std{out,err} and fileno
+#endif
+
 #include <cm/string_view>
 
 #include "cmsys/Directory.hxx"
@@ -178,6 +184,9 @@ static bool cmTarFilesFrom(std::string const& file,
 
 static void cmCatFile(const std::string& fileToAppend)
 {
+#ifdef _WIN32
+  _setmode(fileno(stdout), _O_BINARY);
+#endif
   cmsys::ifstream source(fileToAppend.c_str(),
                          (std::ios::binary | std::ios::in));
   std::cout << source.rdbuf();
@@ -497,7 +506,8 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args)
   return ret;
 }
 
-int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
+int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
+                               std::unique_ptr<cmConsoleBuf> consoleBuf)
 {
   // IF YOU ADD A NEW COMMAND, DOCUMENT IT ABOVE and in cmakemain.cxx
   if (args.size() > 1) {
@@ -951,6 +961,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
           cmSystemTools::Error(arg + ": no such file or directory (ignoring)");
           return_value = 1;
         } else {
+          // Destroy console buffers to drop cout/cerr encoding transform.
+          consoleBuf.reset();
           cmCatFile(arg);
         }
       }
diff --git a/Source/cmcmd.h b/Source/cmcmd.h
index 5b6c813..ffadd5a 100644
--- a/Source/cmcmd.h
+++ b/Source/cmcmd.h
@@ -5,11 +5,14 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <memory>
 #include <string>
 #include <vector>
 
 #include "cmCryptoHash.h"
 
+class cmConsoleBuf;
+
 class cmcmd
 {
 public:
@@ -17,7 +20,8 @@ public:
    * Execute commands during the build process. Supports options such
    * as echo, remove file etc.
    */
-  static int ExecuteCMakeCommand(std::vector<std::string> const&);
+  static int ExecuteCMakeCommand(std::vector<std::string> const&,
+                                 std::unique_ptr<cmConsoleBuf> consoleBuf);
 
 protected:
   static int HandleCoCompileCommands(std::vector<std::string> const& args);
diff --git a/Tests/RunCMake/CommandLine/.gitattributes b/Tests/RunCMake/CommandLine/.gitattributes
new file mode 100644
index 0000000..b0b0588
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/.gitattributes
@@ -0,0 +1,2 @@
+E_cat_binary_files/binary.obj    -text
+E_cat_good_binary_cat-stdout.txt -text -whitespace
diff --git a/Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj b/Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj
new file mode 100644
index 0000000..73f1749
Binary files /dev/null and b/Tests/RunCMake/CommandLine/E_cat_binary_files/binary.obj differ
diff --git a/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt b/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt
new file mode 100644
index 0000000..0951d85
Binary files /dev/null and b/Tests/RunCMake/CommandLine/E_cat_good_binary_cat-stdout.txt differ
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 973391d..abb9050 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -498,6 +498,9 @@ run_cmake_command(E_cat_good_cat
   ${CMAKE_COMMAND} -E cat "${out}/first_file.txt" "${out}/second_file.txt" "${out}/unicode_file.txt")
 unset(out)
 
+run_cmake_command(E_cat_good_binary_cat
+  ${CMAKE_COMMAND} -E cat "${RunCMake_SOURCE_DIR}/E_cat_binary_files/binary.obj" "${RunCMake_SOURCE_DIR}/E_cat_binary_files/binary.obj")
+
 run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env)
 run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1)
 run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1)
-- 
cgit v0.12