Commit aba6b5ed by Russell Belfer

Fix leak in git_index_conflict_cleanup

I introduced a leak into conflict cleanup by removing items from
inside the git_vector_remove_matching call.  This simplifies the
code to just use one common way for the two conflict cleanup APIs.

When an index has an active snapshot, removing an item can cause
an error (inserting into the deferred deletion vector), so I made
the git_index_conflict_cleanup API return an error code.  I felt
like this wasn't so bad since it is just like the other APIs.

I fixed up a couple of comments while I was changing the header.
parent cef170ab
...@@ -575,8 +575,7 @@ GIT_EXTERN(int) git_index_update_all( ...@@ -575,8 +575,7 @@ GIT_EXTERN(int) git_index_update_all(
* @param at_pos the address to which the position of the index entry is written (optional) * @param at_pos the address to which the position of the index entry is written (optional)
* @param index an existing index object * @param index an existing index object
* @param path path to search * @param path path to search
* @return a zero-based position in the index if found; * @return a zero-based position in the index if found; GIT_ENOTFOUND otherwise
* GIT_ENOTFOUND otherwise
*/ */
GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *path); GIT_EXTERN(int) git_index_find(size_t *at_pos, git_index *index, const char *path);
...@@ -620,6 +619,7 @@ GIT_EXTERN(int) git_index_conflict_add( ...@@ -620,6 +619,7 @@ GIT_EXTERN(int) git_index_conflict_add(
* @param their_out Pointer to store the their entry * @param their_out Pointer to store the their entry
* @param index an existing index object * @param index an existing index object
* @param path path to search * @param path path to search
* @return 0 or an error code
*/ */
GIT_EXTERN(int) git_index_conflict_get( GIT_EXTERN(int) git_index_conflict_get(
const git_index_entry **ancestor_out, const git_index_entry **ancestor_out,
...@@ -632,16 +632,18 @@ GIT_EXTERN(int) git_index_conflict_get( ...@@ -632,16 +632,18 @@ GIT_EXTERN(int) git_index_conflict_get(
* Removes the index entries that represent a conflict of a single file. * Removes the index entries that represent a conflict of a single file.
* *
* @param index an existing index object * @param index an existing index object
* @param path to search * @param path path to remove conflicts for
* @return 0 or an error code
*/ */
GIT_EXTERN(int) git_index_conflict_remove(git_index *index, const char *path); GIT_EXTERN(int) git_index_conflict_remove(git_index *index, const char *path);
/** /**
* Remove all conflicts in the index (entries with a stage greater than 0.) * Remove all conflicts in the index (entries with a stage greater than 0).
* *
* @param index an existing index object * @param index an existing index object
* @return 0 or an error code
*/ */
GIT_EXTERN(void) git_index_conflict_cleanup(git_index *index); GIT_EXTERN(int) git_index_conflict_cleanup(git_index *index);
/** /**
* Determine if the index contains entries representing file conflicts. * Determine if the index contains entries representing file conflicts.
...@@ -651,9 +653,12 @@ GIT_EXTERN(void) git_index_conflict_cleanup(git_index *index); ...@@ -651,9 +653,12 @@ GIT_EXTERN(void) git_index_conflict_cleanup(git_index *index);
GIT_EXTERN(int) git_index_has_conflicts(const git_index *index); GIT_EXTERN(int) git_index_has_conflicts(const git_index *index);
/** /**
* Create an iterator for the conflicts in the index. You may not modify the * Create an iterator for the conflicts in the index.
* index while iterating, the results are undefined. *
* The index must not be modified while iterating; the results are undefined.
* *
* @param iterator_out The newly created conflict iterator
* @param index The index to scan
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_index_conflict_iterator_new( GIT_EXTERN(int) git_index_conflict_iterator_new(
......
...@@ -1317,15 +1317,13 @@ int git_index_conflict_get( ...@@ -1317,15 +1317,13 @@ int git_index_conflict_get(
return 0; return 0;
} }
int git_index_conflict_remove(git_index *index, const char *path) static int index_conflict_remove(git_index *index, const char *path)
{ {
size_t pos; size_t pos = 0;
git_index_entry *conflict_entry; git_index_entry *conflict_entry;
int error = 0; int error = 0;
assert(index && path); if (path != NULL && git_index_find(&pos, index, path) < 0)
if (git_index_find(&pos, index, path) < 0)
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
if (git_mutex_lock(&index->lock) < 0) { if (git_mutex_lock(&index->lock) < 0) {
...@@ -1335,7 +1333,8 @@ int git_index_conflict_remove(git_index *index, const char *path) ...@@ -1335,7 +1333,8 @@ int git_index_conflict_remove(git_index *index, const char *path)
while ((conflict_entry = git_vector_get(&index->entries, pos)) != NULL) { while ((conflict_entry = git_vector_get(&index->entries, pos)) != NULL) {
if (index->entries_cmp_path(conflict_entry->path, path) != 0) if (path != NULL &&
index->entries_cmp_path(conflict_entry->path, path) != 0)
break; break;
if (GIT_IDXENTRY_STAGE(conflict_entry) == 0) { if (GIT_IDXENTRY_STAGE(conflict_entry) == 0) {
...@@ -1352,27 +1351,16 @@ int git_index_conflict_remove(git_index *index, const char *path) ...@@ -1352,27 +1351,16 @@ int git_index_conflict_remove(git_index *index, const char *path)
return error; return error;
} }
static int index_conflicts_match(const git_vector *v, size_t idx, void *p) int git_index_conflict_remove(git_index *index, const char *path)
{ {
git_index *index = p; assert(index && path);
git_index_entry *entry = git_vector_get(v, idx); return index_conflict_remove(index, path);
if (GIT_IDXENTRY_STAGE(entry) > 0 &&
!index_remove_entry(index, idx))
return 1;
return 0;
} }
void git_index_conflict_cleanup(git_index *index) int git_index_conflict_cleanup(git_index *index)
{ {
assert(index); assert(index);
return index_conflict_remove(index, NULL);
if (git_mutex_lock(&index->lock) < 0)
return;
git_vector_remove_matching(&index->entries, index_conflicts_match, index);
index_free_deleted(index);
git_mutex_unlock(&index->lock);
} }
int git_index_has_conflicts(const git_index *index) int git_index_has_conflicts(const git_index *index)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment