summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2020-06-05 08:17:03 +0200
committerPatrick Steinhardt <ps@pks.im>2020-07-12 15:25:10 +0200
commite02478b19b1084775c0aa1f7c658958810d29752 (patch)
treeab57d606077379becdebf74db9001b45f3d2441b
parent325375e3b6c2c31152b7ee48794aa6a1f73709d5 (diff)
downloadlibgit2-e02478b19b1084775c0aa1f7c658958810d29752.tar.gz
refdb: extract function to check whether a reflog should be written
The logic to determine whether a reflog should be written is non-trivial. Currently, the only user of this is the filesystem-based refdb, but with the advent of the reftable refdb we're going to add a second user that's interested in having the same behaviour. Let's pull out a new function that checks whether a given reference should cause a reflog to be written as a preparatory step.
-rw-r--r--src/refdb.c37
-rw-r--r--src/refdb.h28
-rw-r--r--src/refdb_fs.c43
3 files changed, 69 insertions, 39 deletions
diff --git a/src/refdb.c b/src/refdb.c
index fbbf5193c..19b9887f5 100644
--- a/src/refdb.c
+++ b/src/refdb.c
@@ -231,6 +231,43 @@ int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name)
return 0;
}
+int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref)
+{
+ int error, logall;
+
+ error = git_repository__configmap_lookup(&logall, db->repo, GIT_CONFIGMAP_LOGALLREFUPDATES);
+ if (error < 0)
+ return error;
+
+ /* Defaults to the opposite of the repo being bare */
+ if (logall == GIT_LOGALLREFUPDATES_UNSET)
+ logall = !git_repository_is_bare(db->repo);
+
+ *out = 0;
+ switch (logall) {
+ case GIT_LOGALLREFUPDATES_FALSE:
+ *out = 0;
+ break;
+
+ case GIT_LOGALLREFUPDATES_TRUE:
+ /* Only write if it already has a log,
+ * or if it's under heads/, remotes/ or notes/
+ */
+ *out = git_refdb_has_log(db, ref->name) ||
+ !git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) ||
+ !git__strcmp(ref->name, GIT_HEAD_FILE) ||
+ !git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) ||
+ !git__prefixcmp(ref->name, GIT_REFS_NOTES_DIR);
+ break;
+
+ case GIT_LOGALLREFUPDATES_ALWAYS:
+ *out = 1;
+ break;
+ }
+
+ return 0;
+}
+
int git_refdb_has_log(git_refdb *db, const char *refname)
{
assert(db && refname);
diff --git a/src/refdb.h b/src/refdb.h
index 2d4ec753a..7578f66e1 100644
--- a/src/refdb.h
+++ b/src/refdb.h
@@ -50,6 +50,34 @@ int git_refdb_delete(git_refdb *refdb, const char *ref_name, const git_oid *old_
int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name);
int git_refdb_reflog_write(git_reflog *reflog);
+/**
+ * Determine whether a reflog entry should be created for the given reference.
+ *
+ * Whether or not writing to a reference should create a reflog entry is
+ * dependent on a number of things. Most importantly, there's the
+ * "core.logAllRefUpdates" setting that controls in which situations a
+ * reference should get a corresponding reflog entry. The following values for
+ * it are understood:
+ *
+ * - "false": Do not log reference updates.
+ *
+ * - "true": Log normal reference updates. This will write entries for
+ * references in "refs/heads", "refs/remotes", "refs/notes" and
+ * "HEAD" or if the reference already has a log entry.
+ *
+ * - "always": Always create a reflog entry.
+ *
+ * If unset, the value will default to "true" for non-bare repositories and
+ * "false" for bare ones.
+ *
+ * @param out pointer to which the result will be written, `1` means a reflog
+ * entry should be written, `0` means none should be written.
+ * @param db The refdb to decide this for.
+ * @param ref The reference one wants to check.
+ * @return `0` on success, a negative error code otherwise.
+ */
+int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref);
+
int git_refdb_has_log(git_refdb *db, const char *refname);
int git_refdb_ensure_log(git_refdb *refdb, const char *refname);
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 28ea474c9..eeddac324 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -1128,44 +1128,6 @@ cleanup:
}
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *author, const char *message);
-static int has_reflog(git_repository *repo, const char *name);
-
-static int should_write_reflog(int *write, git_repository *repo, const char *name)
-{
- int error, logall;
-
- error = git_repository__configmap_lookup(&logall, repo, GIT_CONFIGMAP_LOGALLREFUPDATES);
- if (error < 0)
- return error;
-
- /* Defaults to the opposite of the repo being bare */
- if (logall == GIT_LOGALLREFUPDATES_UNSET)
- logall = !git_repository_is_bare(repo);
-
- *write = 0;
- switch (logall) {
- case GIT_LOGALLREFUPDATES_FALSE:
- *write = 0;
- break;
-
- case GIT_LOGALLREFUPDATES_TRUE:
- /* Only write if it already has a log,
- * or if it's under heads/, remotes/ or notes/
- */
- *write = has_reflog(repo, name) ||
- !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);
- break;
-
- case GIT_LOGALLREFUPDATES_ALWAYS:
- *write = 1;
- break;
- }
-
- return 0;
-}
static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const char *name,
const git_oid *old_id, const char *old_target)
@@ -1335,7 +1297,10 @@ static int refdb_fs_backend__write_tail(
}
if (update_reflog) {
- if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
+ git_refdb *refdb;
+
+ if ((error = git_repository_refdb__weakptr(&refdb, backend->repo)) < 0 ||
+ (error = git_refdb_should_write_reflog(&should_write, refdb, ref)) < 0)
goto on_error;
if (should_write) {