git2wrap

C++20 wrapper for libgit2
git clone git://git.dimitrijedobrota.com/git2wrap.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit 7758d84d392c0d1dbfaa2fd3da18f0f44d583179
parent 680484e2c68408ac14dc11665b10a9e3eb8d4ceb
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Wed, 8 Jan 2025 14:18:46 +0100

Fix memory management

* get rid of const_signature
* Revert back to unique_ptr as there is already internal reference
counting
* Only git_repository* is wrapped in shared_ptr and passed as a param

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 | + --
M include/git2wrap/signature.hpp | +++ ------------------
M include/git2wrap/types.hpp | ++++ --
M source/branch.cpp | + -
M source/commit.cpp | +++++++++++++++ ----
M source/object.cpp | ++++++ ------
M source/reference.cpp | +++++++++++++
M source/signature.cpp | +++++++++++++++++++++++ --

14 files changed, 79 insertions(+), 50 deletions(-)


diff --git a/ CMakeLists.txt b/ CMakeLists.txt

@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)


project(
git2wrap
VERSION 0.1.9
VERSION 0.1.10
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

@@ -16,13 +16,12 @@ public:

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; }

const std::string& get_name();

private:
referencePtr m_ref;
referenceUPtr m_ref;
git_branch_t m_type = {};

std::string m_name;

@@ -47,7 +46,7 @@ public:

const branch_iterator& rhs);

private:
branch_iteratorPtr m_iter;
branch_iteratorUPtr m_iter;
branch m_branch;
};

diff --git a/ include/git2wrap/commit.hpp b/ include/git2wrap/commit.hpp

@@ -15,7 +15,7 @@ public:

commit() = default;

operator bool() const { return m_commit != nullptr; } // NOLINT
commitPtr get() const { return m_commit; }
commit dup() const;

const oid* get_id() const;
const char* get_summary() const;

@@ -25,15 +25,15 @@ public:

const char* get_body() const;
time_t get_time() const;
int get_time_offset() const;
const_signature get_signature() const;
const_signature get_author() const;
signature get_signature() const;
signature get_author() const;
const char* get_raw_header() const;
unsigned get_parentcount() const;
commit get_parent(unsigned n = 0) const;
buf get_header_field(const char *field) const;
buf get_header_field(const char* field) const;

private:
commitPtr m_commit;
commitUPtr m_commit;
repositoryPtr m_repo;
};

diff --git a/ include/git2wrap/object.hpp b/ include/git2wrap/object.hpp

@@ -18,9 +18,7 @@ public:

object() = default;

operator bool() const { return m_obj != nullptr; } // NOLINT
objectPtr get() const { return m_obj; }

object clone();
object dup() const;

const oid* get_id() const;
buf get_id_short() const;

@@ -31,7 +29,7 @@ public:

static git_object_t string2type(const char* str);

private:
objectPtr m_obj;
objectUPtr m_obj;
repositoryPtr m_repo;
};

diff --git a/ include/git2wrap/reference.hpp b/ include/git2wrap/reference.hpp

@@ -14,13 +14,13 @@ public:

explicit reference(git_reference* ref = nullptr);

operator bool() const { return m_ref != nullptr; } // NOLINT
referencePtr get() const { return m_ref; }
reference dup() const;

friend bool operator==(const reference& lhs, const reference& rhs);
friend bool operator!=(const reference& lhs, const reference& rhs);

private:
referencePtr m_ref;
referenceUPtr m_ref;
};

} // namespace git2wrap

diff --git a/ include/git2wrap/repository.hpp b/ include/git2wrap/repository.hpp

@@ -22,6 +22,7 @@ public:

repository(const char* path, unsigned is_bare);
repository(const char* path, init_options* opts);

operator repositoryPtr() const { return m_repo; } // NOLINT
operator bool() const { return m_repo != nullptr; } // NOLINT
repositoryPtr get() const { return m_repo; }

diff --git a/ include/git2wrap/revwalk.hpp b/ include/git2wrap/revwalk.hpp

@@ -16,7 +16,6 @@ public:

revwalk(revwalkPtr revwalk, repositoryPtr repo);

operator bool() const { return m_revwalk != nullptr; } // NOLINT
revwalkPtr get() const { return m_revwalk; }

void push(const git_oid* objid);
void push_glob(const char* glob);

@@ -26,7 +25,7 @@ public:

void reset();

private:
revwalkPtr m_revwalk;
revwalkUPtr m_revwalk;
repositoryPtr m_repo;
};

diff --git a/ include/git2wrap/signature.hpp b/ include/git2wrap/signature.hpp

@@ -11,33 +11,18 @@ namespace git2wrap

class GIT2WRAP_EXPORT signature
{
public:
explicit signature(const git_signature* sig);
explicit signature(git_signature* sig);

operator bool() const { return m_sig != nullptr; } // NOLINT
signaturePtr get() const { return m_sig; }
signature dup() const;

const char* get_email() const { return m_sig->email; }
const char* get_name() const { return m_sig->name; }
time get_time() const { return m_sig->when; }

private:
signaturePtr m_sig;
};

