diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-07-04 12:32:32 +0200 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-07-05 15:16:23 +0200 |
commit | abe2c89fc0e4f41f00aca3510e9bb4902e52c9e7 (patch) | |
tree | 82105fa2275f1d2f403215d6c268b8b419cebeb0 | |
parent | b1ce7ce328e322cafa2401af77a9334c61b72034 (diff) | |
download | justbuild-abe2c89fc0e4f41f00aca3510e9bb4902e52c9e7.tar.gz |
FileSystemManager::CreateFileHardlink: return error code on failure
Instead of returning a plain boolean, return an expected with the same
boolean value that in case of an error indicates the error code. In this
way, an error-specific handling is possible by consumers. While there,
also add proper quoting of the involved file names.
-rw-r--r-- | src/buildtool/file_system/TARGETS | 2 | ||||
-rw-r--r-- | src/buildtool/file_system/file_system_manager.hpp | 33 | ||||
-rw-r--r-- | src/buildtool/serve_api/serve_service/source_tree.cpp | 29 | ||||
-rw-r--r-- | src/other_tools/root_maps/distdir_git_map.cpp | 28 |
4 files changed, 54 insertions, 38 deletions
diff --git a/src/buildtool/file_system/TARGETS b/src/buildtool/file_system/TARGETS index 82ddce24..81c7000d 100644 --- a/src/buildtool/file_system/TARGETS +++ b/src/buildtool/file_system/TARGETS @@ -40,8 +40,10 @@ , ["src/buildtool/logging", "log_level"] , ["src/buildtool/logging", "logging"] , ["src/buildtool/system", "system"] + , ["src/utils/cpp", "expected"] , ["src/utils/cpp", "path"] , ["@", "gsl", "", "gsl"] + , ["@", "json", "", "json"] ] , "stage": ["src", "buildtool", "file_system"] } diff --git a/src/buildtool/file_system/file_system_manager.hpp b/src/buildtool/file_system/file_system_manager.hpp index 93a911d8..ac23691c 100644 --- a/src/buildtool/file_system/file_system_manager.hpp +++ b/src/buildtool/file_system/file_system_manager.hpp @@ -25,7 +25,9 @@ #include <filesystem> #include <fstream> #include <optional> +#include <system_error> #include <unordered_set> +#include <variant> #ifdef __unix__ #include <fcntl.h> @@ -39,10 +41,12 @@ #endif #include "gsl/gsl" +#include "nlohmann/json.hpp" #include "src/buildtool/file_system/object_type.hpp" #include "src/buildtool/logging/log_level.hpp" #include "src/buildtool/logging/logger.hpp" #include "src/buildtool/system/system.hpp" +#include "src/utils/cpp/expected.hpp" #include "src/utils/cpp/path.hpp" namespace detail { @@ -216,21 +220,28 @@ class FileSystemManager { return false; } + /// \brief Try to create a hard link; return unit on success and a + /// std::error_condition describing the failure. [[nodiscard]] static auto CreateFileHardlink( std::filesystem::path const& file_path, std::filesystem::path const& link_path, - LogLevel log_failure_at = LogLevel::Error) noexcept -> bool { - try { - std::filesystem::create_hard_link(file_path, link_path); - return std::filesystem::is_regular_file(link_path); - } catch (std::exception const& e) { - Logger::Log(log_failure_at, - "hard linking {} to {}\n{}", - file_path.string(), - link_path.string(), - e.what()); - return false; + LogLevel log_failure_at = LogLevel::Error) noexcept + -> expected<std::monostate, std::error_code> { + std::error_code ec{}; + std::filesystem::create_hard_link(file_path, link_path, ec); + if (not ec) { + if (std::filesystem::is_regular_file(link_path)) { + return std::monostate{}; + } + return unexpected(std::error_code{}); } + Logger::Log(log_failure_at, + "failed hard linking {} to {}: {}, {}", + nlohmann::json(file_path.string()).dump(), + nlohmann::json(link_path.string()).dump(), + ec.value(), + ec.message()); + return unexpected(ec); } template <ObjectType kType, bool kSetEpochTime = false> diff --git a/src/buildtool/serve_api/serve_service/source_tree.cpp b/src/buildtool/serve_api/serve_service/source_tree.cpp index 74edaca8..480dfd34 100644 --- a/src/buildtool/serve_api/serve_service/source_tree.cpp +++ b/src/buildtool/serve_api/serve_service/source_tree.cpp @@ -895,20 +895,21 @@ auto SourceTreeService::DistdirImportToGit( auto const& tmp_path = distdir_tmp_dir->GetPath(); // link the CAS blobs into the tmp dir auto const& cas = storage_.CAS(); - if (not std::all_of(content_list.begin(), - content_list.end(), - [&cas, tmp_path](auto const& kv) { - auto content_path = cas.BlobPath( - ArtifactDigest( - kv.second.first, 0, /*is_tree=*/false), - kv.second.second); - if (content_path) { - return FileSystemManager::CreateFileHardlink( - *content_path, // from: cas_path/content_id - tmp_path / kv.first); // to: tmp_path/name - } - return false; - })) { + if (not std::all_of( + content_list.begin(), + content_list.end(), + [&cas, tmp_path](auto const& kv) { + auto content_path = cas.BlobPath( + ArtifactDigest(kv.second.first, 0, /*is_tree=*/false), + kv.second.second); + if (content_path) { + return FileSystemManager::CreateFileHardlink( + *content_path, // from: cas_path/content_id + tmp_path / kv.first) // to: tmp_path/name + .has_value(); + } + return false; + })) { logger_->Emit(LogLevel::Error, "Failed to create links to CAS content {}", content_id); diff --git a/src/other_tools/root_maps/distdir_git_map.cpp b/src/other_tools/root_maps/distdir_git_map.cpp index 54abaae2..9171daae 100644 --- a/src/other_tools/root_maps/distdir_git_map.cpp +++ b/src/other_tools/root_maps/distdir_git_map.cpp @@ -42,19 +42,21 @@ namespace { content_list, std::filesystem::path const& tmp_dir) noexcept -> bool { auto const& cas = storage.CAS(); - return std::all_of(content_list->begin(), - content_list->end(), - [&cas, tmp_dir](auto const& kv) { - auto content_path = - cas.BlobPath(ArtifactDigest(kv.second, 0, false), - /*is_executable=*/false); - if (content_path) { - return FileSystemManager::CreateFileHardlink( - *content_path, // from: cas_path/content_id - tmp_dir / kv.first); // to: tmp_dir/name - } - return false; - }); + return std::all_of( + content_list->begin(), + content_list->end(), + [&cas, tmp_dir](auto const& kv) { + auto content_path = + cas.BlobPath(ArtifactDigest(kv.second, 0, false), + /*is_executable=*/false); + if (content_path) { + return FileSystemManager::CreateFileHardlink( + *content_path, // from: cas_path/content_id + tmp_dir / kv.first) // to: tmp_dir/name + .has_value(); + } + return false; + }); } /// \brief Called once we know we have the content blobs in local CAS in order |