diff --git a/src/refdb.c b/src/refdb.c index fbbf519..19b9887 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 2d4ec75..7578f66 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 28ea474..eeddac3 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) {