index: Change the memory management for repo indexes The `git_repository_index` call now returns a brand new index that must be manually free'd.
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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
diff --git a/include/git2/index.h b/include/git2/index.h
index 57401a9..45900d0 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -109,29 +109,24 @@ typedef struct git_index_entry_unmerged {
} git_index_entry_unmerged;
/**
- * Create a new Git index object as a memory representation
+ * Create a new bare Git index object as a memory representation
* of the Git index file in 'index_path', without a repository
* to back it.
*
- * Since there is no ODB behind this index, any Index methods
- * which rely on the ODB (e.g. index_add) will fail with the
- * GIT_EBAREINDEX error code.
+ * Since there is no ODB or working directory behind this index,
+ * any Index methods which rely on these (e.g. index_add) will
+ * fail with the GIT_EBAREINDEX error code.
*
- * @param index the pointer for the new index
- * @param index_path the path to the index file in disk
- * @return 0 on success; error code otherwise
- */
-GIT_EXTERN(int) git_index_open_bare(git_index **index, const char *index_path);
-
-/**
- * Open the Index inside the git repository pointed
- * by 'repo'.
+ * If you need to access the index of an actual repository,
+ * use the `git_repository_index` wrapper.
+ *
+ * The index must be freed once it's no longer in use.
*
* @param index the pointer for the new index
- * @param repo the git repo which owns the index
+ * @param index_path the path to the index file in disk
* @return 0 on success; error code otherwise
*/
-GIT_EXTERN(int) git_index_open_inrepo(git_index **index, git_repository *repo);
+GIT_EXTERN(int) git_index_open(git_index **index, const char *index_path);
/**
* Clear the contents (all the entries) of an index object.
diff --git a/include/git2/repository.h b/include/git2/repository.h
index c47fcfc..0d67ff8 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -141,10 +141,18 @@ GIT_EXTERN(int) git_repository_open3(git_repository **repository,
GIT_EXTERN(git_odb *) git_repository_database(git_repository *repo);
/**
- * Get the Index file of a Git repository
+ * Open the Index file of a Git repository
*
- * This is a cheap operation; the index is only opened on the first call,
- * and subsequent calls only retrieve the previous pointer.
+ * This returns a new and unique `git_index` object representing the
+ * active index for the repository.
+ *
+ * This method may be called more than once (e.g. on different threads).
+ *
+ * Each returned `git_index` object is independent and suffers no race
+ * conditions: synchronization is done at the FS level.
+ *
+ * Each returned `git_index` object must be manually freed by the user,
+ * using `git_index_free`.
*
* @param index Pointer where to store the index
* @param repo a repository object
diff --git a/src/index.c b/src/index.c
index 3897802..c1edd15 100644
--- a/src/index.c
+++ b/src/index.c
@@ -168,13 +168,19 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
return git_index_read(index);
}
-int git_index_open_bare(git_index **index_out, const char *index_path)
+int git_index_open(git_index **index_out, const char *index_path)
{
+ assert(index_out && index_path);
return index_initialize(index_out, NULL, index_path);
}
-int git_index_open_inrepo(git_index **index_out, git_repository *repo)
+/*
+ * Moved from `repository.c`
+ */
+int git_repository_index(git_index **index_out, git_repository *repo)
{
+ assert(index_out && repo);
+
if (repo->is_bare)
return git__throw(GIT_EBAREINDEX, "Failed to open index. Repository is bare");
@@ -183,7 +189,7 @@ int git_index_open_inrepo(git_index **index_out, git_repository *repo)
void git_index_free(git_index *index)
{
- if (index == NULL || index->repository != NULL)
+ if (index == NULL)
return;
git_index_clear(index);
diff --git a/src/repository.c b/src/repository.c
index 468c888..0dd3668 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -315,32 +315,9 @@ void git_repository_free(git_repository *repo)
if (repo->db != NULL)
git_odb_close(repo->db);
- if (repo->index != NULL) {
- repo->index->repository = NULL;
- git_index_free(repo->index);
- }
-
free(repo);
}
-int git_repository_index(git_index **index_out, git_repository *repo)
-{
- int error;
-
- assert(index_out && repo);
-
- if (repo->index == NULL) {
- error = git_index_open_inrepo(&repo->index, repo); /* TODO: move index.c to new error handling */
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open repository index");
-
- assert(repo->index != NULL);
- }
-
- *index_out = repo->index;
- return GIT_SUCCESS;
-}
-
git_odb *git_repository_database(git_repository *repo)
{
assert(repo);
diff --git a/src/repository.h b/src/repository.h
index 813cac9..bcf9b2b 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -25,7 +25,6 @@ struct git_object {
struct git_repository {
git_odb *db;
- git_index *index;
git_cache objects;
git_refcache references;
diff --git a/tests/t06-index.c b/tests/t06-index.c
index 93ca2c0..25adbf7 100644
--- a/tests/t06-index.c
+++ b/tests/t06-index.c
@@ -48,7 +48,7 @@ struct test_entry TEST_ENTRIES[] = {
BEGIN_TEST(read0, "load an empty index")
git_index *index;
- must_pass(git_index_open_bare(&index, "in-memory-index"));
+ must_pass(git_index_open(&index, "in-memory-index"));
must_be_true(index->on_disk == 0);
must_pass(git_index_read(index));
@@ -65,7 +65,7 @@ BEGIN_TEST(read1, "load a standard index (default test index)")
unsigned int i;
git_index_entry **entries;
- must_pass(git_index_open_bare(&index, TEST_INDEX_PATH));
+ must_pass(git_index_open(&index, TEST_INDEX_PATH));
must_be_true(index->on_disk);
must_pass(git_index_read(index));
@@ -90,7 +90,7 @@ END_TEST
BEGIN_TEST(read2, "load a standard index (git.git index)")
git_index *index;
- must_pass(git_index_open_bare(&index, TEST_INDEX2_PATH));
+ must_pass(git_index_open(&index, TEST_INDEX2_PATH));
must_be_true(index->on_disk);
must_pass(git_index_read(index));
@@ -107,7 +107,7 @@ BEGIN_TEST(find0, "find an entry on an index")
git_index *index;
unsigned int i;
- must_pass(git_index_open_bare(&index, TEST_INDEX_PATH));
+ must_pass(git_index_open(&index, TEST_INDEX_PATH));
must_pass(git_index_read(index));
for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) {
@@ -122,7 +122,7 @@ BEGIN_TEST(find1, "find an entry in an empty index")
git_index *index;
unsigned int i;
- must_pass(git_index_open_bare(&index, "fake-index"));
+ must_pass(git_index_open(&index, "fake-index"));
for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) {
int idx = git_index_find(index, TEST_ENTRIES[i].path);
@@ -137,7 +137,7 @@ BEGIN_TEST(write0, "write an index back to disk")
must_pass(copy_file(TEST_INDEXBIG_PATH, "index_rewrite"));
- must_pass(git_index_open_bare(&index, "index_rewrite"));
+ must_pass(git_index_open(&index, "index_rewrite"));
must_pass(git_index_read(index));
must_be_true(index->on_disk);
@@ -165,7 +165,7 @@ END_TEST
BEGIN_TEST(sort1, "sort the entires in an empty index")
git_index *index;
- must_pass(git_index_open_bare(&index, "fake-index"));
+ must_pass(git_index_open(&index, "fake-index"));
/* FIXME: this test is slightly dumb */
must_be_true(index->entries.sorted);