diff --git a/src/branch.c b/src/branch.c index 991314508..a1c2abce6 100644 --- a/src/branch.c +++ b/src/branch.c @@ -89,6 +89,50 @@ cleanup: return error; } +static int delete_config_entries_cb( + const char *var_name, + const char *value, + void *payload) +{ + git_config *config; + + GIT_UNUSED(value); + + config = (git_config *)payload; + + return git_config_delete(config, var_name); +} + +static int delete_branch_config_entries( + git_repository *repo, + const char *branch_name) +{ + git_config *config; + git_buf pattern = GIT_BUF_INIT; + int error = -1; + + git_buf_sets(&pattern, "branch\\."); + git_buf_puts_escape_regex(&pattern, branch_name); + git_buf_puts(&pattern, "\\..+"); + if (git_buf_oom(&pattern)) + goto cleanup; + + if (git_repository_config__weakptr(&config, repo) < 0) + goto cleanup; + + if ((error = git_config_foreach_match( + config, + git_buf_cstr(&pattern), + delete_config_entries_cb, config)) < 0) + goto cleanup; + + error = 0; + +cleanup: + git_buf_free(&pattern); + return error; +} + int git_branch_delete(git_reference *branch) { int is_head; @@ -110,6 +154,11 @@ int git_branch_delete(git_reference *branch) return -1; } + if (delete_branch_config_entries( + git_reference_owner(branch), + git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0) + goto on_error; + return git_reference_delete(branch); } diff --git a/tests-clar/config/config_helpers.c b/tests-clar/config/config_helpers.c new file mode 100644 index 000000000..652f80f94 --- /dev/null +++ b/tests-clar/config/config_helpers.c @@ -0,0 +1,22 @@ +#include "clar_libgit2.h" +#include "config_helpers.h" +#include "repository.h" + +void assert_config_entry_existence( + git_repository *repo, + const char *name, + bool is_supposed_to_exist) +{ + git_config *config; + const char *out; + int result; + + cl_git_pass(git_repository_config__weakptr(&config, repo)); + + result = git_config_get_string(&out, config, name); + + if (is_supposed_to_exist) + cl_git_pass(result); + else + cl_assert_equal_i(GIT_ENOTFOUND, result); +} diff --git a/tests-clar/config/config_helpers.h b/tests-clar/config/config_helpers.h new file mode 100644 index 000000000..d18c6c33d --- /dev/null +++ b/tests-clar/config/config_helpers.h @@ -0,0 +1,4 @@ +extern void assert_config_entry_existence( + git_repository *repo, + const char *name, + bool is_supposed_to_exist); diff --git a/tests-clar/refs/branches/delete.c b/tests-clar/refs/branches/delete.c index 4e9c70904..da7db13fc 100644 --- a/tests-clar/refs/branches/delete.c +++ b/tests-clar/refs/branches/delete.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "refs.h" #include "repo/repo_helpers.h" +#include "config/config_helpers.h" static git_repository *repo; static git_reference *fake_remote; @@ -90,3 +91,17 @@ void test_refs_branches_delete__can_delete_a_remote_branch(void) cl_git_pass(git_branch_lookup(&branch, repo, "nulltoken/master", GIT_BRANCH_REMOTE)); cl_git_pass(git_branch_delete(branch)); } + +void test_refs_branches_delete__deleting_a_branch_removes_related_configuration_data(void) +{ + git_reference *branch; + + assert_config_entry_existence(repo, "branch.track-local.remote", true); + assert_config_entry_existence(repo, "branch.track-local.merge", true); + + cl_git_pass(git_branch_lookup(&branch, repo, "track-local", GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_delete(branch)); + + assert_config_entry_existence(repo, "branch.track-local.remote", false); + assert_config_entry_existence(repo, "branch.track-local.merge", false); +} \ No newline at end of file