diff options
-rw-r--r-- | src/buildtool/file_system/git_repo.cpp | 79 | ||||
-rw-r--r-- | src/buildtool/file_system/git_repo.hpp | 19 |
2 files changed, 98 insertions, 0 deletions
diff --git a/src/buildtool/file_system/git_repo.cpp b/src/buildtool/file_system/git_repo.cpp index 11c5a569..2e142438 100644 --- a/src/buildtool/file_system/git_repo.cpp +++ b/src/buildtool/file_system/git_repo.cpp @@ -2058,6 +2058,85 @@ auto GitRepo::CreateShallowTree(tree_entries_t const& entries) noexcept return std::nullopt; } +[[nodiscard]] auto GitRepo::ReadDirectory( + std::filesystem::path const& dir, + StoreDirEntryFunc const& read_and_store_entry, + anon_logger_ptr const& logger) noexcept -> bool { + try { + for (auto const& entry : std::filesystem::directory_iterator{dir}) { + if (auto type = FileSystemManager::Type(entry.path(), + /*allow_upwards=*/true)) { + if (not read_and_store_entry(entry.path().filename(), *type)) { + (*logger)(fmt::format("could not read and store to ODB " + "subdir entry {}", + entry.path().string()), + /*fatal=*/true); + return false; + } + } + else { + (*logger)(fmt::format("unsupported type for subdir entry {}", + entry.path().string()), + /*fatal=*/true); + return false; + } + } + } catch (std::exception const& ex) { + Logger::Log( + LogLevel::Error, "reading subdirectory {} failed", dir.string()); + return false; + } + return true; // success! +} + +auto GitRepo::CreateTreeFromDirectory(std::filesystem::path const& dir, + anon_logger_ptr const& logger) noexcept + -> std::optional<std::string> { +#ifdef BOOTSTRAP_BUILD_TOOL + return std::nullopt; +#else + tree_entries_t entries{}; + auto dir_read_and_store = [this, &entries, dir, logger](auto name, + auto type) { + const auto full_name = dir / name; + if (IsTreeObject(type)) { + // store subdirectory as a tree in the ODB + if (auto raw_id = + this->CreateTreeFromDirectory(full_name, logger)) { + entries[std::move(*raw_id)].emplace_back(name.string(), + ObjectType::Tree); + return true; + } + (*logger)( + fmt::format("failed creating tree {}", full_name.string()), + /*fatal=*/true); + return false; + } + // for non-tree entries, read content and write it as a blob to the ODB + if (auto content = + FileSystemManager::ReadContentAtPath(full_name, type)) { + if (auto hash = WriteBlob(*content, logger)) { + if (auto raw_id = FromHexString(*hash)) { + entries[std::move(*raw_id)].emplace_back(name.string(), + type); + return true; + } + } + } + (*logger)(fmt::format("failed creating blob {}", full_name.string()), + /*fatal=*/true); + return false; + }; + + if (ReadDirectory(dir, dir_read_and_store, logger)) { + if (auto raw_id = CreateTree(entries)) { + return *raw_id; + } + } + return std::nullopt; +#endif // BOOTSTRAP_BUILD_TOOL +} + void GitRepo::PopulateStrarray( git_strarray* array, std::vector<std::string> const& string_list) noexcept { diff --git a/src/buildtool/file_system/git_repo.hpp b/src/buildtool/file_system/git_repo.hpp index 31d9eb82..2aabf7ee 100644 --- a/src/buildtool/file_system/git_repo.hpp +++ b/src/buildtool/file_system/git_repo.hpp @@ -358,6 +358,25 @@ class GitRepo { [[nodiscard]] auto GetGitOdb() const noexcept -> std::unique_ptr<git_odb, decltype(&odb_closer)> const&; + using StoreDirEntryFunc = + std::function<bool(std::filesystem::path const&, ObjectType type)>; + + /// \brief Helper function to read the entries of a filesystem subdirectory + /// and store them to the ODB. It is a modified version of the same-named + /// function from FileSystemManager which accepts a subdir and a specific + /// logger instead of the default. + [[nodiscard]] static auto ReadDirectory( + std::filesystem::path const& dir, + StoreDirEntryFunc const& read_and_store_entry, + anon_logger_ptr const& logger) noexcept -> bool; + + /// \brief Create a tree from the content of a directory by recursively + /// adding its entries to the object database. + /// \return The raw id of the tree. + [[nodiscard]] auto CreateTreeFromDirectory( + std::filesystem::path const& dir, + anon_logger_ptr const& logger) noexcept -> std::optional<std::string>; + /// \brief Helper function to allocate and populate the char** pointer of a /// git_strarray from a vector of standard strings. User MUST use /// git_strarray_dispose to deallocate the inner pointer when the strarray |