summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buildtool/file_system/git_repo.cpp79
-rw-r--r--src/buildtool/file_system/git_repo.hpp19
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