git2wrapC++20 wrapper for libgit2 |
git clone git://git.dimitrijedobrota.com/git2wrap.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 186542f37a081940bca0185ca52f699adcafb821 |
parent | 8905a7368ee1a9b33768bf745059669cc789e8ab |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Tue, 7 Jan 2025 18:12:07 +0100 |
Improve memory safety and reference passing
Diffstat:M | CMakeLists.txt | | | +- |
M | include/git2wrap/branch.hpp | | | ++++++------- |
M | include/git2wrap/commit.hpp | | | +++++----------- |
M | include/git2wrap/object.hpp | | | ++++++++++----------- |
M | include/git2wrap/reference.hpp | | | ++++-------- |
M | include/git2wrap/repository.hpp | | | +++++++------ |
M | include/git2wrap/revwalk.hpp | | | +++++++++------------ |
A | include/git2wrap/types.hpp | | | +++++++++++++++++++++++++++ |
M | source/branch.cpp | | | +-- |
M | source/commit.cpp | | | +++++------- |
M | source/object.cpp | | | ++++++++--------- |
M | source/reference.cpp | | | ++-- |
M | source/repository.cpp | | | ++++++++++++------- |
M | source/revwalk.cpp | | | +++++++++++----------- |
14 files changed, 108 insertions(+), 94 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
git2wrap
VERSION 0.1.7
VERSION 0.1.8
DESCRIPTION "C++ 20 wrapper for libgit2"
HOMEPAGE_URL "https://git.dimitrijedobrota.com/git2wrap.git"
LANGUAGES CXX
diff --git a/include/git2wrap/branch.hpp b/include/git2wrap/branch.hpp
@@ -3,7 +3,7 @@
#include <git2.h>
#include "git2wrap/git2wrap_export.hpp"
#include "git2wrap/reference.hpp"
#include "git2wrap/types.hpp"
namespace git2wrap
{
@@ -13,16 +13,16 @@ class GIT2WRAP_EXPORT branch
public:
explicit branch(git_reference* ref = nullptr,
git_branch_t type = git_branch_t(0));
explicit branch(referencePtr ref, git_branch_t type = git_branch_t(0));
operator bool() const { return m_ref != nullptr; } // NOLINT
referencePtr get_reference() const { return m_ref; }
git_branch_t get_type() const { return m_type; }
git_reference* get_reference() { return m_ref.get(); }
const git_reference* get_reference() const { return m_ref.get(); }
const std::string& get_name();
private:
reference m_ref;
referencePtr m_ref;
git_branch_t m_type = {};
std::string m_name;
@@ -47,8 +47,7 @@ public:
const branch_iterator& rhs);
private:
using delete_f = std::function<void(git_branch_iterator*)>;
std::unique_ptr<git_branch_iterator, delete_f> m_iter;
branch_iteratorPtr m_iter;
branch m_branch;
};
diff --git a/include/git2wrap/commit.hpp b/include/git2wrap/commit.hpp
@@ -1,34 +1,28 @@
#pragma once
#include <functional>
#include <memory>
#include <git2.h>
#include "git2wrap/git2wrap_export.hpp"
#include "git2wrap/types.hpp"
namespace git2wrap
{
class repository;
class GIT2WRAP_EXPORT commit
{
public:
commit(git_commit* commit, repository& repo);
commit(git_commit* cmt, repositoryPtr repo);
commit() = default;
operator bool() const { return m_commit != nullptr; } // NOLINT
git_commit* get() const { return m_commit.get(); }
commitPtr get() const { return m_commit; }
const git_oid* get_id() const;
const char* get_summary() const;
private:
using delete_f = std::function<void(git_commit*)>;
std::unique_ptr<git_commit, delete_f> m_commit;
repository* m_repo = nullptr;
commitPtr m_commit;
repositoryPtr m_repo;
};
} // namespace git2wrap
diff --git a/include/git2wrap/object.hpp b/include/git2wrap/object.hpp
@@ -1,12 +1,10 @@
#pragma once
#include <functional>
#include <memory>
#include <git2.h>
#include "git2wrap/buf.hpp"
#include "git2wrap/git2wrap_export.hpp"
#include "git2wrap/types.hpp"
namespace git2wrap
{
@@ -18,24 +16,25 @@ class GIT2WRAP_EXPORT object
public:
using object_t = git_object_t;
explicit object(git_object* obj);
object(git_object* obj, repositoryPtr repo);
object() = default;
git_object* get() { return m_obj.get(); }
const git_object* get() const { return m_obj.get(); }
operator bool() const { return m_obj != nullptr; } // NOLINT
objectPtr get() const { return m_obj; }
object clone();
const oid* get_id() const;
buf get_id_short() const;
object_t get_type() const;
// repository get_owner() const;
repositoryPtr get_owner() const;
static const char *type2string(object_t type);
static git_object_t string2type(const char *str);
static const char* type2string(object_t type);
static git_object_t string2type(const char* str);
private:
using delete_f = std::function<void(git_object*)>;
std::unique_ptr<git_object, delete_f> m_obj;
objectPtr m_obj;
repositoryPtr m_repo;
};
} // namespace git2wrap
diff --git a/include/git2wrap/reference.hpp b/include/git2wrap/reference.hpp
@@ -1,11 +1,9 @@
#pragma once
#include <functional>
#include <memory>
#include <git2.h>
#include "git2wrap/git2wrap_export.hpp"
#include "git2wrap/types.hpp"
namespace git2wrap
{
@@ -14,17 +12,15 @@ class GIT2WRAP_EXPORT reference
{
public:
explicit reference(git_reference* ref = nullptr);
explicit operator bool() const { return m_ref != nullptr; }
git_reference* get() { return m_ref.get(); }
const git_reference* get() const { return m_ref.get(); }
operator bool() const { return m_ref != nullptr; } // NOLINT
referencePtr get() const { return m_ref; }
friend bool operator==(const reference& lhs, const reference& rhs);
friend bool operator!=(const reference& lhs, const reference& rhs);
private:
using delete_f = std::function<void(git_reference*)>;
std::unique_ptr<git_reference, delete_f> m_ref;
referencePtr m_ref;
};
} // namespace git2wrap
diff --git a/include/git2wrap/repository.hpp b/include/git2wrap/repository.hpp
@@ -6,6 +6,7 @@
#include "git2wrap/commit.hpp"
#include "git2wrap/git2wrap_export.hpp"
#include "git2wrap/object.hpp"
#include "git2wrap/types.hpp"
namespace git2wrap
{
@@ -17,11 +18,12 @@ public:
using clone_options = git_clone_options;
explicit repository(git_repository* repo);
explicit repository(repositoryPtr repo);
repository(const char* path, unsigned is_bare);
repository(const char* path, init_options* opts);
git_repository* get() { return m_repo.get(); }
const git_repository* get() const { return m_repo.get(); }
operator bool() const { return m_repo != nullptr; } // NOLINT
repositoryPtr get() const { return m_repo; }
static repository clone(const char* url,
const char* local_path,
@@ -33,14 +35,13 @@ public:
const char* ceiling_dirs);
object revparse(const char* spec);
commit commit_lookup(const git_oid* oid);
commit commit_lookup(const git_oid* objid);
branch_iterator branch_begin(git_branch_t list_flags);
branch_iterator branch_begin(git_branch_t list_flags) const;
branch_iterator branch_end() const;
private:
using delete_f = std::function<void(git_repository*)>;
std::unique_ptr<git_repository, delete_f> m_repo;
repositoryPtr m_repo;
};
} // namespace git2wrap
diff --git a/include/git2wrap/revwalk.hpp b/include/git2wrap/revwalk.hpp
@@ -1,13 +1,10 @@
#pragma once
#include <functional>
#include <memory>
#include <git2.h>
#include "git2wrap/commit.hpp"
#include "git2wrap/git2wrap_export.hpp"
#include "git2wrap/repository.hpp"
#include "git2wrap/types.hpp"
namespace git2wrap
{
@@ -15,22 +12,22 @@ namespace git2wrap
class GIT2WRAP_EXPORT revwalk
{
public:
explicit revwalk(repository& repo);
explicit revwalk(repositoryPtr repo);
revwalk(revwalkPtr revwalk, repositoryPtr repo);
operator bool() const { return m_revwalk != nullptr; } // NOLINT
revwalkPtr get() const { return m_revwalk; }
void push(const git_oid* oid);
void push(const git_oid* objid);
void push_glob(const char* glob);
void push_head();
commit next();
void reset();
git_revwalk* get() { return m_revwalk.get(); }
const git_revwalk* get() const { return m_revwalk.get(); }
private:
using delete_f = std::function<void(git_revwalk*)>;
std::unique_ptr<git_revwalk, delete_f> m_revwalk;
repository* m_repo = nullptr;
revwalkPtr m_revwalk;
repositoryPtr m_repo;
};
} // namespace git2wrap
diff --git a/include/git2wrap/types.hpp b/include/git2wrap/types.hpp
@@ -0,0 +1,27 @@
#pragma once
#include <memory>
#include <git2.h>
// NOLINTBEGIN
#define CLASS(T) \
class T; \
using T##Ptr = std::shared_ptr<git_##T>;
// NOLINTEND
namespace git2wrap
{
class branch;
class buf;
class libgit2;
CLASS(branch_iterator)
CLASS(commit)
CLASS(object)
CLASS(reference)
CLASS(repository)
CLASS(revwalk)
} // namespace git2wrap
diff --git a/source/branch.cpp b/source/branch.cpp
@@ -4,9 +4,8 @@
namespace git2wrap
{
branch::branch(git_reference* ref, git_branch_t type)
: m_ref(ref)
: m_ref(ref, git_reference_free)
, m_type(type)
{
}
diff --git a/source/commit.cpp b/source/commit.cpp
@@ -1,24 +1,22 @@
#include "git2wrap/commit.hpp"
#include "git2wrap/error.hpp"
namespace git2wrap
{
commit::commit(git_commit* commit, repository& repo)
: m_commit(commit, git_commit_free)
, m_repo(&repo)
commit::commit(git_commit* cmt, repositoryPtr repo)
: m_commit(cmt, git_commit_free)
, m_repo(std::move(repo))
{
}
const git_oid* commit::get_id() const
{
return git_commit_id(get());
return git_commit_id(m_commit.get());
}
const char* commit::get_summary() const
{
return git_commit_summary(get());
return git_commit_summary(m_commit.get());
}
} // namespace git2wrap
diff --git a/source/object.cpp b/source/object.cpp
@@ -5,8 +5,9 @@
namespace git2wrap
{
object::object(git_object* obj)
object::object(git_object* obj, repositoryPtr repo)
: m_obj(obj, git_object_free)
, m_repo(std::move(repo))
{
}
@@ -19,18 +20,18 @@ object object::clone()
{
git_object* obj = nullptr;
if (auto err = git_object_dup(&obj, get())) {
if (auto err = git_object_dup(&obj, m_obj.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
return object(obj);
return {obj, m_repo};
}
buf object::get_id_short() const
{
buf bufr;
if (auto err = git_object_short_id(bufr.get(), get())) {
if (auto err = git_object_short_id(bufr.get(), m_obj.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
@@ -39,15 +40,13 @@ buf object::get_id_short() const
object::object_t object::get_type() const
{
return git_object_type(get());
return git_object_type(m_obj.get());
}
/*
repository object::get_owner() const
repositoryPtr object::get_owner() const
{
return repository(git_object_owner(get()));
return m_repo;
}
*/
const char* object::type2string(object_t type)
{
diff --git a/source/reference.cpp b/source/reference.cpp
@@ -10,12 +10,12 @@ reference::reference(git_reference* ref)
bool operator==(const reference& lhs, const reference& rhs)
{
return git_reference_cmp(lhs.get(), rhs.get()) == 0;
return git_reference_cmp(lhs.m_ref.get(), rhs.m_ref.get()) == 0;
}
bool operator!=(const reference& lhs, const reference& rhs)
{
return git_reference_cmp(lhs.get(), rhs.get()) != 0;
return !(lhs == rhs);
}
} // namespace git2wrap
diff --git a/source/repository.cpp b/source/repository.cpp
@@ -10,6 +10,11 @@ repository::repository(git_repository* repo)
{
}
repository::repository(repositoryPtr repo)
: m_repo(std::move(repo))
{
}
repository::repository(const char* path, unsigned is_bare)
{
git_repository* repo = nullptr;
@@ -73,21 +78,21 @@ object repository::revparse(const char* spec)
{
git_object* obj = nullptr;
if (auto err = git_revparse_single(&obj, get(), spec)) {
if (auto err = git_revparse_single(&obj, m_repo.get(), spec)) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
return object(obj);
return {obj, m_repo};
}
commit repository::commit_lookup(const git_oid* oid)
commit repository::commit_lookup(const git_oid* objid)
{
git_commit* commit = nullptr;
if (auto err = git_commit_lookup(&commit, get(), oid)) {
if (auto err = git_commit_lookup(&commit, m_repo.get(), objid)) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
return {commit, *this};
return {commit, m_repo};
}
branch_iterator repository::branch_end() const // NOLINT
@@ -95,11 +100,11 @@ branch_iterator repository::branch_end() const // NOLINT
return branch_iterator();
}
branch_iterator repository::branch_begin(git_branch_t list_flags)
branch_iterator repository::branch_begin(git_branch_t list_flags) const
{
git_branch_iterator* iter = nullptr;
if (auto err = git_branch_iterator_new(&iter, get(), list_flags)) {
if (auto err = git_branch_iterator_new(&iter, m_repo.get(), list_flags)) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
diff --git a/source/revwalk.cpp b/source/revwalk.cpp
@@ -6,45 +6,45 @@
namespace git2wrap
{
revwalk::revwalk(repository& repo)
: m_repo(&repo)
revwalk::revwalk(repositoryPtr repo)
: m_repo(std::move(repo))
{
git_revwalk* rwalk = nullptr;
if (auto err = git_revwalk_new(&rwalk, repo.get())) {
if (auto err = git_revwalk_new(&rwalk, m_repo.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
m_revwalk = {rwalk, git_revwalk_free};
}
void revwalk::push(const git_oid* oid)
void revwalk::push(const git_oid* objid)
{
if (auto err = git_revwalk_push(get(), oid)) {
if (auto err = git_revwalk_push(m_revwalk.get(), objid)) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
}
void revwalk::push_glob(const char* glob)
{
if (auto err = git_revwalk_push_glob(get(), glob)) {
if (auto err = git_revwalk_push_glob(m_revwalk.get(), glob)) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
}
void revwalk::push_head()
{
if (auto err = git_revwalk_push_head(get())) {
if (auto err = git_revwalk_push_head(m_revwalk.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
}
commit revwalk::next()
{
static git_oid oid;
static git_oid objid;
if (git_revwalk_next(&oid, get()) == 0) {
return m_repo->commit_lookup(&oid);
if (git_revwalk_next(&objid, m_revwalk.get()) == 0) {
return repository(m_repo).commit_lookup(&objid);
}
return {};
@@ -52,7 +52,7 @@ commit revwalk::next()
void revwalk::reset()
{
if (auto err = git_revwalk_reset(get())) {
if (auto err = git_revwalk_reset(m_revwalk.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}
}