summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2014-06-01 02:16:07 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2014-06-01 02:16:07 +0200
commit8a9419aae185204c9f727285643ab99b1b968610 (patch)
tree3a7925b6855b79c1c62a0e165200291050839477
parent9bc2813bef35ad69dd2a1d491b953ab4d5bf6137 (diff)
downloadlibgit2-8a9419aae185204c9f727285643ab99b1b968610.tar.gz
remote: build up the list of refs to removecmn/remote-delete
When removing the remote-tracking branches, build up the list and remove in two steps, working around an issue with the iterator. Removing while we're iterating over the refs can cause us to miss references.
-rw-r--r--src/remote.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/src/remote.c b/src/remote.c
index f2e2e2f7a..b56bf3b24 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -1809,24 +1809,50 @@ static int remove_branch_config_related_entries(
return error;
}
-static int remove_refs(git_repository *repo, const char *glob)
+static int remove_refs(git_repository *repo, const git_refspec *spec)
{
- git_reference_iterator *iter;
+ git_reference_iterator *iter = NULL;
+ git_vector refs;
const char *name;
+ char *dup;
int error;
+ size_t i;
- if ((error = git_reference_iterator_glob_new(&iter, repo, glob)) < 0)
+ if ((error = git_vector_init(&refs, 8, NULL)) < 0)
return error;
+ if ((error = git_reference_iterator_new(&iter, repo)) < 0)
+ goto cleanup;
+
while ((error = git_reference_next_name(&name, iter)) == 0) {
- if ((error = git_reference_remove(repo, name)) < 0)
- break;
- }
- git_reference_iterator_free(iter);
+ if (!git_refspec_dst_matches(spec, name))
+ continue;
+
+ dup = git__strdup(name);
+ if (!dup) {
+ error = -1;
+ goto cleanup;
+ }
+ if ((error = git_vector_insert(&refs, dup)) < 0)
+ goto cleanup;
+ }
if (error == GIT_ITEROVER)
error = 0;
+ if (error < 0)
+ goto cleanup;
+
+ git_vector_foreach(&refs, i, name) {
+ if ((error = git_reference_remove(repo, name)) < 0)
+ break;
+ }
+cleanup:
+ git_reference_iterator_free(iter);
+ git_vector_foreach(&refs, i, dup) {
+ git__free(dup);
+ }
+ git_vector_free(&refs);
return error;
}
@@ -1848,7 +1874,7 @@ static int remove_remote_tracking(git_repository *repo, const char *remote_name)
if (refspec == NULL)
continue;
- if ((error = remove_refs(repo, git_refspec_dst(refspec))) < 0)
+ if ((error = remove_refs(repo, refspec)) < 0)
break;
}