summaryrefslogtreecommitdiff
path: root/src/buildtool/file_system/git_cas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildtool/file_system/git_cas.cpp')
-rw-r--r--src/buildtool/file_system/git_cas.cpp222
1 files changed, 122 insertions, 100 deletions
diff --git a/src/buildtool/file_system/git_cas.cpp b/src/buildtool/file_system/git_cas.cpp
index b49a75dd..85635c4e 100644
--- a/src/buildtool/file_system/git_cas.cpp
+++ b/src/buildtool/file_system/git_cas.cpp
@@ -58,51 +58,51 @@ auto GitCAS::Open(std::filesystem::path const& repo_path,
#ifdef BOOTSTRAP_BUILD_TOOL
return nullptr;
#else
- auto result = std::make_shared<GitCAS>();
-
- // lock as git_repository API has no thread-safety guarantees
- static std::mutex repo_mutex{};
- std::unique_lock lock{repo_mutex};
- git_repository* repo_ptr = nullptr;
- if (git_repository_open_ext(&repo_ptr,
- repo_path.c_str(),
- GIT_REPOSITORY_OPEN_NO_SEARCH,
- nullptr) != 0 or
- repo_ptr == nullptr) {
- Logger::Log(log_failure,
- "Opening git repository {} failed with:\n{}",
- repo_path.string(),
- GitLastError());
- return nullptr;
- }
- result->repo_.reset(repo_ptr);
+ try {
+ auto result = std::make_shared<GitCAS>();
+
+ // lock as git_repository API has no thread-safety guarantees
+ static std::mutex repo_mutex{};
+ std::unique_lock lock{repo_mutex};
+ git_repository* repo_ptr = nullptr;
+ if (git_repository_open_ext(&repo_ptr,
+ repo_path.c_str(),
+ GIT_REPOSITORY_OPEN_NO_SEARCH,
+ nullptr) != 0 or
+ repo_ptr == nullptr) {
+ Logger::Log(log_failure,
+ "Opening git repository {} failed with:\n{}",
+ repo_path.string(),
+ GitLastError());
+ return nullptr;
+ }
+ result->repo_.reset(repo_ptr);
- git_odb* odb_ptr = nullptr;
- if (git_repository_odb(&odb_ptr, result->repo_.get()) != 0 or
- odb_ptr == nullptr) {
- Logger::Log(log_failure,
- "Obtaining git object database {} failed with:\n{}",
- repo_path.string(),
- GitLastError());
- return nullptr;
- }
- result->odb_.reset(odb_ptr);
+ git_odb* odb_ptr = nullptr;
+ if (git_repository_odb(&odb_ptr, result->repo_.get()) != 0 or
+ odb_ptr == nullptr) {
+ Logger::Log(log_failure,
+ "Obtaining git object database {} failed with:\n{}",
+ repo_path.string(),
+ GitLastError());
+ return nullptr;
+ }
+ result->odb_.reset(odb_ptr);
- auto const git_path =
- git_repository_is_bare(result->repo_.get()) != 0
- ? ToNormalPath(git_repository_path(result->repo_.get()))
- : ToNormalPath(git_repository_workdir(result->repo_.get()));
+ auto const git_path =
+ git_repository_is_bare(result->repo_.get()) != 0
+ ? ToNormalPath(git_repository_path(result->repo_.get()))
+ : ToNormalPath(git_repository_workdir(result->repo_.get()));
- try {
result->git_path_ = std::filesystem::absolute(git_path);
+ return std::const_pointer_cast<GitCAS const>(result);
} catch (std::exception const& e) {
Logger::Log(log_failure,
- "Failed to obtain absolute path for {}: {}",
- git_path.string(),
+ "Unexpected failure opening git object database {}:\n{}",
+ repo_path.string(),
e.what());
return nullptr;
}
- return std::const_pointer_cast<GitCAS const>(result);
#endif
}
@@ -110,27 +110,34 @@ auto GitCAS::CreateEmpty() noexcept -> GitCASPtr {
#ifdef BOOTSTRAP_BUILD_TOOL
return nullptr;
#else
- auto result = std::make_shared<GitCAS>();
+ try {
+ auto result = std::make_shared<GitCAS>();
- git_odb* odb_ptr{nullptr};
- if (git_odb_new(&odb_ptr) != 0 or odb_ptr == nullptr) {
- Logger::Log(LogLevel::Error,
- "creating an empty database failed with:\n{}",
- GitLastError());
- return nullptr;
- }
- result->odb_.reset(odb_ptr); // retain odb pointer
+ git_odb* odb_ptr{nullptr};
+ if (git_odb_new(&odb_ptr) != 0 or odb_ptr == nullptr) {
+ Logger::Log(LogLevel::Error,
+ "Creating an empty database failed with:\n{}",
+ GitLastError());
+ return nullptr;
+ }
+ result->odb_.reset(odb_ptr); // retain odb pointer
- git_repository* repo_ptr = nullptr;
- if (git_repository_wrap_odb(&repo_ptr, result->odb_.get()) != 0 or
- repo_ptr == nullptr) {
+ git_repository* repo_ptr = nullptr;
+ if (git_repository_wrap_odb(&repo_ptr, result->odb_.get()) != 0 or
+ repo_ptr == nullptr) {
+ Logger::Log(LogLevel::Error,
+ "Creating an empty repository failed with:\n{}",
+ GitLastError());
+ return nullptr;
+ }
+ result->repo_.reset(repo_ptr); // retain repo pointer
+ return std::const_pointer_cast<GitCAS const>(result);
+ } catch (std::exception const& e) {
Logger::Log(LogLevel::Error,
- "creating an empty repository failed with:\n{}",
- GitLastError());
+ "Unexpected failure creating empty repository:\n{}",
+ e.what());
return nullptr;
}
- result->repo_.reset(repo_ptr); // retain repo pointer
- return std::const_pointer_cast<GitCAS const>(result);
#endif
}
@@ -142,70 +149,85 @@ auto GitCAS::ReadObject(std::string const& id,
#ifdef BOOTSTRAP_BUILD_TOOL
return std::nullopt;
#else
- if (not odb_) {
- return std::nullopt;
- }
-
- auto oid = GitObjectID(id, is_hex_id);
- if (not oid) {
- return std::nullopt;
- }
-
- git_odb_object* obj = nullptr;
- if (git_odb_read(&obj, odb_.get(), &oid.value()) != 0) {
- Logger::Log(log_failure,
- "reading git object {} from database failed with:\n{}",
- is_hex_id ? id : ToHexString(id),
- GitLastError());
- return std::nullopt;
- }
-
- std::string data(static_cast<char const*>(git_odb_object_data(obj)),
- git_odb_object_size(obj));
- auto obj_type = GitTypeToObjectType(git_odb_object_type(obj));
- git_odb_object_free(obj);
+ try {
+ if (not odb_) {
+ return std::nullopt;
+ }
- if (as_valid_symlink) {
- if (not obj_type) {
+ auto oid = GitObjectID(id, is_hex_id);
+ if (not oid) {
return std::nullopt;
}
- if (not IsTreeObject(*obj_type) and not PathIsNonUpwards(data)) {
+
+ git_odb_object* obj = nullptr;
+ if (git_odb_read(&obj, odb_.get(), &oid.value()) != 0) {
Logger::Log(log_failure,
- "invalid git object {}: upwards symlink",
- is_hex_id ? id : ToHexString(id));
+ "Reading git object {} from database failed with:\n{}",
+ is_hex_id ? id : ToHexString(id),
+ GitLastError());
return std::nullopt;
}
- }
- return data;
+ std::string data(static_cast<char const*>(git_odb_object_data(obj)),
+ git_odb_object_size(obj));
+ auto obj_type = GitTypeToObjectType(git_odb_object_type(obj));
+ git_odb_object_free(obj);
+
+ if (as_valid_symlink) {
+ if (not obj_type) {
+ return std::nullopt;
+ }
+ if (not IsTreeObject(*obj_type) and not PathIsNonUpwards(data)) {
+ Logger::Log(log_failure,
+ "Invalid git object {}: upwards symlink",
+ is_hex_id ? id : ToHexString(id));
+ return std::nullopt;
+ }
+ }
+
+ return data;
+ } catch (std::exception const& e) {
+ Logger::Log(log_failure,
+ "Unexpected failure reading git object {}:\n{}",
+ is_hex_id ? id : ToHexString(id),
+ e.what());
+ return std::nullopt;
+ }
#endif
}
auto GitCAS::ReadHeader(std::string const& id, bool is_hex_id) const noexcept
-> std::optional<std::pair<std::size_t, ObjectType>> {
#ifndef BOOTSTRAP_BUILD_TOOL
- if (not odb_) {
- return std::nullopt;
- }
+ try {
+ if (not odb_) {
+ return std::nullopt;
+ }
- auto oid = GitObjectID(id, is_hex_id);
- if (not oid) {
- return std::nullopt;
- }
+ auto oid = GitObjectID(id, is_hex_id);
+ if (not oid) {
+ return std::nullopt;
+ }
- std::size_t size{};
- git_object_t type{};
- if (git_odb_read_header(&size, &type, odb_.get(), &oid.value()) != 0) {
- Logger::Log(LogLevel::Error,
- "reading git object header {} from database failed "
- "with:\n{}",
- is_hex_id ? id : ToHexString(id),
- GitLastError());
- return std::nullopt;
- }
+ std::size_t size{};
+ git_object_t type{};
+ if (git_odb_read_header(&size, &type, odb_.get(), &oid.value()) != 0) {
+ Logger::Log(LogLevel::Debug,
+ "Reading git object header {} from database failed "
+ "with:\n{}",
+ is_hex_id ? id : ToHexString(id),
+ GitLastError());
+ return std::nullopt;
+ }
- if (auto obj_type = GitTypeToObjectType(type)) {
- return std::make_pair(size, *obj_type);
+ if (auto obj_type = GitTypeToObjectType(type)) {
+ return std::make_pair(size, *obj_type);
+ }
+ } catch (std::exception const& e) {
+ Logger::Log(LogLevel::Debug,
+ "Unexpected failure reading git object header {}:\n{}",
+ is_hex_id ? id : ToHexString(id),
+ e.what());
}
#endif
return std::nullopt;