diff options
author | Jens Lindström <jl@opera.com> | 2014-05-23 12:29:45 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-05-27 12:30:42 -0700 |
commit | c9e768bb77762765f739fffb5c09d0888f3de20e (patch) | |
tree | ec3e7555084a3d62830bbef801590ce64cada955 /builtin/remote.c | |
parent | b07bdd3472886cbdd412ee3e7489273522c43133 (diff) | |
download | git-c9e768bb77762765f739fffb5c09d0888f3de20e.tar.gz git-c9e768bb77762765f739fffb5c09d0888f3de20e.tar.xz |
remote: repack packed-refs once when deleting multiple refs
When 'git remote rm' or 'git remote prune' were used in a repository
with many refs, and needed to delete many remote-tracking refs, a lot
of time was spent deleting those refs since for each deleted ref,
repack_without_refs() was called to rewrite packed-refs without just
that deleted ref.
To avoid this, call repack_without_refs() first to repack without all
the refs that will be deleted, before calling delete_ref() to delete
each one completely. The call to repack_without_ref() in delete_ref()
then becomes a no-op, since packed-refs already won't contain any of
the deleted refs.
Signed-off-by: Jens Lindström <jl@opera.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/remote.c')
-rw-r--r-- | builtin/remote.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/builtin/remote.c b/builtin/remote.c index 84802cd0a..d33abe659 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -749,15 +749,23 @@ static int mv(int argc, const char **argv) static int remove_branches(struct string_list *branches) { + const char **branch_names; int i, result = 0; + + branch_names = xmalloc(branches->nr * sizeof(*branch_names)); + for (i = 0; i < branches->nr; i++) + branch_names[i] = branches->items[i].string; + result |= repack_without_refs(branch_names, branches->nr); + free(branch_names); + for (i = 0; i < branches->nr; i++) { struct string_list_item *item = branches->items + i; const char *refname = item->string; - unsigned char *sha1 = item->util; - if (delete_ref(refname, sha1, 0)) + if (delete_ref(refname, NULL, 0)) result |= error(_("Could not remove branch %s"), refname); } + return result; } @@ -1305,6 +1313,7 @@ static int prune_remote(const char *remote, int dry_run) { int result = 0, i; struct ref_states states; + const char **delete_refs; const char *dangling_msg = dry_run ? _(" %s will become dangling!") : _(" %s has become dangling!"); @@ -1318,6 +1327,13 @@ static int prune_remote(const char *remote, int dry_run) states.remote->url_nr ? states.remote->url[0] : _("(no URL)")); + + delete_refs = xmalloc(states.stale.nr * sizeof(*delete_refs)); + for (i = 0; i < states.stale.nr; i++) + delete_refs[i] = states.stale.items[i].util; + if (!dry_run) + result |= repack_without_refs(delete_refs, states.stale.nr); + free(delete_refs); } for (i = 0; i < states.stale.nr; i++) { |