summaryrefslogtreecommitdiff
path: root/src/buildtool/main/install_cas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildtool/main/install_cas.cpp')
-rw-r--r--src/buildtool/main/install_cas.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/buildtool/main/install_cas.cpp b/src/buildtool/main/install_cas.cpp
index cdeca553..1c0290df 100644
--- a/src/buildtool/main/install_cas.cpp
+++ b/src/buildtool/main/install_cas.cpp
@@ -16,6 +16,9 @@
#include "src/buildtool/compatibility/compatibility.hpp"
#include "src/buildtool/crypto/hash_function.hpp"
+#ifndef BOOTSTRAP_BUILD_TOOL
+#include "src/buildtool/execution_api/bazel_msg/bazel_msg_factory.hpp"
+#endif
#include "src/buildtool/execution_api/remote/config.hpp"
namespace {
@@ -76,6 +79,101 @@ auto FetchAndInstallArtifacts(
}
}
+ if (clargs.sub_path) {
+ std::filesystem::path sofar{};
+ for (auto const& segment : *clargs.sub_path) {
+ if (object_info.type != ObjectType::Tree) {
+ Logger::Log(
+ LogLevel::Warning,
+ "Non-tree found at path '{}', cannot follow to '{}'",
+ sofar.string(),
+ segment.string());
+ break;
+ }
+ auto data = api->RetrieveToMemory(object_info);
+ if (not data) {
+ Logger::Log(LogLevel::Error,
+ "Failed to retrieve artifact {} at path '{}'",
+ object_info.ToString(),
+ sofar.string());
+ return false;
+ }
+ if (Compatibility::IsCompatible()) {
+ auto directory =
+ BazelMsgFactory::MessageFromString<bazel_re::Directory>(
+ *data);
+ if (not directory) {
+ Logger::Log(
+ LogLevel::Warning,
+ "Failed to parse directory message at path '{}'",
+ sofar.string());
+ break;
+ }
+ std::optional<Artifact::ObjectInfo> new_object_info{};
+ if (not BazelMsgFactory::ReadObjectInfosFromDirectory(
+ *directory,
+ [&new_object_info, &segment](auto path, auto info) {
+ if (path == segment) {
+ new_object_info = info;
+ }
+ return true;
+ })) {
+ Logger::Log(
+ LogLevel::Warning,
+ "Failed to process directory message at path '{}'",
+ sofar.string());
+ break;
+ }
+ if (not new_object_info) {
+ Logger::Log(LogLevel::Warning,
+ "Entry {} not found at path '{}'",
+ segment.string(),
+ sofar.string());
+ break;
+ }
+ object_info = *new_object_info;
+ }
+ else {
+ auto entries = GitRepo::ReadTreeData(
+ *data,
+ HashFunction::ComputeTreeHash(*data).Bytes(),
+ [](auto const& /*unused*/) { return true; },
+ /*is_hex_id=*/false);
+ if (not entries) {
+ Logger::Log(LogLevel::Warning,
+ "Failed to parse tree {} at path '{}'",
+ object_info.ToString(),
+ sofar.string());
+ break;
+ }
+ std::optional<Artifact::ObjectInfo> new_object_info{};
+ if (not BazelMsgFactory::ReadObjectInfosFromGitTree(
+ *entries,
+ [&new_object_info, &segment](auto path, auto info) {
+ if (path == segment) {
+ new_object_info = info;
+ }
+ return true;
+ })) {
+ Logger::Log(LogLevel::Warning,
+ "Failed to process tree entries at path '{}'",
+ sofar.string());
+ break;
+ }
+
+ if (not new_object_info) {
+ Logger::Log(LogLevel::Warning,
+ "Entry {} not found at path '{}'",
+ segment.string(),
+ sofar.string());
+ break;
+ }
+ object_info = *new_object_info;
+ }
+ sofar /= segment;
+ }
+ }
+
if (clargs.output_path) {
auto output_path = (*clargs.output_path / "").parent_path();
if (FileSystemManager::IsDirectory(output_path)) {