diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/file_system/file_root.hpp | 112 | ||||
-rw-r--r-- | src/buildtool/main/TARGETS | 1 | ||||
-rw-r--r-- | src/buildtool/main/main.cpp | 142 |
3 files changed, 139 insertions, 116 deletions
diff --git a/src/buildtool/file_system/file_root.hpp b/src/buildtool/file_system/file_root.hpp index 4d71fe23..4c6b07a3 100644 --- a/src/buildtool/file_system/file_root.hpp +++ b/src/buildtool/file_system/file_root.hpp @@ -611,6 +611,118 @@ class FileRoot { return std::nullopt; } + /// \brief Parses a FileRoot from string. On errors, populates error_msg. + /// \returns the FileRoot and optional local path (if the root is local), + /// nullopt on errors. + [[nodiscard]] static auto ParseRoot(std::string const& repo, + std::string const& keyword, + nlohmann::json const& root, + gsl::not_null<std::string*> error_msg) + -> std::optional< + std::pair<FileRoot, std::optional<std::filesystem::path>>> { + if ((not root.is_array()) or root.empty()) { + *error_msg = fmt::format( + "Expected {} for {} to be of the form [<scheme>, ...], but " + "found {}", + keyword, + repo, + root.dump()); + return std::nullopt; + } + if (root[0] == "file") { + if (root.size() != 2 or (not root[1].is_string())) { + *error_msg = fmt::format( + "\"file\" scheme expects precisely one string argument, " + "but found {} for {} of repository {}", + root.dump(), + keyword, + repo); + return std::nullopt; + } + auto path = std::filesystem::path{root[1].get<std::string>()}; + return std::pair(FileRoot{path}, std::move(path)); + } + if (root[0] == FileRoot::kGitTreeMarker) { + if (not(root.size() == 3 and root[1].is_string() and + root[2].is_string()) and + not(root.size() == 2 and root[1].is_string())) { + *error_msg = fmt::format( + "\"git tree\" scheme expects one or two string " + "arguments, but found {} for {} of repository {}", + root.dump(), + keyword, + repo); + return std::nullopt; + } + if (root.size() == 3) { + if (auto git_root = FileRoot::FromGit(root[2], root[1])) { + return std::pair(std::move(*git_root), std::nullopt); + } + *error_msg = fmt::format( + "Could not create file root for {}tree id {}", + root.size() == 3 + ? fmt::format("git repository {} and ", root[2]) + : "", + root[1]); + return std::nullopt; + } + // return absent root + return std::pair(FileRoot{std::string{root[1]}}, std::nullopt); + } + if (root[0] == FileRoot::kFileIgnoreSpecialMarker) { + if (root.size() != 2 or (not root[1].is_string())) { + *error_msg = fmt::format( + "\"file ignore-special\" scheme expects precisely " + "one string " + "argument, but found {} for {} of repository {}", + root.dump(), + keyword, + repo); + return std::nullopt; + } + auto path = std::filesystem::path{root[1].get<std::string>()}; + return std::pair(FileRoot{path, /*ignore_special=*/true}, + std::move(path)); + } + if (root[0] == FileRoot::kGitTreeIgnoreSpecialMarker) { + if (not(root.size() == 3 and root[1].is_string() and + root[2].is_string()) and + not(root.size() == 2 and root[1].is_string())) { + *error_msg = fmt::format( + "\"git tree ignore-special\" scheme expects one or two " + "string arguments, but found {} for {} of repository {}", + root.dump(), + keyword, + repo); + return std::nullopt; + } + if (root.size() == 3) { + if (auto git_root = FileRoot::FromGit( + root[2], root[1], /*ignore_special=*/true)) { + return std::pair(std::move(*git_root), std::nullopt); + } + *error_msg = fmt::format( + "Could not create ignore-special file root for {}tree id " + "{}", + root.size() == 3 + ? fmt::format("git repository {} and ", root[2]) + : "", + root[1]); + return std::nullopt; + } + // return absent root + return std::pair( + FileRoot{std::string{root[1]}, /*ignore_special=*/true}, + std::nullopt); + } + *error_msg = fmt::format( + "Unknown scheme in the specification {} of {} of repository {}", + root.dump(), + keyword, + repo); + return std::nullopt; + } + private: root_t root_; // If set, forces lookups to ignore entries which are neither file nor diff --git a/src/buildtool/main/TARGETS b/src/buildtool/main/TARGETS index d8eedaf2..d1c5ba08 100644 --- a/src/buildtool/main/TARGETS +++ b/src/buildtool/main/TARGETS @@ -22,6 +22,7 @@ , ["src/buildtool/execution_api/execution_service", "operation_cache"] , ["src/buildtool/execution_api/local", "config"] , ["src/buildtool/execution_api/remote", "config"] + , ["src/buildtool/file_system", "file_root"] , ["src/buildtool/serve_api/remote", "config"] , ["src/buildtool/serve_api/serve_service", "serve_server_implementation"] , "common" diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp index 7839e510..97acb90b 100644 --- a/src/buildtool/main/main.cpp +++ b/src/buildtool/main/main.cpp @@ -29,6 +29,7 @@ #include "src/buildtool/common/repository_config.hpp" #include "src/buildtool/compatibility/compatibility.hpp" #include "src/buildtool/execution_api/local/config.hpp" +#include "src/buildtool/file_system/file_root.hpp" #include "src/buildtool/main/analyse.hpp" #include "src/buildtool/main/cli.hpp" #include "src/buildtool/main/constants.hpp" @@ -530,113 +531,6 @@ void SetupHashFunction() { return root / *root_dir; } -// returns FileRoot and optional local path, if the root is local -auto ParseRoot(std::string const& repo, - std::string const& keyword, - nlohmann::json const& root) - -> std::pair<FileRoot, std::optional<std::filesystem::path>> { - if ((not root.is_array()) or root.empty()) { - Logger::Log(LogLevel::Error, - "Expected {} for {} to be of the form [<scheme>, ...], but " - "found {}", - keyword, - repo, - root.dump()); - std::exit(kExitFailure); - } - if (root[0] == "file") { - if (root.size() != 2 or (not root[1].is_string())) { - Logger::Log(LogLevel::Error, - "\"file\" scheme expects precisely one string " - "argument, but found {} for {} of repository {}", - root.dump(), - keyword, - repo); - std::exit(kExitFailure); - } - auto path = std::filesystem::path{root[1].get<std::string>()}; - return {FileRoot{path}, std::move(path)}; - } - if (root[0] == FileRoot::kGitTreeMarker) { - if (not(root.size() == 3 and root[1].is_string() and - root[2].is_string()) and - not(root.size() == 2 and root[1].is_string())) { - Logger::Log(LogLevel::Error, - "\"git tree\" scheme expects one or two string " - "arguments, but found {} for {} of repository {}", - root.dump(), - keyword, - repo); - std::exit(kExitFailure); - } - if (root.size() == 3) { - if (auto git_root = FileRoot::FromGit(root[2], root[1])) { - return {std::move(*git_root), std::nullopt}; - } - Logger::Log(LogLevel::Error, - "Could not create file root for {}tree id {}", - root.size() == 3 - ? fmt::format("git repository {} and ", root[2]) - : "", - root[1]); - std::exit(kExitFailure); - } - // return absent root - return {FileRoot{std::string{root[1]}}, std::nullopt}; - } - if (root[0] == FileRoot::kFileIgnoreSpecialMarker) { - if (root.size() != 2 or (not root[1].is_string())) { - Logger::Log( - LogLevel::Error, - "\"file ignore-special\" scheme expects precisely one string " - "argument, but found {} for {} of repository {}", - root.dump(), - keyword, - repo); - std::exit(kExitFailure); - } - auto path = std::filesystem::path{root[1].get<std::string>()}; - return {FileRoot{path, /*ignore_special=*/true}, std::move(path)}; - } - if (root[0] == FileRoot::kGitTreeIgnoreSpecialMarker) { - if (not(root.size() == 3 and root[1].is_string() and - root[2].is_string()) and - not(root.size() == 2 and root[1].is_string())) { - Logger::Log( - LogLevel::Error, - "\"git tree ignore-special\" scheme expects one or two string " - "arguments, but found {} for {} of repository {}", - root.dump(), - keyword, - repo); - std::exit(kExitFailure); - } - if (root.size() == 3) { - if (auto git_root = FileRoot::FromGit( - root[2], root[1], /*ignore_special=*/true)) { - return {std::move(*git_root), std::nullopt}; - } - Logger::Log( - LogLevel::Error, - "Could not create ignore-special file root for {}tree id {}", - root.size() == 3 - ? fmt::format("git repository {} and ", root[2]) - : "", - root[1]); - std::exit(kExitFailure); - } - // return absent root - return {FileRoot{std::string{root[1]}, /*ignore_special=*/true}, - std::nullopt}; - } - Logger::Log(LogLevel::Error, - "Unknown scheme in the specification {} of {} of repository {}", - root.dump(), - keyword, - repo); - std::exit(kExitFailure); -} - // Set all roots and name mappings from the command-line arguments and // return the name of the main repository and main workspace path if local. auto DetermineRoots(gsl::not_null<RepositoryConfig*> const& repository_config, @@ -700,15 +594,22 @@ auto DetermineRoots(gsl::not_null<RepositoryConfig*> const& repository_config, repos[main_repo] = nlohmann::json::object(); } + std::string error_msg; for (auto const& [repo, desc] : repos.items()) { std::optional<FileRoot> ws_root{}; bool const is_main_repo{repo == main_repo}; auto it_ws = desc.find("workspace_root"); if (it_ws != desc.end()) { - auto [root, path] = ParseRoot(repo, "workspace_root", *it_ws); - ws_root = std::move(root); - if (is_main_repo and path.has_value()) { - main_ws_root = std::move(path); + if (auto parsed_root = FileRoot::ParseRoot( + repo, "workspace_root", *it_ws, &error_msg)) { + ws_root = std::move(parsed_root->first); + if (is_main_repo and parsed_root->second.has_value()) { + main_ws_root = std::move(parsed_root->second); + } + } + else { + Logger::Log(LogLevel::Error, error_msg); + std::exit(kExitFailure); } } if (is_main_repo) { @@ -731,13 +632,22 @@ auto DetermineRoots(gsl::not_null<RepositoryConfig*> const& repository_config, std::exit(kExitFailure); } auto info = RepositoryConfig::RepositoryInfo{std::move(*ws_root)}; - auto parse_keyword_root = [&desc = desc, &repo = repo, is_main_repo]( - FileRoot* keyword_root, - std::string const& keyword, - auto const& keyword_carg) { + auto parse_keyword_root = [&desc = desc, + &repo = repo, + &error_msg = error_msg, + is_main_repo](FileRoot* keyword_root, + std::string const& keyword, + auto const& keyword_carg) { auto it = desc.find(keyword); if (it != desc.end()) { - (*keyword_root) = ParseRoot(repo, keyword, *it).first; + if (auto parsed_root = + FileRoot::ParseRoot(repo, keyword, *it, &error_msg)) { + (*keyword_root) = parsed_root->first; + } + else { + Logger::Log(LogLevel::Error, error_msg); + std::exit(kExitFailure); + } } if (is_main_repo && keyword_carg) { |