reflog: follow core.logallrefupdates On bare by default, or when core.logallrefupdates is false, we must not write the reflog.
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 137 138 139 140 141 142 143 144 145 146 147 148 149
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 25316fe..9b10ef1 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -925,16 +925,34 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
static int has_reflog(git_repository *repo, const char *name);
/* We only write if it's under heads/, remotes/ or notes/ or if it already has a log */
-static bool should_write_reflog(git_repository *repo, const char *name)
+static int should_write_reflog(int *write, git_repository *repo, const char *name)
{
- if (has_reflog(repo, name))
- return 1;
+ git_config *config;
+ int error, logall, is_bare;
- if (!git__prefixcmp(name, GIT_REFS_HEADS_DIR) ||
- !git__strcmp(name, GIT_HEAD_FILE) ||
- !git__prefixcmp(name, GIT_REFS_REMOTES_DIR) ||
- !git__prefixcmp(name, GIT_REFS_NOTES_DIR))
- return 1;
+ /* Defaults to the oppsite of being bare */
+ is_bare = git_repository_is_bare(repo);
+ logall = !is_bare;
+
+ if ((error = git_repository_config__weakptr(&config, repo)) < 0)
+ return error;
+
+ error = git_config_get_bool(&logall, config, "core.logallrefupdates");
+ if (error < 0 && error != GIT_ENOTFOUND)
+ return error;
+
+ if (!logall) {
+ *write = 0;
+ } else if (has_reflog(repo, name)) {
+ *write = 1;
+ } else if (!git__prefixcmp(name, GIT_REFS_HEADS_DIR) ||
+ !git__strcmp(name, GIT_HEAD_FILE) ||
+ !git__prefixcmp(name, GIT_REFS_REMOTES_DIR) ||
+ !git__prefixcmp(name, GIT_REFS_NOTES_DIR)) {
+ *write = 1;
+ } else {
+ *write = 0;
+ }
return 0;
}
@@ -1056,7 +1074,7 @@ static int refdb_fs_backend__write(
{
refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
git_filebuf file = GIT_FILEBUF_INIT;
- int error = 0, cmp = 0;
+ int error = 0, cmp = 0, should_write;
const char *new_target = NULL;
const git_oid *new_id = NULL;
@@ -1094,7 +1112,10 @@ static int refdb_fs_backend__write(
goto on_error; /* not really error */
}
- if (should_write_reflog(backend->repo, ref->name)) {
+ if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
+ goto on_error;
+
+ if (should_write) {
if ((error = reflog_append(backend, ref, NULL, NULL, who, message)) < 0)
goto on_error;
if ((error = maybe_append_head(backend, ref, who, message)) < 0)
diff --git a/tests/refs/reflog/reflog.c b/tests/refs/reflog/reflog.c
index a50d40a..792b0f0 100644
--- a/tests/refs/reflog/reflog.c
+++ b/tests/refs/reflog/reflog.c
@@ -261,3 +261,76 @@ void test_refs_reflog_reflog__do_not_append_when_no_update(void)
cl_assert_equal_i(nlogs_after, nlogs);
}
+
+static void assert_no_reflog_update(void)
+{
+ size_t nlogs, nlogs_after;
+ size_t nlogs_master, nlogs_master_after;
+ git_reference *ref;
+ git_reflog *log;
+ git_oid id;
+
+ cl_git_pass(git_reflog_read(&log, g_repo, "HEAD"));
+ nlogs = git_reflog_entrycount(log);
+ git_reflog_free(log);
+
+ cl_git_pass(git_reflog_read(&log, g_repo, "refs/heads/master"));
+ nlogs_master = git_reflog_entrycount(log);
+ git_reflog_free(log);
+
+ /* Move it back */
+ git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
+ cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/master", &id, 1, NULL, NULL));
+ git_reference_free(ref);
+
+ cl_git_pass(git_reflog_read(&log, g_repo, "HEAD"));
+ nlogs_after = git_reflog_entrycount(log);
+ git_reflog_free(log);
+
+ cl_assert_equal_i(nlogs_after, nlogs);
+
+ cl_git_pass(git_reflog_read(&log, g_repo, "refs/heads/master"));
+ nlogs_master_after = git_reflog_entrycount(log);
+ git_reflog_free(log);
+
+ cl_assert_equal_i(nlogs_after, nlogs);
+ cl_assert_equal_i(nlogs_master_after, nlogs_master);
+
+}
+
+void test_refs_reflog_reflog__logallrefupdates_bare_set_false(void)
+{
+ git_config *config;
+
+ cl_git_pass(git_repository_config(&config, g_repo));
+ cl_git_pass(git_config_set_bool(config, "core.logallrefupdates", false));
+ git_config_free(config);
+
+ assert_no_reflog_update();
+}
+
+void test_refs_reflog_reflog__logallrefupdates_bare_unset(void)
+{
+ git_config *config;
+
+ cl_git_pass(git_repository_config(&config, g_repo));
+ cl_git_pass(git_config_delete_entry(config, "core.logallrefupdates"));
+ git_config_free(config);
+
+ assert_no_reflog_update();
+}
+
+void test_refs_reflog_reflog__logallrefupdates_nonbare_set_false(void)
+{
+ git_config *config;
+
+ cl_git_sandbox_cleanup();
+ g_repo = cl_git_sandbox_init("testrepo");
+
+
+ cl_git_pass(git_repository_config(&config, g_repo));
+ cl_git_pass(git_config_set_bool(config, "core.logallrefupdates", false));
+ git_config_free(config);
+
+ assert_no_reflog_update();
+}