diff options
author | Oliver Reiche <oliver.reiche@huawei.com> | 2025-06-23 14:56:04 +0200 |
---|---|---|
committer | Oliver Reiche <oliver.reiche@huawei.com> | 2025-06-24 14:56:58 +0200 |
commit | bbcc5977f49646941ac35060bb74a27eda5fbd76 (patch) | |
tree | 4e11ded4722ea740fbeea12510efd34fe698c04b /src/buildtool/execution_api/local/local_action.cpp | |
parent | c498bf564fa5d781c176f65c7a9a2d43376a81f1 (diff) | |
download | justbuild-bbcc5977f49646941ac35060bb74a27eda5fbd76.tar.gz |
ExecutionAPI: Support output_paths in requests
... and prepare local execution for clients
using only RBEv2.1 (setting only output_paths).
Diffstat (limited to 'src/buildtool/execution_api/local/local_action.cpp')
-rw-r--r-- | src/buildtool/execution_api/local/local_action.cpp | 121 |
1 files changed, 119 insertions, 2 deletions
diff --git a/src/buildtool/execution_api/local/local_action.cpp b/src/buildtool/execution_api/local/local_action.cpp index d9733f18..8050c3d7 100644 --- a/src/buildtool/execution_api/local/local_action.cpp +++ b/src/buildtool/execution_api/local/local_action.cpp @@ -134,8 +134,11 @@ auto LocalAction::Execute(Logger const* logger) noexcept if (auto result = local_context_.storage->ActionCache().CachedResult(*action)) { if (result->exit_code() == 0 and - ActionResultContainsExpectedOutputs( - *result, output_files_, output_dirs_)) { + (mode_ == RequestMode::kV2_1 + ? ActionResultContainsExpectedOutputs(*result, + output_paths_) + : ActionResultContainsExpectedOutputs( + *result, output_files_, output_dirs_))) { return create_response( logger, action->hash(), @@ -376,6 +379,16 @@ auto LocalAction::CreateDirectoryStructure( } return true; }; + + if (mode_ == RequestMode::kV2_1) { + return std::all_of( + output_paths_.begin(), + output_paths_.end(), + [this, &exec_path, &create_dir](auto const& local_path) { + auto dir = (exec_path / cwd_ / local_path).parent_path(); + return create_dir(dir); + }); + } return std::all_of(output_files_.begin(), output_files_.end(), [this, &exec_path, &create_dir](auto const& local_path) { @@ -487,11 +500,109 @@ auto LocalAction::CollectOutputDirOrSymlink( return std::nullopt; } +auto LocalAction::CollectOutputPath( + std::filesystem::path const& exec_path, + std::string const& local_path) const noexcept -> std::optional<OutputPath> { + auto out_path = exec_path / local_path; + auto type = FileSystemManager::Type(out_path, /*allow_upwards=*/true); + if (not type) { + logger_.Emit(LogLevel::Error, "expected known type at {}", local_path); + return std::nullopt; + } + if (IsSymlinkObject(*type)) { + if (auto content = FileSystemManager::ReadSymlink(out_path)) { + // in native mode: check validity of symlink + if (ProtocolTraits::IsNative( + local_context_.storage->GetHashFunction().GetType()) and + not PathIsNonUpwards(*content)) { + logger_.Emit( + LogLevel::Error, "found invalid symlink at {}", local_path); + return std::nullopt; + } + if (local_context_.storage->CAS().StoreBlob(*content)) { + auto out_symlink = bazel_re::OutputSymlink{}; + out_symlink.set_path(local_path); + out_symlink.set_target(*content); + return out_symlink; + } + } + } + else if (IsFileObject(*type)) { + bool is_executable = IsExecutableObject(*type); + auto digest = local_context_.storage->CAS().StoreBlob</*kOwner=*/true>( + out_path, is_executable); + if (digest) { + auto out_file = bazel_re::OutputFile{}; + out_file.set_path(local_path); + *out_file.mutable_digest() = + ArtifactDigestFactory::ToBazel(*digest); + out_file.set_is_executable(is_executable); + return out_file; + } + } + else if (IsTreeObject(*type)) { + if (auto digest = CreateDigestFromLocalOwnedTree( + *local_context_.storage, out_path)) { + auto out_dir = bazel_re::OutputDirectory{}; + out_dir.set_path(local_path); + (*out_dir.mutable_tree_digest()) = + ArtifactDigestFactory::ToBazel(*digest); + return out_dir; + } + logger_.Emit(LogLevel::Error, + "found invalid entries in directory at {}", + local_path); + } + else { + logger_.Emit(LogLevel::Error, + "expected file, directory, or symlink at {}", + local_path); + } + return std::nullopt; +} + auto LocalAction::CollectAndStoreOutputs( bazel_re::ActionResult* result, std::filesystem::path const& exec_path) const noexcept -> bool { try { logger_.Emit(LogLevel::Trace, "collecting outputs:"); + if (mode_ == RequestMode::kV2_1) { + for (auto const& path : output_paths_) { + auto out = CollectOutputPath(exec_path, path); + if (not out) { + logger_.Emit(LogLevel::Error, + "could not collect output path {}", + path); + return false; + } + if (std::holds_alternative<bazel_re::OutputSymlink>(*out)) { + auto out_symlink = std::get<bazel_re::OutputSymlink>(*out); + logger_.Emit(LogLevel::Trace, + " - symlink {}: {}", + path, + out_symlink.target()); + result->mutable_output_symlinks()->Add( + std::move(out_symlink)); + } + else if (std::holds_alternative<bazel_re::OutputFile>(*out)) { + auto out_file = std::get<bazel_re::OutputFile>(*out); + auto const& digest = out_file.digest().hash(); + logger_.Emit( + LogLevel::Trace, " - file {}: {}", path, digest); + result->mutable_output_files()->Add(std::move(out_file)); + } + else { + auto out_dir = std::get<bazel_re::OutputDirectory>(*out); + auto const& digest = out_dir.tree_digest().hash(); + logger_.Emit( + LogLevel::Trace, " - dir {}: {}", path, digest); + result->mutable_output_directories()->Add( + std::move(out_dir)); + } + } + return true; + } + // if mode_ is RequestMode::kV2_0 or RequestMode::kBestEffort for (auto const& path : output_files_) { auto out = CollectOutputFileOrSymlink(exec_path, path); if (not out) { @@ -506,6 +617,9 @@ auto LocalAction::CollectAndStoreOutputs( " - symlink {}: {}", path, out_symlink.target()); + if (mode_ == RequestMode::kBestEffort) { + *result->mutable_output_symlinks()->Add() = out_symlink; + } result->mutable_output_file_symlinks()->Add( std::move(out_symlink)); } @@ -530,6 +644,9 @@ auto LocalAction::CollectAndStoreOutputs( " - symlink {}: {}", path, out_symlink.target()); + if (mode_ == RequestMode::kBestEffort) { + *result->mutable_output_symlinks()->Add() = out_symlink; + } result->mutable_output_directory_symlinks()->Add( std::move(out_symlink)); } |