summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buildtool/common/TARGETS1
-rw-r--r--src/buildtool/common/artifact_blob.cpp70
-rw-r--r--src/buildtool/common/artifact_blob.hpp31
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_;