summaryrefslogtreecommitdiff
path: root/src/buildtool/common/repository_config.hpp
blob: 62c2c4ffc72c0277391384871e47d12cd76495bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifndef INCLUDED_SRC_BUILDTOOL_COMMON_REPOSITORY_CONFIG_HPP
#define INCLUDED_SRC_BUILDTOOL_COMMON_REPOSITORY_CONFIG_HPP

#include <filesystem>
#include <string>
#include <unordered_map>

#include "src/buildtool/file_system/file_root.hpp"
#include "src/buildtool/file_system/git_cas.hpp"

class RepositoryConfig {
  public:
    struct RepositoryInfo {
        FileRoot workspace_root;
        FileRoot target_root{workspace_root};
        FileRoot rule_root{target_root};
        FileRoot expression_root{rule_root};
        std::unordered_map<std::string, std::string> name_mapping{};
        std::string target_file_name{"TARGETS"};
        std::string rule_file_name{"RULES"};
        std::string expression_file_name{"EXPRESSIONS"};
    };

    [[nodiscard]] static auto Instance() noexcept -> RepositoryConfig& {
        static RepositoryConfig instance{};
        return instance;
    }

    void SetInfo(std::string const& repo, RepositoryInfo&& info) {
        infos_.emplace(repo, std::move(info));
    }

    [[nodiscard]] auto SetGitCAS(
        std::filesystem::path const& repo_path) noexcept {
        git_cas_ = GitCAS::Open(repo_path);
        return static_cast<bool>(git_cas_);
    }

    [[nodiscard]] auto Info(std::string const& repo) const noexcept
        -> RepositoryInfo const* {
        auto it = infos_.find(repo);
        if (it != infos_.end()) {
            return &it->second;
        }
        return nullptr;
    }

    [[nodiscard]] auto ReadBlobFromGitCAS(std::string const& hex_id)
        const noexcept -> std::optional<std::string> {
        return git_cas_ ? git_cas_->ReadObject(hex_id, /*is_hex_id=*/true)
                        : std::nullopt;
    }

    [[nodiscard]] auto WorkspaceRoot(std::string const& repo) const noexcept
        -> FileRoot const* {
        return Get<FileRoot>(
            repo, [](auto const& info) { return &info.workspace_root; });
    }

    [[nodiscard]] auto TargetRoot(std::string const& repo) const noexcept
        -> FileRoot const* {
        return Get<FileRoot>(
            repo, [](auto const& info) { return &info.target_root; });
    }

    [[nodiscard]] auto RuleRoot(std::string const& repo) const
        -> FileRoot const* {
        return Get<FileRoot>(repo,
                             [](auto const& info) { return &info.rule_root; });
    }

    [[nodiscard]] auto ExpressionRoot(std::string const& repo) const noexcept
        -> FileRoot const* {
        return Get<FileRoot>(
            repo, [](auto const& info) { return &info.expression_root; });
    }

    [[nodiscard]] auto GlobalName(std::string const& repo,
                                  std::string const& local_name) const noexcept
        -> std::string const* {
        return Get<std::string>(
            repo, [&local_name](auto const& info) -> std::string const* {
                auto it = info.name_mapping.find(local_name);
                if (it != info.name_mapping.end()) {
                    return &it->second;
                }
                return nullptr;
            });
    }

    [[nodiscard]] auto TargetFileName(std::string const& repo) const noexcept
        -> std::string const* {
        return Get<std::string>(
            repo, [](auto const& info) { return &info.target_file_name; });
    }

    [[nodiscard]] auto RuleFileName(std::string const& repo) const noexcept
        -> std::string const* {
        return Get<std::string>(
            repo, [](auto const& info) { return &info.rule_file_name; });
    }

    [[nodiscard]] auto ExpressionFileName(
        std::string const& repo) const noexcept -> std::string const* {
        return Get<std::string>(
            repo, [](auto const& info) { return &info.expression_file_name; });
    }

    // used for testing
    void Reset() {
        infos_.clear();
        git_cas_.reset();
    }

  private:
    std::unordered_map<std::string, RepositoryInfo> infos_;
    GitCASPtr git_cas_;

    template <class T>
    [[nodiscard]] auto Get(std::string const& repo,
                           std::function<T const*(RepositoryInfo const&)> const&
                               getter) const noexcept -> T const* {
        if (auto const* info = Info(repo)) {
            try {  // satisfy clang-tidy's bugprone-exception-escape
                return getter(*info);
            } catch (...) {
            }
        }
        return nullptr;
    }
};

#endif  // INCLUDED_SRC_BUILDTOOL_COMMON_REPOSITORY_CONFIG_HPP