mirror of
https://github.com/git/git.git
synced 2024-11-23 18:05:29 +08:00
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>
This commit is contained in:
parent
c9e768bb77
commit
e6bea66db6
@ -1313,6 +1313,7 @@ static int prune_remote(const char *remote, int dry_run)
|
||||
{
|
||||
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 @@ static int prune_remote(const char *remote, int dry_run)
|
||||
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 @@ static int prune_remote(const char *remote, int dry_run)
|
||||
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;
|
||||
}
|
||||
|
19
refs.c
19
refs.c
@ -1611,6 +1611,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
|
||||
struct warn_if_dangling_data {
|
||||
FILE *fp;
|
||||
const char *refname;
|
||||
const struct string_list *refnames;
|
||||
const char *msg_fmt;
|
||||
};
|
||||
|
||||
@ -1625,8 +1626,12 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha
|
||||
return 0;
|
||||
|
||||
resolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);
|
||||
if (!resolves_to || strcmp(resolves_to, d->refname))
|
||||
if (!resolves_to
|
||||
|| (d->refname
|
||||
? strcmp(resolves_to, d->refname)
|
||||
: !string_list_has_string(d->refnames, resolves_to))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(d->fp, d->msg_fmt, refname);
|
||||
fputc('\n', d->fp);
|
||||
@ -1639,6 +1644,18 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
|
||||
|
||||
data.fp = fp;
|
||||
data.refname = refname;
|
||||
data.refnames = NULL;
|
||||
data.msg_fmt = msg_fmt;
|
||||
for_each_rawref(warn_if_dangling_symref, &data);
|
||||
}
|
||||
|
||||
void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
|
||||
{
|
||||
struct warn_if_dangling_data data;
|
||||
|
||||
data.fp = fp;
|
||||
data.refname = NULL;
|
||||
data.refnames = refnames;
|
||||
data.msg_fmt = msg_fmt;
|
||||
for_each_rawref(warn_if_dangling_symref, &data);
|
||||
}
|
||||
|
1
refs.h
1
refs.h
@ -89,6 +89,7 @@ static inline const char *has_glob_specials(const char *pattern)
|
||||
extern int for_each_rawref(each_ref_fn, void *);
|
||||
|
||||
extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname);
|
||||
extern void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list* refnames);
|
||||
|
||||
/*
|
||||
* Lock the packed-refs file for writing. Flags is passed to
|
||||
|
Loading…
Reference in New Issue
Block a user