summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/file_system/file_root.hpp112
-rw-r--r--src/buildtool/main/TARGETS1
-rw-r--r--src/buildtool/main/main.cpp142
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) {