summaryrefslogtreecommitdiff
path: root/src/buildtool/tree_structure/tree_structure_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildtool/tree_structure/tree_structure_utils.cpp')
-rw-r--r--src/buildtool/tree_structure/tree_structure_utils.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/buildtool/tree_structure/tree_structure_utils.cpp b/src/buildtool/tree_structure/tree_structure_utils.cpp
index b607cb9f..7cc04b6f 100644
--- a/src/buildtool/tree_structure/tree_structure_utils.cpp
+++ b/src/buildtool/tree_structure/tree_structure_utils.cpp
@@ -15,6 +15,7 @@
#include "src/buildtool/tree_structure/tree_structure_utils.hpp"
#include <algorithm>
+#include <cstddef>
#include <filesystem>
#include <functional>
#include <memory>
@@ -27,7 +28,9 @@
#include "src/buildtool/common/artifact.hpp"
#include "src/buildtool/common/artifact_digest_factory.hpp"
#include "src/buildtool/common/protocol_traits.hpp"
+#include "src/buildtool/common/repository_config.hpp"
#include "src/buildtool/crypto/hash_function.hpp"
+#include "src/buildtool/execution_api/git/git_api.hpp"
#include "src/buildtool/file_system/file_system_manager.hpp"
#include "src/buildtool/file_system/git_repo.hpp"
#include "src/buildtool/file_system/object_type.hpp"
@@ -198,3 +201,38 @@ auto TreeStructureUtils::ImportToGit(
}
return *digest;
}
+
+auto TreeStructureUtils::ExportFromGit(
+ ArtifactDigest const& tree,
+ std::vector<std::filesystem::path> const& source_repos,
+ IExecutionApi const& target_api) noexcept -> expected<bool, std::string> {
+ if (not tree.IsTree() or not ProtocolTraits::IsNative(tree.GetHashType())) {
+ return unexpected{fmt::format("Not a git tree: {}", tree.hash())};
+ }
+
+ // Find git repo that contains the tree:
+ std::filesystem::path const* repo = nullptr;
+ for (std::size_t i = 0; i < source_repos.size() and repo == nullptr; ++i) {
+ auto in_repo = GitRepo::IsTreeInRepo(source_repos[i], tree.hash());
+ if (not in_repo.has_value()) {
+ return unexpected{std::move(in_repo).error()};
+ }
+ if (*in_repo) {
+ repo = &source_repos[i];
+ }
+ }
+
+ // Check that at least one repo contains the tree:
+ if (repo == nullptr) {
+ return false;
+ }
+
+ RepositoryConfig repo_config{};
+ if (not repo_config.SetGitCAS(*repo)) {
+ return unexpected{
+ fmt::format("Failed to set git cas at {}", repo->string())};
+ }
+ auto const git_api = GitApi{&repo_config};
+ return git_api.RetrieveToCas({Artifact::ObjectInfo{tree, ObjectType::Tree}},
+ target_api);
+}