diff options
-rw-r--r-- | src/buildtool/common/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/common/artifact_blob.cpp | 70 | ||||
-rw-r--r-- | src/buildtool/common/artifact_blob.hpp | 31 |
3 files changed, 101 insertions, 1 deletions
diff --git a/src/buildtool/common/TARGETS b/src/buildtool/common/TARGETS index 9e124045..4c75627b 100644 --- a/src/buildtool/common/TARGETS +++ b/src/buildtool/common/TARGETS @@ -70,6 +70,7 @@ , ["src/buildtool/file_system", "object_type"] , ["src/utils/cpp", "expected"] , ["src/utils/cpp", "incremental_reader"] + , ["src/utils/cpp", "tmp_dir"] ] , "private-deps": [ ["@", "fmt", "", "fmt"] diff --git a/src/buildtool/common/artifact_blob.cpp b/src/buildtool/common/artifact_blob.cpp index a9c70621..8c48d34e 100644 --- a/src/buildtool/common/artifact_blob.cpp +++ b/src/buildtool/common/artifact_blob.cpp @@ -91,12 +91,79 @@ auto ArtifactBlob::FromFile(HashFunction hash_function, } } +auto ArtifactBlob::FromTempFile(HashFunction hash_function, + ObjectType type, + TmpFile::Ptr file) noexcept + -> expected<ArtifactBlob, std::string> { + try { + if (file == nullptr) { + return unexpected<std::string>{ + "ArtifactBlob::CreateFromTempFile: missing temp file."}; + } + + auto digest = IsTreeObject(type) + ? ArtifactDigestFactory::HashFileAs<ObjectType::Tree>( + hash_function, file->GetPath()) + : ArtifactDigestFactory::HashFileAs<ObjectType::File>( + hash_function, file->GetPath()); + if (not digest.has_value()) { + return unexpected{fmt::format( + "ArtifactBlob::CreateFromTempFile: Failed to hash {}", + file->GetPath().string())}; + } + return ArtifactBlob{ + *std::move(digest), std::move(file), IsExecutableObject(type)}; + } catch (const std::exception& e) { + return unexpected{fmt::format( + "ArtifactBlob::FromTempFile: Got an exception:\n{}", e.what())}; + } catch (...) { + return unexpected<std::string>{ + "ArtifactBlob::FromTempFile: Got an unknown exception."}; + } +} + +auto ArtifactBlob::FromTempFile(HashFunction hash_type, + ObjectType type, + TmpDir::Ptr const& temp_space, + std::string const& content) noexcept + -> expected<ArtifactBlob, std::string> { + try { + if (temp_space == nullptr) { + return unexpected<std::string>{ + "ArtifactBlob::FromTempFile: missing temp space."}; + } + + auto file = TmpDir::CreateFile(temp_space); + if (file == nullptr) { + return unexpected<std::string>{ + "ArtifactBlob::FromTempFile: failed to create a new temp " + "file."}; + } + + if (not FileSystemManager::WriteFile(content, file->GetPath())) { + return unexpected<std::string>{ + "ArtifactBlob::FromTempFile: failed to write content to a " + "temp file."}; + } + return FromTempFile(hash_type, type, std::move(file)); + } catch (const std::exception& e) { + return unexpected{fmt::format( + "ArtifactBlob::FromTempFile: Got an exception:\n{}", e.what())}; + } catch (...) { + return unexpected<std::string>{ + "ArtifactBlob::FromTempFile: Got an unknown exception."}; + } +} + auto ArtifactBlob::ReadContent() const noexcept -> std::shared_ptr<std::string const> { using Result = std::shared_ptr<std::string const>; static constexpr InPlaceVisitor kVisitor{ [](InMemory const& value) -> Result { return value; }, [](InFile const& value) -> Result { return ::ReadFromFile(value); }, + [](InTempFile const& value) -> Result { + return ::ReadFromFile(value->GetPath()); + }, }; try { return std::visit(kVisitor, content_); @@ -119,6 +186,9 @@ auto ArtifactBlob::ReadIncrementally(std::size_t chunk_size) const& noexcept [chunk_size](InFile const& value) -> Result { return IncrementalReader::FromFile(chunk_size, value); }, + [chunk_size](InTempFile const& value) -> Result { + return IncrementalReader::FromFile(chunk_size, value->GetPath()); + }, }; try { return std::visit(visitor, content_); diff --git a/src/buildtool/common/artifact_blob.hpp b/src/buildtool/common/artifact_blob.hpp index 092dd2b1..1e54f71b 100644 --- a/src/buildtool/common/artifact_blob.hpp +++ b/src/buildtool/common/artifact_blob.hpp @@ -28,6 +28,7 @@ #include "src/buildtool/file_system/object_type.hpp" #include "src/utils/cpp/expected.hpp" #include "src/utils/cpp/incremental_reader.hpp" +#include "src/utils/cpp/tmp_dir.hpp" class ArtifactBlob final { public: @@ -54,6 +55,33 @@ class ArtifactBlob final { std::filesystem::path file) noexcept -> expected<ArtifactBlob, std::string>; + /// \brief Create ArtifactBlob based on the existing temporary file. The + /// content is hashed based on the given hash function and ObjectType. + /// \param hash_function HashFunction that must be used for hashing. + /// \param type Type of the content. + /// \param file Temporary file to be used as the source of + /// content. + /// \return Valid ArtifactBlob on success or an error message on failure. + [[nodiscard]] static auto FromTempFile(HashFunction hash_function, + ObjectType type, + TmpFile::Ptr file) noexcept + -> expected<ArtifactBlob, std::string>; + + /// \brief Create ArtifactBlob and write the given content to the temporary + /// space. The content is hashed based on the given hash function and + /// ObjectType. + /// \param hash_function HashFunction that must be used for hashing. + /// \param type Type of the content. + /// \param temp_space Temporary space where a new temporary file may + /// be created. + /// \param content Content to be stored in the temporary file. + /// \return Valid ArtifactBlob on success or an error message on failure. + [[nodiscard]] static auto FromTempFile(HashFunction hash_type, + ObjectType type, + TmpDir::Ptr const& temp_space, + std::string const& content) noexcept + -> expected<ArtifactBlob, std::string>; + [[nodiscard]] auto operator==(ArtifactBlob const& other) const noexcept -> bool { return digest_ == other.digest_ and @@ -96,7 +124,8 @@ class ArtifactBlob final { private: using InMemory = std::shared_ptr<std::string const>; using InFile = std::filesystem::path; - using ContentSource = std::variant<InMemory, InFile>; + using InTempFile = TmpFile::Ptr; + using ContentSource = std::variant<InMemory, InFile, InTempFile>; ArtifactDigest digest_; ContentSource content_; |