Skip to content

Commit f6ef8ba

Browse files
committed
Merge branch 'ph/use-delete-refs'
When removing many branches and tags, the code used to do so one ref at a time. There is another API it can use to delete multiple refs, and it makes quite a lot of performance difference when the refs are packed. * ph/use-delete-refs: use delete_refs when deleting tags or branches
2 parents 6254fa1 + 8198907 commit f6ef8ba

File tree

2 files changed

+62
-29
lines changed

2 files changed

+62
-29
lines changed

builtin/branch.c

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
202202
int remote_branch = 0;
203203
struct strbuf bname = STRBUF_INIT;
204204
unsigned allowed_interpret;
205+
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
206+
struct string_list_item *item;
207+
int branch_name_pos;
205208

206209
switch (kinds) {
207210
case FILTER_REFS_REMOTES:
@@ -219,6 +222,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
219222
default:
220223
die(_("cannot use -a with -d"));
221224
}
225+
branch_name_pos = strcspn(fmt, "%");
222226

223227
if (!force) {
224228
head_rev = lookup_commit_reference(the_repository, &head_oid);
@@ -265,30 +269,35 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
265269
goto next;
266270
}
267271

268-
if (delete_ref(NULL, name, is_null_oid(&oid) ? NULL : &oid,
269-
REF_NO_DEREF)) {
270-
error(remote_branch
271-
? _("Error deleting remote-tracking branch '%s'")
272-
: _("Error deleting branch '%s'"),
273-
bname.buf);
274-
ret = 1;
275-
goto next;
276-
}
277-
if (!quiet) {
278-
printf(remote_branch
279-
? _("Deleted remote-tracking branch %s (was %s).\n")
280-
: _("Deleted branch %s (was %s).\n"),
281-
bname.buf,
282-
(flags & REF_ISBROKEN) ? "broken"
283-
: (flags & REF_ISSYMREF) ? target
284-
: find_unique_abbrev(&oid, DEFAULT_ABBREV));
285-
}
286-
delete_branch_config(bname.buf);
272+
item = string_list_append(&refs_to_delete, name);
273+
item->util = xstrdup((flags & REF_ISBROKEN) ? "broken"
274+
: (flags & REF_ISSYMREF) ? target
275+
: find_unique_abbrev(&oid, DEFAULT_ABBREV));
287276

288277
next:
289278
free(target);
290279
}
291280

281+
if (delete_refs(NULL, &refs_to_delete, REF_NO_DEREF))
282+
ret = 1;
283+
284+
for_each_string_list_item(item, &refs_to_delete) {
285+
char *describe_ref = item->util;
286+
char *name = item->string;
287+
if (!ref_exists(name)) {
288+
char *refname = name + branch_name_pos;
289+
if (!quiet)
290+
printf(remote_branch
291+
? _("Deleted remote-tracking branch %s (was %s).\n")
292+
: _("Deleted branch %s (was %s).\n"),
293+
name + branch_name_pos, describe_ref);
294+
295+
delete_branch_config(refname);
296+
}
297+
free(describe_ref);
298+
}
299+
string_list_clear(&refs_to_delete, 0);
300+
292301
free(name);
293302
strbuf_release(&bname);
294303

builtin/tag.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
7272
}
7373

7474
typedef int (*each_tag_name_fn)(const char *name, const char *ref,
75-
const struct object_id *oid, const void *cb_data);
75+
const struct object_id *oid, void *cb_data);
7676

7777
static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
78-
const void *cb_data)
78+
void *cb_data)
7979
{
8080
const char **p;
8181
struct strbuf ref = STRBUF_INIT;
@@ -97,18 +97,42 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
9797
return had_error;
9898
}
9999

100-
static int delete_tag(const char *name, const char *ref,
101-
const struct object_id *oid, const void *cb_data)
100+
static int collect_tags(const char *name, const char *ref,
101+
const struct object_id *oid, void *cb_data)
102102
{
103-
if (delete_ref(NULL, ref, oid, 0))
104-
return 1;
105-
printf(_("Deleted tag '%s' (was %s)\n"), name,
106-
find_unique_abbrev(oid, DEFAULT_ABBREV));
103+
struct string_list *ref_list = cb_data;
104+
105+
string_list_append(ref_list, ref);
106+
ref_list->items[ref_list->nr - 1].util = oiddup(oid);
107107
return 0;
108108
}
109109

110+
static int delete_tags(const char **argv)
111+
{
112+
int result;
113+
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
114+
struct string_list_item *item;
115+
116+
result = for_each_tag_name(argv, collect_tags, (void *)&refs_to_delete);
117+
if (delete_refs(NULL, &refs_to_delete, REF_NO_DEREF))
118+
result = 1;
119+
120+
for_each_string_list_item(item, &refs_to_delete) {
121+
const char *name = item->string;
122+
struct object_id *oid = item->util;
123+
if (!ref_exists(name))
124+
printf(_("Deleted tag '%s' (was %s)\n"),
125+
item->string + 10,
126+
find_unique_abbrev(oid, DEFAULT_ABBREV));
127+
128+
free(oid);
129+
}
130+
string_list_clear(&refs_to_delete, 0);
131+
return result;
132+
}
133+
110134
static int verify_tag(const char *name, const char *ref,
111-
const struct object_id *oid, const void *cb_data)
135+
const struct object_id *oid, void *cb_data)
112136
{
113137
int flags;
114138
const struct ref_format *format = cb_data;
@@ -512,7 +536,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
512536
if (filter.reachable_from || filter.unreachable_from)
513537
die(_("--merged and --no-merged options are only allowed in list mode"));
514538
if (cmdmode == 'd')
515-
return for_each_tag_name(argv, delete_tag, NULL);
539+
return delete_tags(argv);
516540
if (cmdmode == 'v') {
517541
if (format.format && verify_ref_format(&format))
518542
usage_with_options(git_tag_usage, options);

0 commit comments

Comments
 (0)