repo: ensure is_empty() checks there are no refs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
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)