mirror of
https://github.com/git/git.git
synced 2026-03-01 18:24:00 +01:00
Merge branch 'ps/refs-for-each' into jch
Code refactoring around refs-for-each-* API functions. * ps/refs-for-each: refs: replace `refs_for_each_fullref_in()` refs: replace `refs_for_each_namespaced_ref()` refs: replace `refs_for_each_glob_ref()` refs: replace `refs_for_each_glob_ref_in()` refs: replace `refs_for_each_rawref_in()` refs: replace `refs_for_each_rawref()` refs: replace `refs_for_each_ref_in()` refs: improve verification for-each-ref options refs: generalize `refs_for_each_fullref_in_prefixes()` refs: generalize `refs_for_each_namespaced_ref()` refs: speed up `refs_for_each_glob_ref_in()` refs: introduce `refs_for_each_ref_ext` refs: rename `each_ref_fn` refs: rename `do_for_each_ref_flags` refs: move `do_for_each_ref_flags` further up refs: move `refs_head_ref_namespaced()` refs: remove unused `refs_for_each_include_root_ref()`
This commit is contained in:
16
bisect.c
16
bisect.c
@@ -473,8 +473,12 @@ static int register_ref(const struct reference *ref, void *cb_data UNUSED)
|
||||
|
||||
static int read_bisect_refs(void)
|
||||
{
|
||||
return refs_for_each_ref_in(get_main_ref_store(the_repository),
|
||||
"refs/bisect/", register_ref, NULL);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/bisect/",
|
||||
.trim_prefix = strlen("refs/bisect/"),
|
||||
};
|
||||
return refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
register_ref, NULL, &opts);
|
||||
}
|
||||
|
||||
static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
|
||||
@@ -1186,13 +1190,15 @@ static int mark_for_removal(const struct reference *ref, void *cb_data)
|
||||
|
||||
int bisect_clean_state(void)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/bisect/",
|
||||
};
|
||||
int result = 0;
|
||||
|
||||
/* There may be some refs packed during bisection */
|
||||
struct string_list refs_for_removal = STRING_LIST_INIT_DUP;
|
||||
refs_for_each_fullref_in(get_main_ref_store(the_repository),
|
||||
"refs/bisect/", NULL, mark_for_removal,
|
||||
&refs_for_removal);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
mark_for_removal, &refs_for_removal, &opts);
|
||||
string_list_append(&refs_for_removal, "BISECT_HEAD");
|
||||
string_list_append(&refs_for_removal, "BISECT_EXPECTED_REV");
|
||||
result = refs_delete_refs(get_main_ref_store(the_repository),
|
||||
|
||||
@@ -422,13 +422,17 @@ static void bisect_status(struct bisect_state *state,
|
||||
{
|
||||
char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
|
||||
char *good_glob = xstrfmt("%s-*", terms->term_good);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.pattern = good_glob,
|
||||
.prefix = "refs/bisect/",
|
||||
.trim_prefix = strlen("refs/bisect/"),
|
||||
};
|
||||
|
||||
if (refs_ref_exists(get_main_ref_store(the_repository), bad_ref))
|
||||
state->nr_bad = 1;
|
||||
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository), inc_nr,
|
||||
good_glob, "refs/bisect/",
|
||||
(void *) &state->nr_good);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
inc_nr, &state->nr_good, &opts);
|
||||
|
||||
free(good_glob);
|
||||
free(bad_ref);
|
||||
@@ -562,6 +566,10 @@ static int add_bisect_ref(const struct reference *ref, void *cb)
|
||||
|
||||
static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/bisect/",
|
||||
.trim_prefix = strlen("refs/bisect/"),
|
||||
};
|
||||
int res = 0;
|
||||
struct add_bisect_ref_data cb = { revs };
|
||||
char *good = xstrfmt("%s-*", terms->term_good);
|
||||
@@ -581,11 +589,16 @@ static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
|
||||
reset_revision_walk();
|
||||
repo_init_revisions(the_repository, revs, NULL);
|
||||
setup_revisions(0, NULL, revs, NULL);
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
|
||||
add_bisect_ref, bad, "refs/bisect/", &cb);
|
||||
|
||||
opts.pattern = bad;
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
add_bisect_ref, &cb, &opts);
|
||||
|
||||
cb.object_flags = UNINTERESTING;
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
|
||||
add_bisect_ref, good, "refs/bisect/", &cb);
|
||||
opts.pattern = good;
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
add_bisect_ref, &cb, &opts);
|
||||
|
||||
if (prepare_revision_walk(revs))
|
||||
res = error(_("revision walk setup failed"));
|
||||
|
||||
@@ -1191,10 +1204,14 @@ static int verify_good(const struct bisect_terms *terms, const char *command)
|
||||
char *good_glob = xstrfmt("%s-*", terms->term_good);
|
||||
int no_checkout = refs_ref_exists(get_main_ref_store(the_repository),
|
||||
"BISECT_HEAD");
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.pattern = good_glob,
|
||||
.prefix = "refs/bisect/",
|
||||
.trim_prefix = strlen("refs/bisect/"),
|
||||
};
|
||||
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
|
||||
get_first_good, good_glob, "refs/bisect/",
|
||||
&good_rev);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
get_first_good, &good_rev, &opts);
|
||||
free(good_glob);
|
||||
|
||||
if (refs_read_ref(get_main_ref_store(the_repository), no_checkout ? "BISECT_HEAD" : "HEAD", ¤t_rev))
|
||||
|
||||
@@ -641,6 +641,9 @@ int cmd_describe(int argc,
|
||||
const char *prefix,
|
||||
struct repository *repo UNUSED )
|
||||
{
|
||||
struct refs_for_each_ref_options for_each_ref_opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
int contains = 0;
|
||||
struct option options[] = {
|
||||
OPT_BOOL(0, "contains", &contains, N_("find the tag that comes after the commit")),
|
||||
@@ -738,8 +741,8 @@ int cmd_describe(int argc,
|
||||
}
|
||||
|
||||
hashmap_init(&names, commit_name_neq, NULL, 0);
|
||||
refs_for_each_rawref(get_main_ref_store(the_repository), get_name,
|
||||
NULL);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
get_name, NULL, &for_each_ref_opts);
|
||||
if (!hashmap_get_size(&names) && !always)
|
||||
die(_("No names found, cannot describe anything."));
|
||||
|
||||
|
||||
@@ -1541,6 +1541,9 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
|
||||
|
||||
for (i = 0; i < negotiation_tip.nr; i++) {
|
||||
const char *s = negotiation_tip.items[i].string;
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.pattern = s,
|
||||
};
|
||||
int old_nr;
|
||||
if (!has_glob_specials(s)) {
|
||||
struct object_id oid;
|
||||
@@ -1552,8 +1555,8 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
|
||||
continue;
|
||||
}
|
||||
old_nr = oids->nr;
|
||||
refs_for_each_glob_ref(get_main_ref_store(the_repository),
|
||||
add_oid, s, oids);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
add_oid, oids, &opts);
|
||||
if (old_nr == oids->nr)
|
||||
warning("ignoring --negotiation-tip=%s because it does not match any refs",
|
||||
s);
|
||||
|
||||
@@ -582,6 +582,9 @@ static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
|
||||
|
||||
static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
struct worktree **worktrees, **p;
|
||||
const char *head_points_at;
|
||||
struct object_id head_oid;
|
||||
@@ -607,8 +610,8 @@ static void snapshot_refs(struct snapshot *snap, int argc, const char **argv)
|
||||
return;
|
||||
}
|
||||
|
||||
refs_for_each_rawref(get_main_ref_store(the_repository),
|
||||
snapshot_ref, snap);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
snapshot_ref, snap, &opts);
|
||||
|
||||
worktrees = get_worktrees();
|
||||
for (p = worktrees; *p; p++) {
|
||||
|
||||
@@ -343,9 +343,9 @@ static void show_one_alternate_ref(const struct object_id *oid,
|
||||
|
||||
static void write_head_info(void)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = { 0 };
|
||||
static struct oidset seen = OIDSET_INIT;
|
||||
struct strvec excludes_vector = STRVEC_INIT;
|
||||
const char **exclude_patterns;
|
||||
|
||||
/*
|
||||
* We need access to the reference names both with and without their
|
||||
@@ -353,12 +353,12 @@ static void write_head_info(void)
|
||||
* thus have to adapt exclude patterns to carry the namespace prefix
|
||||
* ourselves.
|
||||
*/
|
||||
exclude_patterns = get_namespaced_exclude_patterns(
|
||||
opts.exclude_patterns = get_namespaced_exclude_patterns(
|
||||
hidden_refs_to_excludes(&hidden_refs),
|
||||
get_git_namespace(), &excludes_vector);
|
||||
|
||||
refs_for_each_fullref_in(get_main_ref_store(the_repository), "",
|
||||
exclude_patterns, show_ref_cb, &seen);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
show_ref_cb, &seen, &opts);
|
||||
odb_for_each_alternate_ref(the_repository->objects,
|
||||
show_one_alternate_ref, &seen);
|
||||
|
||||
|
||||
@@ -912,6 +912,9 @@ static int mv(int argc, const char **argv, const char *prefix,
|
||||
old_remote_context.buf);
|
||||
|
||||
if (refspecs_need_update) {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
rename.transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
|
||||
0, &err);
|
||||
if (!rename.transaction)
|
||||
@@ -923,9 +926,10 @@ static int mv(int argc, const char **argv, const char *prefix,
|
||||
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "refs/remotes/%s/", rename.old_name);
|
||||
opts.prefix = buf.buf;
|
||||
|
||||
result = refs_for_each_rawref_in(get_main_ref_store(the_repository), buf.buf,
|
||||
rename_one_ref, &rename);
|
||||
result = refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
rename_one_ref, &rename, &opts);
|
||||
if (result < 0)
|
||||
die(_("queueing remote ref renames failed: %s"), rename.err->buf);
|
||||
|
||||
|
||||
@@ -613,13 +613,22 @@ static int opt_with_value(const char *arg, const char *opt, const char **value)
|
||||
|
||||
static void handle_ref_opt(const char *pattern, const char *prefix)
|
||||
{
|
||||
if (pattern)
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
|
||||
show_reference, pattern, prefix,
|
||||
NULL);
|
||||
else
|
||||
refs_for_each_ref_in(get_main_ref_store(the_repository),
|
||||
prefix, show_reference, NULL);
|
||||
if (pattern) {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.pattern = pattern,
|
||||
.prefix = prefix,
|
||||
.trim_prefix = prefix ? strlen(prefix) : 0,
|
||||
};
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
show_reference, NULL, &opts);
|
||||
} else {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = prefix,
|
||||
.trim_prefix = strlen(prefix),
|
||||
};
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
show_reference, NULL, &opts);
|
||||
}
|
||||
clear_ref_exclusions(&ref_excludes);
|
||||
}
|
||||
|
||||
@@ -931,14 +940,13 @@ int cmd_rev_parse(int argc,
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--bisect")) {
|
||||
refs_for_each_fullref_in(get_main_ref_store(the_repository),
|
||||
"refs/bisect/bad",
|
||||
NULL, show_reference,
|
||||
NULL);
|
||||
refs_for_each_fullref_in(get_main_ref_store(the_repository),
|
||||
"refs/bisect/good",
|
||||
NULL, anti_reference,
|
||||
NULL);
|
||||
struct refs_for_each_ref_options opts = { 0 };
|
||||
opts.prefix = "refs/bisect/bad";
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
show_reference, NULL, &opts);
|
||||
opts.prefix = "refs/bisect/good";
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
anti_reference, NULL, &opts);
|
||||
continue;
|
||||
}
|
||||
if (opt_with_value(arg, "--branches", &arg)) {
|
||||
|
||||
@@ -215,14 +215,19 @@ static int cmd_show_ref__patterns(const struct patterns_options *opts,
|
||||
refs_head_ref(get_main_ref_store(the_repository), show_ref,
|
||||
&show_ref_data);
|
||||
if (opts->branches_only || opts->tags_only) {
|
||||
if (opts->branches_only)
|
||||
refs_for_each_fullref_in(get_main_ref_store(the_repository),
|
||||
"refs/heads/", NULL,
|
||||
show_ref, &show_ref_data);
|
||||
if (opts->tags_only)
|
||||
refs_for_each_fullref_in(get_main_ref_store(the_repository),
|
||||
"refs/tags/", NULL, show_ref,
|
||||
&show_ref_data);
|
||||
struct refs_for_each_ref_options for_each_ref_opts = { 0 };
|
||||
|
||||
if (opts->branches_only) {
|
||||
for_each_ref_opts.prefix = "refs/heads/";
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
show_ref, &show_ref_data, &for_each_ref_opts);
|
||||
}
|
||||
|
||||
if (opts->tags_only) {
|
||||
for_each_ref_opts.prefix = "refs/tags/";
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
show_ref, &show_ref_data, &for_each_ref_opts);
|
||||
}
|
||||
} else {
|
||||
refs_for_each_ref(get_main_ref_store(the_repository),
|
||||
show_ref, &show_ref_data);
|
||||
|
||||
15
fetch-pack.c
15
fetch-pack.c
@@ -293,11 +293,14 @@ static int next_flush(int stateless_rpc, int count)
|
||||
static void mark_tips(struct fetch_negotiator *negotiator,
|
||||
const struct oid_array *negotiation_tips)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
int i;
|
||||
|
||||
if (!negotiation_tips) {
|
||||
refs_for_each_rawref(get_main_ref_store(the_repository),
|
||||
rev_list_insert_ref_oid, negotiator);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
rev_list_insert_ref_oid, negotiator, &opts);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -793,8 +796,12 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
|
||||
*/
|
||||
trace2_region_enter("fetch-pack", "mark_complete_local_refs", NULL);
|
||||
if (!args->deepen) {
|
||||
refs_for_each_rawref(get_main_ref_store(the_repository),
|
||||
mark_complete_oid, NULL);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
mark_complete_oid, NULL, &opts);
|
||||
for_each_cached_alternate(NULL, mark_alternate_complete);
|
||||
if (cutoff)
|
||||
mark_recent_complete_commits(args, cutoff);
|
||||
|
||||
@@ -565,9 +565,13 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
|
||||
run_service(argv, 0);
|
||||
|
||||
} else {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.namespace = get_git_namespace(),
|
||||
};
|
||||
|
||||
select_getanyfile(hdr);
|
||||
refs_for_each_namespaced_ref(get_main_ref_store(the_repository),
|
||||
NULL, show_text_ref, &buf);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
show_text_ref, &buf, &opts);
|
||||
send_strbuf(hdr, "text/plain", &buf);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
|
||||
11
ls-refs.c
11
ls-refs.c
@@ -160,6 +160,7 @@ static int ls_refs_config(const char *var, const char *value,
|
||||
|
||||
int ls_refs(struct repository *r, struct packet_reader *request)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = { 0 };
|
||||
struct ls_refs_data data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
@@ -201,10 +202,12 @@ int ls_refs(struct repository *r, struct packet_reader *request)
|
||||
send_possibly_unborn_head(&data);
|
||||
if (!data.prefixes.nr)
|
||||
strvec_push(&data.prefixes, "");
|
||||
refs_for_each_fullref_in_prefixes(get_main_ref_store(r),
|
||||
get_git_namespace(), data.prefixes.v,
|
||||
hidden_refs_to_excludes(&data.hidden_refs),
|
||||
send_ref, &data);
|
||||
|
||||
opts.exclude_patterns = hidden_refs_to_excludes(&data.hidden_refs);
|
||||
opts.namespace = get_git_namespace();
|
||||
|
||||
refs_for_each_ref_in_prefixes(get_main_ref_store(r), data.prefixes.v,
|
||||
&opts, send_ref, &data);
|
||||
packet_fflush(stdout);
|
||||
strvec_clear(&data.prefixes);
|
||||
strbuf_release(&data.buf);
|
||||
|
||||
7
notes.c
7
notes.c
@@ -952,8 +952,11 @@ void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
|
||||
{
|
||||
assert(list->strdup_strings);
|
||||
if (has_glob_specials(glob)) {
|
||||
refs_for_each_glob_ref(get_main_ref_store(the_repository),
|
||||
string_list_add_one_ref, glob, list);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.pattern = glob,
|
||||
};
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
string_list_add_one_ref, list, &opts);
|
||||
} else {
|
||||
struct object_id oid;
|
||||
if (repo_get_oid(the_repository, glob, &oid))
|
||||
|
||||
@@ -3324,8 +3324,9 @@ static const struct string_list *bitmap_preferred_tips(struct repository *r)
|
||||
}
|
||||
|
||||
void for_each_preferred_bitmap_tip(struct repository *repo,
|
||||
each_ref_fn cb, void *cb_data)
|
||||
refs_for_each_cb cb, void *cb_data)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = { 0 };
|
||||
struct string_list_item *item;
|
||||
const struct string_list *preferred_tips;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
@@ -3335,16 +3336,16 @@ void for_each_preferred_bitmap_tip(struct repository *repo,
|
||||
return;
|
||||
|
||||
for_each_string_list_item(item, preferred_tips) {
|
||||
const char *pattern = item->string;
|
||||
opts.prefix = item->string;
|
||||
|
||||
if (!ends_with(pattern, "/")) {
|
||||
if (!ends_with(opts.prefix, "/")) {
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addf(&buf, "%s/", pattern);
|
||||
pattern = buf.buf;
|
||||
strbuf_addf(&buf, "%s/", opts.prefix);
|
||||
opts.prefix = buf.buf;
|
||||
}
|
||||
|
||||
refs_for_each_ref_in(get_main_ref_store(repo),
|
||||
pattern, cb, cb_data);
|
||||
refs_for_each_ref_ext(get_main_ref_store(repo),
|
||||
cb, cb_data, &opts);
|
||||
}
|
||||
|
||||
strbuf_release(&buf);
|
||||
|
||||
@@ -105,7 +105,7 @@ int for_each_bitmapped_object(struct bitmap_index *bitmap_git,
|
||||
* "pack.preferBitmapTips" and invoke the callback on each function.
|
||||
*/
|
||||
void for_each_preferred_bitmap_tip(struct repository *repo,
|
||||
each_ref_fn cb, void *cb_data);
|
||||
refs_for_each_cb cb, void *cb_data);
|
||||
|
||||
#define GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL \
|
||||
"GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL"
|
||||
|
||||
19
ref-filter.c
19
ref-filter.c
@@ -2762,7 +2762,7 @@ static int start_ref_iterator_after(struct ref_iterator *iter, const char *marke
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int for_each_fullref_with_seek(struct ref_filter *filter, each_ref_fn cb,
|
||||
static int for_each_fullref_with_seek(struct ref_filter *filter, refs_for_each_cb cb,
|
||||
void *cb_data, unsigned int flags)
|
||||
{
|
||||
struct ref_iterator *iter;
|
||||
@@ -2785,13 +2785,17 @@ static int for_each_fullref_with_seek(struct ref_filter *filter, each_ref_fn cb,
|
||||
* pattern match, so the callback still has to match each ref individually.
|
||||
*/
|
||||
static int for_each_fullref_in_pattern(struct ref_filter *filter,
|
||||
each_ref_fn cb,
|
||||
refs_for_each_cb cb,
|
||||
void *cb_data)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.exclude_patterns = filter->exclude.v,
|
||||
};
|
||||
|
||||
if (filter->kind & FILTER_REFS_ROOT_REFS) {
|
||||
/* In this case, we want to print all refs including root refs. */
|
||||
return for_each_fullref_with_seek(filter, cb, cb_data,
|
||||
DO_FOR_EACH_INCLUDE_ROOT_REFS);
|
||||
REFS_FOR_EACH_INCLUDE_ROOT_REFS);
|
||||
}
|
||||
|
||||
if (!filter->match_as_path) {
|
||||
@@ -2817,10 +2821,9 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
|
||||
return for_each_fullref_with_seek(filter, cb, cb_data, 0);
|
||||
}
|
||||
|
||||
return refs_for_each_fullref_in_prefixes(get_main_ref_store(the_repository),
|
||||
NULL, filter->name_patterns,
|
||||
filter->exclude.v,
|
||||
cb, cb_data);
|
||||
return refs_for_each_ref_in_prefixes(get_main_ref_store(the_repository),
|
||||
filter->name_patterns, &opts,
|
||||
cb, cb_data);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3284,7 +3287,7 @@ void filter_is_base(struct repository *r,
|
||||
free(bases);
|
||||
}
|
||||
|
||||
static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref_fn fn, void *cb_data)
|
||||
static int do_filter_refs(struct ref_filter *filter, unsigned int type, refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
const char *prefix = NULL;
|
||||
int ret = 0;
|
||||
|
||||
287
refs.c
287
refs.c
@@ -443,8 +443,8 @@ char *refs_resolve_refdup(struct ref_store *refs,
|
||||
/* The argument to for_each_filter_refs */
|
||||
struct for_each_ref_filter {
|
||||
const char *pattern;
|
||||
const char *prefix;
|
||||
each_ref_fn *fn;
|
||||
size_t trim_prefix;
|
||||
refs_for_each_cb *fn;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
@@ -474,9 +474,11 @@ static int for_each_filter_refs(const struct reference *ref, void *data)
|
||||
|
||||
if (wildmatch(filter->pattern, ref->name, 0))
|
||||
return 0;
|
||||
if (filter->prefix) {
|
||||
if (filter->trim_prefix) {
|
||||
struct reference skipped = *ref;
|
||||
skip_prefix(skipped.name, filter->prefix, &skipped.name);
|
||||
if (strlen(skipped.name) <= filter->trim_prefix)
|
||||
BUG("attempt to trim too many characters");
|
||||
skipped.name += filter->trim_prefix;
|
||||
return filter->fn(&skipped, filter->cb_data);
|
||||
} else {
|
||||
return filter->fn(ref, filter->cb_data);
|
||||
@@ -523,25 +525,40 @@ void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp,
|
||||
.indent = indent,
|
||||
.dry_run = dry_run,
|
||||
};
|
||||
refs_for_each_rawref(refs, warn_if_dangling_symref, &data);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
refs_for_each_ref_ext(refs, warn_if_dangling_symref, &data, &opts);
|
||||
}
|
||||
|
||||
int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_tag_ref(struct ref_store *refs, refs_for_each_cb cb, void *cb_data)
|
||||
{
|
||||
return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/tags/",
|
||||
.trim_prefix = strlen("refs/tags/"),
|
||||
};
|
||||
return refs_for_each_ref_ext(refs, cb, cb_data, &opts);
|
||||
}
|
||||
|
||||
int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_branch_ref(struct ref_store *refs, refs_for_each_cb cb, void *cb_data)
|
||||
{
|
||||
return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/heads/",
|
||||
.trim_prefix = strlen("refs/heads/"),
|
||||
};
|
||||
return refs_for_each_ref_ext(refs, cb, cb_data, &opts);
|
||||
}
|
||||
|
||||
int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_remote_ref(struct ref_store *refs, refs_for_each_cb cb, void *cb_data)
|
||||
{
|
||||
return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/remotes/",
|
||||
.trim_prefix = strlen("refs/remotes/"),
|
||||
};
|
||||
return refs_for_each_ref_ext(refs, cb, cb_data, &opts);
|
||||
}
|
||||
|
||||
int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
int refs_head_ref_namespaced(struct ref_store *refs, refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret = 0;
|
||||
@@ -589,42 +606,6 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,
|
||||
strbuf_release(&normalized_pattern);
|
||||
}
|
||||
|
||||
int refs_for_each_glob_ref_in(struct ref_store *refs, each_ref_fn fn,
|
||||
const char *pattern, const char *prefix, void *cb_data)
|
||||
{
|
||||
struct strbuf real_pattern = STRBUF_INIT;
|
||||
struct for_each_ref_filter filter;
|
||||
int ret;
|
||||
|
||||
if (!prefix && !starts_with(pattern, "refs/"))
|
||||
strbuf_addstr(&real_pattern, "refs/");
|
||||
else if (prefix)
|
||||
strbuf_addstr(&real_pattern, prefix);
|
||||
strbuf_addstr(&real_pattern, pattern);
|
||||
|
||||
if (!has_glob_specials(pattern)) {
|
||||
/* Append implied '/' '*' if not present. */
|
||||
strbuf_complete(&real_pattern, '/');
|
||||
/* No need to check for '*', there is none. */
|
||||
strbuf_addch(&real_pattern, '*');
|
||||
}
|
||||
|
||||
filter.pattern = real_pattern.buf;
|
||||
filter.prefix = prefix;
|
||||
filter.fn = fn;
|
||||
filter.cb_data = cb_data;
|
||||
ret = refs_for_each_ref(refs, for_each_filter_refs, &filter);
|
||||
|
||||
strbuf_release(&real_pattern);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int refs_for_each_glob_ref(struct ref_store *refs, each_ref_fn fn,
|
||||
const char *pattern, void *cb_data)
|
||||
{
|
||||
return refs_for_each_glob_ref_in(refs, fn, pattern, NULL, cb_data);
|
||||
}
|
||||
|
||||
const char *prettify_refname(const char *name)
|
||||
{
|
||||
if (skip_prefix(name, "refs/heads/", &name) ||
|
||||
@@ -1787,7 +1768,7 @@ const char *find_descendant_ref(const char *dirname,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
int refs_head_ref(struct ref_store *refs, refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
struct object_id oid;
|
||||
int flag;
|
||||
@@ -1811,7 +1792,7 @@ struct ref_iterator *refs_ref_iterator_begin(
|
||||
const char *prefix,
|
||||
const char **exclude_patterns,
|
||||
int trim,
|
||||
enum do_for_each_ref_flags flags)
|
||||
enum refs_for_each_flag flags)
|
||||
{
|
||||
struct ref_iterator *iter;
|
||||
struct strvec normalized_exclude_patterns = STRVEC_INIT;
|
||||
@@ -1833,14 +1814,14 @@ struct ref_iterator *refs_ref_iterator_begin(
|
||||
exclude_patterns = normalized_exclude_patterns.v;
|
||||
}
|
||||
|
||||
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
|
||||
if (!(flags & REFS_FOR_EACH_INCLUDE_BROKEN)) {
|
||||
static int ref_paranoia = -1;
|
||||
|
||||
if (ref_paranoia < 0)
|
||||
ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 1);
|
||||
if (ref_paranoia) {
|
||||
flags |= DO_FOR_EACH_INCLUDE_BROKEN;
|
||||
flags |= DO_FOR_EACH_OMIT_DANGLING_SYMREFS;
|
||||
flags |= REFS_FOR_EACH_INCLUDE_BROKEN;
|
||||
flags |= REFS_FOR_EACH_OMIT_DANGLING_SYMREFS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1857,85 +1838,105 @@ struct ref_iterator *refs_ref_iterator_begin(
|
||||
return iter;
|
||||
}
|
||||
|
||||
static int do_for_each_ref(struct ref_store *refs, const char *prefix,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, int trim,
|
||||
enum do_for_each_ref_flags flags, void *cb_data)
|
||||
{
|
||||
struct ref_iterator *iter;
|
||||
|
||||
if (!refs)
|
||||
return 0;
|
||||
|
||||
iter = refs_ref_iterator_begin(refs, prefix, exclude_patterns, trim,
|
||||
flags);
|
||||
|
||||
return do_for_each_ref_iterator(iter, fn, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(refs, "", NULL, fn, 0, 0, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(refs, prefix, NULL, fn, strlen(prefix), 0, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(refs, prefix, exclude_patterns, fn, 0, 0, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_replace_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
{
|
||||
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
|
||||
return do_for_each_ref(refs, git_replace_ref_base, NULL, fn,
|
||||
strlen(git_replace_ref_base),
|
||||
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_namespaced_ref(struct ref_store *refs,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_ref_ext(struct ref_store *refs,
|
||||
refs_for_each_cb cb, void *cb_data,
|
||||
const struct refs_for_each_ref_options *opts)
|
||||
{
|
||||
struct strvec namespaced_exclude_patterns = STRVEC_INIT;
|
||||
struct strbuf prefix = STRBUF_INIT;
|
||||
struct strbuf namespaced_prefix = STRBUF_INIT;
|
||||
struct strbuf real_pattern = STRBUF_INIT;
|
||||
struct for_each_ref_filter filter;
|
||||
struct ref_iterator *iter;
|
||||
size_t trim_prefix = opts->trim_prefix;
|
||||
const char **exclude_patterns;
|
||||
const char *prefix;
|
||||
int ret;
|
||||
|
||||
exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns,
|
||||
get_git_namespace(),
|
||||
&namespaced_exclude_patterns);
|
||||
if (!refs)
|
||||
BUG("no ref store passed");
|
||||
|
||||
strbuf_addf(&prefix, "%srefs/", get_git_namespace());
|
||||
ret = do_for_each_ref(refs, prefix.buf, exclude_patterns, fn, 0, 0, cb_data);
|
||||
if (opts->trim_prefix) {
|
||||
size_t prefix_len;
|
||||
|
||||
if (!opts->prefix)
|
||||
BUG("trimming only allowed with a prefix");
|
||||
|
||||
prefix_len = strlen(opts->prefix);
|
||||
if (prefix_len == opts->trim_prefix && opts->prefix[prefix_len - 1] != '/')
|
||||
BUG("ref pattern must end in a trailing slash when trimming");
|
||||
}
|
||||
|
||||
if (opts->pattern) {
|
||||
if (!opts->prefix && !starts_with(opts->pattern, "refs/"))
|
||||
strbuf_addstr(&real_pattern, "refs/");
|
||||
else if (opts->prefix)
|
||||
strbuf_addstr(&real_pattern, opts->prefix);
|
||||
strbuf_addstr(&real_pattern, opts->pattern);
|
||||
|
||||
if (!has_glob_specials(opts->pattern)) {
|
||||
/* Append implied '/' '*' if not present. */
|
||||
strbuf_complete(&real_pattern, '/');
|
||||
/* No need to check for '*', there is none. */
|
||||
strbuf_addch(&real_pattern, '*');
|
||||
}
|
||||
|
||||
filter.pattern = real_pattern.buf;
|
||||
filter.trim_prefix = opts->trim_prefix;
|
||||
filter.fn = cb;
|
||||
filter.cb_data = cb_data;
|
||||
|
||||
/*
|
||||
* We need to trim the prefix in the callback function as the
|
||||
* pattern is expected to match on the full refname.
|
||||
*/
|
||||
trim_prefix = 0;
|
||||
|
||||
cb = for_each_filter_refs;
|
||||
cb_data = &filter;
|
||||
}
|
||||
|
||||
if (opts->namespace) {
|
||||
strbuf_addstr(&namespaced_prefix, opts->namespace);
|
||||
if (opts->prefix)
|
||||
strbuf_addstr(&namespaced_prefix, opts->prefix);
|
||||
else
|
||||
strbuf_addstr(&namespaced_prefix, "refs/");
|
||||
|
||||
prefix = namespaced_prefix.buf;
|
||||
exclude_patterns = get_namespaced_exclude_patterns(opts->exclude_patterns,
|
||||
opts->namespace,
|
||||
&namespaced_exclude_patterns);
|
||||
} else {
|
||||
prefix = opts->prefix ? opts->prefix : "";
|
||||
exclude_patterns = opts->exclude_patterns;
|
||||
}
|
||||
|
||||
iter = refs_ref_iterator_begin(refs, prefix, exclude_patterns,
|
||||
trim_prefix, opts->flags);
|
||||
|
||||
ret = do_for_each_ref_iterator(iter, cb, cb_data);
|
||||
|
||||
strvec_clear(&namespaced_exclude_patterns);
|
||||
strbuf_release(&prefix);
|
||||
strbuf_release(&namespaced_prefix);
|
||||
strbuf_release(&real_pattern);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_ref(struct ref_store *refs, refs_for_each_cb cb, void *cb_data)
|
||||
{
|
||||
return refs_for_each_rawref_in(refs, "", fn, cb_data);
|
||||
struct refs_for_each_ref_options opts = { 0 };
|
||||
return refs_for_each_ref_ext(refs, cb, cb_data, &opts);
|
||||
}
|
||||
|
||||
int refs_for_each_rawref_in(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_replace_ref(struct ref_store *refs, refs_for_each_cb cb, void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(refs, prefix, NULL, fn, 0,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
|
||||
}
|
||||
|
||||
int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
|
||||
void *cb_data)
|
||||
{
|
||||
return do_for_each_ref(refs, "", NULL, fn, 0,
|
||||
DO_FOR_EACH_INCLUDE_ROOT_REFS, cb_data);
|
||||
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = git_replace_ref_base,
|
||||
.trim_prefix = strlen(git_replace_ref_base),
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
return refs_for_each_ref_ext(refs, cb, cb_data, &opts);
|
||||
}
|
||||
|
||||
static int qsort_strcmp(const void *va, const void *vb)
|
||||
@@ -1996,40 +1997,31 @@ static void find_longest_prefixes(struct string_list *out,
|
||||
strbuf_release(&prefix);
|
||||
}
|
||||
|
||||
int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
|
||||
const char *namespace,
|
||||
const char **patterns,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
int refs_for_each_ref_in_prefixes(struct ref_store *ref_store,
|
||||
const char **prefixes,
|
||||
const struct refs_for_each_ref_options *opts,
|
||||
refs_for_each_cb cb, void *cb_data)
|
||||
{
|
||||
struct strvec namespaced_exclude_patterns = STRVEC_INIT;
|
||||
struct string_list prefixes = STRING_LIST_INIT_DUP;
|
||||
struct string_list longest_prefixes = STRING_LIST_INIT_DUP;
|
||||
struct string_list_item *prefix;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret = 0, namespace_len;
|
||||
int ret = 0;
|
||||
|
||||
find_longest_prefixes(&prefixes, patterns);
|
||||
if (opts->prefix)
|
||||
BUG("refs_for_each_ref_in_prefixes called with specific prefix");
|
||||
|
||||
if (namespace)
|
||||
strbuf_addstr(&buf, namespace);
|
||||
namespace_len = buf.len;
|
||||
find_longest_prefixes(&longest_prefixes, prefixes);
|
||||
|
||||
exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns,
|
||||
namespace,
|
||||
&namespaced_exclude_patterns);
|
||||
for_each_string_list_item(prefix, &longest_prefixes) {
|
||||
struct refs_for_each_ref_options prefix_opts = *opts;
|
||||
prefix_opts.prefix = prefix->string;
|
||||
|
||||
for_each_string_list_item(prefix, &prefixes) {
|
||||
strbuf_addstr(&buf, prefix->string);
|
||||
ret = refs_for_each_fullref_in(ref_store, buf.buf,
|
||||
exclude_patterns, fn, cb_data);
|
||||
ret = refs_for_each_ref_ext(ref_store, cb, cb_data,
|
||||
&prefix_opts);
|
||||
if (ret)
|
||||
break;
|
||||
strbuf_setlen(&buf, namespace_len);
|
||||
}
|
||||
|
||||
strvec_clear(&namespaced_exclude_patterns);
|
||||
string_list_clear(&prefixes, 0);
|
||||
strbuf_release(&buf);
|
||||
string_list_clear(&longest_prefixes, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2847,7 +2839,7 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
|
||||
|
||||
if (!iter)
|
||||
iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN);
|
||||
REFS_FOR_EACH_INCLUDE_BROKEN);
|
||||
else if (ref_iterator_seek(iter, dirname.buf,
|
||||
REF_ITERATOR_SEEK_SET_PREFIX) < 0)
|
||||
goto cleanup;
|
||||
@@ -3293,6 +3285,9 @@ int repo_migrate_ref_storage_format(struct repository *repo,
|
||||
struct strbuf *errbuf)
|
||||
{
|
||||
struct ref_store *old_refs = NULL, *new_refs = NULL;
|
||||
struct refs_for_each_ref_options for_each_ref_opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_ROOT_REFS | REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
struct ref_transaction *transaction = NULL;
|
||||
struct strbuf new_gitdir = STRBUF_INIT;
|
||||
struct migration_data data = {
|
||||
@@ -3376,7 +3371,7 @@ int repo_migrate_ref_storage_format(struct repository *repo,
|
||||
data.errbuf = errbuf;
|
||||
|
||||
/*
|
||||
* We need to use the internal `do_for_each_ref()` here so that we can
|
||||
* We need to use `refs_for_each_ref_ext()` here so that we can
|
||||
* also include broken refs and symrefs. These would otherwise be
|
||||
* skipped silently.
|
||||
*
|
||||
@@ -3386,9 +3381,7 @@ int repo_migrate_ref_storage_format(struct repository *repo,
|
||||
* allow for a central lock due to its design. It's thus on the user to
|
||||
* ensure that there are no concurrent writes.
|
||||
*/
|
||||
ret = do_for_each_ref(old_refs, "", NULL, migrate_one_ref, 0,
|
||||
DO_FOR_EACH_INCLUDE_ROOT_REFS | DO_FOR_EACH_INCLUDE_BROKEN,
|
||||
&data);
|
||||
ret = refs_for_each_ref_ext(old_refs, migrate_one_ref, &data, &for_each_ref_opts);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
|
||||
207
refs.h
207
refs.h
@@ -170,7 +170,7 @@ int ref_store_remove_on_disk(struct ref_store *refs, struct strbuf *err);
|
||||
*
|
||||
* peel_object(r, oid, &peeled);
|
||||
*
|
||||
* with the "oid" value given to the each_ref_fn callback, except
|
||||
* with the "oid" value given to the refs_for_each_cb callback, except
|
||||
* that some ref storage may be able to answer the query without
|
||||
* actually loading the object in memory.
|
||||
*/
|
||||
@@ -329,7 +329,7 @@ int check_tag_ref(struct strbuf *sb, const char *name);
|
||||
struct ref_transaction;
|
||||
|
||||
/*
|
||||
* Bit values set in the flags argument passed to each_ref_fn() and
|
||||
* Bit values set in the flags argument passed to refs_for_each_cb() and
|
||||
* stored in ref_iterator::flags. Other bits are for internal use
|
||||
* only:
|
||||
*/
|
||||
@@ -400,7 +400,44 @@ int reference_get_peeled_oid(struct repository *repo,
|
||||
* argument is only guaranteed to be valid for the duration of a
|
||||
* single callback invocation.
|
||||
*/
|
||||
typedef int each_ref_fn(const struct reference *ref, void *cb_data);
|
||||
typedef int refs_for_each_cb(const struct reference *ref, void *cb_data);
|
||||
|
||||
/*
|
||||
* These flags are passed to refs_ref_iterator_begin() (and do_for_each_ref(),
|
||||
* which feeds it).
|
||||
*/
|
||||
enum refs_for_each_flag {
|
||||
/*
|
||||
* Include broken references in a do_for_each_ref*() iteration, which
|
||||
* would normally be omitted. This includes both refs that point to
|
||||
* missing objects (a true repository corruption), ones with illegal
|
||||
* names (which we prefer not to expose to callers), as well as
|
||||
* dangling symbolic refs (i.e., those that point to a non-existent
|
||||
* ref; this is not a corruption, but as they have no valid oid, we
|
||||
* omit them from normal iteration results).
|
||||
*/
|
||||
REFS_FOR_EACH_INCLUDE_BROKEN = (1 << 0),
|
||||
|
||||
/*
|
||||
* Only include per-worktree refs in a do_for_each_ref*() iteration.
|
||||
* Normally this will be used with a files ref_store, since that's
|
||||
* where all reference backends will presumably store their
|
||||
* per-worktree refs.
|
||||
*/
|
||||
REFS_FOR_EACH_PER_WORKTREE_ONLY = (1 << 1),
|
||||
|
||||
/*
|
||||
* Omit dangling symrefs from output; this only has an effect with
|
||||
* INCLUDE_BROKEN, since they are otherwise not included at all.
|
||||
*/
|
||||
REFS_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2),
|
||||
|
||||
/*
|
||||
* Include root refs i.e. HEAD and pseudorefs along with the regular
|
||||
* refs.
|
||||
*/
|
||||
REFS_FOR_EACH_INCLUDE_ROOT_REFS = (1 << 3),
|
||||
};
|
||||
|
||||
/*
|
||||
* The following functions invoke the specified callback function for
|
||||
@@ -412,70 +449,75 @@ typedef int each_ref_fn(const struct reference *ref, void *cb_data);
|
||||
* stop the iteration. Returned references are sorted.
|
||||
*/
|
||||
int refs_head_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_tag_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_branch_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_remote_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_replace_ref(struct ref_store *refs,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
int refs_head_ref_namespaced(struct ref_store *refs,
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
|
||||
/*
|
||||
* references matching any pattern in "exclude_patterns" are omitted from the
|
||||
* result set on a best-effort basis.
|
||||
*/
|
||||
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
struct refs_for_each_ref_options {
|
||||
/* Only iterate over references that have this given prefix. */
|
||||
const char *prefix;
|
||||
|
||||
/*
|
||||
* A globbing pattern that can be used to only yield refs that match.
|
||||
* If given, refs will be matched against the pattern with
|
||||
* `wildmatch()`.
|
||||
*
|
||||
* If the pattern doesn't contain any globbing characters then it is
|
||||
* treated as if it was ending with "/" and "*".
|
||||
*/
|
||||
const char *pattern;
|
||||
|
||||
/*
|
||||
* If set, only yield refs part of the configured namespace. Exclude
|
||||
* patterns will be rewritten to apply to the namespace, and the prefix
|
||||
* will be considered relative to the namespace.
|
||||
*/
|
||||
const char *namespace;
|
||||
|
||||
/*
|
||||
* Exclude any references that match any of these patterns on a
|
||||
* best-effort basis. The caller needs to be prepared for the exclude
|
||||
* patterns to be ignored.
|
||||
*
|
||||
* The array must be terminated with a NULL sentinel value.
|
||||
*/
|
||||
const char **exclude_patterns;
|
||||
|
||||
/*
|
||||
* The number of bytes to trim from the refname. Note that the trimmed
|
||||
* bytes must not cause the reference to become empty. As such, this
|
||||
* field should typically only be set when one uses a `prefix` ending
|
||||
* in a slash.
|
||||
*/
|
||||
size_t trim_prefix;
|
||||
|
||||
/* Flags that change which refs will be included. */
|
||||
enum refs_for_each_flag flags;
|
||||
};
|
||||
|
||||
int refs_for_each_ref(struct ref_store *refs,
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
int refs_for_each_ref_ext(struct ref_store *refs,
|
||||
refs_for_each_cb cb, void *cb_data,
|
||||
const struct refs_for_each_ref_options *opts);
|
||||
int refs_for_each_tag_ref(struct ref_store *refs,
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
int refs_for_each_branch_ref(struct ref_store *refs,
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
int refs_for_each_remote_ref(struct ref_store *refs,
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
int refs_for_each_replace_ref(struct ref_store *refs,
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
|
||||
/**
|
||||
* iterate all refs in "patterns" by partitioning patterns into disjoint sets
|
||||
* Iterate all refs in "prefixes" by partitioning prefixes into disjoint sets
|
||||
* and iterating the longest-common prefix of each set.
|
||||
*
|
||||
* references matching any pattern in "exclude_patterns" are omitted from the
|
||||
* result set on a best-effort basis.
|
||||
*
|
||||
* callers should be prepared to ignore references that they did not ask for.
|
||||
*/
|
||||
int refs_for_each_fullref_in_prefixes(struct ref_store *refs,
|
||||
const char *namespace,
|
||||
const char **patterns,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
/* iterates all refs that match the specified glob pattern. */
|
||||
int refs_for_each_glob_ref(struct ref_store *refs, each_ref_fn fn,
|
||||
const char *pattern, void *cb_data);
|
||||
|
||||
int refs_for_each_glob_ref_in(struct ref_store *refs, each_ref_fn fn,
|
||||
const char *pattern, const char *prefix, void *cb_data);
|
||||
|
||||
int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_data);
|
||||
|
||||
/*
|
||||
* references matching any pattern in "exclude_patterns" are omitted from the
|
||||
* result set on a best-effort basis.
|
||||
*/
|
||||
int refs_for_each_namespaced_ref(struct ref_store *refs,
|
||||
const char **exclude_patterns,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
/* can be used to learn about broken ref and symref */
|
||||
int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data);
|
||||
int refs_for_each_rawref_in(struct ref_store *refs, const char *prefix,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
|
||||
/*
|
||||
* Iterates over all refs including root refs, i.e. pseudorefs and HEAD.
|
||||
*/
|
||||
int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
|
||||
void *cb_data);
|
||||
int refs_for_each_ref_in_prefixes(struct ref_store *refs,
|
||||
const char **prefixes,
|
||||
const struct refs_for_each_ref_options *opts,
|
||||
refs_for_each_cb cb, void *cb_data);
|
||||
|
||||
/*
|
||||
* Normalizes partial refs to their fully qualified form.
|
||||
@@ -1331,43 +1373,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
|
||||
*/
|
||||
struct ref_iterator;
|
||||
|
||||
/*
|
||||
* These flags are passed to refs_ref_iterator_begin() (and do_for_each_ref(),
|
||||
* which feeds it).
|
||||
*/
|
||||
enum do_for_each_ref_flags {
|
||||
/*
|
||||
* Include broken references in a do_for_each_ref*() iteration, which
|
||||
* would normally be omitted. This includes both refs that point to
|
||||
* missing objects (a true repository corruption), ones with illegal
|
||||
* names (which we prefer not to expose to callers), as well as
|
||||
* dangling symbolic refs (i.e., those that point to a non-existent
|
||||
* ref; this is not a corruption, but as they have no valid oid, we
|
||||
* omit them from normal iteration results).
|
||||
*/
|
||||
DO_FOR_EACH_INCLUDE_BROKEN = (1 << 0),
|
||||
|
||||
/*
|
||||
* Only include per-worktree refs in a do_for_each_ref*() iteration.
|
||||
* Normally this will be used with a files ref_store, since that's
|
||||
* where all reference backends will presumably store their
|
||||
* per-worktree refs.
|
||||
*/
|
||||
DO_FOR_EACH_PER_WORKTREE_ONLY = (1 << 1),
|
||||
|
||||
/*
|
||||
* Omit dangling symrefs from output; this only has an effect with
|
||||
* INCLUDE_BROKEN, since they are otherwise not included at all.
|
||||
*/
|
||||
DO_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2),
|
||||
|
||||
/*
|
||||
* Include root refs i.e. HEAD and pseudorefs along with the regular
|
||||
* refs.
|
||||
*/
|
||||
DO_FOR_EACH_INCLUDE_ROOT_REFS = (1 << 3),
|
||||
};
|
||||
|
||||
/*
|
||||
* Return an iterator that goes over each reference in `refs` for
|
||||
* which the refname begins with prefix. If trim is non-zero, then
|
||||
@@ -1377,7 +1382,7 @@ enum do_for_each_ref_flags {
|
||||
struct ref_iterator *refs_ref_iterator_begin(
|
||||
struct ref_store *refs,
|
||||
const char *prefix, const char **exclude_patterns,
|
||||
int trim, enum do_for_each_ref_flags flags);
|
||||
int trim, enum refs_for_each_flag flags);
|
||||
|
||||
/*
|
||||
* Advance the iterator to the first or next item and return ITER_OK.
|
||||
@@ -1426,7 +1431,7 @@ void ref_iterator_free(struct ref_iterator *ref_iterator);
|
||||
* iterator style.
|
||||
*/
|
||||
int do_for_each_ref_iterator(struct ref_iterator *iter,
|
||||
each_ref_fn fn, void *cb_data);
|
||||
refs_for_each_cb fn, void *cb_data);
|
||||
|
||||
/*
|
||||
* Git only recognizes a directory as a repository if it contains:
|
||||
|
||||
@@ -446,7 +446,7 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs,
|
||||
|
||||
dir = get_ref_dir(refs->loose->root);
|
||||
|
||||
if (flags & DO_FOR_EACH_INCLUDE_ROOT_REFS)
|
||||
if (flags & REFS_FOR_EACH_INCLUDE_ROOT_REFS)
|
||||
add_root_refs(refs, dir);
|
||||
|
||||
/*
|
||||
@@ -962,17 +962,17 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
||||
int ok;
|
||||
|
||||
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
|
||||
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
|
||||
if (iter->flags & REFS_FOR_EACH_PER_WORKTREE_ONLY &&
|
||||
parse_worktree_ref(iter->iter0->ref.name, NULL, NULL,
|
||||
NULL) != REF_WORKTREE_CURRENT)
|
||||
continue;
|
||||
|
||||
if ((iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS) &&
|
||||
if ((iter->flags & REFS_FOR_EACH_OMIT_DANGLING_SYMREFS) &&
|
||||
(iter->iter0->ref.flags & REF_ISSYMREF) &&
|
||||
(iter->iter0->ref.flags & REF_ISBROKEN))
|
||||
continue;
|
||||
|
||||
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
|
||||
if (!(iter->flags & REFS_FOR_EACH_INCLUDE_BROKEN) &&
|
||||
!ref_resolves_to_object(iter->iter0->ref.name,
|
||||
iter->repo,
|
||||
iter->iter0->ref.oid,
|
||||
@@ -1019,7 +1019,7 @@ static struct ref_iterator *files_ref_iterator_begin(
|
||||
struct ref_iterator *ref_iterator;
|
||||
unsigned int required_flags = REF_STORE_READ;
|
||||
|
||||
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
|
||||
if (!(flags & REFS_FOR_EACH_INCLUDE_BROKEN))
|
||||
required_flags |= REF_STORE_ODB;
|
||||
|
||||
refs = files_downcast(ref_store, required_flags, "ref_iterator_begin");
|
||||
@@ -1057,7 +1057,7 @@ static struct ref_iterator *files_ref_iterator_begin(
|
||||
*/
|
||||
packed_iter = refs_ref_iterator_begin(
|
||||
refs->packed_ref_store, prefix, exclude_patterns, 0,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN);
|
||||
REFS_FOR_EACH_INCLUDE_BROKEN);
|
||||
|
||||
overlay_iter = overlay_ref_iterator_begin(loose_iter, packed_iter);
|
||||
|
||||
@@ -3156,6 +3156,9 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
|
||||
struct ref_transaction *transaction,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.flags = REFS_FOR_EACH_INCLUDE_BROKEN,
|
||||
};
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
|
||||
@@ -3180,8 +3183,8 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
|
||||
* so here we really only check that none of the references
|
||||
* that we are creating already exists.
|
||||
*/
|
||||
if (refs_for_each_rawref(&refs->base, ref_present,
|
||||
&transaction->refnames))
|
||||
if (refs_for_each_ref_ext(&refs->base, ref_present,
|
||||
&transaction->refnames, &opts))
|
||||
BUG("initial ref transaction called with existing refs");
|
||||
|
||||
packed_transaction = ref_store_transaction_begin(refs->packed_ref_store,
|
||||
|
||||
@@ -423,7 +423,7 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
|
||||
}
|
||||
|
||||
int do_for_each_ref_iterator(struct ref_iterator *iter,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
int retval = 0, ok;
|
||||
|
||||
|
||||
@@ -987,11 +987,11 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
||||
const char *refname = iter->base.ref.name;
|
||||
const char *prefix = iter->prefix;
|
||||
|
||||
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
|
||||
if (iter->flags & REFS_FOR_EACH_PER_WORKTREE_ONLY &&
|
||||
!is_per_worktree_ref(iter->base.ref.name))
|
||||
continue;
|
||||
|
||||
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
|
||||
if (!(iter->flags & REFS_FOR_EACH_INCLUDE_BROKEN) &&
|
||||
!ref_resolves_to_object(iter->base.ref.name, iter->repo,
|
||||
&iter->oid, iter->flags))
|
||||
continue;
|
||||
@@ -1164,7 +1164,7 @@ static struct ref_iterator *packed_ref_iterator_begin(
|
||||
struct ref_iterator *ref_iterator;
|
||||
unsigned int required_flags = REF_STORE_READ;
|
||||
|
||||
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
|
||||
if (!(flags & REFS_FOR_EACH_INCLUDE_BROKEN))
|
||||
required_flags |= REF_STORE_ODB;
|
||||
refs = packed_downcast(ref_store, required_flags, "ref_iterator_begin");
|
||||
|
||||
@@ -1406,7 +1406,7 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
|
||||
* of updates is exhausted, leave i set to updates->nr.
|
||||
*/
|
||||
iter = packed_ref_iterator_begin(&refs->base, "", NULL,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN);
|
||||
REFS_FOR_EACH_INCLUDE_BROKEN);
|
||||
if ((ok = ref_iterator_advance(iter)) != ITER_OK) {
|
||||
ref_iterator_free(iter);
|
||||
iter = NULL;
|
||||
|
||||
@@ -629,7 +629,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
||||
* the root refs are to be included. We emulate the same behaviour here.
|
||||
*/
|
||||
if (!starts_with(iter->ref.refname, "refs/") &&
|
||||
!(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
|
||||
!(iter->flags & REFS_FOR_EACH_INCLUDE_ROOT_REFS &&
|
||||
is_root_ref(iter->ref.refname))) {
|
||||
continue;
|
||||
}
|
||||
@@ -643,7 +643,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
||||
if (iter->exclude_patterns && should_exclude_current_ref(iter))
|
||||
continue;
|
||||
|
||||
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
|
||||
if (iter->flags & REFS_FOR_EACH_PER_WORKTREE_ONLY &&
|
||||
parse_worktree_ref(iter->ref.refname, NULL, NULL, NULL) !=
|
||||
REF_WORKTREE_CURRENT)
|
||||
continue;
|
||||
@@ -681,12 +681,12 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
||||
flags |= REF_BAD_NAME | REF_ISBROKEN;
|
||||
}
|
||||
|
||||
if (iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS &&
|
||||
if (iter->flags & REFS_FOR_EACH_OMIT_DANGLING_SYMREFS &&
|
||||
flags & REF_ISSYMREF &&
|
||||
flags & REF_ISBROKEN)
|
||||
continue;
|
||||
|
||||
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
|
||||
if (!(iter->flags & REFS_FOR_EACH_INCLUDE_BROKEN) &&
|
||||
!ref_resolves_to_object(iter->ref.refname, refs->base.repo,
|
||||
&iter->oid, flags))
|
||||
continue;
|
||||
@@ -838,7 +838,7 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto
|
||||
struct reftable_ref_store *refs;
|
||||
unsigned int required_flags = REF_STORE_READ;
|
||||
|
||||
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN))
|
||||
if (!(flags & REFS_FOR_EACH_INCLUDE_BROKEN))
|
||||
required_flags |= REF_STORE_ODB;
|
||||
refs = reftable_be_downcast(ref_store, required_flags, "ref_iterator_begin");
|
||||
|
||||
|
||||
49
revision.c
49
revision.c
@@ -1647,7 +1647,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
|
||||
|
||||
static void handle_refs(struct ref_store *refs,
|
||||
struct rev_info *revs, unsigned flags,
|
||||
int (*for_each)(struct ref_store *, each_ref_fn, void *))
|
||||
int (*for_each)(struct ref_store *, refs_for_each_cb, void *))
|
||||
{
|
||||
struct all_refs_cb cb;
|
||||
|
||||
@@ -2731,23 +2731,25 @@ void revision_opts_finish(struct rev_info *revs)
|
||||
}
|
||||
}
|
||||
|
||||
static int for_each_bisect_ref(struct ref_store *refs, each_ref_fn fn,
|
||||
static int for_each_bisect_ref(struct ref_store *refs, refs_for_each_cb fn,
|
||||
void *cb_data, const char *term)
|
||||
{
|
||||
struct refs_for_each_ref_options opts = { 0 };
|
||||
struct strbuf bisect_refs = STRBUF_INIT;
|
||||
int status;
|
||||
strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
|
||||
status = refs_for_each_fullref_in(refs, bisect_refs.buf, NULL, fn, cb_data);
|
||||
opts.prefix = bisect_refs.buf;
|
||||
status = refs_for_each_ref_ext(refs, fn, cb_data, &opts);
|
||||
strbuf_release(&bisect_refs);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int for_each_bad_bisect_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
static int for_each_bad_bisect_ref(struct ref_store *refs, refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
return for_each_bisect_ref(refs, fn, cb_data, term_bad);
|
||||
}
|
||||
|
||||
static int for_each_good_bisect_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
|
||||
static int for_each_good_bisect_ref(struct ref_store *refs, refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
return for_each_bisect_ref(refs, fn, cb_data, term_good);
|
||||
}
|
||||
@@ -2817,10 +2819,13 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
|
||||
handle_refs(refs, revs, *flags, refs_for_each_remote_ref);
|
||||
clear_ref_exclusions(&revs->ref_excludes);
|
||||
} else if ((argcount = parse_long_opt("glob", argv, &optarg))) {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.pattern = optarg,
|
||||
};
|
||||
struct all_refs_cb cb;
|
||||
init_all_refs_cb(&cb, revs, *flags);
|
||||
refs_for_each_glob_ref(get_main_ref_store(the_repository),
|
||||
handle_one_ref, optarg, &cb);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
handle_one_ref, &cb, &opts);
|
||||
clear_ref_exclusions(&revs->ref_excludes);
|
||||
return argcount;
|
||||
} else if ((argcount = parse_long_opt("exclude", argv, &optarg))) {
|
||||
@@ -2830,34 +2835,46 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
|
||||
exclude_hidden_refs(&revs->ref_excludes, optarg);
|
||||
return argcount;
|
||||
} else if (skip_prefix(arg, "--branches=", &optarg)) {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/heads/",
|
||||
.trim_prefix = strlen("refs/heads/"),
|
||||
.pattern = optarg,
|
||||
};
|
||||
struct all_refs_cb cb;
|
||||
if (revs->ref_excludes.hidden_refs_configured)
|
||||
return error(_("options '%s' and '%s' cannot be used together"),
|
||||
"--exclude-hidden", "--branches");
|
||||
init_all_refs_cb(&cb, revs, *flags);
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
|
||||
handle_one_ref, optarg,
|
||||
"refs/heads/", &cb);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
handle_one_ref, &cb, &opts);
|
||||
clear_ref_exclusions(&revs->ref_excludes);
|
||||
} else if (skip_prefix(arg, "--tags=", &optarg)) {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/tags/",
|
||||
.trim_prefix = strlen("refs/tags/"),
|
||||
.pattern = optarg,
|
||||
};
|
||||
struct all_refs_cb cb;
|
||||
if (revs->ref_excludes.hidden_refs_configured)
|
||||
return error(_("options '%s' and '%s' cannot be used together"),
|
||||
"--exclude-hidden", "--tags");
|
||||
init_all_refs_cb(&cb, revs, *flags);
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
|
||||
handle_one_ref, optarg,
|
||||
"refs/tags/", &cb);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
handle_one_ref, &cb, &opts);
|
||||
clear_ref_exclusions(&revs->ref_excludes);
|
||||
} else if (skip_prefix(arg, "--remotes=", &optarg)) {
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = "refs/remotes/",
|
||||
.trim_prefix = strlen("refs/remotes/"),
|
||||
.pattern = optarg,
|
||||
};
|
||||
struct all_refs_cb cb;
|
||||
if (revs->ref_excludes.hidden_refs_configured)
|
||||
return error(_("options '%s' and '%s' cannot be used together"),
|
||||
"--exclude-hidden", "--remotes");
|
||||
init_all_refs_cb(&cb, revs, *flags);
|
||||
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
|
||||
handle_one_ref, optarg,
|
||||
"refs/remotes/", &cb);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
handle_one_ref, &cb, &opts);
|
||||
clear_ref_exclusions(&revs->ref_excludes);
|
||||
} else if (!strcmp(arg, "--reflog")) {
|
||||
add_reflogs_to_pending(revs, *flags);
|
||||
|
||||
@@ -101,7 +101,7 @@ int is_staging_gitmodules_ok(struct index_state *istate)
|
||||
}
|
||||
|
||||
static int for_each_remote_ref_submodule(const char *submodule,
|
||||
each_ref_fn fn, void *cb_data)
|
||||
refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
return refs_for_each_remote_ref(repo_get_submodule_ref_store(the_repository,
|
||||
submodule),
|
||||
|
||||
@@ -163,17 +163,22 @@ static int each_ref(const struct reference *ref, void *cb_data UNUSED)
|
||||
static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *prefix = notnull(*argv++, "prefix");
|
||||
|
||||
return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = prefix,
|
||||
.trim_prefix = strlen(prefix),
|
||||
};
|
||||
return refs_for_each_ref_ext(refs, each_ref, NULL, &opts);
|
||||
}
|
||||
|
||||
static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv)
|
||||
{
|
||||
const char *prefix = notnull(*argv++, "prefix");
|
||||
const char **exclude_patterns = argv;
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.prefix = prefix,
|
||||
.exclude_patterns = argv,
|
||||
};
|
||||
|
||||
return refs_for_each_fullref_in(refs, prefix, exclude_patterns, each_ref,
|
||||
NULL);
|
||||
return refs_for_each_ref_ext(refs, each_ref, NULL, &opts);
|
||||
}
|
||||
|
||||
static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
|
||||
|
||||
@@ -607,10 +607,13 @@ static int allow_hidden_refs(enum allow_uor allow_uor)
|
||||
return !(allow_uor & (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1));
|
||||
}
|
||||
|
||||
static void for_each_namespaced_ref_1(each_ref_fn fn,
|
||||
static void for_each_namespaced_ref_1(refs_for_each_cb fn,
|
||||
struct upload_pack_data *data)
|
||||
{
|
||||
const char **excludes = NULL;
|
||||
struct refs_for_each_ref_options opts = {
|
||||
.namespace = get_git_namespace(),
|
||||
};
|
||||
|
||||
/*
|
||||
* If `data->allow_uor` allows fetching hidden refs, we need to
|
||||
* mark all references (including hidden ones), to check in
|
||||
@@ -621,10 +624,10 @@ static void for_each_namespaced_ref_1(each_ref_fn fn,
|
||||
* hidden references.
|
||||
*/
|
||||
if (allow_hidden_refs(data->allow_uor))
|
||||
excludes = hidden_refs_to_excludes(&data->hidden_refs);
|
||||
opts.exclude_patterns = hidden_refs_to_excludes(&data->hidden_refs);
|
||||
|
||||
refs_for_each_namespaced_ref(get_main_ref_store(the_repository),
|
||||
excludes, fn, data);
|
||||
refs_for_each_ref_ext(get_main_ref_store(the_repository),
|
||||
fn, data, &opts);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -595,7 +595,7 @@ void strbuf_worktree_ref(const struct worktree *wt,
|
||||
strbuf_addstr(sb, refname);
|
||||
}
|
||||
|
||||
int other_head_refs(each_ref_fn fn, void *cb_data)
|
||||
int other_head_refs(refs_for_each_cb fn, void *cb_data)
|
||||
{
|
||||
struct worktree **worktrees, **p;
|
||||
struct strbuf refname = STRBUF_INIT;
|
||||
|
||||
@@ -197,7 +197,7 @@ int is_shared_symref(const struct worktree *wt,
|
||||
* Similar to head_ref() for all HEADs _except_ one from the current
|
||||
* worktree, which is covered by head_ref().
|
||||
*/
|
||||
int other_head_refs(each_ref_fn fn, void *cb_data);
|
||||
int other_head_refs(refs_for_each_cb fn, void *cb_data);
|
||||
|
||||
int is_worktree_being_rebased(const struct worktree *wt, const char *target);
|
||||
int is_worktree_being_bisected(const struct worktree *wt, const char *target);
|
||||
|
||||
Reference in New Issue
Block a user