]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add “--extract-result” option
authorJoel Rosdahl <joel@rosdahl.net>
Sun, 5 Jul 2020 20:07:06 +0000 (22:07 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Mon, 6 Jul 2020 17:59:58 +0000 (19:59 +0200)
“ccache --extract-result” extracts data stored in a result file to the
current working directory.

doc/MANUAL.adoc
src/CMakeLists.txt
src/Result.cpp
src/Result.hpp
src/ResultExtractor.cpp [new file with mode: 0644]
src/ResultExtractor.hpp [new file with mode: 0644]
src/ResultRetriever.hpp
src/ccache.cpp

index 11fb5691d92ecb33a03f3510caf7340c9a70c57b..e5811f7bdecfc1664ca4401b83c964690d7469aa 100644 (file)
@@ -159,13 +159,19 @@ Options for scripting or debugging
 
 *`--dump-manifest`* _PATH_::
 
-    Dump manifest file at _PATH_ in text format. This is only useful when
-    debugging ccache and its behavior.
+    Dump manifest file at _PATH_ in text format to standard output. This is
+    only useful when debugging ccache and its behavior.
 
 *`--dump-result`* _PATH_::
 
-    Dump result file at _PATH_ in text format. This is only useful when
-    debugging ccache and its behavior.
+    Dump result file at _PATH_ in text format to standard output. This is only
+    useful when debugging ccache and its behavior.
+
+*`--extract-result`* _PATH_::
+
+    Extract data stored in the result file at _PATH_. The data will be written
+    to *ccache-result.** files in to the current working directory. This is
+    only useful when debugging ccache and its behavior.
 
 *`-k`* _KEY_, *`--get-config`* _KEY_::
 
index 9e50e135574251af59cc9adb87ff4295a8e8750a..29838355edb8fc95f2a97ae478b67bf276b2144d 100644 (file)
@@ -18,6 +18,7 @@ set(
   ProgressBar.cpp
   Result.cpp
   ResultDumper.cpp
+  ResultExtractor.cpp
   ResultRetriever.cpp
   SignalHandler.cpp
   Stat.cpp
index 6661084df4240b62204748411c82baece91004bf..375e911e264ff3f809f5e3d4d747ced68d200233 100644 (file)
@@ -140,6 +140,7 @@ namespace Result {
 
 const uint8_t k_magic[4] = {'c', 'C', 'r', 'S'};
 const uint8_t k_version = 1;
+const char* const k_unknown_file_type = "<unknown type>";
 
 const char*
 file_type_to_string(FileType type)
@@ -167,7 +168,7 @@ file_type_to_string(FileType type)
     return ".dwo";
   }
 
-  return "<unknown type>";
+  return k_unknown_file_type;
 }
 
 Result::Reader::Reader(const std::string& result_path)
index 8918996b69c2177ea7876c93e341eedba5ed32f7..ff80174b17cf134733cf5571014b19694a21025f 100644 (file)
@@ -34,6 +34,7 @@ namespace Result {
 
 extern const uint8_t k_magic[4];
 extern const uint8_t k_version;
+extern const char* const k_unknown_file_type;
 
 using UnderlyingFileTypeInt = uint8_t;
 enum class FileType : UnderlyingFileTypeInt {
diff --git a/src/ResultExtractor.cpp b/src/ResultExtractor.cpp
new file mode 100644 (file)
index 0000000..4409b06
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright (C) 2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "ResultExtractor.hpp"
+
+#include "Context.hpp"
+#include "logging.hpp"
+
+#include "third_party/nonstd/string_view.hpp"
+
+using string_view = nonstd::string_view;
+
+ResultExtractor::ResultExtractor(const std::string& directory)
+  : m_directory(directory)
+{
+}
+
+void
+ResultExtractor::on_header(CacheEntryReader& /*cache_entry_reader*/)
+{
+}
+
+void
+ResultExtractor::on_entry_start(uint32_t /*entry_number*/,
+                                Result::FileType file_type,
+                                uint64_t /*file_len*/,
+                                nonstd::optional<std::string> raw_file)
+{
+  std::string suffix = Result::file_type_to_string(file_type);
+  if (suffix == Result::k_unknown_file_type) {
+    suffix = fmt::format(".type_{}", file_type);
+  } else if (suffix[0] == '<') {
+    suffix[0] = '.';
+    suffix.resize(suffix.length() - 1);
+  }
+
+  m_dest_path = fmt::format("{}/ccache-result{}", m_directory, suffix);
+
+  if (!raw_file) {
+    m_dest_fd = Fd(
+      open(m_dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666));
+    if (!m_dest_fd) {
+      throw Error(fmt::format(
+        "Failed to open {} for writing: {}", m_dest_path, strerror(errno)));
+    }
+
+  } else if (!copy_file(raw_file->c_str(), m_dest_path.c_str(), false)) {
+    throw Error(fmt::format(
+      "Failed to copy {} to {}: {}", *raw_file, m_dest_path, strerror(errno)));
+  }
+}
+
+void
+ResultExtractor::on_entry_data(const uint8_t* data, size_t size)
+{
+  assert(m_dest_fd);
+
+  if (!write_fd(*m_dest_fd, data, size)) {
+    throw Error(fmt::format("Failed to write to {}", m_dest_path));
+  }
+}
+
+void
+ResultExtractor::on_entry_end()
+{
+  if (m_dest_fd) {
+    m_dest_fd.close();
+  }
+}
diff --git a/src/ResultExtractor.hpp b/src/ResultExtractor.hpp
new file mode 100644 (file)
index 0000000..14b6871
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#pragma once
+
+#include "system.hpp"
+
+#include "Fd.hpp"
+#include "Result.hpp"
+
+class Context;
+
+// This class extracts the parts of a result entry to a directory.
+class ResultExtractor : public Result::Reader::Consumer
+{
+public:
+  ResultExtractor(const std::string& directory);
+
+  virtual void on_header(CacheEntryReader& cache_entry_reader);
+  virtual void on_entry_start(uint32_t entry_number,
+                              Result::FileType file_type,
+                              uint64_t file_len,
+                              nonstd::optional<std::string> raw_file);
+  virtual void on_entry_data(const uint8_t* data, size_t size);
+  virtual void on_entry_end();
+
+private:
+  const std::string m_directory;
+  Fd m_dest_fd;
+  std::string m_dest_path;
+};
index 48cb84b44ae4e5a378fa07781e97ee98e4d5891c..a5baba328b1bba839a0a0cd533b3ca649280ce6b 100644 (file)
@@ -25,7 +25,7 @@
 
 class Context;
 
-// This class retrieves an result entry to the local file system.
+// This class retrieves a result entry to the local file system.
 class ResultRetriever : public Result::Reader::Consumer
 {
 public:
index 685dbc468456b2fb4c0235c8b53e0eb11f3b5fd1..6d2a821ae79032b940422bcfaaf2daaf66ccc82e 100644 (file)
@@ -30,6 +30,7 @@
 #include "ProgressBar.hpp"
 #include "Result.hpp"
 #include "ResultDumper.hpp"
+#include "ResultExtractor.hpp"
 #include "ResultRetriever.hpp"
 #include "SignalHandler.hpp"
 #include "StdMakeUnique.hpp"
@@ -108,6 +109,8 @@ Common options:
 Options for scripting or debugging:
         --dump-manifest PATH  dump manifest file at PATH in text format
         --dump-result PATH    dump result file at PATH in text format
+        --extract-result PATH extract data stored in result file at PATH to the
+                              current working directory
     -k, --get-config KEY      print the value of configuration key KEY
         --hash-file PATH      print the hash (160 bit BLAKE3) of the file at
                               PATH
@@ -2189,6 +2192,7 @@ handle_main_options(int argc, const char* const* argv)
   enum longopts {
     DUMP_MANIFEST,
     DUMP_RESULT,
+    EXTRACT_RESULT,
     HASH_FILE,
     PRINT_STATS,
   };
@@ -2197,6 +2201,7 @@ handle_main_options(int argc, const char* const* argv)
     {"clear", no_argument, nullptr, 'C'},
     {"dump-manifest", required_argument, nullptr, DUMP_MANIFEST},
     {"dump-result", required_argument, nullptr, DUMP_RESULT},
+    {"extract-result", required_argument, nullptr, EXTRACT_RESULT},
     {"get-config", required_argument, nullptr, 'k'},
     {"hash-file", required_argument, nullptr, HASH_FILE},
     {"help", no_argument, nullptr, 'h'},
@@ -2236,6 +2241,16 @@ handle_main_options(int argc, const char* const* argv)
       return error ? EXIT_FAILURE : EXIT_SUCCESS;
     }
 
+    case EXTRACT_RESULT: {
+      ResultExtractor result_extractor(".");
+      Result::Reader result_reader(optarg);
+      auto error = result_reader.read(result_extractor);
+      if (error) {
+        fmt::print(stderr, "Error: {}\n", *error);
+      }
+      return error ? EXIT_FAILURE : EXIT_SUCCESS;
+    }
+
     case HASH_FILE: {
       struct hash* hash = hash_init();
       if (str_eq(optarg, "-")) {