Commit 33248b9edb74a6bac4223873402efe68a76a30a0

Carlos Martín Nieto 2016-03-10T12:22:34

refdb: remove a check-delete race when removing a loose ref It does not help us to check whether the file exists before trying to unlink it since it might be gone by the time unlink is called. Instead try to remove it and handle the resulting error if it did not exist.

diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 6b55960..ab309c8 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -1281,15 +1281,14 @@ static int refdb_fs_backend__delete_tail(
 	if (git_buf_joinpath(&loose_path, backend->path, ref_name) < 0)
 		return -1;
 
-	if (git_path_isfile(loose_path.ptr)) {
-		error = p_unlink(loose_path.ptr);
-		loose_deleted = 1;
-	}
-
-	git_buf_free(&loose_path);
 
-	if (error != 0)
+	error = p_unlink(loose_path.ptr);
+	if (error < 0 && errno == ENOENT)
+		error = 0;
+	else if (error < 0)
 		goto cleanup;
+	else if (error == 0)
+		loose_deleted = 1;
 
 	if ((error = packed_reload(backend)) < 0)
 		goto cleanup;
@@ -1312,6 +1311,7 @@ static int refdb_fs_backend__delete_tail(
 	error = packed_write(backend);
 
 cleanup:
+	git_buf_free(&loose_path);
 	git_filebuf_cleanup(file);
 
 	return error;