summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/file_system/TARGETS2
-rw-r--r--src/buildtool/file_system/file_system_manager.hpp49
-rw-r--r--src/buildtool/system/TARGETS1
-rw-r--r--src/buildtool/system/system.hpp36
-rw-r--r--src/utils/cpp/concepts.hpp14
5 files changed, 88 insertions, 14 deletions
diff --git a/src/buildtool/file_system/TARGETS b/src/buildtool/file_system/TARGETS
index d780c47a..929c372f 100644
--- a/src/buildtool/file_system/TARGETS
+++ b/src/buildtool/file_system/TARGETS
@@ -66,4 +66,4 @@
]
, "stage": ["src", "buildtool", "file_system"]
}
-} \ No newline at end of file
+}
diff --git a/src/buildtool/file_system/file_system_manager.hpp b/src/buildtool/file_system/file_system_manager.hpp
index 0bdfb8a6..c5618e8b 100644
--- a/src/buildtool/file_system/file_system_manager.hpp
+++ b/src/buildtool/file_system/file_system_manager.hpp
@@ -1,6 +1,7 @@
#ifndef INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_FILE_SYSTEM_MANAGER_HPP
#define INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_FILE_SYSTEM_MANAGER_HPP
+#include <chrono>
#include <cstdio> // for std::fopen
#include <exception>
#include <filesystem>
@@ -118,7 +119,7 @@ class FileSystemManager {
}
}
- template <ObjectType kType>
+ template <ObjectType kType, bool kSetEpochTime = false>
requires(IsFileObject(kType))
[[nodiscard]] static auto CreateFileHardlinkAs(
std::filesystem::path const& file_path,
@@ -127,20 +128,23 @@ class FileSystemManager {
// that the created link has the correct permissions as soon as the link
// creation is finished.
return SetFilePermissions(file_path, IsExecutableObject(kType)) and
+ (not kSetEpochTime or SetEpochTime(file_path)) and
CreateFileHardlink(file_path, link_path);
}
+ template <bool kSetEpochTime = false>
[[nodiscard]] static auto CreateFileHardlinkAs(
std::filesystem::path const& file_path,
std::filesystem::path const& link_path,
ObjectType output_type) noexcept -> bool {
switch (output_type) {
case ObjectType::File:
- return CreateFileHardlinkAs<ObjectType::File>(file_path,
- link_path);
+ return CreateFileHardlinkAs<ObjectType::File, kSetEpochTime>(
+ file_path, link_path);
case ObjectType::Executable:
- return CreateFileHardlinkAs<ObjectType::Executable>(file_path,
- link_path);
+ return CreateFileHardlinkAs<ObjectType::Executable,
+ kSetEpochTime>(file_path,
+ link_path);
case ObjectType::Tree:
return false;
}
@@ -206,7 +210,7 @@ class FileSystemManager {
return CopyFileImpl(src, dst, opt);
}
- template <ObjectType kType>
+ template <ObjectType kType, bool kSetEpochTime = false>
requires(IsFileObject(kType)) [[nodiscard]] static auto CopyFileAs(
std::filesystem::path const& src,
std::filesystem::path const& dst,
@@ -215,9 +219,11 @@ class FileSystemManager {
std::filesystem::copy_options::overwrite_existing) noexcept
-> bool {
return CopyFile(src, dst, fd_less, opt) and
- SetFilePermissions(dst, IsExecutableObject(kType));
+ SetFilePermissions(dst, IsExecutableObject(kType)) and
+ (not kSetEpochTime or SetEpochTime(dst));
}
+ template <bool kSetEpochTime = false>
[[nodiscard]] static auto CopyFileAs(
std::filesystem::path const& src,
std::filesystem::path const& dst,
@@ -228,9 +234,10 @@ class FileSystemManager {
-> bool {
switch (type) {
case ObjectType::File:
- return CopyFileAs<ObjectType::File>(src, dst, fd_less, opt);
+ return CopyFileAs<ObjectType::File, kSetEpochTime>(
+ src, dst, fd_less, opt);
case ObjectType::Executable:
- return CopyFileAs<ObjectType::Executable>(
+ return CopyFileAs<ObjectType::Executable, kSetEpochTime>(
src, dst, fd_less, opt);
case ObjectType::Tree:
break;
@@ -513,16 +520,18 @@ class FileSystemManager {
return WriteFileImpl(content, file);
}
- template <ObjectType kType>
+ template <ObjectType kType, bool kSetEpochTime = false>
requires(IsFileObject(kType))
[[nodiscard]] static auto WriteFileAs(std::string const& content,
std::filesystem::path const& file,
bool fd_less = false) noexcept
-> bool {
return WriteFile(content, file, fd_less) and
- SetFilePermissions(file, IsExecutableObject(kType));
+ SetFilePermissions(file, IsExecutableObject(kType)) and
+ (not kSetEpochTime or SetEpochTime(file));
}
+ template <bool kSetEpochTime = false>
[[nodiscard]] static auto WriteFileAs(std::string const& content,
std::filesystem::path const& file,
ObjectType output_type,
@@ -530,9 +539,10 @@ class FileSystemManager {
-> bool {
switch (output_type) {
case ObjectType::File:
- return WriteFileAs<ObjectType::File>(content, file, fd_less);
+ return WriteFileAs<ObjectType::File, kSetEpochTime>(
+ content, file, fd_less);
case ObjectType::Executable:
- return WriteFileAs<ObjectType::Executable>(
+ return WriteFileAs<ObjectType::Executable, kSetEpochTime>(
content, file, fd_less);
case ObjectType::Tree:
return false;
@@ -681,6 +691,19 @@ class FileSystemManager {
return false;
}
}
+
+ static auto SetEpochTime(std::filesystem::path const& file_path) noexcept
+ -> bool {
+ static auto const kPosixEpochTime =
+ System::GetPosixEpoch<std::chrono::file_clock>();
+ try {
+ std::filesystem::last_write_time(file_path, kPosixEpochTime);
+ return true;
+ } catch (std::exception const& e) {
+ Logger::Log(LogLevel::Error, e.what());
+ return false;
+ }
+ }
}; // class FileSystemManager
#endif // INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_FILE_SYSTEM_MANAGER_HPP
diff --git a/src/buildtool/system/TARGETS b/src/buildtool/system/TARGETS
index d71245b1..ddc7ae4d 100644
--- a/src/buildtool/system/TARGETS
+++ b/src/buildtool/system/TARGETS
@@ -9,6 +9,7 @@
, "cond": {"type": "var", "name": "VALGRIND_BUILD"}
, "then": ["VALGRIND_BUILD"]
}
+ , "deps": [["src/utils/cpp", "concepts"]]
, "stage": ["src", "buildtool", "system"]
}
, "system_command":
diff --git a/src/buildtool/system/system.hpp b/src/buildtool/system/system.hpp
index 2038d5c7..fc67471b 100644
--- a/src/buildtool/system/system.hpp
+++ b/src/buildtool/system/system.hpp
@@ -1,10 +1,46 @@
#ifndef INCLUDED_SRC_BUILDTOOL_SYSTEM_SYSTEM_HPP
#define INCLUDED_SRC_BUILDTOOL_SYSTEM_SYSTEM_HPP
+#include <chrono>
+
+#include "src/utils/cpp/concepts.hpp"
+
namespace System {
void ExitWithoutCleanup(int exit_code);
+/// \brief Obtain POSIX epoch time for a given clock.
+/// Clocks may have different epoch times. To obtain the POSIX epoch time
+/// (1970-01-01 00:00:00 UTC) for a given clock, it must be converted.
+template <class T_Clock>
+static auto GetPosixEpoch() -> std::chrono::time_point<T_Clock> {
+ // Since C++20, the system clock's default value is the POSIX epoch time.
+ std::chrono::time_point<std::chrono::system_clock> sys_epoch{};
+ if constexpr (std::is_same_v<T_Clock, std::chrono::system_clock>) {
+ // No conversion necessary for the system clock.
+ return sys_epoch;
+ }
+ else if constexpr (ClockHasFromSys<T_Clock>) {
+ // The correct C++20 way to perform the time point conversion.
+ return T_Clock::from_sys(sys_epoch);
+ }
+ else if constexpr (ClockHasFromTime<T_Clock>) {
+ // Older releases of libcxx did not implement the standard conversion
+ // function from_sys() for std::chrono::file_clock. Instead the
+ // non-standard function file_clock::from_time_t() must be used. Since
+ // libcxx 14.0.0, this has been fixed by:
+ // - https://reviews.llvm.org/D113027
+ // - https://reviews.llvm.org/D113430
+ // TODO(modernize): remove this once we require clang version >= 14.0.0
+ return T_Clock::from_time_t(
+ std::chrono::system_clock::to_time_t(sys_epoch));
+ }
+ static_assert(std::is_same_v<T_Clock, std::chrono::system_clock> or
+ ClockHasFromSys<T_Clock> or ClockHasFromTime<T_Clock>,
+ "Time point conversion function unavailable.");
+ return {};
}
+} // namespace System
+
#endif // INCLUDED_SRC_BUILDTOOL_SYSTEM_SYSTEM_HPP
diff --git a/src/utils/cpp/concepts.hpp b/src/utils/cpp/concepts.hpp
index 92718b43..597179e1 100644
--- a/src/utils/cpp/concepts.hpp
+++ b/src/utils/cpp/concepts.hpp
@@ -1,6 +1,7 @@
#ifndef INCLUDED_SRC_UTILS_CPP_CONCEPTS_HPP
#define INCLUDED_SRC_UTILS_CPP_CONCEPTS_HPP
+#include <chrono>
#include <string>
#include <type_traits>
@@ -52,4 +53,17 @@ template <class T>
concept InputIterableStringContainer =
InputIterableContainer<T>and ContainsString<T>;
+// TODO(modernize): remove this once we require clang version >= 14.0.0
+template <typename T>
+concept ClockHasFromSys =
+ requires(std::chrono::time_point<std::chrono::system_clock> const tp) {
+ T::from_sys(tp);
+};
+
+// TODO(modernize): remove this once we require clang version >= 14.0.0
+template <typename T>
+concept ClockHasFromTime = requires(std::time_t const t) {
+ T::from_time_t(t);
+};
+
#endif // INCLUDED_SRC_UTILS_CPP_CONCEPTS_HPP