Commit 6091457e76638503fec46de269bc158f63e4721a

nulltoken 2012-11-17T07:19:14

repo: ensure is_empty() checks there are no refs

diff --git a/include/git2/repository.h b/include/git2/repository.h
index d606cfa..f891e91 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -305,7 +305,7 @@ GIT_EXTERN(int) git_repository_head_orphan(git_repository *repo);
  * Check if a repository is empty
  *
  * An empty repository has just been initialized and contains
- * no commits.
+ * no references.
  *
  * @param repo Repo to test
  * @return 1 if the repository is empty, 0 if it isn't, error code
diff --git a/src/repository.c b/src/repository.c
index 101497c..2d6ce4d 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1241,36 +1241,47 @@ int git_repository_head_orphan(git_repository *repo)
 	return 0;
 }
 
-int git_repository_is_empty(git_repository *repo)
+int at_least_one_cb(const char *refname, void *payload)
 {
-	git_reference *head = NULL, *branch = NULL;
-	int error;
+	GIT_UNUSED(refname);
+	GIT_UNUSED(payload);
 
-	if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0)
-		return -1;
+	return GIT_EUSER;
+}
 
-	if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
-		git_reference_free(head);
-		return 0;
-	}
+static int repo_contains_no_reference(git_repository *repo)
+{
+	int error;
+	
+	error = git_reference_foreach(repo, GIT_REF_LISTALL, at_least_one_cb, NULL);
 
-	if (strcmp(git_reference_target(head), GIT_REFS_HEADS_DIR "master") != 0) {
-		git_reference_free(head);
+	if (error == GIT_EUSER)
 		return 0;
-	}
 
-	error = git_reference_resolve(&branch, head);
-
-	git_reference_free(head);
-	git_reference_free(branch);
+	return error == 0 ? 1 : error;
+}
 
-	if (error == GIT_ENOTFOUND)
-		return 1;
+int git_repository_is_empty(git_repository *repo)
+{
+	git_reference *head = NULL;
+	int error, ref_count = 0;
 
-	if (error < 0)
+	if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0)
 		return -1;
 
-	return 0;
+	if (!(error = git_reference_type(head) == GIT_REF_SYMBOLIC))
+		goto cleanup;
+
+	if (!(error = strcmp(
+		git_reference_target(head),
+		GIT_REFS_HEADS_DIR "master") == 0))
+			goto cleanup;
+
+	error = repo_contains_no_reference(repo);
+
+cleanup:
+	git_reference_free(head);
+	return error < 0 ? -1 : error;
 }
 
 const char *git_repository_path(git_repository *repo)
diff --git a/tests-clar/repo/getters.c b/tests-clar/repo/getters.c
index 299a2cb..b372f5b 100644
--- a/tests-clar/repo/getters.c
+++ b/tests-clar/repo/getters.c
@@ -1,16 +1,26 @@
 #include "clar_libgit2.h"
 
-void test_repo_getters__empty(void)
+void test_repo_getters__is_empty_correctly_deals_with_pristine_looking_repos(void)
 {
-	git_repository *repo_empty, *repo_normal;
+	git_repository *repo;
+
+	repo = cl_git_sandbox_init("empty_bare.git");
+	cl_git_remove_placeholders(git_repository_path(repo), "dummy-marker.txt");
+
+	cl_assert_equal_i(true, git_repository_is_empty(repo));
 
-	cl_git_pass(git_repository_open(&repo_normal, cl_fixture("testrepo.git")));
-	cl_assert(git_repository_is_empty(repo_normal) == 0);
-	git_repository_free(repo_normal);
+	cl_git_sandbox_cleanup();
+}
 
-	cl_git_pass(git_repository_open(&repo_empty, cl_fixture("empty_bare.git")));
-	cl_assert(git_repository_is_empty(repo_empty) == 1);
-	git_repository_free(repo_empty);
+void test_repo_getters__is_empty_can_detect_used_repositories(void)
+{
+	git_repository *repo;
+
+	cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+
+	cl_assert_equal_i(false, git_repository_is_empty(repo));
+
+	git_repository_free(repo);
 }
 
 void test_repo_getters__retrieving_the_odb_honors_the_refcount(void)