Skip to content

Commit 7b625c2

Browse files
committed
Merge branch 'ph/fetch-prune-optim'
"git fetch --prune" used to be O(n^2) expensive when there are many refs, which has been corrected. * ph/fetch-prune-optim: clean up interface for refs_warn_dangling_symrefs refs: remove old refs_warn_dangling_symref fetch-prune: optimize dangling-ref reporting
2 parents 32571a0 + 87d8d8c commit 7b625c2

File tree

4 files changed

+23
-40
lines changed

4 files changed

+23
-40
lines changed

builtin/fetch.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,9 +1340,10 @@ static int prune_refs(struct display_state *display_state,
13401340
int result = 0;
13411341
struct ref *ref, *stale_refs = get_stale_heads(rs, ref_map);
13421342
struct strbuf err = STRBUF_INIT;
1343-
const char *dangling_msg = dry_run
1344-
? _(" (%s will become dangling)")
1345-
: _(" (%s has become dangling)");
1343+
struct string_list refnames = STRING_LIST_INIT_NODUP;
1344+
1345+
for (ref = stale_refs; ref; ref = ref->next)
1346+
string_list_append(&refnames, ref->name);
13461347

13471348
if (!dry_run) {
13481349
if (transaction) {
@@ -1353,15 +1354,9 @@ static int prune_refs(struct display_state *display_state,
13531354
goto cleanup;
13541355
}
13551356
} else {
1356-
struct string_list refnames = STRING_LIST_INIT_NODUP;
1357-
1358-
for (ref = stale_refs; ref; ref = ref->next)
1359-
string_list_append(&refnames, ref->name);
1360-
13611357
result = refs_delete_refs(get_main_ref_store(the_repository),
13621358
"fetch: prune", &refnames,
13631359
0);
1364-
string_list_clear(&refnames, 0);
13651360
}
13661361
}
13671362

@@ -1373,12 +1368,14 @@ static int prune_refs(struct display_state *display_state,
13731368
_("(none)"), ref->name,
13741369
&ref->new_oid, &ref->old_oid,
13751370
summary_width);
1376-
refs_warn_dangling_symref(get_main_ref_store(the_repository),
1377-
stderr, dangling_msg, ref->name);
13781371
}
1372+
string_list_sort(&refnames);
1373+
refs_warn_dangling_symrefs(get_main_ref_store(the_repository),
1374+
stderr, " ", dry_run, &refnames);
13791375
}
13801376

13811377
cleanup:
1378+
string_list_clear(&refnames, 0);
13821379
strbuf_release(&err);
13831380
free_refs(stale_refs);
13841381
return result;

builtin/remote.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,9 +1521,6 @@ static int prune_remote(const char *remote, int dry_run)
15211521
struct ref_states states = REF_STATES_INIT;
15221522
struct string_list refs_to_prune = STRING_LIST_INIT_NODUP;
15231523
struct string_list_item *item;
1524-
const char *dangling_msg = dry_run
1525-
? _(" %s will become dangling!")
1526-
: _(" %s has become dangling!");
15271524

15281525
get_remote_ref_states(remote, &states, GET_REF_STATES);
15291526

@@ -1555,7 +1552,7 @@ static int prune_remote(const char *remote, int dry_run)
15551552
}
15561553

15571554
refs_warn_dangling_symrefs(get_main_ref_store(the_repository),
1558-
stdout, dangling_msg, &refs_to_prune);
1555+
stdout, " ", dry_run, &refs_to_prune);
15591556

15601557
string_list_clear(&refs_to_prune, 0);
15611558
free_remote_ref_states(&states);

refs.c

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -439,54 +439,44 @@ static int for_each_filter_refs(const char *refname, const char *referent,
439439
struct warn_if_dangling_data {
440440
struct ref_store *refs;
441441
FILE *fp;
442-
const char *refname;
443442
const struct string_list *refnames;
444-
const char *msg_fmt;
443+
const char *indent;
444+
int dry_run;
445445
};
446446

447447
static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED,
448448
const struct object_id *oid UNUSED,
449449
int flags, void *cb_data)
450450
{
451451
struct warn_if_dangling_data *d = cb_data;
452-
const char *resolves_to;
452+
const char *resolves_to, *msg;
453453

454454
if (!(flags & REF_ISSYMREF))
455455
return 0;
456456

457457
resolves_to = refs_resolve_ref_unsafe(d->refs, refname, 0, NULL, NULL);
458458
if (!resolves_to
459-
|| (d->refname
460-
? strcmp(resolves_to, d->refname)
461-
: !string_list_has_string(d->refnames, resolves_to))) {
459+
|| !string_list_has_string(d->refnames, resolves_to)) {
462460
return 0;
463461
}
464462

465-
fprintf(d->fp, d->msg_fmt, refname);
466-
fputc('\n', d->fp);
463+
msg = d->dry_run
464+
? _("%s%s will become dangling after %s is deleted\n")
465+
: _("%s%s has become dangling after %s was deleted\n");
466+
fprintf(d->fp, msg, d->indent, refname, resolves_to);
467467
return 0;
468468
}
469469

470-
void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp,
471-
const char *msg_fmt, const char *refname)
472-
{
473-
struct warn_if_dangling_data data = {
474-
.refs = refs,
475-
.fp = fp,
476-
.refname = refname,
477-
.msg_fmt = msg_fmt,
478-
};
479-
refs_for_each_rawref(refs, warn_if_dangling_symref, &data);
480-
}
481-
482470
void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,
483-
const char *msg_fmt, const struct string_list *refnames)
471+
const char *indent, int dry_run,
472+
const struct string_list *refnames)
484473
{
485474
struct warn_if_dangling_data data = {
486475
.refs = refs,
487476
.fp = fp,
488477
.refnames = refnames,
489-
.msg_fmt = msg_fmt,
478+
.indent = indent,
479+
.dry_run = dry_run,
490480
};
491481
refs_for_each_rawref(refs, warn_if_dangling_symref, &data);
492482
}

refs.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,9 @@ static inline const char *has_glob_specials(const char *pattern)
452452
return strpbrk(pattern, "?*[");
453453
}
454454

455-
void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp,
456-
const char *msg_fmt, const char *refname);
457455
void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,
458-
const char *msg_fmt, const struct string_list *refnames);
456+
const char *indent, int dry_run,
457+
const struct string_list *refnames);
459458

460459
/*
461460
* Flags for controlling behaviour of pack_refs()

0 commit comments

Comments
 (0)