summaryrefslogtreecommitdiff
path: root/src/buildtool/file_system/git_repo.cpp
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2024-08-19 09:58:42 +0200
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2024-08-26 12:12:02 +0200
commit959523b077acdbd75adc4c6328e45c43cda3087c (patch)
tree83d1d61b2f83c04c58b0df925b4fece3a48276ab /src/buildtool/file_system/git_repo.cpp
parentc889b852a652115f4a6936a96ebdee9410571997 (diff)
downloadjustbuild-959523b077acdbd75adc4c6328e45c43cda3087c.tar.gz
GitRepo: Add method to create tree from directory
The tree is traversed bottom-up and each entry is explicitly added to the object database: non-directory entries have their content read and are added as blobs with corresponding permissions based on file type (regular, executable, symlink), while subdirectories are added as trees via CreateTree based on the already added blobs.
Diffstat (limited to 'src/buildtool/file_system/git_repo.cpp')
-rw-r--r--src/buildtool/file_system/git_repo.cpp79
1 files changed, 79 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 {