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
|
// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_GIT_TREE_HPP
#define INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_GIT_TREE_HPP
#include <filesystem>
#include <optional>
#include <unordered_map>
#include "gsl-lite/gsl-lite.hpp"
#include "src/buildtool/file_system/git_repo.hpp"
#include "src/buildtool/file_system/object_type.hpp"
#include "src/buildtool/multithreading/atomic_value.hpp"
#include "src/utils/cpp/hex_string.hpp"
class GitTreeEntry;
using GitTreeEntryPtr = std::shared_ptr<GitTreeEntry const>;
class GitTree {
friend class GitTreeEntry;
public:
using entries_t =
std::unordered_map<std::string, gsl::not_null<GitTreeEntryPtr>>;
/// \brief Read tree with given id from Git repository.
/// \param repo_path Path to the Git repository.
/// \param tree_id Tree id as as hex string.
[[nodiscard]] static auto Read(std::filesystem::path const& repo_path,
std::string const& tree_id) noexcept
-> std::optional<GitTree>;
/// \brief Read tree with given id from CAS.
/// \param cas Git CAS that contains the tree id.
/// \param tree_id Tree id as as hex string.
[[nodiscard]] static auto Read(gsl::not_null<GitCASPtr> const& cas,
std::string const& tree_id) noexcept
-> std::optional<GitTree>;
/// \brief Lookup by dir entry name. '.' and '..' are not allowed.
[[nodiscard]] auto LookupEntryByName(std::string const& name) const noexcept
-> GitTreeEntryPtr;
/// \brief Lookup by relative path. '.' is not allowed.
[[nodiscard]] auto LookupEntryByPath(
std::filesystem::path const& path) const noexcept -> GitTreeEntryPtr;
[[nodiscard]] auto begin() const noexcept { return entries_.begin(); }
[[nodiscard]] auto end() const noexcept { return entries_.end(); }
[[nodiscard]] auto Hash() const noexcept { return ToHexString(raw_id_); }
[[nodiscard]] auto RawHash() const noexcept { return raw_id_; }
[[nodiscard]] auto Size() const noexcept -> std::optional<std::size_t>;
[[nodiscard]] auto RawData() const noexcept -> std::optional<std::string>;
private:
gsl::not_null<GitCASPtr> cas_;
entries_t entries_;
std::string raw_id_;
GitTree(gsl::not_null<GitCASPtr> cas,
entries_t&& entries,
std::string raw_id) noexcept
: cas_{std::move(cas)},
entries_{std::move(entries)},
raw_id_{std::move(raw_id)} {}
[[nodiscard]] static auto FromEntries(gsl::not_null<GitCASPtr> cas,
GitRepo::tree_entries_t&& entries,
std::string raw_id) noexcept
-> std::optional<GitTree> {
entries_t e{};
e.reserve(entries.size());
for (auto& [id, es] : entries) {
for (auto& entry : es) {
try {
e.emplace(
std::move(entry.name),
std::make_shared<GitTreeEntry>(cas, id, entry.type));
} catch (...) {
return std::nullopt;
}
}
}
return GitTree(std::move(cas), std::move(e), std::move(raw_id));
}
};
class GitTreeEntry {
public:
GitTreeEntry(gsl::not_null<GitCASPtr> cas,
std::string raw_id,
ObjectType type) noexcept
: cas_{std::move(cas)}, raw_id_{std::move(raw_id)}, type_{type} {}
[[nodiscard]] auto IsBlob() const noexcept { return IsFileObject(type_); }
[[nodiscard]] auto IsTree() const noexcept { return IsTreeObject(type_); }
[[nodiscard]] auto Blob() const noexcept -> std::optional<std::string>;
[[nodiscard]] auto Tree() && = delete;
[[nodiscard]] auto Tree() const& noexcept -> std::optional<GitTree> const&;
[[nodiscard]] auto Hash() const noexcept { return ToHexString(raw_id_); }
[[nodiscard]] auto Type() const noexcept { return type_; }
// Use with care. Implementation might read entire object to obtain
// size. Consider using Blob()->size() instead.
[[nodiscard]] auto Size() const noexcept -> std::optional<std::size_t>;
[[nodiscard]] auto RawData() const noexcept -> std::optional<std::string>;
private:
gsl::not_null<GitCASPtr> cas_;
std::string raw_id_;
ObjectType type_;
AtomicValue<std::optional<GitTree>> tree_cached_{};
};
using GitTreePtr = std::shared_ptr<GitTree const>;
#endif // INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_GIT_TREE_HPP
|