Commit e02478b1 by Patrick Steinhardt

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.
parent 325375e3
......@@ -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);
......
......@@ -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);
......
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment