From c974b1eb4df53dc23bd80dd13ad514d8828dc986 Mon Sep 17 00:00:00 2001 From: Oliver Reiche Date: Mon, 1 Aug 2022 14:30:37 +0200 Subject: GitCAS: Implement reading git tree via libgit2 --- src/buildtool/file_system/git_tree.cpp | 82 +++------------------------------- 1 file changed, 7 insertions(+), 75 deletions(-) (limited to 'src/buildtool/file_system/git_tree.cpp') diff --git a/src/buildtool/file_system/git_tree.cpp b/src/buildtool/file_system/git_tree.cpp index f4912a7b..8d220e30 100644 --- a/src/buildtool/file_system/git_tree.cpp +++ b/src/buildtool/file_system/git_tree.cpp @@ -11,64 +11,6 @@ extern "C" { namespace { -constexpr auto kOIDRawSize{GIT_OID_RAWSZ}; - -[[nodiscard]] auto PermToType(std::string const& perm_str) noexcept - -> std::optional { - constexpr auto kPermBase = 8; - constexpr auto kTreePerm = 040000; - constexpr auto kFilePerm = 0100644; - constexpr auto kExecPerm = 0100755; - constexpr auto kLinkPerm = 0120000; - - int perm = std::stoi(perm_str, nullptr, kPermBase); - - switch (perm) { - case kTreePerm: - return ObjectType::Tree; - case kFilePerm: - return ObjectType::File; - case kExecPerm: - return ObjectType::Executable; - case kLinkPerm: - Logger::Log(LogLevel::Error, "symlinks are not yet supported"); - return std::nullopt; - default: - Logger::Log(LogLevel::Error, "unsupported permission {}", perm_str); - return std::nullopt; - } -} - -auto ParseRawTreeObject(GitCASPtr const& cas, - std::string const& raw_tree) noexcept - -> std::optional { - std::string perm{}; - std::string path{}; - std::string hash(kOIDRawSize, '\0'); - std::istringstream iss{raw_tree}; - GitTree::entries_t entries{}; - // raw tree format is: " \0[next entries...]" - while (std::getline(iss, perm, ' ') and // - std::getline(iss, path, '\0') and // - iss.read(hash.data(), // - static_cast(hash.size()))) { - auto type = PermToType(perm); - if (not type) { - return std::nullopt; - } - try { - entries.emplace(path, - std::make_shared(cas, hash, *type)); - } catch (std::exception const& ex) { - Logger::Log(LogLevel::Error, - "parsing git raw tree object failed with:\n{}", - ex.what()); - return std::nullopt; - } - } - return entries; -} - // resolve '.' and '..' in path. [[nodiscard]] auto ResolveRelativePath( std::filesystem::path const& path) noexcept -> std::filesystem::path { @@ -111,19 +53,12 @@ auto GitTree::Read(std::filesystem::path const& repo_path, auto GitTree::Read(gsl::not_null const& cas, std::string const& tree_id) noexcept -> std::optional { - auto raw_id = FromHexString(tree_id); - if (not raw_id) { - return std::nullopt; - } - auto obj = cas->ReadObject(*raw_id); - if (not obj) { - return std::nullopt; - } - auto entries = ParseRawTreeObject(cas, *obj); - if (not entries) { - return std::nullopt; + if (auto raw_id = FromHexString(tree_id)) { + if (auto entries = cas->ReadTree(*raw_id)) { + return GitTree::FromEntries(cas, std::move(*entries), *raw_id); + } } - return GitTree{cas, std::move(*entries), std::move(*raw_id)}; + return std::nullopt; } auto GitTree::LookupEntryByName(std::string const& name) const noexcept @@ -152,12 +87,9 @@ auto GitTreeEntry::Blob() const noexcept -> std::optional { auto GitTreeEntry::Tree() const& noexcept -> std::optional const& { return tree_cached_.SetOnceAndGet([this]() -> std::optional { - std::optional obj{}; if (IsTree()) { - if (auto obj = cas_->ReadObject(raw_id_)) { - if (auto entries = ParseRawTreeObject(cas_, *obj)) { - return GitTree{cas_, std::move(*entries), raw_id_}; - } + if (auto entries = cas_->ReadTree(raw_id_)) { + return GitTree::FromEntries(cas_, std::move(*entries), raw_id_); } } return std::nullopt; -- cgit v1.2.3