Skip to content

Commit e02478b

Browse files
committed
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.
1 parent 325375e commit e02478b

File tree

3 files changed

+69
-39
lines changed

3 files changed

+69
-39
lines changed

src/refdb.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,43 @@ int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name)
231231
return 0;
232232
}
233233

234+
int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref)
235+
{
236+
int error, logall;
237+
238+
error = git_repository__configmap_lookup(&logall, db->repo, GIT_CONFIGMAP_LOGALLREFUPDATES);
239+
if (error < 0)
240+
return error;
241+
242+
/* Defaults to the opposite of the repo being bare */
243+
if (logall == GIT_LOGALLREFUPDATES_UNSET)
244+
logall = !git_repository_is_bare(db->repo);
245+
246+
*out = 0;
247+
switch (logall) {
248+
case GIT_LOGALLREFUPDATES_FALSE:
249+
*out = 0;
250+
break;
251+
252+
case GIT_LOGALLREFUPDATES_TRUE:
253+
/* Only write if it already has a log,
254+
* or if it's under heads/, remotes/ or notes/
255+
*/
256+
*out = git_refdb_has_log(db, ref->name) ||
257+
!git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) ||
258+
!git__strcmp(ref->name, GIT_HEAD_FILE) ||
259+
!git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) ||
260+
!git__prefixcmp(ref->name, GIT_REFS_NOTES_DIR);
261+
break;
262+
263+
case GIT_LOGALLREFUPDATES_ALWAYS:
264+
*out = 1;
265+
break;
266+
}
267+
268+
return 0;
269+
}
270+
234271
int git_refdb_has_log(git_refdb *db, const char *refname)
235272
{
236273
assert(db && refname);

src/refdb.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,34 @@ int git_refdb_delete(git_refdb *refdb, const char *ref_name, const git_oid *old_
5050
int git_refdb_reflog_read(git_reflog **out, git_refdb *db, const char *name);
5151
int git_refdb_reflog_write(git_reflog *reflog);
5252

53+
/**
54+
* Determine whether a reflog entry should be created for the given reference.
55+
*
56+
* Whether or not writing to a reference should create a reflog entry is
57+
* dependent on a number of things. Most importantly, there's the
58+
* "core.logAllRefUpdates" setting that controls in which situations a
59+
* reference should get a corresponding reflog entry. The following values for
60+
* it are understood:
61+
*
62+
* - "false": Do not log reference updates.
63+
*
64+
* - "true": Log normal reference updates. This will write entries for
65+
* references in "refs/heads", "refs/remotes", "refs/notes" and
66+
* "HEAD" or if the reference already has a log entry.
67+
*
68+
* - "always": Always create a reflog entry.
69+
*
70+
* If unset, the value will default to "true" for non-bare repositories and
71+
* "false" for bare ones.
72+
*
73+
* @param out pointer to which the result will be written, `1` means a reflog
74+
* entry should be written, `0` means none should be written.
75+
* @param db The refdb to decide this for.
76+
* @param ref The reference one wants to check.
77+
* @return `0` on success, a negative error code otherwise.
78+
*/
79+
int git_refdb_should_write_reflog(int *out, git_refdb *db, const git_reference *ref);
80+
5381
int git_refdb_has_log(git_refdb *db, const char *refname);
5482
int git_refdb_ensure_log(git_refdb *refdb, const char *refname);
5583

src/refdb_fs.c

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,44 +1128,6 @@ static int packed_delete(refdb_fs_backend *backend, const char *ref_name)
11281128
}
11291129

11301130
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);
1131-
static int has_reflog(git_repository *repo, const char *name);
1132-
1133-
static int should_write_reflog(int *write, git_repository *repo, const char *name)
1134-
{
1135-
int error, logall;
1136-
1137-
error = git_repository__configmap_lookup(&logall, repo, GIT_CONFIGMAP_LOGALLREFUPDATES);
1138-
if (error < 0)
1139-
return error;
1140-
1141-
/* Defaults to the opposite of the repo being bare */
1142-
if (logall == GIT_LOGALLREFUPDATES_UNSET)
1143-
logall = !git_repository_is_bare(repo);
1144-
1145-
*write = 0;
1146-
switch (logall) {
1147-
case GIT_LOGALLREFUPDATES_FALSE:
1148-
*write = 0;
1149-
break;
1150-
1151-
case GIT_LOGALLREFUPDATES_TRUE:
1152-
/* Only write if it already has a log,
1153-
* or if it's under heads/, remotes/ or notes/
1154-
*/
1155-
*write = has_reflog(repo, name) ||
1156-
!git__prefixcmp(name, GIT_REFS_HEADS_DIR) ||
1157-
!git__strcmp(name, GIT_HEAD_FILE) ||
1158-
!git__prefixcmp(name, GIT_REFS_REMOTES_DIR) ||
1159-
!git__prefixcmp(name, GIT_REFS_NOTES_DIR);
1160-
break;
1161-
1162-
case GIT_LOGALLREFUPDATES_ALWAYS:
1163-
*write = 1;
1164-
break;
1165-
}
1166-
1167-
return 0;
1168-
}
11691131

11701132
static int cmp_old_ref(int *cmp, git_refdb_backend *backend, const char *name,
11711133
const git_oid *old_id, const char *old_target)
@@ -1335,7 +1297,10 @@ static int refdb_fs_backend__write_tail(
13351297
}
13361298

13371299
if (update_reflog) {
1338-
if ((error = should_write_reflog(&should_write, backend->repo, ref->name)) < 0)
1300+
git_refdb *refdb;
1301+
1302+
if ((error = git_repository_refdb__weakptr(&refdb, backend->repo)) < 0 ||
1303+
(error = git_refdb_should_write_reflog(&should_write, refdb, ref)) < 0)
13391304
goto on_error;
13401305

13411306
if (should_write) {

0 commit comments

Comments
 (0)