Use lambdas instead of manual frees for libgit2

Simon Quigley 1 day ago
parent 19620ff4d1
commit 7c5cab998b

@ -200,7 +200,11 @@ static void git_init_once() {
static void git_fetch_and_checkout(const fs::path &repo_path, const std::string &repo_url, const std::optional<std::string> &branch) { static void git_fetch_and_checkout(const fs::path &repo_path, const std::string &repo_url, const std::optional<std::string> &branch) {
log_info("Fetching and checking out repository: " + repo_url + " into " + repo_path.string()); log_info("Fetching and checking out repository: " + repo_url + " into " + repo_path.string());
git_init_once(); git_init_once();
git_repository* repo = nullptr;
// Define unique_ptrs with lambda-based deleters for libgit2 resources
auto repo_deleter = [](git_repository* r) { if (r) git_repository_free(r); };
std::unique_ptr<git_repository, decltype(repo_deleter)> repo(nullptr, repo_deleter);
bool need_clone = false; bool need_clone = false;
if(fs::exists(repo_path)) { if(fs::exists(repo_path)) {
@ -218,53 +222,47 @@ static void git_fetch_and_checkout(const fs::path &repo_path, const std::string
need_clone = true; need_clone = true;
} }
if(!need_clone && repo != nullptr) { if(!need_clone && repo) {
git_remote* remote = nullptr; // Define unique_ptr for git_remote with lambda-based deleter
int err = git_remote_lookup(&remote, repo, "origin"); auto remote_deleter = [](git_remote* r) { if (r) git_remote_free(r); };
std::unique_ptr<git_remote, decltype(remote_deleter)> remote(nullptr, remote_deleter);
int err = git_remote_lookup(&remote, repo.get(), "origin");
if(err < 0) { if(err < 0) {
log_warning("No origin remote found. Recloning."); log_warning("No origin remote found. Recloning.");
git_repository_free(repo);
fs::remove_all(repo_path); fs::remove_all(repo_path);
need_clone = true; need_clone = true;
} else { } else {
const char* url = git_remote_url(remote); const char* url = git_remote_url(remote.get());
if(!url || repo_url != url) { if(!url || repo_url != url) {
log_warning("Remote URL differs. Recloning."); log_warning("Remote URL differs. Recloning.");
git_remote_free(remote);
git_repository_free(repo);
fs::remove_all(repo_path); fs::remove_all(repo_path);
need_clone = true; need_clone = true;
} else { } else {
log_verbose("Remote URL matches. Fetching latest changes."); log_verbose("Remote URL matches. Fetching latest changes.");
git_remote_free(remote); git_remote_fetch(remote.get(), nullptr, nullptr, nullptr);
git_remote* origin = nullptr;
git_remote_lookup(&origin, repo, "origin");
git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
git_remote_fetch(origin, nullptr, &fetch_opts, nullptr);
git_remote_free(origin);
log_verbose("Fetch completed."); log_verbose("Fetch completed.");
if(branch) { if(branch) {
git_reference* ref = nullptr; // Define unique_ptr for git_reference with lambda-based deleter
auto ref_deleter = [](git_reference* r) { if (r) git_reference_free(r); };
std::unique_ptr<git_reference, decltype(ref_deleter)> ref(nullptr, ref_deleter);
std::string fullbranch = "refs/remotes/origin/" + *branch; std::string fullbranch = "refs/remotes/origin/" + *branch;
if(git_reference_lookup(&ref, repo, fullbranch.c_str()) == 0) { if(git_reference_lookup(&ref, repo.get(), fullbranch.c_str()) == 0) {
git_object* target = nullptr; // Define unique_ptr for git_object with lambda-based deleter
git_reference_peel(&target, ref, GIT_OBJECT_COMMIT); auto target_deleter = [](git_object* o) { if (o) git_object_free(o); };
std::unique_ptr<git_object, decltype(target_deleter)> target(nullptr, target_deleter);
git_reference_peel(&target, ref.get(), GIT_OBJECT_COMMIT);
git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT; git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT;
co_opts.checkout_strategy = GIT_CHECKOUT_FORCE; co_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
git_checkout_tree(repo, target, &co_opts); git_checkout_tree(repo.get(), target.get(), &co_opts);
git_reference_free(ref); git_repository_set_head_detached(repo.get(), git_object_id(target.get()));
git_repository_set_head_detached(repo, git_object_id(target));
git_object_free(target);
log_info("Checked out branch: " + *branch); log_info("Checked out branch: " + *branch);
} else { } else {
log_warning("Branch " + *branch + " not found, recloning."); log_warning("Branch " + *branch + " not found, recloning.");
git_repository_free(repo);
fs::remove_all(repo_path); fs::remove_all(repo_path);
need_clone = true; need_clone = true;
} }
} }
git_repository_free(repo);
} }
} }
} }
@ -275,7 +273,9 @@ static void git_fetch_and_checkout(const fs::path &repo_path, const std::string
git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT; git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT;
co_opts.checkout_strategy = GIT_CHECKOUT_FORCE; co_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
clone_opts.checkout_opts = co_opts; clone_opts.checkout_opts = co_opts;
git_repository* newrepo = nullptr; // Define unique_ptr for new repository with lambda-based deleter
auto newrepo_deleter = [](git_repository* r) { if (r) git_repository_free(r); };
std::unique_ptr<git_repository, decltype(newrepo_deleter)> newrepo(nullptr, newrepo_deleter);
int err = git_clone(&newrepo, repo_url.c_str(), repo_path.string().c_str(), &clone_opts); int err = git_clone(&newrepo, repo_url.c_str(), repo_path.string().c_str(), &clone_opts);
if(err < 0) { if(err < 0) {
const git_error* e = git_error_last(); const git_error* e = git_error_last();
@ -285,25 +285,26 @@ static void git_fetch_and_checkout(const fs::path &repo_path, const std::string
log_info("Repository cloned successfully."); log_info("Repository cloned successfully.");
if(branch) { if(branch) {
git_reference* ref = nullptr; // Define unique_ptr for git_reference with lambda-based deleter
auto ref_deleter = [](git_reference* r) { if (r) git_reference_free(r); };
std::unique_ptr<git_reference, decltype(ref_deleter)> ref(nullptr, ref_deleter);
std::string fullbranch = "refs/remotes/origin/" + *branch; std::string fullbranch = "refs/remotes/origin/" + *branch;
if(git_reference_lookup(&ref, newrepo, fullbranch.c_str()) == 0) { if(git_reference_lookup(&ref, newrepo.get(), fullbranch.c_str()) == 0) {
git_object* target = nullptr; // Define unique_ptr for git_object with lambda-based deleter
git_reference_peel(&target, ref, GIT_OBJECT_COMMIT); auto target_deleter = [](git_object* o) { if (o) git_object_free(o); };
std::unique_ptr<git_object, decltype(target_deleter)> target(nullptr, target_deleter);
git_reference_peel(&target, ref.get(), GIT_OBJECT_COMMIT);
git_checkout_options co_opts_clone = GIT_CHECKOUT_OPTIONS_INIT; git_checkout_options co_opts_clone = GIT_CHECKOUT_OPTIONS_INIT;
co_opts_clone.checkout_strategy = GIT_CHECKOUT_FORCE; co_opts_clone.checkout_strategy = GIT_CHECKOUT_FORCE;
git_checkout_tree(newrepo, target, &co_opts_clone); git_checkout_tree(newrepo.get(), target.get(), &co_opts_clone);
git_reference_free(ref); git_repository_set_head_detached(newrepo.get(), git_object_id(target.get()));
git_repository_set_head_detached(newrepo, git_object_id(target));
git_object_free(target);
log_info("Checked out branch: " + *branch + " after clone."); log_info("Checked out branch: " + *branch + " after clone.");
} else { } else {
log_warning("Git checkout of branch " + *branch + " failed after clone."); log_warning("Git checkout of branch " + *branch + " failed after clone.");
git_repository_free(newrepo);
throw std::runtime_error("Branch checkout failed"); throw std::runtime_error("Branch checkout failed");
} }
} }
git_repository_free(newrepo); // newrepo will be automatically freed when it goes out of scope
} }
log_verbose("Finished fetching and checking out repository: " + repo_path.string()); log_verbose("Finished fetching and checking out repository: " + repo_path.string());
} }

Loading…
Cancel
Save