Commit 01d0c02dbaa8856c4e2481ab1435bdf7df58690a

Carlos Martín Nieto 2015-07-12T19:08:06

refdb: delete a ref's reflog upon deletion Removing a reflog upon ref deletion is something which only some backends might wish to do. Backends which are database-backed may wish to archive a reflog, log-based ones may not need to do anything.

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0a819e..243b696 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,10 @@ v0.23 + 1
 
 * `git_cert` descendent types now have a proper `parent` member
 
+* It is the responsibility fo the refdb backend to decide what to do
+  with the reflog on ref deletion. The file-based backend must delete
+  it, a database-backed one may wish to archive it.
+
 v0.23
 ------
 
diff --git a/include/git2/sys/refdb_backend.h b/include/git2/sys/refdb_backend.h
index d943e55..9f2a99b 100644
--- a/include/git2/sys/refdb_backend.h
+++ b/include/git2/sys/refdb_backend.h
@@ -103,8 +103,9 @@ struct git_refdb_backend {
 		const git_signature *who, const char *message);
 
 	/**
-	 * Deletes the given reference from the refdb.  A refdb implementation
-	 * must provide this function.
+	 * Deletes the given reference (and if necessary its reflog)
+	 * from the refdb.  A refdb implementation must provide this
+	 * function.
 	 */
 	int (*del)(git_refdb_backend *backend, const char *ref_name, const git_oid *old_id, const char *old_target);
 
diff --git a/src/branch.c b/src/branch.c
index 791d551..0dcc14c 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -155,18 +155,7 @@ int git_branch_delete(git_reference *branch)
 		git_reference_owner(branch), git_buf_cstr(&config_section), NULL) < 0)
 		goto on_error;
 
-	if (git_reference_delete(branch) < 0)
-		goto on_error;
-
-	if ((error = git_reflog_delete(git_reference_owner(branch), git_reference_name(branch))) < 0) {
-		if (error == GIT_ENOTFOUND) {
-			giterr_clear();
-			error = 0;
-		}
-		goto on_error;
-	}
-
-	error = 0;
+	error = git_reference_delete(branch);
 
 on_error:
 	git_buf_free(&config_section);
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index e1a77f3..55d535e 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -63,6 +63,8 @@ typedef struct refdb_fs_backend {
 	uint32_t direach_flags;
 } refdb_fs_backend;
 
+static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name);
+
 static int packref_cmp(const void *a_, const void *b_)
 {
 	const struct packref *a = a_, *b = b_;
@@ -1217,6 +1219,11 @@ static int refdb_fs_backend__delete(
 	if ((error = loose_lock(&file, backend, ref_name)) < 0)
 		return error;
 
+	if ((error = refdb_reflog_fs__delete(_backend, ref_name)) < 0) {
+		git_filebuf_cleanup(&file);
+		return error;
+	}
+
 	return refdb_fs_backend__delete_tail(_backend, &file, ref_name, old_id, old_target);
 }
 
diff --git a/tests/refs/branches/delete.c b/tests/refs/branches/delete.c
index 343ff0f..8807db2 100644
--- a/tests/refs/branches/delete.c
+++ b/tests/refs/branches/delete.c
@@ -132,6 +132,8 @@ void test_refs_branches_delete__removes_reflog(void)
 	cl_git_pass(git_branch_delete(branch));
 	git_reference_free(branch);
 
+	cl_assert_equal_i(false, git_reference_has_log(repo, "refs/heads/track-local"));
+
 	/* Reading a nonexistant reflog creates it, but it should be empty */
 	cl_git_pass(git_reflog_read(&log, repo, "refs/heads/track-local"));
 	cl_assert_equal_i(0, git_reflog_entrycount(log));