Commit 6f13a305 by Carlos Martín Nieto

reflog: write to the reflog following git's rules

git-core only writes to the reflogs of HEAD, refs/heads/ and,
refs/notes/ or if there is already a reflog in place. Adjust our code to
follow these semantics.
parent 13c9e44a
...@@ -911,6 +911,22 @@ fail: ...@@ -911,6 +911,22 @@ fail:
} }
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_signature *author, const char *message); static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_signature *author, const char *message);
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)
{
if (has_reflog(repo, name))
return 1;
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;
return 0;
}
static int refdb_fs_backend__write( static int refdb_fs_backend__write(
git_refdb_backend *_backend, git_refdb_backend *_backend,
...@@ -933,7 +949,8 @@ static int refdb_fs_backend__write( ...@@ -933,7 +949,8 @@ static int refdb_fs_backend__write(
if ((error = loose_lock(&file, backend, ref)) < 0) if ((error = loose_lock(&file, backend, ref)) < 0)
return error; return error;
if ((error = reflog_append(backend, ref, who, message)) < 0) { if (should_write_reflog(backend->repo, ref->name) &&
(error = reflog_append(backend, ref, who, message)) < 0) {
git_filebuf_cleanup(&file); git_filebuf_cleanup(&file);
return error; return error;
} }
...@@ -1228,6 +1245,21 @@ GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const ...@@ -1228,6 +1245,21 @@ GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const
return git_buf_join_n(path, '/', 3, repo->path_repository, GIT_REFLOG_DIR, name); return git_buf_join_n(path, '/', 3, repo->path_repository, GIT_REFLOG_DIR, name);
} }
static int has_reflog(git_repository *repo, const char *name)
{
int ret = 0;
git_buf path = GIT_BUF_INIT;
if (retrieve_reflog_path(&path, repo, name) < 0)
goto cleanup;
ret = git_path_isfile(git_buf_cstr(&path));
cleanup:
git_buf_free(&path);
return ret;
}
static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend, const char *name) static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend, const char *name)
{ {
int error = -1; int error = -1;
...@@ -1338,7 +1370,6 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo ...@@ -1338,7 +1370,6 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo
int error = -1; int error = -1;
unsigned int i; unsigned int i;
git_reflog_entry *entry; git_reflog_entry *entry;
git_repository *repo;
refdb_fs_backend *backend; refdb_fs_backend *backend;
git_buf log = GIT_BUF_INIT; git_buf log = GIT_BUF_INIT;
git_filebuf fbuf = GIT_FILEBUF_INIT; git_filebuf fbuf = GIT_FILEBUF_INIT;
...@@ -1346,7 +1377,6 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo ...@@ -1346,7 +1377,6 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo
assert(_backend && reflog); assert(_backend && reflog);
backend = (refdb_fs_backend *) _backend; backend = (refdb_fs_backend *) _backend;
repo = backend->repo;
if ((error = lock_reflog(&fbuf, backend, reflog->ref_name)) < 0) if ((error = lock_reflog(&fbuf, backend, reflog->ref_name)) < 0)
return -1; return -1;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/" #define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/"
#define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/" #define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/"
#define GIT_REFS_REMOTES_DIR GIT_REFS_DIR "remotes/" #define GIT_REFS_REMOTES_DIR GIT_REFS_DIR "remotes/"
#define GIT_REFS_NOTES_DIR GIT_REFS_DIR "notes/"
#define GIT_REFS_DIR_MODE 0777 #define GIT_REFS_DIR_MODE 0777
#define GIT_REFS_FILE_MODE 0666 #define GIT_REFS_FILE_MODE 0666
......
...@@ -187,3 +187,39 @@ void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC ...@@ -187,3 +187,39 @@ void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC
cl_assert_equal_i(GIT_EINVALIDSPEC, cl_assert_equal_i(GIT_EINVALIDSPEC,
git_reflog_rename(g_repo, "refs/heads/master", "refs/heads/Inv@{id")); git_reflog_rename(g_repo, "refs/heads/master", "refs/heads/Inv@{id"));
} }
void test_refs_reflog_reflog__write_only_std_locations(void)
{
git_reference *ref;
git_oid id;
git_oid_fromstr(&id, current_master_tip);
cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/foo", &id, 1));
git_reference_free(ref);
cl_git_pass(git_reference_create(&ref, g_repo, "refs/tags/foo", &id, 1));
git_reference_free(ref);
cl_git_pass(git_reference_create(&ref, g_repo, "refs/notes/foo", &id, 1));
git_reference_free(ref);
assert_has_reflog(true, "refs/heads/foo");
assert_has_reflog(false, "refs/tags/foo");
assert_has_reflog(true, "refs/notes/foo");
}
void test_refs_reflog_reflog__write_when_explicitly_active(void)
{
git_reference *ref;
git_oid id;
git_buf path = GIT_BUF_INIT;
git_oid_fromstr(&id, current_master_tip);
cl_git_pass(git_buf_join(&path, '/', git_repository_path(g_repo), "logs/refs/tags/foo"));
cl_git_pass(git_futils_mkpath2file(git_buf_cstr(&path), 0777));
cl_git_mkfile(git_buf_cstr(&path), "");
cl_git_pass(git_reference_create(&ref, g_repo, "refs/tags/foo", &id, 1));
git_reference_free(ref);
assert_has_reflog(true, "refs/tags/foo");
}
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