branch: remove config section upon deletion
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
diff --git a/src/branch.c b/src/branch.c
index 9913145..a1c2abc 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 0000000..652f80f
--- /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 0000000..d18c6c3
--- /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 4e9c709..da7db13 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