class GIT2WRAP_EXPORT const_signature
{
public:
explicit const_signature(const git_signature* sig);

operator bool() const { return m_sig != nullptr; } // NOLINT
const git_signature* get() const { return m_sig; }

const char* get_email() const { return m_sig->email; }
const char* get_name() const { return m_sig->name; }
time get_time() const { return m_sig->when; }

private:
const git_signature* m_sig;
signatureUPtr m_sig;
};

} // namespace git2wrap

diff --git a/ include/git2wrap/types.hpp b/ include/git2wrap/types.hpp

@@ -1,5 +1,6 @@

#pragma once

#include <functional>
#include <memory>

#include <git2.h>

@@ -7,13 +8,14 @@

// NOLINTBEGIN
#define CLASS(T) \
class T; \
using T##Ptr = std::shared_ptr<git_##T>;
using T##Del = std::function<void(git_##T*)>; \
using T##Ptr = std::shared_ptr<git_##T>; \
using T##UPtr = std::unique_ptr<git_##T, T##Del>;
// NOLINTEND

namespace git2wrap
{

class const_signature;
class branch;
class buf;
class libgit2;

diff --git a/ source/branch.cpp b/ source/branch.cpp

@@ -49,7 +49,7 @@ branch_iterator& branch_iterator::operator++()


bool operator==(const branch_iterator& lhs, const branch_iterator& rhs)
{
return lhs.m_branch.get_reference() == rhs.m_branch.get_reference();
return lhs.m_branch == rhs.m_branch;
}

bool operator!=(const branch_iterator& lhs, const branch_iterator& rhs)

diff --git a/ source/commit.cpp b/ source/commit.cpp

@@ -13,6 +13,17 @@ commit::commit(git_commit* cmt, repositoryPtr repo)

{
}

commit commit::dup() const
{
git_commit* cmt = nullptr;

if (auto err = git_commit_dup(&cmt, m_commit.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}

return {cmt, m_repo};
}

const git_oid* commit::get_id() const
{
return git_commit_id(m_commit.get());

@@ -53,14 +64,14 @@ int commit::get_time_offset() const

return git_commit_time_offset(m_commit.get());
}

const_signature commit::get_signature() const
signature commit::get_signature() const
{
return const_signature(git_commit_committer(m_commit.get()));
return signature(git_commit_committer(m_commit.get()));
}

const_signature commit::get_author() const
signature commit::get_author() const
{
return const_signature(git_commit_author(m_commit.get()));
return signature(git_commit_author(m_commit.get()));
}

const char* commit::get_raw_header() const

diff --git a/ source/object.cpp b/ source/object.cpp

@@ -11,12 +11,7 @@ object::object(git_object* obj, repositoryPtr repo)

{
}

const oid* object::get_id() const
{
return git_object_id(m_obj.get());
}

object object::clone()
object object::dup() const
{
git_object* obj = nullptr;

@@ -27,6 +22,11 @@ object object::clone()

return {obj, m_repo};
}

const oid* object::get_id() const
{
return git_object_id(m_obj.get());
}

buf object::get_id_short() const
{
buf bufr;

diff --git a/ source/reference.cpp b/ source/reference.cpp

@@ -1,5 +1,7 @@

#include "git2wrap/reference.hpp"

#include "git2wrap/error.hpp"

namespace git2wrap
{

@@ -8,6 +10,17 @@ reference::reference(git_reference* ref)

{
}

reference reference::dup() const
{
git_reference* ref = nullptr;

if (auto err = git_reference_dup(&ref, m_ref.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}

return reference(ref);
}

bool operator==(const reference& lhs, const reference& rhs)
{
return git_reference_cmp(lhs.m_ref.get(), rhs.m_ref.get()) == 0;

diff --git a/ source/signature.cpp b/ source/signature.cpp

@@ -1,16 +1,37 @@

#include "git2wrap/signature.hpp"

#include "git2wrap/error.hpp"

static const struct empty_lambda_t // static and const applies to the object!
{
template<typename... T>
void operator()(T&&...) const // NOLINT
{
} // does nothing
} empty_lambda {}; // declare an object which is static and const

namespace git2wrap
{

signature::signature(const git_signature* sig)
: m_sig(const_cast<git_signature*>(sig), empty_lambda) // NOLINT
{
}

signature::signature(git_signature* sig)
: m_sig(sig, git_signature_free)
{
}

const_signature::const_signature(const git_signature* sig)
: m_sig(sig)
signature signature::dup() const
{
git_signature* sig = nullptr;

if (auto err = git_signature_dup(&sig, m_sig.get())) {
throw error(err, git_error_last(), __FILE__, __LINE__);
}

return signature(sig);
}

} // namespace git2wrap