diff options
Diffstat (limited to 'src/buildtool/serve_api/serve_service/source_tree.cpp')
-rw-r--r-- | src/buildtool/serve_api/serve_service/source_tree.cpp | 94 |
1 files changed, 57 insertions, 37 deletions
diff --git a/src/buildtool/serve_api/serve_service/source_tree.cpp b/src/buildtool/serve_api/serve_service/source_tree.cpp index d2ba33f6..acc29ba9 100644 --- a/src/buildtool/serve_api/serve_service/source_tree.cpp +++ b/src/buildtool/serve_api/serve_service/source_tree.cpp @@ -23,6 +23,7 @@ #include "fmt/core.h" #include "src/buildtool/common/artifact.hpp" #include "src/buildtool/common/artifact_digest.hpp" +#include "src/buildtool/common/artifact_digest_factory.hpp" #include "src/buildtool/compatibility/compatibility.hpp" #include "src/buildtool/crypto/hash_function.hpp" #include "src/buildtool/execution_api/git/git_api.hpp" @@ -34,6 +35,7 @@ #include "src/buildtool/storage/garbage_collector.hpp" #include "src/buildtool/storage/repository_garbage_collector.hpp" #include "src/utils/archive/archive_ops.hpp" +#include "src/utils/cpp/expected.hpp" namespace { @@ -294,17 +296,25 @@ auto SourceTreeService::SyncGitEntryToCas( return TResponse::SYNC_ERROR; } - auto digest = ArtifactDigest{object_hash, 0, IsTreeObject(kType)}; auto repo = RepositoryConfig{}; if (not repo.SetGitCAS(repo_path)) { logger_->Emit( LogLevel::Error, "Failed to SetGitCAS at {}", repo_path.string()); return TResponse::INTERNAL_ERROR; } + auto const digest = + ArtifactDigestFactory::Create(storage_config_.hash_function.GetType(), + object_hash, + 0, + IsTreeObject(kType)); + if (not digest) { + logger_->Emit(LogLevel::Error, "{}", digest.error()); + return TResponse::INTERNAL_ERROR; + } auto git_api = GitApi{&repo}; if (not git_api.RetrieveToCas( - {Artifact::ObjectInfo{.digest = digest, .type = kType}}, + {Artifact::ObjectInfo{.digest = *digest, .type = kType}}, *apis_.remote)) { logger_->Emit(LogLevel::Error, "Failed to sync object {} from repository {}", @@ -754,9 +764,11 @@ auto SourceTreeService::ServeArchiveTree( return ::grpc::Status::OK; } // check if content is in local CAS already - auto digest = ArtifactDigest(content, 0, false); + auto const digest = ArtifactDigestFactory::Create( + storage_config_.hash_function.GetType(), content, 0, /*is_tree=*/false); auto const& cas = storage_.CAS(); - auto content_cas_path = cas.BlobPath(digest, /*is_executable=*/false); + auto content_cas_path = + digest ? cas.BlobPath(*digest, /*is_executable=*/false) : std::nullopt; if (not content_cas_path) { // check if content blob is in Git cache auto res = GetBlobFromRepo(storage_config_.GitRoot(), content, logger_); @@ -796,11 +808,11 @@ auto SourceTreeService::ServeArchiveTree( } } } - if (not content_cas_path) { + if (digest and not content_cas_path) { // try to retrieve it from remote CAS - if (not(apis_.remote->IsAvailable(digest) and + if (not(apis_.remote->IsAvailable(*digest) and apis_.remote->RetrieveToCas( - {Artifact::ObjectInfo{.digest = digest, + {Artifact::ObjectInfo{.digest = *digest, .type = ObjectType::File}}, *apis_.local))) { // content could not be found @@ -808,7 +820,7 @@ auto SourceTreeService::ServeArchiveTree( return ::grpc::Status::OK; } // content should now be in CAS - content_cas_path = cas.BlobPath(digest, /*is_executable=*/false); + content_cas_path = cas.BlobPath(*digest, /*is_executable=*/false); if (not content_cas_path) { logger_->Emit(LogLevel::Error, "Retrieving content {} from CAS failed unexpectedly", @@ -879,9 +891,15 @@ auto SourceTreeService::DistdirImportToGit( 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); + auto const digest = ArtifactDigestFactory::Create( + cas.GetHashFunction().GetType(), + kv.second.first, + 0, + /*is_tree=*/false); + if (not digest) { + return false; + } + auto content_path = cas.BlobPath(*digest, kv.second.second); if (content_path) { return FileSystemManager::CreateFileHardlink( *content_path, // from: cas_path/content_id @@ -960,10 +978,14 @@ auto SourceTreeService::ServeDistdirTree( // check content blob is known // first check the local CAS itself, provided it uses the same type // of identifier + auto const digest = ArtifactDigestFactory::Create( + storage_config_.hash_function.GetType(), + content, + 0, + /*is_tree=*/false); + if (not Compatibility::IsCompatible()) { - auto digest = ArtifactDigest(content, 0, /*is_tree=*/false); - blob_found = - static_cast<bool>(cas.BlobPath(digest, kv.executable())); + blob_found = digest and cas.BlobPath(*digest, kv.executable()); } if (blob_found) { blob_digest = content; @@ -1031,19 +1053,13 @@ auto SourceTreeService::ServeDistdirTree( } } if (not blob_found) { - // Explanation: clang-tidy gets confused by the break in the - // for-loop above into falsely believing that it can reach - // this point with the variable "digest" already moved, so - // we work around this by creating a new variable here - auto digest_clone = - ArtifactDigest(content, 0, /*is_tree=*/false); // check remote CAS - if ((not Compatibility::IsCompatible()) and - apis_.remote->IsAvailable(digest_clone)) { + if (not Compatibility::IsCompatible() and digest and + apis_.remote->IsAvailable(*digest)) { // retrieve content to local CAS if (not apis_.remote->RetrieveToCas( {Artifact::ObjectInfo{ - .digest = digest_clone, + .digest = *digest, .type = kv.executable() ? ObjectType::Executable : ObjectType::File}}, @@ -1221,10 +1237,11 @@ auto SourceTreeService::ServeContent( } // check also in the local CAS - auto const digest = ArtifactDigest{content, 0, /*is_tree=*/false}; - if (apis_.local->IsAvailable(digest)) { + auto const digest = ArtifactDigestFactory::Create( + storage_config_.hash_function.GetType(), content, 0, /*is_tree=*/false); + if (digest and apis_.local->IsAvailable(*digest)) { if (not apis_.local->RetrieveToCas( - {Artifact::ObjectInfo{.digest = digest, + {Artifact::ObjectInfo{.digest = *digest, .type = ObjectType::File}}, *apis_.remote)) { logger_->Emit(LogLevel::Error, @@ -1299,8 +1316,9 @@ auto SourceTreeService::ServeTree( } } // check also in the local CAS - auto digest = ArtifactDigest{tree_id, 0, /*is_tree=*/true}; - if (apis_.local->IsAvailable(digest)) { + auto const digest = ArtifactDigestFactory::Create( + storage_config_.hash_function.GetType(), tree_id, 0, /*is_tree=*/true); + if (digest and apis_.local->IsAvailable(*digest)) { // upload tree to remote CAS; only possible in native mode if (Compatibility::IsCompatible()) { logger_->Emit(LogLevel::Error, @@ -1311,7 +1329,7 @@ auto SourceTreeService::ServeTree( return ::grpc::Status::OK; } if (not apis_.local->RetrieveToCas( - {Artifact::ObjectInfo{.digest = digest, + {Artifact::ObjectInfo{.digest = *digest, .type = ObjectType::Tree}}, *apis_.remote)) { logger_->Emit(LogLevel::Error, @@ -1381,8 +1399,9 @@ auto SourceTreeService::CheckRootTree( } } // now check in the local CAS - auto digest = ArtifactDigest{tree_id, 0, /*is_tree=*/true}; - if (auto path = storage_.CAS().TreePath(digest)) { + auto const digest = ArtifactDigestFactory::Create( + storage_config_.hash_function.GetType(), tree_id, 0, /*is_tree=*/true); + if (digest and storage_.CAS().TreePath(*digest)) { // As we currently build only against roots in Git repositories, we need // to move the tree from CAS to local Git storage auto tmp_dir = @@ -1391,12 +1410,12 @@ auto SourceTreeService::CheckRootTree( logger_->Emit(LogLevel::Error, "Failed to create tmp directory for copying git-tree " "{} from remote CAS", - digest.hash()); + digest->hash()); response->set_status(CheckRootTreeResponse::INTERNAL_ERROR); return ::grpc::Status::OK; } if (not apis_.local->RetrieveToPaths( - {Artifact::ObjectInfo{.digest = digest, + {Artifact::ObjectInfo{.digest = *digest, .type = ObjectType::Tree}}, {tmp_dir->GetPath()})) { logger_->Emit(LogLevel::Error, @@ -1451,8 +1470,9 @@ auto SourceTreeService::GetRemoteTree( } // get tree from remote CAS into tmp dir - auto digest = ArtifactDigest{tree_id, 0, /*is_tree=*/true}; - if (not apis_.remote->IsAvailable(digest)) { + auto const digest = ArtifactDigestFactory::Create( + storage_config_.hash_function.GetType(), tree_id, 0, /*is_tree=*/true); + if (not digest or not apis_.remote->IsAvailable(*digest)) { logger_->Emit(LogLevel::Error, "Remote CAS does not contain expected tree {}", tree_id); @@ -1465,12 +1485,12 @@ auto SourceTreeService::GetRemoteTree( logger_->Emit(LogLevel::Error, "Failed to create tmp directory for copying git-tree {} " "from remote CAS", - digest.hash()); + digest->hash()); response->set_status(GetRemoteTreeResponse::INTERNAL_ERROR); return ::grpc::Status::OK; } if (not apis_.remote->RetrieveToPaths( - {Artifact::ObjectInfo{.digest = digest, .type = ObjectType::Tree}}, + {Artifact::ObjectInfo{.digest = *digest, .type = ObjectType::Tree}}, {tmp_dir->GetPath()}, &(*apis_.local))) { logger_->Emit(LogLevel::Error, |