]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
refactor: Create util::filesystem wrappers returning nonstd::expected
authorJoel Rosdahl <joel@rosdahl.net>
Sat, 15 Jul 2023 14:06:31 +0000 (16:06 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 15 Jul 2023 20:21:12 +0000 (22:21 +0200)
src/MiniTrace.cpp
src/Util.cpp
src/ccache.cpp
src/storage/local/LocalStorage.cpp
src/util/LockFile.cpp
src/util/filesystem.hpp [new file with mode: 0644]
src/util/path.cpp

index f52564649ffacf10cd495048e3e4e30da8a8ae91..db4141d033592fa704d3fa419b73fa5f36525f3d 100644 (file)
 #include <core/wincompat.hpp>
 #include <util/TimePoint.hpp>
 #include <util/file.hpp>
+#include <util/filesystem.hpp>
 
 #ifdef HAVE_UNISTD_H
 #  include <unistd.h>
 #endif
 
-#include <filesystem>
-
-namespace fs = std::filesystem;
+namespace fs = util::filesystem;
 
 MiniTrace::MiniTrace(const ArgsInfo& args_info)
   : m_args_info(args_info),
     m_trace_id(reinterpret_cast<void*>(getpid()))
 {
-  std::error_code ec;
-  auto tmp_dir = fs::temp_directory_path(ec);
-  if (ec) {
+  auto tmp_dir = fs::temp_directory_path();
+  if (!tmp_dir) {
     tmp_dir = "/tmp";
   }
-  TemporaryFile tmp_file((tmp_dir / "ccache-trace").string());
+  TemporaryFile tmp_file((*tmp_dir / "ccache-trace").string());
   m_tmp_trace_file = tmp_file.path;
 
   mtr_init(m_tmp_trace_file.c_str());
index 9b157b6dbbb714d7f53584c389547113b48358c7..afd28d4e0918fba920a8a7c6f71a06b824877251 100644 (file)
@@ -32,6 +32,7 @@
 #include <fmtmacros.hpp>
 #include <util/TimePoint.hpp>
 #include <util/file.hpp>
+#include <util/filesystem.hpp>
 #include <util/path.hpp>
 #include <util/string.hpp>
 
@@ -51,7 +52,7 @@
 
 using IncludeDelimiter = util::Tokenizer::IncludeDelimiter;
 
-namespace fs = std::filesystem;
+namespace fs = util::filesystem;
 
 namespace {
 
@@ -284,12 +285,15 @@ ensure_dir_exists(std::string_view dir)
 std::string
 get_actual_cwd()
 {
-  std::error_code ec;
-  auto cwd = fs::current_path(ec).string();
+  auto cwd = fs::current_path();
+  if (!cwd) {
+    return {};
+  }
+  auto cwd_str = cwd->string();
 #ifdef _WIN32
-  std::replace(cwd.begin(), cwd.end(), '\\', '/');
+  std::replace(cwd_str.begin(), cwd_str.end(), '\\', '/');
 #endif
-  return cwd;
+  return cwd_str;
 }
 
 std::string
index 75dc41b604a01df915f86f9c147b063ff17d03f1..45b7b1af4777a09baf9aabbabeb51e66b3b5534c 100644 (file)
@@ -57,6 +57,7 @@
 #include <util/environment.hpp>
 #include <util/expected.hpp>
 #include <util/file.hpp>
+#include <util/filesystem.hpp>
 #include <util/path.hpp>
 #include <util/process.hpp>
 #include <util/string.hpp>
@@ -65,7 +66,6 @@
 
 #include <fcntl.h>
 
-#include <filesystem>
 #include <optional>
 #include <string_view>
 
@@ -80,7 +80,7 @@
 #include <memory>
 #include <unordered_map>
 
-namespace fs = std::filesystem;
+namespace fs = util::filesystem;
 
 using core::Statistic;
 
@@ -245,17 +245,16 @@ guess_compiler(std::string_view path)
   // Follow symlinks to the real compiler to learn its name. We're not using
   // util::real_path in order to save some unnecessary stat calls.
   while (true) {
-    std::error_code ec;
-    auto symlink_target = fs::read_symlink(compiler_path, ec);
-    if (ec) {
+    auto symlink_target = fs::read_symlink(compiler_path);
+    if (!symlink_target) {
       // Not a symlink.
       break;
     }
-    if (symlink_target.is_absolute()) {
-      compiler_path = symlink_target;
+    if (symlink_target->is_absolute()) {
+      compiler_path = *symlink_target;
     } else {
       compiler_path =
-        FMT("{}/{}", Util::dir_name(compiler_path), symlink_target.string());
+        FMT("{}/{}", Util::dir_name(compiler_path), symlink_target->string());
     }
   }
 #endif
index 5410bc9623a885e9c54b9f37cd2ca35554b4b6f1..9aaf2c6beb41c6b39e90fde7ae32f58ff2a37e46 100644 (file)
@@ -39,6 +39,7 @@
 #include <util/TextTable.hpp>
 #include <util/expected.hpp>
 #include <util/file.hpp>
+#include <util/filesystem.hpp>
 #include <util/process.hpp>
 #include <util/string.hpp>
 
 #include <algorithm>
 #include <atomic>
 #include <cstdlib>
-#include <filesystem>
 #include <memory>
 #include <numeric>
 #include <string>
 #include <utility>
 
-namespace fs = std::filesystem;
+namespace fs = util::filesystem;
 
 using core::Statistic;
 using core::StatisticsCounters;
@@ -650,11 +650,16 @@ LocalStorage::clone_hard_link_or_copy_file(const std::string& source,
     // run, but it's only we who can create the file entry now so we don't try
     // to handle a race between remove() and create_hard_link() below.
 
-    std::error_code ec;
-    fs::remove(dest, ec); // Ignore any error.
+    fs::remove(dest); // Ignore any error.
     LOG("Hard linking {} to {}", source, dest);
-    fs::create_hard_link(source, dest, ec);
-    if (!ec) {
+    if (auto result = fs::create_hard_link(source, dest); !result) {
+      LOG("Failed to hard link {} to {}: {}",
+          source,
+          dest,
+          result.error().message());
+      // Fall back to copying.
+    } else {
+      // Success.
 #ifndef _WIN32
       if (chmod(dest.c_str(), 0444 & ~util::get_umask()) != 0) {
         LOG("Failed to chmod {}: {}", dest.c_str(), strerror(errno));
@@ -662,8 +667,6 @@ LocalStorage::clone_hard_link_or_copy_file(const std::string& source,
 #endif
       return;
     }
-    LOG("Failed to hard link {} to {}: {}", source, dest, ec.message());
-    // Fall back to copying.
   }
 
   LOG("Copying {} to {}", source, dest);
index 03346986853a93b59e1babbadce19877fd70c7b5..219a635351150f15692011262b73074ed60f8b49 100644 (file)
@@ -26,6 +26,7 @@
 #include <core/exceptions.hpp>
 #include <core/wincompat.hpp>
 #include <util/file.hpp>
+#include <util/filesystem.hpp>
 
 #include "third_party/fmt/core.h"
 
@@ -44,7 +45,7 @@ const double k_max_sleep_time = 0.050;
 const util::Duration k_staleness_limit(2);
 #endif
 
-namespace fs = std::filesystem;
+namespace fs = util::filesystem;
 
 namespace {
 
@@ -262,18 +263,20 @@ LockFile::do_acquire(const bool blocking)
       return false;
     }
 
-    std::error_code ec;
-    std::string content = fs::read_symlink(m_lock_file, ec);
-    if (ec) {
-      if (ec == std::errc::no_such_file_or_directory) {
+    auto content_path = fs::read_symlink(m_lock_file);
+    if (!content_path) {
+      if (content_path.error() == std::errc::no_such_file_or_directory) {
         // The symlink was removed after the symlink() call above, so retry
         // acquiring it.
         continue;
       } else {
-        LOG("Could not read symlink {}: {}", m_lock_file, ec.message());
+        LOG("Could not read symlink {}: {}",
+            m_lock_file,
+            content_path.error().message());
         return false;
       }
     }
+    auto content = content_path->string();
 
     if (content == my_content) {
       // Lost NFS reply?
diff --git a/src/util/filesystem.hpp b/src/util/filesystem.hpp
new file mode 100644 (file)
index 0000000..f780164
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright (C) 2023 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 <third_party/nonstd/expected.hpp>
+
+#include <filesystem>
+
+namespace util::filesystem {
+
+using directory_iterator = std::filesystem::directory_iterator;
+using path = std::filesystem::path;
+
+#define DEFINE_FS_WRAPPER(name_, fnspec_)                                      \
+  template<typename... Args>                                                   \
+  nonstd::expected<decltype(std::filesystem::name_ fnspec_), std::error_code>  \
+  name_(Args&&... args)                                                        \
+  {                                                                            \
+    std::error_code ec;                                                        \
+    if constexpr (std::is_same<decltype(std::filesystem::name_ fnspec_),       \
+                               void>::value) {                                 \
+      std::filesystem::name_(std::forward<Args>(args)..., ec);                 \
+      if (ec) {                                                                \
+        return nonstd::make_unexpected(ec);                                    \
+      }                                                                        \
+      return {};                                                               \
+    } else {                                                                   \
+      auto result = std::filesystem::name_(std::forward<Args>(args)..., ec);   \
+      if (ec) {                                                                \
+        return nonstd::make_unexpected(ec);                                    \
+      }                                                                        \
+      return result;                                                           \
+    }                                                                          \
+  }
+
+#define DEFINE_FS_PREDICATE_WRAPPER(name_, fnspec_)                            \
+  template<typename... Args> bool name_(Args&&... args)                        \
+  {                                                                            \
+    std::error_code ec;                                                        \
+    auto result = std::filesystem::name_(std::forward<Args>(args)..., ec);     \
+    return !ec && result;                                                      \
+  }
+
+DEFINE_FS_WRAPPER(canonical, (path{}))
+DEFINE_FS_WRAPPER(create_hard_link, (path{}, path{}))
+DEFINE_FS_WRAPPER(current_path, ())
+DEFINE_FS_WRAPPER(read_symlink, (path{}))
+DEFINE_FS_WRAPPER(remove, (path{}))
+DEFINE_FS_WRAPPER(temp_directory_path, ())
+
+DEFINE_FS_PREDICATE_WRAPPER(exists, (path{}))
+DEFINE_FS_PREDICATE_WRAPPER(is_directory, (path{}))
+
+#undef DEFINE_FS_PREDICATE_WRAPPER
+#undef DEFINE_FS_WRAPPER
+
+} // namespace util::filesystem
index 5a9ab4addf051dfc431705383895f067e961bc17..1106a6d65ab899cef318679b4b8ea1946eb60534 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <Util.hpp>
 #include <fmtmacros.hpp>
+#include <util/filesystem.hpp>
 
 #ifdef _WIN32
 const char k_dev_null_path[] = "nul:";
@@ -29,7 +30,7 @@ const char k_dev_null_path[] = "/dev/null";
 const char k_path_delimiter[] = ":";
 #endif
 
-namespace fs = std::filesystem;
+namespace fs = util::filesystem;
 
 namespace util {
 
@@ -90,9 +91,8 @@ path_starts_with(std::string_view path, std::string_view prefix)
 std::string
 real_path(std::string_view path)
 {
-  std::error_code ec;
-  auto real_path = fs::canonical(path, ec).string();
-  return ec ? std::string(path) : real_path;
+  auto real_path = fs::canonical(path);
+  return real_path ? real_path->string() : std::string(path);
 }
 
 std::vector<std::string>