diff options
Diffstat (limited to 'src/buildtool/file_system/git_tree.hpp')
-rw-r--r-- | src/buildtool/file_system/git_tree.hpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/buildtool/file_system/git_tree.hpp b/src/buildtool/file_system/git_tree.hpp new file mode 100644 index 00000000..57cb3b52 --- /dev/null +++ b/src/buildtool/file_system/git_tree.hpp @@ -0,0 +1,87 @@ +#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_cas.hpp" +#include "src/buildtool/file_system/object_type.hpp" +#include "src/utils/cpp/atomic.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(); } + + private: + gsl::not_null<GitCASPtr> cas_; + entries_t entries_; + + GitTree(gsl::not_null<GitCASPtr> cas, entries_t&& entries) noexcept + : cas_{std::move(cas)}, entries_{std::move(entries)} {} +}; + +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>; + + private: + gsl::not_null<GitCASPtr> cas_; + std::string raw_id_; + ObjectType type_; + mutable atomic_shared_ptr<std::optional<GitTree>> tree_cached_{nullptr}; + mutable std::atomic<bool> tree_loading_{false}; +}; + +using GitTreePtr = std::shared_ptr<GitTree const>; + +#endif // INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_GIT_TREE_HPP |