summaryrefslogtreecommitdiff
path: root/src/other_tools/root_maps/fpath_git_map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/other_tools/root_maps/fpath_git_map.cpp')
-rw-r--r--src/other_tools/root_maps/fpath_git_map.cpp158
1 files changed, 135 insertions, 23 deletions
diff --git a/src/other_tools/root_maps/fpath_git_map.cpp b/src/other_tools/root_maps/fpath_git_map.cpp
index e26b3a9d..f0a12fd4 100644
--- a/src/other_tools/root_maps/fpath_git_map.cpp
+++ b/src/other_tools/root_maps/fpath_git_map.cpp
@@ -16,20 +16,121 @@
#include "src/buildtool/execution_api/local/config.hpp"
#include "src/buildtool/file_system/file_root.hpp"
+#include "src/buildtool/file_system/git_repo.hpp"
#include "src/buildtool/storage/config.hpp"
+#include "src/other_tools/git_operations/git_repo_remote.hpp"
#include "src/utils/cpp/tmp_dir.hpp"
+namespace {
+
+void ResolveFilePathTree(
+
+ std::string const& repo_root,
+ std::string const& target_path,
+ std::string const& tree_hash,
+ std::optional<PragmaSpecial> const& pragma_special,
+ gsl::not_null<ResolveSymlinksMap*> const& resolve_symlinks_map,
+ gsl::not_null<TaskSystem*> const& ts,
+ FilePathGitMap::SetterPtr const& ws_setter,
+ FilePathGitMap::LoggerPtr const& logger) {
+ if (pragma_special) {
+ // get the resolved tree
+ auto tree_id_file =
+ JustMR::Utils::GetResolvedTreeIDFile(tree_hash, *pragma_special);
+ if (FileSystemManager::Exists(tree_id_file)) {
+ // read resolved tree id
+ auto resolved_tree_id = FileSystemManager::ReadFile(tree_id_file);
+ if (not resolved_tree_id) {
+ (*logger)(fmt::format("Failed to read resolved "
+ "tree id from file {}",
+ tree_id_file.string()),
+ /*fatal=*/true);
+ return;
+ }
+ // set the workspace root
+ (*ws_setter)(nlohmann::json::array(
+ {FileRoot::kGitTreeMarker, *resolved_tree_id, repo_root}));
+ }
+ else {
+ // resolve tree
+ resolve_symlinks_map->ConsumeAfterKeysReady(
+ ts,
+ {GitObjectToResolve(tree_hash,
+ ".",
+ *pragma_special,
+ /*known_info=*/std::nullopt)},
+ [resolve_symlinks_map,
+ tree_hash,
+ repo_root,
+ tree_id_file,
+ ws_setter,
+ logger](auto const& hashes) {
+ if (not hashes[0]) {
+ // check for cycles
+ auto error = DetectAndReportCycle(*resolve_symlinks_map,
+ tree_hash);
+ if (error) {
+ (*logger)(fmt::format("Failed to resolve symlinks "
+ "in tree {}:\n{}",
+ tree_hash,
+ *error),
+ /*fatal=*/true);
+ return;
+ }
+ (*logger)(fmt::format("Unknown error in resolving "
+ "symlinks in tree {}",
+ tree_hash),
+ /*fatal=*/true);
+ return;
+ }
+ auto const& resolved_tree = *hashes[0];
+ // cache the resolved tree in the CAS map
+ if (not JustMR::Utils::WriteTreeIDFile(tree_id_file,
+ resolved_tree.id)) {
+ (*logger)(fmt::format("Failed to write resolved tree "
+ "id to file {}",
+ tree_id_file.string()),
+ /*fatal=*/true);
+ return;
+ }
+ // set the workspace root
+ (*ws_setter)(
+ nlohmann::json::array({FileRoot::kGitTreeMarker,
+ resolved_tree.id,
+ repo_root}));
+ },
+ [logger, target_path](auto const& msg, bool fatal) {
+ (*logger)(fmt::format(
+ "While resolving symlinks for target {}:\n{}",
+ target_path,
+ msg),
+ fatal);
+ });
+ }
+ }
+ else {
+ // set the workspace root as-is
+ (*ws_setter)(nlohmann::json::array(
+ {FileRoot::kGitTreeMarker, tree_hash, repo_root}));
+ }
+}
+
+} // namespace
+
auto CreateFilePathGitMap(
std::optional<std::string> const& current_subcmd,
gsl::not_null<CriticalGitOpMap*> const& critical_git_op_map,
gsl::not_null<ImportToGitMap*> const& import_to_git_map,
+ gsl::not_null<ResolveSymlinksMap*> const& resolve_symlinks_map,
std::size_t jobs) -> FilePathGitMap {
- auto dir_to_git = [current_subcmd, critical_git_op_map, import_to_git_map](
- auto ts,
- auto setter,
- auto logger,
- auto /*unused*/,
- auto const& key) {
+ auto dir_to_git = [current_subcmd,
+ critical_git_op_map,
+ import_to_git_map,
+ resolve_symlinks_map](auto ts,
+ auto setter,
+ auto logger,
+ auto /*unused*/,
+ auto const& key) {
// setup wrapped logger
auto wrapped_logger = std::make_shared<AsyncMapConsumerLogger>(
[logger](auto const& msg, bool fatal) {
@@ -75,6 +176,8 @@ auto CreateFilePathGitMap(
pragma_special = key.pragma_special,
git_cas = std::move(git_cas),
repo_root = std::move(*repo_root),
+ resolve_symlinks_map,
+ ts,
setter,
logger](auto const& values) {
GitOpValue op_result = *values[0];
@@ -102,19 +205,21 @@ auto CreateFilePathGitMap(
msg),
fatal);
});
- // get tree id and return workspace root
+ // get tree id
auto tree_hash = git_repo->GetSubtreeFromPath(
fpath, *op_result.result, wrapped_logger);
if (not tree_hash) {
return;
}
- // set the workspace root
- (*setter)(nlohmann::json::array(
- {pragma_special == PragmaSpecial::Ignore
- ? FileRoot::kGitTreeIgnoreSpecialMarker
- : FileRoot::kGitTreeMarker,
- *tree_hash,
- repo_root}));
+ // resolve tree and set workspace root
+ ResolveFilePathTree(repo_root.string(),
+ fpath.string(),
+ *tree_hash,
+ pragma_special,
+ resolve_symlinks_map,
+ ts,
+ setter,
+ logger);
},
[logger, target_path = *repo_root](auto const& msg,
bool fatal) {
@@ -159,8 +264,13 @@ auto CreateFilePathGitMap(
{std::move(c_info)},
// tmp_dir passed, to ensure folder is not removed until import
// to git is done
- [tmp_dir, pragma_special = key.pragma_special, setter, logger](
- auto const& values) {
+ [tmp_dir,
+ fpath = key.fpath,
+ pragma_special = key.pragma_special,
+ resolve_symlinks_map,
+ ts,
+ setter,
+ logger](auto const& values) {
// check for errors
if (not values[0]->second) {
(*logger)("Importing to git failed",
@@ -169,13 +279,15 @@ auto CreateFilePathGitMap(
}
// we only need the tree
std::string tree = values[0]->first;
- // set the workspace root
- (*setter)(nlohmann::json::array(
- {pragma_special == PragmaSpecial::Ignore
- ? FileRoot::kGitTreeIgnoreSpecialMarker
- : FileRoot::kGitTreeMarker,
- tree,
- StorageConfig::GitRoot()}));
+ // resolve tree and set workspace root
+ ResolveFilePathTree(StorageConfig::GitRoot().string(),
+ fpath.string(),
+ tree,
+ pragma_special,
+ resolve_symlinks_map,
+ ts,
+ setter,
+ logger);
},
[logger, target_path = key.fpath](auto const& msg, bool fatal) {
(*logger)(