From 7c5cab998bafee259898c35ad8aa17f50513f7dd Mon Sep 17 00:00:00 2001 From: Simon Quigley Date: Fri, 20 Dec 2024 22:08:09 -0600 Subject: [PATCH] Use lambdas instead of manual frees for libgit2 --- cpp/build-packages.cpp | 71 +++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/cpp/build-packages.cpp b/cpp/build-packages.cpp index a79e0f0..94dceed 100644 --- a/cpp/build-packages.cpp +++ b/cpp/build-packages.cpp @@ -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 &branch) { log_info("Fetching and checking out repository: " + repo_url + " into " + repo_path.string()); 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 repo(nullptr, repo_deleter); + bool need_clone = false; 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; } - if(!need_clone && repo != nullptr) { - git_remote* remote = nullptr; - int err = git_remote_lookup(&remote, repo, "origin"); + if(!need_clone && repo) { + // Define unique_ptr for git_remote with lambda-based deleter + auto remote_deleter = [](git_remote* r) { if (r) git_remote_free(r); }; + std::unique_ptr remote(nullptr, remote_deleter); + int err = git_remote_lookup(&remote, repo.get(), "origin"); if(err < 0) { log_warning("No origin remote found. Recloning."); - git_repository_free(repo); fs::remove_all(repo_path); need_clone = true; } else { - const char* url = git_remote_url(remote); + const char* url = git_remote_url(remote.get()); if(!url || repo_url != url) { log_warning("Remote URL differs. Recloning."); - git_remote_free(remote); - git_repository_free(repo); fs::remove_all(repo_path); need_clone = true; } else { log_verbose("Remote URL matches. Fetching latest changes."); - git_remote_free(remote); - 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); + git_remote_fetch(remote.get(), nullptr, nullptr, nullptr); log_verbose("Fetch completed."); 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 ref(nullptr, ref_deleter); std::string fullbranch = "refs/remotes/origin/" + *branch; - if(git_reference_lookup(&ref, repo, fullbranch.c_str()) == 0) { - git_object* target = nullptr; - git_reference_peel(&target, ref, GIT_OBJECT_COMMIT); + if(git_reference_lookup(&ref, repo.get(), fullbranch.c_str()) == 0) { + // Define unique_ptr for git_object with lambda-based deleter + auto target_deleter = [](git_object* o) { if (o) git_object_free(o); }; + std::unique_ptr target(nullptr, target_deleter); + git_reference_peel(&target, ref.get(), GIT_OBJECT_COMMIT); git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT; co_opts.checkout_strategy = GIT_CHECKOUT_FORCE; - git_checkout_tree(repo, target, &co_opts); - git_reference_free(ref); - git_repository_set_head_detached(repo, git_object_id(target)); - git_object_free(target); + git_checkout_tree(repo.get(), target.get(), &co_opts); + git_repository_set_head_detached(repo.get(), git_object_id(target.get())); log_info("Checked out branch: " + *branch); } else { log_warning("Branch " + *branch + " not found, recloning."); - git_repository_free(repo); fs::remove_all(repo_path); 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; co_opts.checkout_strategy = GIT_CHECKOUT_FORCE; 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 newrepo(nullptr, newrepo_deleter); int err = git_clone(&newrepo, repo_url.c_str(), repo_path.string().c_str(), &clone_opts); if(err < 0) { 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."); 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 ref(nullptr, ref_deleter); std::string fullbranch = "refs/remotes/origin/" + *branch; - if(git_reference_lookup(&ref, newrepo, fullbranch.c_str()) == 0) { - git_object* target = nullptr; - git_reference_peel(&target, ref, GIT_OBJECT_COMMIT); + if(git_reference_lookup(&ref, newrepo.get(), fullbranch.c_str()) == 0) { + // Define unique_ptr for git_object with lambda-based deleter + auto target_deleter = [](git_object* o) { if (o) git_object_free(o); }; + std::unique_ptr target(nullptr, target_deleter); + git_reference_peel(&target, ref.get(), GIT_OBJECT_COMMIT); git_checkout_options co_opts_clone = GIT_CHECKOUT_OPTIONS_INIT; co_opts_clone.checkout_strategy = GIT_CHECKOUT_FORCE; - git_checkout_tree(newrepo, target, &co_opts_clone); - git_reference_free(ref); - git_repository_set_head_detached(newrepo, git_object_id(target)); - git_object_free(target); + git_checkout_tree(newrepo.get(), target.get(), &co_opts_clone); + git_repository_set_head_detached(newrepo.get(), git_object_id(target.get())); log_info("Checked out branch: " + *branch + " after clone."); } else { log_warning("Git checkout of branch " + *branch + " failed after clone."); - git_repository_free(newrepo); 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()); }