remote prune: optimize "dangling symref" check/warning

When 'git remote prune' was used to delete many refs in a repository
with many refs, a lot of time was spent checking for (now) dangling
symbolic refs pointing to the deleted ref, since warn_dangling_symref()
was once per deleted ref to check all other refs in the repository.

Avoid this using the new warn_dangling_symrefs() function which
makes one pass over all refs and checks for all the deleted refs in
one go, after they have all been deleted.

Signed-off-by: Jens Lindström <jl@opera.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/builtin/remote.c b/builtin/remote.c
index d33abe6..9b3e368 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1313,6 +1313,7 @@
 {
 	int result = 0, i;
 	struct ref_states states;
+	struct string_list delete_refs_list = STRING_LIST_INIT_NODUP;
 	const char **delete_refs;
 	const char *dangling_msg = dry_run
 		? _(" %s will become dangling!")
@@ -1339,6 +1340,8 @@
 	for (i = 0; i < states.stale.nr; i++) {
 		const char *refname = states.stale.items[i].util;
 
+		string_list_insert(&delete_refs_list, refname);
+
 		if (!dry_run)
 			result |= delete_ref(refname, NULL, 0);
 
@@ -1348,9 +1351,11 @@
 		else
 			printf_ln(_(" * [pruned] %s"),
 			       abbrev_ref(refname, "refs/remotes/"));
-		warn_dangling_symref(stdout, dangling_msg, refname);
 	}
 
+	warn_dangling_symrefs(stdout, dangling_msg, &delete_refs_list);
+	string_list_clear(&delete_refs_list, 0);
+
 	free_remote_ref_states(&states);
 	return result;
 }