* [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 17:26 [PATCH 0/4] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
@ 2024-06-06 17:26 ` John Cai via GitGitGadget
2024-06-06 18:21 ` Junio C Hamano
2024-06-11 8:50 ` Jeff King
2024-06-06 17:26 ` [PATCH 2/4] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
` (3 subsequent siblings)
4 siblings, 2 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-06-06 17:26 UTC (permalink / raw)
To: git; +Cc: Phillip Wood [ ]
From: John Cai <johncai86@gmail.com>
refs_resolve_ref_unsafe retrieves the referent, the unresolved value of
a reference. Add a parameter to allow refs_resolve_ref_unsafe to pass up
the value of referent to the caller so it can save this value in ref
iterators for more efficient access.
Signed-off-by: John Cai <johncai86@gmail.com>
---
add-interactive.c | 6 +++---
blame.c | 4 ++--
builtin/bisect.c | 2 +-
builtin/blame.c | 2 +-
builtin/branch.c | 2 +-
builtin/fsck.c | 2 +-
builtin/log.c | 1 +
builtin/rebase.c | 6 +++---
builtin/receive-pack.c | 2 +-
builtin/remote.c | 2 +-
builtin/stash.c | 2 +-
builtin/submodule--helper.c | 4 ++--
builtin/symbolic-ref.c | 2 +-
config.c | 2 +-
http-backend.c | 1 +
log-tree.c | 2 +-
ls-refs.c | 3 ++-
refs.c | 20 ++++++++++++--------
refs.h | 1 +
refs/files-backend.c | 16 ++++++++--------
refs/reftable-backend.c | 6 +++---
remote.c | 6 +++---
revision.c | 2 +-
sequencer.c | 9 +++++----
t/helper/test-ref-store.c | 2 +-
transport-helper.c | 1 +
transport.c | 2 +-
upload-pack.c | 2 +-
worktree.c | 4 +++-
29 files changed, 64 insertions(+), 52 deletions(-)
diff --git a/add-interactive.c b/add-interactive.c
index b5d6cd689a1..041d30cf2b3 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -533,7 +533,7 @@ static int get_modified_files(struct repository *r,
{
struct object_id head_oid;
int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", RESOLVE_REF_READING,
+ "HEAD", NULL, RESOLVE_REF_READING,
&head_oid, NULL);
struct collection_status s = { 0 };
int i;
@@ -763,7 +763,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
struct object_id oid;
int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", RESOLVE_REF_READING,
+ "HEAD", NULL, RESOLVE_REF_READING,
&oid,
NULL);
struct lock_file index_lock;
@@ -994,7 +994,7 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
struct object_id oid;
int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", RESOLVE_REF_READING,
+ "HEAD", NULL, RESOLVE_REF_READING,
&oid,
NULL);
if (get_modified_files(s->r, INDEX_ONLY, files, ps, NULL, NULL) < 0)
diff --git a/blame.c b/blame.c
index 33586b97772..9e5d0cd788f 100644
--- a/blame.c
+++ b/blame.c
@@ -2700,7 +2700,7 @@ static struct commit *dwim_reverse_initial(struct rev_info *revs,
return NULL;
/* Do we have HEAD? */
- if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING, &head_oid, NULL))
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", NULL, RESOLVE_REF_READING, &head_oid, NULL))
return NULL;
head_commit = lookup_commit_reference_gently(revs->repo,
&head_oid, 1);
@@ -2803,7 +2803,7 @@ void setup_scoreboard(struct blame_scoreboard *sb,
if (sb->final) {
parent_oid = &sb->final->object.oid;
} else {
- if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING, &head_oid, NULL))
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", NULL, RESOLVE_REF_READING, &head_oid, NULL))
die("no such ref: HEAD");
parent_oid = &head_oid;
}
diff --git a/builtin/bisect.c b/builtin/bisect.c
index a58432b9d90..76ce5f0e0df 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -783,7 +783,7 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
* Verify HEAD
*/
head = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", 0, &head_oid, &flags);
+ "HEAD", NULL, 0, &head_oid, &flags);
if (!head)
if (repo_get_oid(the_repository, "HEAD", &head_oid))
return error(_("bad HEAD - I need a HEAD"));
diff --git a/builtin/blame.c b/builtin/blame.c
index fadba1a5304..1504a2ed99d 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1092,7 +1092,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
struct commit *head_commit;
struct object_id head_oid;
- if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING,
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", NULL, RESOLVE_REF_READING,
&head_oid, NULL) ||
!(head_commit = lookup_commit_reference_gently(revs.repo,
&head_oid, 1)))
diff --git a/builtin/branch.c b/builtin/branch.c
index 48cac74f97f..dd871d44f2d 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -503,7 +503,7 @@ static void print_current_branch_name(void)
{
int flags;
const char *refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", 0, NULL, &flags);
+ "HEAD", NULL, 0, NULL, &flags);
const char *shortname;
if (!refname)
die(_("could not resolve HEAD"));
diff --git a/builtin/fsck.c b/builtin/fsck.c
index d13a226c2ed..2c0ac6653ca 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -716,7 +716,7 @@ static int fsck_head_link(const char *head_ref_name,
fprintf_ln(stderr, _("Checking %s link"), head_ref_name);
*head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- head_ref_name, 0, head_oid,
+ head_ref_name, NULL, 0, head_oid,
NULL);
if (!*head_points_at) {
errors_found |= ERROR_REFS;
diff --git a/builtin/log.c b/builtin/log.c
index c8ce0c0d88a..337f367e974 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -2228,6 +2228,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
const char *ref, *v;
ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
"HEAD",
+ NULL,
RESOLVE_REF_READING,
NULL, NULL);
if (ref && skip_prefix(ref, "refs/heads/", &v))
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 0466d9414af..fd14b1e4505 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1641,7 +1641,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
} else if (argc == 0) {
/* Do not need to switch branches, we are already on it. */
options.head_name =
- xstrdup_or_null(refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, NULL,
+ xstrdup_or_null(refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", NULL, 0, NULL,
&flags));
if (!options.head_name)
die(_("No such ref: %s"), "HEAD");
@@ -1736,7 +1736,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (!(options.flags & REBASE_NO_QUIET))
; /* be quiet */
else if (!strcmp(branch_name, "HEAD") &&
- refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, NULL, &flag))
+ refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", NULL, 0, NULL, &flag))
puts(_("HEAD is up to date."));
else
printf(_("Current branch %s is up to date.\n"),
@@ -1746,7 +1746,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
} else if (!(options.flags & REBASE_NO_QUIET))
; /* be quiet */
else if (!strcmp(branch_name, "HEAD") &&
- refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, NULL, &flag))
+ refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", NULL, 0, NULL, &flag))
puts(_("HEAD is up to date, rebase forced."));
else
printf(_("Current branch %s is up to date, rebase "
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index be8969a84a8..d9e2c4bbe39 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1695,7 +1695,7 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
dst_name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- buf.buf, 0, NULL, &flag);
+ buf.buf, NULL, 0, NULL, &flag);
check_aliased_update_internal(cmd, list, dst_name, flag);
strbuf_release(&buf);
}
diff --git a/builtin/remote.c b/builtin/remote.c
index 447ef1d3c92..039d1d6c55a 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -599,7 +599,7 @@ static int read_remote_branches(const char *refname,
if (starts_with(refname, buf.buf)) {
item = string_list_append(rename->remote_branches, refname);
symref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- refname, RESOLVE_REF_READING,
+ refname, NULL, RESOLVE_REF_READING,
NULL, &flag);
if (symref && (flag & REF_ISSYMREF)) {
item->util = xstrdup(symref);
diff --git a/builtin/stash.c b/builtin/stash.c
index 7859bc0866a..b733492cead 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1386,7 +1386,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
}
branch_ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", 0, NULL, &flags);
+ "HEAD", NULL, 0, NULL, &flags);
if (flags & REF_ISSYMREF)
skip_prefix(branch_ref, "refs/heads/", &branch_name);
head_short_sha1 = repo_find_unique_abbrev(the_repository,
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 897f19868e8..e3e1f08a58c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -44,7 +44,7 @@ static int repo_get_default_remote(struct repository *repo, char **default_remot
char *dest = NULL;
struct strbuf sb = STRBUF_INIT;
struct ref_store *store = get_main_ref_store(repo);
- const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL,
+ const char *refname = refs_resolve_ref_unsafe(store, "HEAD", NULL, 0, NULL,
NULL);
if (!refname)
@@ -2459,7 +2459,7 @@ static int remote_submodule_branch(const char *path, const char **branch)
if (!strcmp(*branch, ".")) {
const char *refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", 0, NULL,
+ "HEAD", NULL, 0, NULL,
NULL);
if (!refname)
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index 81abdd170fe..96fa311b075 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -19,7 +19,7 @@ static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, i
resolve_flags = (recurse ? 0 : RESOLVE_REF_NO_RECURSE);
refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- HEAD, resolve_flags, NULL, &flag);
+ HEAD, NULL, resolve_flags, NULL, &flag);
if (!refname)
die("No such ref: %s", HEAD);
diff --git a/config.c b/config.c
index 14461312b33..3cc1dab0fb9 100644
--- a/config.c
+++ b/config.c
@@ -304,7 +304,7 @@ static int include_by_branch(const char *cond, size_t cond_len)
struct strbuf pattern = STRBUF_INIT;
const char *refname = !the_repository->gitdir ?
NULL : refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", 0, NULL, &flags);
+ "HEAD", NULL, 0, NULL, &flags);
const char *shortname;
if (!refname || !(flags & REF_ISSYMREF) ||
diff --git a/http-backend.c b/http-backend.c
index 5b65287ac90..20c3ff8fa95 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -574,6 +574,7 @@ static int show_head_ref(const char *refname, const struct object_id *oid,
if (flag & REF_ISSYMREF) {
const char *target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
refname,
+ NULL,
RESOLVE_REF_READING,
NULL, NULL);
diff --git a/log-tree.c b/log-tree.c
index 41416de4e3f..da06c6e982f 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -280,7 +280,7 @@ static const struct name_decoration *current_pointed_by_HEAD(const struct name_d
/* Now resolve and find the matching current branch */
branch_name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD", 0, NULL, &rru_flags);
+ "HEAD", NULL, 0, NULL, &rru_flags);
if (!branch_name || !(rru_flags & REF_ISSYMREF))
return NULL;
diff --git a/ls-refs.c b/ls-refs.c
index 398afe4ce39..3d047bbc64f 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -97,6 +97,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
struct object_id unused;
const char *symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
refname,
+ NULL,
0,
&unused,
&flag);
@@ -128,7 +129,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
int oid_is_null;
strbuf_addf(&namespaced, "%sHEAD", get_git_namespace());
- if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), namespaced.buf, 0, &oid, &flag))
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), namespaced.buf, NULL, 0, &oid, &flag))
return; /* bad ref */
oid_is_null = is_null_oid(&oid);
if (!oid_is_null ||
diff --git a/refs.c b/refs.c
index 31032588e0e..2c592a9ae29 100644
--- a/refs.c
+++ b/refs.c
@@ -378,7 +378,7 @@ char *refs_resolve_refdup(struct ref_store *refs,
{
const char *result;
- result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
+ result = refs_resolve_ref_unsafe(refs, refname, NULL, resolve_flags,
oid, flags);
return xstrdup_or_null(result);
}
@@ -394,7 +394,7 @@ struct for_each_ref_filter {
int refs_read_ref_full(struct ref_store *refs, const char *refname,
int resolve_flags, struct object_id *oid, int *flags)
{
- if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
+ if (refs_resolve_ref_unsafe(refs, refname, NULL, resolve_flags,
oid, flags))
return 0;
return -1;
@@ -407,7 +407,7 @@ int refs_read_ref(struct ref_store *refs, const char *refname, struct object_id
int refs_ref_exists(struct ref_store *refs, const char *refname)
{
- return !!refs_resolve_ref_unsafe(refs, refname, RESOLVE_REF_READING,
+ return !!refs_resolve_ref_unsafe(refs, refname, NULL, RESOLVE_REF_READING,
NULL, NULL);
}
@@ -442,7 +442,7 @@ static int warn_if_dangling_symref(const char *refname,
if (!(flags & REF_ISSYMREF))
return 0;
- resolves_to = refs_resolve_ref_unsafe(d->refs, refname, 0, NULL, NULL);
+ resolves_to = refs_resolve_ref_unsafe(d->refs, refname, NULL, 0, NULL, NULL);
if (!resolves_to
|| (d->refname
? strcmp(resolves_to, d->refname)
@@ -716,7 +716,7 @@ int expand_ref(struct repository *repo, const char *str, int len,
this_result = refs_found ? &oid_from_ref : oid;
strbuf_reset(&fullref);
strbuf_addf(&fullref, *p, len, str);
- r = refs_resolve_ref_unsafe(refs, fullref.buf,
+ r = refs_resolve_ref_unsafe(refs, fullref.buf, NULL,
RESOLVE_REF_READING,
this_result, &flag);
if (r) {
@@ -750,7 +750,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
strbuf_reset(&path);
strbuf_addf(&path, *p, len, str);
- ref = refs_resolve_ref_unsafe(refs, path.buf,
+ ref = refs_resolve_ref_unsafe(refs, path.buf, NULL,
RESOLVE_REF_READING,
oid ? &hash : NULL, NULL);
if (!ref)
@@ -1522,7 +1522,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
struct object_id oid;
int flag;
- if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
+ if (refs_resolve_ref_unsafe(refs, "HEAD", NULL, RESOLVE_REF_READING,
&oid, &flag))
return fn("HEAD", &oid, flag, cb_data);
@@ -1761,6 +1761,7 @@ int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
const char *refs_resolve_ref_unsafe(struct ref_store *refs,
const char *refname,
+ const char *referent,
int resolve_flags,
struct object_id *oid,
int *flags)
@@ -1822,6 +1823,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
}
*flags |= read_flags;
+ if (referent && (read_flags & REF_ISSYMREF) &&
+ sb_refname.len > 0)
+ referent = sb_refname.buf;
if (!(read_flags & REF_ISSYMREF)) {
if (*flags & REF_BAD_NAME) {
@@ -1865,7 +1869,7 @@ int repo_resolve_gitlink_ref(struct repository *r,
if (!refs)
return -1;
- if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
+ if (!refs_resolve_ref_unsafe(refs, refname, NULL, 0, oid, &flags) ||
is_null_oid(oid))
return -1;
return 0;
diff --git a/refs.h b/refs.h
index fe7f0db35e6..ea4a3217658 100644
--- a/refs.h
+++ b/refs.h
@@ -68,6 +68,7 @@ const char *ref_storage_format_to_name(unsigned int ref_storage_format);
const char *refs_resolve_ref_unsafe(struct ref_store *refs,
const char *refname,
+ const char *referent,
int resolve_flags,
struct object_id *oid,
int *flags);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 324c59b096c..bf2ffe062ea 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -244,7 +244,7 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
struct object_id oid;
int flag;
- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
+ if (!refs_resolve_ref_unsafe(&refs->base, refname, NULL, RESOLVE_REF_READING,
&oid, &flag)) {
oidclr(&oid);
flag |= REF_ISBROKEN;
@@ -1118,7 +1118,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs,
goto error_return;
}
- if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, 0,
+ if (!refs_resolve_ref_unsafe(&refs->base, lock->ref_name, NULL, 0,
&lock->old_oid, NULL))
oidclr(&lock->old_oid);
goto out;
@@ -1455,7 +1455,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
goto out;
}
- if (!refs_resolve_ref_unsafe(&refs->base, oldrefname,
+ if (!refs_resolve_ref_unsafe(&refs->base, oldrefname, NULL,
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
&orig_oid, &flag)) {
ret = error("refname %s not found", oldrefname);
@@ -1501,7 +1501,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
* the safety anyway; we want to delete the reference whatever
* its current value.
*/
- if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname,
+ if (!copy && refs_resolve_ref_unsafe(&refs->base, newrefname, NULL,
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
NULL, NULL) &&
refs_delete_ref(&refs->base, NULL, newrefname,
@@ -1875,7 +1875,7 @@ static int commit_ref_update(struct files_ref_store *refs,
int head_flag;
const char *head_ref;
- head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD",
+ head_ref = refs_resolve_ref_unsafe(&refs->base, "HEAD", NULL,
RESOLVE_REF_READING,
NULL, &head_flag);
if (head_ref && (head_flag & REF_ISSYMREF) &&
@@ -2464,7 +2464,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
* to record and possibly check old_oid:
*/
if (!refs_resolve_ref_unsafe(&refs->base,
- referent.buf, 0,
+ referent.buf, NULL, 0,
&lock->old_oid, NULL)) {
if (update->flags & REF_HAVE_OLD) {
strbuf_addf(err, "cannot lock ref '%s': "
@@ -2823,7 +2823,7 @@ static int parse_and_write_reflog(struct files_ref_store *refs,
* We want to get the resolved OID for the target, to ensure
* that the correct value is added to the reflog.
*/
- if (!refs_resolve_ref_unsafe(&refs->base, update->new_target,
+ if (!refs_resolve_ref_unsafe(&refs->base, update->new_target, NULL,
RESOLVE_REF_READING,
&update->new_oid, NULL)) {
/*
@@ -3229,7 +3229,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
int type;
const char *ref;
- ref = refs_resolve_ref_unsafe(&refs->base, refname,
+ ref = refs_resolve_ref_unsafe(&refs->base, refname, NULL,
RESOLVE_REF_NO_RECURSE,
NULL, &type);
update = !!(ref && !(type & REF_ISSYMREF));
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 438b5c478b4..9e03582e7da 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -438,7 +438,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
oidread(&iter->oid, iter->ref.value.val2.value);
break;
case REFTABLE_REF_SYMREF:
- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
+ if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname, NULL,
RESOLVE_REF_READING, &iter->oid, &flags))
oidclr(&iter->oid);
break;
@@ -926,7 +926,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
* so it is safe to call `refs_resolve_ref_unsafe()`
* here without causing races.
*/
- const char *resolved = refs_resolve_ref_unsafe(&refs->base, u->refname, 0,
+ const char *resolved = refs_resolve_ref_unsafe(&refs->base, u->refname, NULL, 0,
¤t_oid, NULL);
if (u->flags & REF_NO_DEREF) {
@@ -1148,7 +1148,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
int create_reflog = 1;
if (u->new_target) {
- if (!refs_resolve_ref_unsafe(&arg->refs->base, u->new_target,
+ if (!refs_resolve_ref_unsafe(&arg->refs->base, u->new_target, NULL,
RESOLVE_REF_READING, &u->new_oid, NULL)) {
/*
* TODO: currently we skip creating reflogs for dangling
diff --git a/remote.c b/remote.c
index 5898da2bb5c..c9718ee0ca1 100644
--- a/remote.c
+++ b/remote.c
@@ -520,7 +520,7 @@ static void read_config(struct repository *repo, int early)
repo->remote_state->current_branch = NULL;
if (startup_info->have_repository && !early) {
const char *head_ref = refs_resolve_ref_unsafe(
- get_main_ref_store(repo), "HEAD", 0, NULL, &flag);
+ get_main_ref_store(repo), "HEAD", NULL, 0, NULL, &flag);
if (head_ref && (flag & REF_ISSYMREF) &&
skip_prefix(head_ref, "refs/heads/", &head_ref)) {
repo->remote_state->current_branch = make_branch(
@@ -1201,7 +1201,7 @@ static char *guess_ref(const char *name, struct ref *peer)
struct strbuf buf = STRBUF_INIT;
const char *r = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- peer->name,
+ peer->name, NULL,
RESOLVE_REF_READING,
NULL, NULL);
if (!r)
@@ -1321,7 +1321,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
int flag;
dst_value = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- matched_src->name,
+ matched_src->name, NULL,
RESOLVE_REF_READING,
NULL, &flag);
if (!dst_value ||
diff --git a/revision.c b/revision.c
index 7ddf0f151a3..6aca4f42303 100644
--- a/revision.c
+++ b/revision.c
@@ -2920,7 +2920,7 @@ static void NORETURN diagnose_missing_default(const char *def)
const char *refname;
refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- def, 0, NULL, &flags);
+ def, NULL, 0, NULL, &flags);
if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN))
die(_("your current branch appears to be broken"));
diff --git a/sequencer.c b/sequencer.c
index aa2a2398357..cf7a2a9a112 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -839,10 +839,10 @@ static int is_index_unchanged(struct repository *r)
struct index_state *istate = r->index;
const char *head_name;
- if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING, &head_oid, NULL)) {
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", NULL, RESOLVE_REF_READING, &head_oid, NULL)) {
/* Check to see if this is an unborn branch */
head_name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- "HEAD",
+ "HEAD", NULL,
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
&head_oid, NULL);
if (!head_name ||
@@ -1480,7 +1480,7 @@ void print_commit_summary(struct repository *r,
diff_setup_done(&rev.diffopt);
refs = get_main_ref_store(r);
- head = refs_resolve_ref_unsafe(refs, "HEAD", 0, NULL, NULL);
+ head = refs_resolve_ref_unsafe(refs, "HEAD", NULL, 0, NULL, NULL);
if (!head)
die(_("unable to resolve HEAD after creating commit"));
if (!strcmp(head, "HEAD"))
@@ -4715,7 +4715,7 @@ static int apply_save_autostash_ref(struct repository *r, const char *refname,
if (!refs_ref_exists(get_main_ref_store(r), refname))
return 0;
- if (!refs_resolve_ref_unsafe(get_main_ref_store(r), refname,
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(r), refname, NULL,
RESOLVE_REF_READING, &stash_oid, &flag))
return -1;
if (flag & REF_ISSYMREF)
@@ -6213,6 +6213,7 @@ static int add_decorations_to_list(const struct commit *commit,
const struct name_decoration *decoration = get_name_decoration(&commit->object);
const char *head_ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
"HEAD",
+ NULL,
RESOLVE_REF_READING,
NULL,
NULL);
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index c9efd74c2b5..ef1d6acbfae 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -184,7 +184,7 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
int flags;
const char *ref;
- ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
+ ref = refs_resolve_ref_unsafe(refs, refname, NULL, resolve_flags,
&oid, &flags);
printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
return ref ? 0 : 1;
diff --git a/transport-helper.c b/transport-helper.c
index 780fcaf5292..27d85748b60 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1110,6 +1110,7 @@ static int push_refs_with_export(struct transport *transport,
/* Follow symbolic refs (mainly for HEAD). */
name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
ref->peer_ref->name,
+ NULL,
RESOLVE_REF_READING,
&oid,
&flag);
diff --git a/transport.c b/transport.c
index 0ad04b77fd2..8818ba75e7a 100644
--- a/transport.c
+++ b/transport.c
@@ -101,7 +101,7 @@ static void set_upstreams(struct transport *transport, struct ref *refs,
localname = ref->peer_ref->name;
remotename = ref->name;
tmp = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- localname, RESOLVE_REF_READING,
+ localname, NULL, RESOLVE_REF_READING,
NULL, &flag);
if (tmp && flag & REF_ISSYMREF &&
starts_with(tmp, "refs/heads/"))
diff --git a/upload-pack.c b/upload-pack.c
index bbfb04c8bd8..4fddc081237 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1291,7 +1291,7 @@ static int find_symref(const char *refname,
if ((flag & REF_ISSYMREF) == 0)
return 0;
symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- refname, 0, NULL, &flag);
+ refname, NULL, 0, NULL, &flag);
if (!symref_target || (flag & REF_ISSYMREF) == 0)
die("'%s' is a symref but it is not?", refname);
item = string_list_append(cb_data, strip_namespace(refname));
diff --git a/worktree.c b/worktree.c
index 12eadacc618..ed89bab481d 100644
--- a/worktree.c
+++ b/worktree.c
@@ -42,6 +42,7 @@ static void add_head_info(struct worktree *wt)
target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
"HEAD",
+ NULL,
0,
&wt->head_oid, &flags);
if (!target)
@@ -448,7 +449,7 @@ int is_shared_symref(const struct worktree *wt, const char *symref,
}
refs = get_worktree_ref_store(wt);
- symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
+ symref_target = refs_resolve_ref_unsafe(refs, symref, NULL, 0,
NULL, &flags);
if ((flags & REF_ISSYMREF) &&
symref_target && !strcmp(symref_target, target))
@@ -549,6 +550,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
strbuf_worktree_ref(wt, &refname, "HEAD");
if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
refname.buf,
+ NULL,
RESOLVE_REF_READING,
&oid, &flag))
ret = fn(refname.buf, &oid, flag, cb_data);
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 17:26 ` [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe John Cai via GitGitGadget
@ 2024-06-06 18:21 ` Junio C Hamano
2024-06-06 18:23 ` Junio C Hamano
2024-06-06 21:02 ` John Cai
2024-06-11 8:50 ` Jeff King
1 sibling, 2 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-06-06 18:21 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, John Cai
ADMINISTRIVIA. Check the address you place on the CC: line. What
we can see for this message at
https://lore.kernel.org/git/011c10f488610b0a795a843bff66723477783761.1717694801.git.gitgitgadget@gmail.com/raw
looks like this.
Cc: "Phillip Wood [ ]" <phillip.wood123@gmail.com>,
Kristoffer Haugsbakk <[code@khaugsbakk.name]>,
"Jeff King [ ]" <peff@peff.net>,
"Patrick Steinhardt [ ]" <ps@pks.im>,
"=?UTF-8?Q?Jean-No=C3=ABl?= Avila [ ]" <avila.jn@gmail.com>,
John Cai <johncai86@gmail.com>,
John Cai <johncai86@gmail.com>
I fixed them manually, but it wasn't pleasant. I think we saw a
similar breakage earlier coming via GGG, but I do not recall the
details of how to cause such breakages (iow, what to avoid repeating
this).
Anyway.
"John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> 29 files changed, 64 insertions(+), 52 deletions(-)
Wow, the blast radius of this thing is rather big. Among these
existing callers of refs_resolve_ref_unsafe(), how many of them
will benefit from being able to pass a non NULL parameter at the end
of the series, and more importantly, in the future to take advantage
of the new feature possibly with a separate series?
I am assuming that this will benefit only a selected few and the
callers that would want to take advantage of the new feature will
remain low. Have you considered renaming refs_resolve_ref_unsafe()
to a new name (say, refs_resolve_ref_unsafe_with_referent()) and
implement the new feature (which is only triggered when the new
parameter gets a non NULL value), make refs_resolve_ref_unsafe() a
very thin wrapper that passes NULL to the new thing?
That way, you do not have to touch those existing callers that will
never benefit from the new capability in the future. You won't risk
conflicting with in flight topics semantically, either.
Or will they also benefit from the new feature in the future?
Offhand, I do not know how a caller like this ...
> diff --git a/add-interactive.c b/add-interactive.c
> index b5d6cd689a1..041d30cf2b3 100644
> --- a/add-interactive.c
> +++ b/add-interactive.c
> @@ -533,7 +533,7 @@ static int get_modified_files(struct repository *r,
> {
> struct object_id head_oid;
> int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
> - "HEAD", RESOLVE_REF_READING,
> + "HEAD", NULL, RESOLVE_REF_READING,
> &head_oid, NULL);
> struct collection_status s = { 0 };
> int i;
... would be helped.
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 18:21 ` Junio C Hamano
@ 2024-06-06 18:23 ` Junio C Hamano
2024-06-07 13:43 ` John Cai
2024-06-10 7:29 ` Patrick Steinhardt
2024-06-06 21:02 ` John Cai
1 sibling, 2 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-06-06 18:23 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, John Cai
Junio C Hamano <gitster@pobox.com> writes:
> "John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> 29 files changed, 64 insertions(+), 52 deletions(-)
>
> Wow, the blast radius of this thing is rather big. Among these
> existing callers of refs_resolve_ref_unsafe(), how many of them
> will benefit from being able to pass a non NULL parameter at the end
> of the series, and more importantly, in the future to take advantage
> of the new feature possibly with a separate series?
> ...
> That way, you do not have to touch those existing callers that will
> never benefit from the new capability in the future. You won't risk
> conflicting with in flight topics semantically, either.
The same comment applies to [3/4], but I do not want to fix the Cc: header
again, so I am replying to this message.
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 18:23 ` Junio C Hamano
@ 2024-06-07 13:43 ` John Cai
2024-06-07 15:21 ` Junio C Hamano
2024-06-10 7:29 ` Patrick Steinhardt
1 sibling, 1 reply; 44+ messages in thread
From: John Cai @ 2024-06-07 13:43 UTC (permalink / raw)
To: Junio C Hamano
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila
Hi Junio,
On 6 Jun 2024, at 14:23, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> "John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
>>
>>> 29 files changed, 64 insertions(+), 52 deletions(-)
>>
>> Wow, the blast radius of this thing is rather big. Among these
>> existing callers of refs_resolve_ref_unsafe(), how many of them
>> will benefit from being able to pass a non NULL parameter at the end
>> of the series, and more importantly, in the future to take advantage
>> of the new feature possibly with a separate series?
>> ...
>> That way, you do not have to touch those existing callers that will
>> never benefit from the new capability in the future. You won't risk
>> conflicting with in flight topics semantically, either.
>
> The same comment applies to [3/4], but I do not want to fix the Cc: header
> again, so I am replying to this message.
Yes, so for 3/4 I was exploring doing the same thing. However, each_repo_fn goes
pretty deep in the callstack and to provide an alternate set of functions that
use something like each_repo_referent_fn would still lead to a relatively large
blast radius, eg, something like:
diff --git a/ref-filter.c b/ref-filter.c
index f7fb0c7e0e..770d3715c2 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2631,12 +2631,12 @@ static int filter_exclude_match(struct ref_filter *filter, const char *refname)
* 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,
+ each_ref_with_referent_fn cb,
void *cb_data)
{
if (filter->kind & FILTER_REFS_ROOT_REFS) {
/* In this case, we want to print all refs including root refs. */
- return refs_for_each_include_root_refs(get_main_ref_store(the_repository),
+ return refs_for_each_include_root_refs_with_referent(get_main_ref_store(the_repository),
cb, cb_data);
}
@@ -2646,7 +2646,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
* prefixes like "refs/heads/" etc. are stripped off,
* so we have to look at everything:
*/
- return refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ return refs_for_each_fullref_in_with_referent(get_main_ref_store(the_repository),
"", NULL, cb, cb_data);
}
@@ -2656,17 +2656,17 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
* so just return everything and let the caller
* sort it out.
*/
- return refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ return refs_for_each_fullref_in_with_referent(get_main_ref_store(the_repository),
"", NULL, cb, cb_data);
}
if (!filter->name_patterns[0]) {
/* no patterns; we have to look at everything */
- return refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ return refs_for_each_fullref_in_with_referent(get_main_ref_store(the_repository),
"", filter->exclude.v, cb, cb_data);
}
- return refs_for_each_fullref_in_prefixes(get_main_ref_store(the_repository),
+ return refs_for_each_fullref_in_prefixes_with_referent(get_main_ref_store(the_repository),
NULL, filter->name_patterns,
filter->exclude.v,
cb, cb_data);
@@ -2781,7 +2781,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
return ref_kind_from_refname(refname);
}
-static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
+static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
int flag, struct ref_filter *filter)
{
struct ref_array_item *ref;
@@ -2850,6 +2850,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
ref->commit = commit;
ref->flag = flag;
ref->kind = kind;
+ ref->symref = referent;
return ref;
}
@@ -2863,12 +2864,12 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (ref)
ref_array_append(ref_cbdata->array, ref);
@@ -2898,13 +2899,13 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (!ref)
return 0;
@@ -3050,7 +3051,7 @@ void filter_ahead_behind(struct repository *r,
free(commits);
}
-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, each_ref_with_referent_fn fn, void *cb_data)
{
int ret = 0;
@@ -3070,15 +3071,15 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref
* of filter_ref_kind().
*/
if (filter->kind == FILTER_REFS_BRANCHES)
- ret = refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ ret = refs_for_each_fullref_in_with_referent(get_main_ref_store(the_repository),
"refs/heads/", NULL,
fn, cb_data);
else if (filter->kind == FILTER_REFS_REMOTES)
- ret = refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ ret = refs_for_each_fullref_in_with_referent(get_main_ref_store(the_repository),
"refs/remotes/", NULL,
fn, cb_data);
else if (filter->kind == FILTER_REFS_TAGS)
- ret = refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ ret = refs_for_each_fullref_in_with_referent(get_main_ref_store(the_repository),
"refs/tags/", NULL, fn,
cb_data);
else if (filter->kind & FILTER_REFS_REGULAR)
@@ -3090,7 +3091,7 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref
*/
if (!ret && !(filter->kind & FILTER_REFS_ROOT_REFS) &&
(filter->kind & FILTER_REFS_DETACHED_HEAD))
- refs_head_ref(get_main_ref_store(the_repository), fn,
+ refs_head_ref_referent(get_main_ref_store(the_repository), fn,
cb_data);
}
diff --git a/refs.c b/refs.c
index 6dcb0288cb..4366f35586 100644
--- a/refs.c
+++ b/refs.c
@@ -1529,6 +1529,19 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
return 0;
}
+int refs_head_ref_referent(struct ref_store *refs, each_ref_with_referent_fn fn, void *cb_data)
+{
+ struct object_id oid;
+ int flag;
+ const char *referent;
+
+ if (refs_resolve_ref_unsafe_with_referent(refs, "HEAD", referent, RESOLVE_REF_READING,
+ &oid, &flag))
+ return fn("HEAD", referent, &oid, flag, cb_data);
+
+ return 0;
+}
+
struct ref_iterator *refs_ref_iterator_begin(
struct ref_store *refs,
const char *prefix,
@@ -1560,6 +1573,22 @@ struct ref_iterator *refs_ref_iterator_begin(
return iter;
}
+static int do_for_each_ref_with_referent(struct ref_store *refs, const char *prefix,
+ const char **exclude_patterns,
+ each_ref_with_referent_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_with_referent(iter, fn, cb_data);
+}
+
static int do_for_each_ref(struct ref_store *refs, const char *prefix,
const char **exclude_patterns,
each_ref_fn fn, int trim,
@@ -1594,6 +1623,13 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
return do_for_each_ref(refs, prefix, exclude_patterns, fn, 0, 0, cb_data);
}
+int refs_for_each_fullref_in_with_referent(struct ref_store *refs, const char *prefix,
+ const char **exclude_patterns,
+ each_ref_with_referent_fn fn, void *cb_data)
+{
+ return do_for_each_ref_with_referent(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;
@@ -1627,6 +1663,13 @@ int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
DO_FOR_EACH_INCLUDE_ROOT_REFS, cb_data);
}
+int refs_for_each_include_root_refs_with_referent(struct ref_store *refs, each_ref_with_referent_fn fn,
+ void *cb_data)
+{
+ return do_for_each_ref_with_referent(refs, "", NULL, fn, 0,
+ DO_FOR_EACH_INCLUDE_ROOT_REFS, cb_data);
+}
+
static int qsort_strcmp(const void *va, const void *vb)
{
const char *a = *(const char **)va;
@@ -1716,6 +1759,37 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store,
return ret;
}
+int refs_for_each_fullref_in_prefixes_with_referent(struct ref_store *ref_store,
+ const char *namespace,
+ const char **patterns,
+ const char **exclude_patterns,
+ each_ref_with_referent_fn fn, void *cb_data)
+{
+ struct string_list prefixes = STRING_LIST_INIT_DUP;
+ struct string_list_item *prefix;
+ struct strbuf buf = STRBUF_INIT;
+ int ret = 0, namespace_len;
+
+ find_longest_prefixes(&prefixes, patterns);
+
+ if (namespace)
+ strbuf_addstr(&buf, namespace);
+ namespace_len = buf.len;
+
+ for_each_string_list_item(prefix, &prefixes) {
+ strbuf_addstr(&buf, prefix->string);
+ ret = refs_for_each_fullref_in_with_referent(ref_store, buf.buf,
+ exclude_patterns, fn, cb_data);
+ if (ret)
+ break;
+ strbuf_setlen(&buf, namespace_len);
+ }
+
+ string_list_clear(&prefixes, 0);
+ strbuf_release(&buf);
+ return ret;
+}
+
static int refs_read_special_head(struct ref_store *ref_store,
const char *refname, struct object_id *oid,
struct strbuf *referent, unsigned int *type,
diff --git a/refs.h b/refs.h
index ba6d0e0753..d8387c6296 100644
--- a/refs.h
+++ b/refs.h
@@ -304,6 +304,9 @@ struct ref_transaction;
typedef int each_ref_fn(const char *refname,
const struct object_id *oid, int flags, void *cb_data);
+typedef int each_ref_with_referent_fn(const char *refname, const char *referent,
+ const struct object_id *oid, int flags, void *cb_data);
+
/*
* The following functions invoke the specified callback function for
* each reference indicated. If the function ever returns a nonzero
@@ -315,6 +318,8 @@ typedef int each_ref_fn(const char *refname,
*/
int refs_head_ref(struct ref_store *refs,
each_ref_fn fn, void *cb_data);
+int refs_head_ref_referent(struct ref_store *refs,
+ each_ref_with_referent_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,
@@ -351,6 +356,17 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *refs,
const char **exclude_patterns,
each_ref_fn fn, void *cb_data);
+int refs_for_each_fullref_in_prefixes_with_referent(struct ref_store *refs,
+ const char *namespace,
+ const char **patterns,
+ const char **exclude_patterns,
+ each_ref_with_referent_fn fn, void *cb_data);
+
+int refs_for_each_fullref_in_with_referent(struct ref_store *refs, const char *prefix,
+ const char **exclude_patterns,
+ each_ref_with_referent_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);
@@ -377,6 +393,10 @@ int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data);
int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
void *cb_data);
+int refs_for_each_include_root_refs_with_referent(struct ref_store *refs, each_ref_with_referent_fn fn,
+ void *cb_data);
+
+
/*
* Normalizes partial refs to their fully qualified form.
* Will prepend <prefix> to the <pattern> if it doesn't start with 'refs/'.
diff --git a/refs/iterator.c b/refs/iterator.c
index 26acb6bd64..26c38ec6de 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -469,3 +469,30 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
return -1;
return retval;
}
+
+int do_for_each_ref_iterator_with_referent(struct ref_iterator *iter,
+ each_ref_with_referent_fn fn, void *cb_data)
+{
+ int retval = 0, ok;
+ struct ref_iterator *old_ref_iter = current_ref_iter;
+
+ current_ref_iter = iter;
+ while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
+ retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
+ if (retval) {
+ /*
+ * If ref_iterator_abort() returns ITER_ERROR,
+ * we ignore that error in deference to the
+ * callback function's return value.
+ */
+ ref_iterator_abort(iter);
+ goto out;
+ }
+ }
+
+out:
+ current_ref_iter = old_ref_iter;
+ if (ok == ITER_ERROR)
+ return -1;
+ return retval;
+}
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 0775451435..ebec407468 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -486,6 +486,9 @@ extern struct ref_iterator *current_ref_iter;
*/
int do_for_each_ref_iterator(struct ref_iterator *iter,
each_ref_fn fn, void *cb_data);
+int do_for_each_ref_iterator_with_referent(struct ref_iterator *iter,
+ each_ref_with_referent_fn fn, void *cb_data);
+
struct ref_store;
Which is a little bit unseemly in my view...so between the two options I would be
inclined to go with modifying each_repo_fn than create a whole subset set of
helpers. wdyt?
thanks
John
>
> Thanks.
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-07 13:43 ` John Cai
@ 2024-06-07 15:21 ` Junio C Hamano
0 siblings, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-06-07 15:21 UTC (permalink / raw)
To: John Cai
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila
John Cai <johncai86@gmail.com> writes:
> Yes, so for 3/4 I was exploring doing the same thing. However, each_repo_fn goes
> pretty deep in the callstack and to provide an alternate set of functions that
> use something like each_repo_referent_fn would still lead to a relatively large
> blast radius, eg, something like:
Hmph. You only care about teaching referent to calls to
refs_for_each_ref_in() and friends in apply_ref_filter()
and nowhere else. So for example, to preserve the current
calling pattern for this pair of caller/callback (and you have
dozens more exactly like this one you touch in [3/4]):
static int register_ref(const char *refname,
const struct object_id *oid,
int flags,
void *cb_data);
static int read_bisect_refs(void)
{
return refs_for_each_ref_in(get_main_ref_store(the_repository),
"refs/bisect", register_ref, NULL);
}
you could arrange your _new_ API the way you want, e.g.,
typedef int each_ref_with_referent_fn(const char *refname,
const char *referent,
const struct object_id *oid,
int flags,
void *cb_data);
int refs_for_each_ref_with_referent_in(struct ref_store *refs,
const char *prefix,
each_ref_with_referent_fn fn,
void *cb_data);
to help the single caller, i.e., apply_ref_filter(), and rebuild the
existing API on top as a thin wrapper, e.g.
/* This cannot change without butchering existing callers */
typedef int each_ref_fn(const char *refname,
const struct object_id *oid,
int flags,
void *cb_data);
/* Hence we introduce an adapter */
struct each_ref_fn_adapter_cbdata {
each_ref_fn user_each_ref_fn;
void *user_cb_data;
};
/* This is designed to work as an each_ref_with_referent_fn */
static int each_ref_adapter_fn(const char *refname,
const char *referent,
const struct object_id *oid,
int flags,
void *cb_data)
{
struct each_ref_fn_adapter_cbdata *adapter_cbdata = cbdata;
/* the callers have no need for referent */
return adapter_cbdata->user_each_ref_fn(refname, oid, flags,
adapter_cbdata->user_cbdata);
}
/*
* The function signature must stay the same to help existing,
* callers, but the implementation is now a thin wrapper.
*/
int refs_for_each_ref_in(struct ref_store *refs,
const char *prefix,
each_ref_fn fn,
void *cb_data)
{
struct each_ref_fn_adapter_cbdata adapter_cbdata = {
.user_each_ref_fn = fn,
.user_cb_data = cb_data,
};
return refs_for_each_ref_with_referetnt_in(refs, prefix,
each_ref_adapter_fn,
&adapter_cbdata);
}
no?
You'd need to pass through the new parameter "referent" through the
code paths that implement refs_for_each_ref_in() and friends to
update them to refs_for_each_ref_with_referent_in() and friends no
matter what, but there are limited number of the top-level
refs_for_each_ref_in() and friends that are unaware of the
"referent", and each of them would need the above ~20 lines (couting
the comment) adapter function that all can share the single
each_ref_adapter_fn() callback function.
Or am I missing some other intricacy in the existing for-each-* API?
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 18:23 ` Junio C Hamano
2024-06-07 13:43 ` John Cai
@ 2024-06-10 7:29 ` Patrick Steinhardt
2024-06-10 18:09 ` Junio C Hamano
1 sibling, 1 reply; 44+ messages in thread
From: Patrick Steinhardt @ 2024-06-10 7:29 UTC (permalink / raw)
To: Junio C Hamano
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Jean-Noël Avila, John Cai
[-- Attachment #1: Type: text/plain, Size: 1650 bytes --]
On Thu, Jun 06, 2024 at 11:23:18AM -0700, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
> > "John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> >
> >> 29 files changed, 64 insertions(+), 52 deletions(-)
> >
> > Wow, the blast radius of this thing is rather big. Among these
> > existing callers of refs_resolve_ref_unsafe(), how many of them
> > will benefit from being able to pass a non NULL parameter at the end
> > of the series, and more importantly, in the future to take advantage
> > of the new feature possibly with a separate series?
> > ...
> > That way, you do not have to touch those existing callers that will
> > never benefit from the new capability in the future. You won't risk
> > conflicting with in flight topics semantically, either.
>
> The same comment applies to [3/4], but I do not want to fix the Cc: header
> again, so I am replying to this message.
I wonder whether we can future-proof the code a bit more by introducing
a struct that contains everything we want to pass to the callback
function. That wouldn't fix the blast radius of this patch, but would
mean that we can easily add additional fielids to that struct in the
future without having to adapt any callers at all anymore.
Something like:
struct ref_data {
const char *refname;
const struct object_id *oid;
const char *referent;
int flags;
};
This would also allow us to get rid of this awful `peel_iterated_oid()`
function that relies on global state in many places, as we can put the
peeled OID into that structure, as well.
Patrick
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-10 7:29 ` Patrick Steinhardt
@ 2024-06-10 18:09 ` Junio C Hamano
0 siblings, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-06-10 18:09 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Jean-Noël Avila, John Cai
Patrick Steinhardt <ps@pks.im> writes:
> I wonder whether we can future-proof the code a bit more by introducing
> a struct that contains everything we want to pass to the callback
> function.
That would hopefully make a change with a large blast a one-time
event. But at the same time, it may end up making it too opaque and
hard to verify if all the API functions are using/updating/verifying
all the members of the struct as they should. Compared to that,
unused parameters are easier to verify mechanically by compilers.
> This would also allow us to get rid of this awful `peel_iterated_oid()`
> function that relies on global state in many places, as we can put the
> peeled OID into that structure, as well.
Yes, such a benefit may justify a one-time "affect many callers"
event. Or the underlying for_each_*() friend of functions can be
updated to use a single struct and then the current "only selected
parameters that are used ar passed" API can be made into a set of
thin wrappers around it, and then callers can be converted one step
at a time, in a multi-step series, perhaps.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 18:21 ` Junio C Hamano
2024-06-06 18:23 ` Junio C Hamano
@ 2024-06-06 21:02 ` John Cai
2024-06-06 22:44 ` Junio C Hamano
1 sibling, 1 reply; 44+ messages in thread
From: John Cai @ 2024-06-06 21:02 UTC (permalink / raw)
To: Junio C Hamano
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila
Hi Junio,
On 6 Jun 2024, at 14:21, Junio C Hamano wrote:
> ADMINISTRIVIA. Check the address you place on the CC: line. What
> we can see for this message at
>
> https://lore.kernel.org/git/011c10f488610b0a795a843bff66723477783761.1717694801.git.gitgitgadget@gmail.com/raw
>
> looks like this.
>
> Cc: "Phillip Wood [ ]" <phillip.wood123@gmail.com>,
> Kristoffer Haugsbakk <[code@khaugsbakk.name]>,
> "Jeff King [ ]" <peff@peff.net>,
> "Patrick Steinhardt [ ]" <ps@pks.im>,
> "=?UTF-8?Q?Jean-No=C3=ABl?= Avila [ ]" <avila.jn@gmail.com>,
> John Cai <johncai86@gmail.com>,
> John Cai <johncai86@gmail.com>
>
> I fixed them manually, but it wasn't pleasant. I think we saw a
> similar breakage earlier coming via GGG, but I do not recall the
> details of how to cause such breakages (iow, what to avoid repeating
> this).
oof, apologies. Didn't notice that. I'll be more mindful about the cc line.
>
> Anyway.
>
> "John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> 29 files changed, 64 insertions(+), 52 deletions(-)
>
> Wow, the blast radius of this thing is rather big. Among these
> existing callers of refs_resolve_ref_unsafe(), how many of them
> will benefit from being able to pass a non NULL parameter at the end
> of the series, and more importantly, in the future to take advantage
> of the new feature possibly with a separate series?
>
> I am assuming that this will benefit only a selected few and the
> callers that would want to take advantage of the new feature will
> remain low. Have you considered renaming refs_resolve_ref_unsafe()
> to a new name (say, refs_resolve_ref_unsafe_with_referent()) and
> implement the new feature (which is only triggered when the new
> parameter gets a non NULL value), make refs_resolve_ref_unsafe() a
> very thin wrapper that passes NULL to the new thing?
>
> That way, you do not have to touch those existing callers that will
> never benefit from the new capability in the future. You won't risk
> conflicting with in flight topics semantically, either.
>
> Or will they also benefit from the new feature in the future?
>
> Offhand, I do not know how a caller like this ...
>
>> diff --git a/add-interactive.c b/add-interactive.c
>> index b5d6cd689a1..041d30cf2b3 100644
>> --- a/add-interactive.c
>> +++ b/add-interactive.c
>> @@ -533,7 +533,7 @@ static int get_modified_files(struct repository *r,
>> {
>> struct object_id head_oid;
>> int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
>> - "HEAD", RESOLVE_REF_READING,
>> + "HEAD", NULL, RESOLVE_REF_READING,
>> &head_oid, NULL);
>> struct collection_status s = { 0 };
>> int i;
>
> ... would be helped.
Good point. I was sensing the same thing as I made all the callsite changes so
this feedback makes it clear what we should do.
>
> Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 21:02 ` John Cai
@ 2024-06-06 22:44 ` Junio C Hamano
2024-06-28 15:30 ` Kristoffer Haugsbakk
0 siblings, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2024-06-06 22:44 UTC (permalink / raw)
To: John Cai, Aryan Gupta
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila
John Cai <johncai86@gmail.com> writes:
> On 6 Jun 2024, at 14:21, Junio C Hamano wrote:
>
>> ADMINISTRIVIA. Check the address you place on the CC: line. What
>> we can see for this message at
>> ...
>> I fixed them manually, but it wasn't pleasant. I think we saw a
>> similar breakage earlier coming via GGG, but I do not recall the
>> details of how to cause such breakages (iow, what to avoid repeating
>> this).
>
> oof, apologies. Didn't notice that. I'll be more mindful about the cc line.
I found the previous occurrences of the same problem:
https://lore.kernel.org/git/xmqqjzm3qumx.fsf@gitster.g/
https://lore.kernel.org/git/xmqqh6hkxox6.fsf@gitster.g/
The last message in the thread
https://lore.kernel.org/git/CAMbn=B7J4ODf9ybJQpL1bZZ7qdWSDGaLEyTmVv+ZBiSeC9T+yw@mail.gmail.com/
says that the original user of GGG found what was wrong in the way
the user was using GGG to send and fixed it, but unfortunately we
didn't hear exactly *what* the breakage was and *how* it was fixed.
Aryan, do you remember what the problem was and more importantly
what the fix was?
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 22:44 ` Junio C Hamano
@ 2024-06-28 15:30 ` Kristoffer Haugsbakk
2024-06-28 19:47 ` Junio C Hamano
0 siblings, 1 reply; 44+ messages in thread
From: Kristoffer Haugsbakk @ 2024-06-28 15:30 UTC (permalink / raw)
To: Junio C Hamano
Cc: Josh Soref, git, Phillip Wood, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, John Cai, Aryan Gupta, Linus Arver
On Fri, Jun 7, 2024, at 00:44, Junio C Hamano wrote:
> I found the previous occurrences of the same problem:
>
> https://lore.kernel.org/git/xmqqjzm3qumx.fsf@gitster.g/
> https://lore.kernel.org/git/xmqqh6hkxox6.fsf@gitster.g/
>
> The last message in the thread
>
>
> https://lore.kernel.org/git/CAMbn=B7J4ODf9ybJQpL1bZZ7qdWSDGaLEyTmVv+ZBiSeC9T+yw@mail.gmail.com/
>
> says that the original user of GGG found what was wrong in the way
> the user was using GGG to send and fixed it, but unfortunately we
> didn't hear exactly *what* the breakage was and *how* it was fixed.
>
> Aryan, do you remember what the problem was and more importantly
> what the fix was?
>
> Thanks.
Yes, Aryan didn’t explain what the issue was. But Linus Arver (+CC) in
that first thread/link figured out what was happening in his case:[1]
> I realize now that it's because I copy/pasted the "Cc: ..." lines in the PR
> description from
> https://github.com/gitgitgadget/git/pull/1632#issue-2068188239, such
> that when I pasted those in for the PR description for this series at
> https://github.com/gitgitgadget/git/pull/1694#issue-2187804953, it
> carried over the email addresses as Markdown-formatted hyperlinks.
> Currently it reads
>
> Cc: Christian Couder [chriscool@tuxfamily.org](mailto:chriscool@tuxfamily.org)
> Cc: Junio C Hamano [gitster@pobox.com](mailto:gitster@pobox.com)
> Cc: Emily Shaffer [nasamuffin@google.com](mailto:nasamuffin@google.com)
> cc: Josh Steadmon [steadmon@google.com](mailto:steadmon@google.com)
> cc: Randall S. Becker [rsbecker@nexbridge.com](mailto:rsbecker@nexbridge.com)
> cc: Christian Couder [christian.couder@gmail.com](mailto:christian.couder@gmail.com)
> cc: "Kristoffer Haugsbakk" [code@khaugsbakk.name](mailto:code@khaugsbakk.name)
> cc: "Kristoffer Haugsbakk" <code@khaugsbakk.name>
>
> when I click on "edit", where the last line must be from your manual
> fix which GGG picked up. I've cleaned up the PR description manually
> now, and for this message I'm also attempting to clean up those square
> brackets.
When I read that I assumed that Aryan had made the same mistake.
🔗 1: https://lore.kernel.org/git/owly4jd741ph.fsf@fine.c.googlers.com/
--
Kristoffer Haugsbakk
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-28 15:30 ` Kristoffer Haugsbakk
@ 2024-06-28 19:47 ` Junio C Hamano
2024-06-30 10:12 ` Linus Arver
0 siblings, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2024-06-28 19:47 UTC (permalink / raw)
To: Kristoffer Haugsbakk
Cc: Josh Soref, git, Phillip Wood, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, John Cai, Aryan Gupta, Linus Arver
"Kristoffer Haugsbakk" <code@khaugsbakk.name> writes:
>> ...
>> https://github.com/gitgitgadget/git/pull/1694#issue-2187804953, it
>> carried over the email addresses as Markdown-formatted hyperlinks.
>> Currently it reads
>>
>> Cc: Christian Couder [chriscool@tuxfamily.org](mailto:chriscool@tuxfamily.org)
>>...
>> cc: "Kristoffer Haugsbakk" <code@khaugsbakk.name>
>>
>> when I click on "edit", where the last line must be from your manual
>> fix which GGG picked up. I've cleaned up the PR description manually
>> now, and for this message I'm also attempting to clean up those square
>> brackets.
>
> When I read that I assumed that Aryan had made the same mistake.
Ah, I see.
I wonder if there are things we can do to help reduce the pain in
future users of GGG here.
- Is there some documentation update we can make on our end,
perhaps in Documentation/MyFirstContribution (SubmittingPatches
does not talk about GGG other than refering readers to
MyFirstContribution)?
- Or the welcome message GGG adds to the pull-request that begins
with "Thanks for taking the time to contribute" can mention
something about this?
- Or possibly the handling of Cc: addresses done by GGG can be
tweaked not to cause this?
Anything else?
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-28 19:47 ` Junio C Hamano
@ 2024-06-30 10:12 ` Linus Arver
2024-06-30 18:19 ` Junio C Hamano
0 siblings, 1 reply; 44+ messages in thread
From: Linus Arver @ 2024-06-30 10:12 UTC (permalink / raw)
To: Junio C Hamano, Kristoffer Haugsbakk
Cc: Josh Soref, git, Phillip Wood, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, John Cai, Aryan Gupta, Linus Arver,
Johannes Schindelin
Junio C Hamano <gitster@pobox.com> writes:
> "Kristoffer Haugsbakk" <code@khaugsbakk.name> writes:
>
>>> ...
>>> https://github.com/gitgitgadget/git/pull/1694#issue-2187804953, it
>>> carried over the email addresses as Markdown-formatted hyperlinks.
>>> Currently it reads
>>>
>>> Cc: Christian Couder [chriscool@tuxfamily.org](mailto:chriscool@tuxfamily.org)
>>>...
>>> cc: "Kristoffer Haugsbakk" <code@khaugsbakk.name>
>>>
>>> when I click on "edit", where the last line must be from your manual
>>> fix which GGG picked up. I've cleaned up the PR description manually
>>> now, and for this message I'm also attempting to clean up those square
>>> brackets.
>>
>> When I read that I assumed that Aryan had made the same mistake.
>
> Ah, I see.
>
> I wonder if there are things we can do to help reduce the pain in
> future users of GGG here.
>
> [...]
>
> - Or the welcome message GGG adds to the pull-request that begins
> with "Thanks for taking the time to contribute" can mention
> something about this?
I've created https://github.com/gitgitgadget/gitgitgadget/pull/1644 to
address this for now.
>
> - Or possibly the handling of Cc: addresses done by GGG can be
> tweaked not to cause this?
I wanted to do this first but was deterred by my lack of familiarity
with TypeScript.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-30 10:12 ` Linus Arver
@ 2024-06-30 18:19 ` Junio C Hamano
0 siblings, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-06-30 18:19 UTC (permalink / raw)
To: Linus Arver
Cc: Kristoffer Haugsbakk, Josh Soref, git, Phillip Wood, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, John Cai, Aryan Gupta,
Linus Arver, Johannes Schindelin
Linus Arver <linusarver@gmail.com> writes:
>> - Or the welcome message GGG adds to the pull-request that begins
>> with "Thanks for taking the time to contribute" can mention
>> something about this?
>
> I've created https://github.com/gitgitgadget/gitgitgadget/pull/1644 to
> address this for now.
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-06 17:26 ` [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe John Cai via GitGitGadget
2024-06-06 18:21 ` Junio C Hamano
@ 2024-06-11 8:50 ` Jeff King
2024-07-30 14:38 ` John Cai
1 sibling, 1 reply; 44+ messages in thread
From: Jeff King @ 2024-06-11 8:50 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Junio C Hamano, Kristoffer Haugsbakk,
Jeff King, Patrick Steinhardt, Jean-Noël Avila, John Cai
On Thu, Jun 06, 2024 at 05:26:37PM +0000, John Cai via GitGitGadget wrote:
> From: John Cai <johncai86@gmail.com>
>
> refs_resolve_ref_unsafe retrieves the referent, the unresolved value of
> a reference. Add a parameter to allow refs_resolve_ref_unsafe to pass up
> the value of referent to the caller so it can save this value in ref
> iterators for more efficient access.
This commit message left me with a lot of questions.
For one, it wasn't immediately obvious to me what a "referent" is. ;) I
think an example could help. If I understand, you mean that if you have
a situation like:
- refs/heads/one is a symref pointing to refs/heads/two
- refs/heads/two is a regular ref
and we resolve "one", then "two" is the referent? And the caller might
want to know that?
But I think we already pass that out as the return value from
refs_resolve_ref_unsafe(). That is how something like "rev-parse
--symbolic-full-name" works now.
But there are some subtleties. In a chain of symbolic refs (say, "two"
is a symbolic ref to "three"), we return only the final name ("three").
And you might want to know about "two".
You can pass RESOLVE_REF_NO_RECURSE to inhibit this, and get back just
"two". You can see that now with "git symbolic-ref --no-recurse". The
downside is that we never look at the referent at all, so you get only
the symref value (and no information about the actual oid, or if the
referent even exists). You would still get an oid for any non-symrefs
you examine.
So reading between the lines, you have a caller in mind which wants to
know the immediate referent in addition to the final recursive oid?
Looking at the rest of your series, I guess that caller is the one in
loose_fill_ref_dir_regular_file(), so that it can get passed to the
for-each-ref callback. But why is it right thing for it to record and
pass along the immediate referent there, and not the final one? For that
matter, would a caller ever want to see the whole chain of
one/two/three?
> @@ -1761,6 +1761,7 @@ int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
>
> const char *refs_resolve_ref_unsafe(struct ref_store *refs,
> const char *refname,
> + const char *referent,
> int resolve_flags,
> struct object_id *oid,
> int *flags)
Unless I am misunderstanding the purpose of your patch completely, this
"referent" is meant to be an out-parameter, right? In which case,
shouldn't it be "const char **referent"?
As the code is now:
> @@ -1822,6 +1823,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
> }
>
> *flags |= read_flags;
> + if (referent && (read_flags & REF_ISSYMREF) &&
> + sb_refname.len > 0)
> + referent = sb_refname.buf;
>
> if (!(read_flags & REF_ISSYMREF)) {
> if (*flags & REF_BAD_NAME) {
...we'd assign the local "referent" pointer to our refname buf, but
the caller would never see that. Plus doing so would not help you
anyway, since sb_refname will be used again as we recurse. So at best,
you end up with the final name in the chain anyway. Or at worst,
sb_refname gets reallocated and "referent" is left as a dangling
pointer.
-Peff
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe
2024-06-11 8:50 ` Jeff King
@ 2024-07-30 14:38 ` John Cai
0 siblings, 0 replies; 44+ messages in thread
From: John Cai @ 2024-07-30 14:38 UTC (permalink / raw)
To: Jeff King
Cc: John Cai via GitGitGadget, git, Phillip Wood, Junio C Hamano,
Kristoffer Haugsbakk, Patrick Steinhardt, Jean-Noël Avila
Hey Peff,
On 11 Jun 2024, at 4:50, Jeff King wrote:
> On Thu, Jun 06, 2024 at 05:26:37PM +0000, John Cai via GitGitGadget wrote:
>
>> From: John Cai <johncai86@gmail.com>
>>
>> refs_resolve_ref_unsafe retrieves the referent, the unresolved value of
>> a reference. Add a parameter to allow refs_resolve_ref_unsafe to pass up
>> the value of referent to the caller so it can save this value in ref
>> iterators for more efficient access.
>
> This commit message left me with a lot of questions.
>
> For one, it wasn't immediately obvious to me what a "referent" is. ;) I
> think an example could help. If I understand, you mean that if you have
> a situation like:
>
> - refs/heads/one is a symref pointing to refs/heads/two
> - refs/heads/two is a regular ref
>
> and we resolve "one", then "two" is the referent? And the caller might
> want to know that?
>
> But I think we already pass that out as the return value from
> refs_resolve_ref_unsafe(). That is how something like "rev-parse
> --symbolic-full-name" works now.
Yes, exactly. I think you're right that it'd be preferable to just use the
output of refs_resolve_ref_unsafe() to get the value of the referent.
>
> But there are some subtleties. In a chain of symbolic refs (say, "two"
> is a symbolic ref to "three"), we return only the final name ("three").
> And you might want to know about "two".
>
> You can pass RESOLVE_REF_NO_RECURSE to inhibit this, and get back just
> "two". You can see that now with "git symbolic-ref --no-recurse". The
> downside is that we never look at the referent at all, so you get only
> the symref value (and no information about the actual oid, or if the
> referent even exists). You would still get an oid for any non-symrefs
> you examine.
>
> So reading between the lines, you have a caller in mind which wants to
> know the immediate referent in addition to the final recursive oid?
The goal is to keep track of the value that %(symref) would need in the
iterator so that a separate call doesn't need to be made.
>
> Looking at the rest of your series, I guess that caller is the one in
> loose_fill_ref_dir_regular_file(), so that it can get passed to the
> for-each-ref callback. But why is it right thing for it to record and
> pass along the immediate referent there, and not the final one? For that
> matter, would a caller ever want to see the whole chain of
> one/two/three?
Right, the final referent is the right one to pass down.
>
>> @@ -1761,6 +1761,7 @@ int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
>>
>> const char *refs_resolve_ref_unsafe(struct ref_store *refs,
>> const char *refname,
>> + const char *referent,
>> int resolve_flags,
>> struct object_id *oid,
>> int *flags)
>
> Unless I am misunderstanding the purpose of your patch completely, this
> "referent" is meant to be an out-parameter, right? In which case,
> shouldn't it be "const char **referent"?
>
> As the code is now:
>
>> @@ -1822,6 +1823,9 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
>> }
>>
>> *flags |= read_flags;
>> + if (referent && (read_flags & REF_ISSYMREF) &&
>> + sb_refname.len > 0)
>> + referent = sb_refname.buf;
>>
>> if (!(read_flags & REF_ISSYMREF)) {
>> if (*flags & REF_BAD_NAME) {
>
> ...we'd assign the local "referent" pointer to our refname buf, but
> the caller would never see that. Plus doing so would not help you
> anyway, since sb_refname will be used again as we recurse. So at best,
> you end up with the final name in the chain anyway. Or at worst,
> sb_refname gets reallocated and "referent" is left as a dangling
> pointer.
Going to include changes to remove the out-parameter which will simplify things
quite a bit.
>
> -Peff
thanks for the review!
John
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 2/4] refs: keep track of unresolved reference value in iterators
2024-06-06 17:26 [PATCH 0/4] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-06-06 17:26 ` [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe John Cai via GitGitGadget
@ 2024-06-06 17:26 ` John Cai via GitGitGadget
2024-06-11 9:01 ` Jeff King
2024-06-06 17:26 ` [PATCH 3/4] refs: add referent to each_ref_fn John Cai via GitGitGadget
` (2 subsequent siblings)
4 siblings, 1 reply; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-06-06 17:26 UTC (permalink / raw)
To: git; +Cc: Phillip Wood [ ]
From: John Cai <johncai86@gmail.com>
Since ref iterators do not hold onto the direct value of a reference
without resolving it, the only way to get ahold of a direct value of a
symbolic ref is to make a separate call to refs_read_symbolic_ref.
To make accessing the direct value of a symbolic ref more efficient,
let's save the direct value of the ref in the iterators for both the
files backend and the reftable backend.
Signed-off-by: John Cai <johncai86@gmail.com>
---
refs/files-backend.c | 8 ++++++--
refs/iterator.c | 3 +++
refs/ref-cache.c | 6 ++++++
refs/ref-cache.h | 2 ++
refs/refs-internal.h | 1 +
refs/reftable-backend.c | 2 +-
6 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index bf2ffe062ea..a963d796a29 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -243,8 +243,9 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
{
struct object_id oid;
int flag;
+ const char* referent = NULL;
- if (!refs_resolve_ref_unsafe(&refs->base, refname, NULL, RESOLVE_REF_READING,
+ if (!refs_resolve_ref_unsafe(&refs->base, refname, referent, RESOLVE_REF_READING,
&oid, &flag)) {
oidclr(&oid);
flag |= REF_ISBROKEN;
@@ -266,7 +267,7 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
oidclr(&oid);
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
- add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
+ add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
}
/*
@@ -854,6 +855,9 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
iter->base.refname = iter->iter0->refname;
iter->base.oid = iter->iter0->oid;
iter->base.flags = iter->iter0->flags;
+ if (iter->iter0->flags & REF_ISSYMREF)
+ iter->base.referent = iter->iter0->referent;
+
return ITER_OK;
}
diff --git a/refs/iterator.c b/refs/iterator.c
index d355ebf0d59..26acb6bd640 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -7,6 +7,7 @@
#include "refs.h"
#include "refs/refs-internal.h"
#include "iterator.h"
+#include "strbuf.h"
int ref_iterator_advance(struct ref_iterator *ref_iterator)
{
@@ -29,6 +30,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
{
iter->vtable = vtable;
iter->refname = NULL;
+ iter->referent = NULL;
iter->oid = NULL;
iter->flags = 0;
}
@@ -199,6 +201,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
}
if (selection & ITER_YIELD_CURRENT) {
+ iter->base.referent = (*iter->current)->referent;
iter->base.refname = (*iter->current)->refname;
iter->base.oid = (*iter->current)->oid;
iter->base.flags = (*iter->current)->flags;
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index b6c53fc8ed2..e8ce5822cc1 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -5,6 +5,7 @@
#include "refs-internal.h"
#include "ref-cache.h"
#include "../iterator.h"
+#include "../strbuf.h"
void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
{
@@ -34,12 +35,16 @@ struct ref_dir *get_ref_dir(struct ref_entry *entry)
}
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag)
{
struct ref_entry *ref;
FLEX_ALLOC_STR(ref, name, refname);
oidcpy(&ref->u.value.oid, oid);
+ if (referent)
+ ref->u.value.referent = xstrdup(referent);
+
ref->flag = flag;
return ref;
}
@@ -429,6 +434,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
level->index = -1;
} else {
iter->base.refname = entry->name;
+ iter->base.referent = entry->u.value.referent;
iter->base.oid = &entry->u.value.oid;
iter->base.flags = entry->flag;
return ITER_OK;
diff --git a/refs/ref-cache.h b/refs/ref-cache.h
index 95c76e27c83..12ddee4fddc 100644
--- a/refs/ref-cache.h
+++ b/refs/ref-cache.h
@@ -42,6 +42,7 @@ struct ref_value {
* referred to by the last reference in the symlink chain.
*/
struct object_id oid;
+ const char *referent;
};
/*
@@ -173,6 +174,7 @@ struct ref_entry *create_dir_entry(struct ref_cache *cache,
const char *dirname, size_t len);
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag);
/*
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 33749fbd839..07754514355 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -299,6 +299,7 @@ enum do_for_each_ref_flags {
struct ref_iterator {
struct ref_iterator_vtable *vtable;
const char *refname;
+ const char *referent;
const struct object_id *oid;
unsigned int flags;
};
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 9e03582e7da..6328c0f77dc 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -438,7 +438,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
oidread(&iter->oid, iter->ref.value.val2.value);
break;
case REFTABLE_REF_SYMREF:
- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname, NULL,
+ if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname, iter->base.referent,
RESOLVE_REF_READING, &iter->oid, &flags))
oidclr(&iter->oid);
break;
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH 2/4] refs: keep track of unresolved reference value in iterators
2024-06-06 17:26 ` [PATCH 2/4] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-06-11 9:01 ` Jeff King
0 siblings, 0 replies; 44+ messages in thread
From: Jeff King @ 2024-06-11 9:01 UTC (permalink / raw)
To: John Cai via GitGitGadget; +Cc: git
On Thu, Jun 06, 2024 at 05:26:38PM +0000, John Cai via GitGitGadget wrote:
> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index bf2ffe062ea..a963d796a29 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -243,8 +243,9 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
> {
> struct object_id oid;
> int flag;
> + const char* referent = NULL;
>
> - if (!refs_resolve_ref_unsafe(&refs->base, refname, NULL, RESOLVE_REF_READING,
> + if (!refs_resolve_ref_unsafe(&refs->base, refname, referent, RESOLVE_REF_READING,
> &oid, &flag)) {
> oidclr(&oid);
> flag |= REF_ISBROKEN;
Here we pass in NULL, so the code in refs_resolve_ref_unsafe() won't do
anything. And our copy of "referent" here will remain NULL, so the rest
of this patch also does nothing. Again, I think that the function should
take a "char **", and you'd pass in &referent here?
Though if we are OK with surfacing just the final value in a
multi-element chain, then you could just use the existing return value,
like:
referent = refs_resolve_ref_unsafe(&refs->base, refname,
RESOLVE_REF_REAEDING, &oid, &flags);
if (!referent) {
oidclr(&oid);
flag |= REF_ISBROKEN;
}
and then later pass "referent" to create_ref_entry() if flags contains
REF_ISSYMREF (or since we pass it the flags, it could do that check
itself).
-Peff
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 3/4] refs: add referent to each_ref_fn
2024-06-06 17:26 [PATCH 0/4] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-06-06 17:26 ` [PATCH 1/4] refs: add referent parameter to refs_resolve_ref_unsafe John Cai via GitGitGadget
2024-06-06 17:26 ` [PATCH 2/4] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-06-06 17:26 ` John Cai via GitGitGadget
2024-06-06 17:26 ` [PATCH 4/4] ref-filter: populate symref from iterator John Cai via GitGitGadget
2024-08-01 14:58 ` [PATCH v2 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
4 siblings, 0 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-06-06 17:26 UTC (permalink / raw)
To: git; +Cc: Phillip Wood [ ]
From: John Cai <johncai86@gmail.com>
Add a parameter to each_ref_fn so that callers to the ref APIs
that use this function as a callback can have acess to the
unresolved value of a symbolic ref.
Signed-off-by: John Cai <johncai86@gmail.com>
---
bisect.c | 3 ++-
builtin/bisect.c | 4 +++-
builtin/checkout.c | 2 +-
builtin/describe.c | 2 +-
builtin/fetch.c | 3 ++-
builtin/fsck.c | 4 ++--
builtin/gc.c | 1 +
builtin/name-rev.c | 2 +-
builtin/pack-objects.c | 5 +++--
builtin/receive-pack.c | 2 +-
builtin/remote.c | 4 +++-
builtin/repack.c | 1 +
builtin/replace.c | 1 +
builtin/rev-parse.c | 4 ++--
builtin/show-branch.c | 8 ++++----
builtin/show-ref.c | 3 ++-
builtin/submodule--helper.c | 1 +
builtin/worktree.c | 1 +
commit-graph.c | 1 +
delta-islands.c | 2 +-
fetch-pack.c | 2 ++
help.c | 2 +-
http-backend.c | 4 ++--
log-tree.c | 2 +-
ls-refs.c | 4 ++--
midx-write.c | 2 +-
negotiator/default.c | 2 +-
negotiator/skipping.c | 2 +-
notes.c | 2 +-
object-name.c | 2 +-
reachable.c | 2 +-
ref-filter.c | 4 ++--
reflog.c | 1 +
refs.c | 12 ++++++------
refs.h | 2 +-
refs/files-backend.c | 2 +-
refs/iterator.c | 2 +-
remote.c | 4 ++--
replace-object.c | 1 +
revision.c | 2 +-
server-info.c | 2 +-
shallow.c | 2 ++
submodule.c | 2 ++
t/helper/test-ref-store.c | 2 +-
upload-pack.c | 8 ++++----
walker.c | 1 +
worktree.c | 2 +-
47 files changed, 76 insertions(+), 53 deletions(-)
diff --git a/bisect.c b/bisect.c
index 4ea703bec11..e22b3acf082 100644
--- a/bisect.c
+++ b/bisect.c
@@ -446,7 +446,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
clear_commit_weight(&commit_weight);
}
-static int register_ref(const char *refname, const struct object_id *oid,
+static int register_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data UNUSED)
{
struct strbuf good_prefix = STRBUF_INIT;
@@ -1168,6 +1168,7 @@ int estimate_bisect_steps(int all)
}
static int mark_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 76ce5f0e0df..142e56d6020 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -355,6 +355,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
}
static int inc_nr(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
@@ -544,7 +545,7 @@ static int bisect_append_log_quoted(const char **argv)
return res;
}
-static int add_bisect_ref(const char *refname, const struct object_id *oid,
+static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct add_bisect_ref_data *data = cb;
@@ -1161,6 +1162,7 @@ static int bisect_visualize(struct bisect_terms *terms, int argc,
}
static int get_first_good(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/checkout.c b/builtin/checkout.c
index f90a4ca4b7a..ccd27c277d9 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1045,7 +1045,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
report_tracking(new_branch_info);
}
-static int add_pending_uninteresting_ref(const char *refname,
+static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/describe.c b/builtin/describe.c
index e5287eddf2d..d95a9109eed 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -145,7 +145,7 @@ static void add_to_known_names(const char *path,
}
}
-static int get_name(const char *path, const struct object_id *oid,
+static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
int is_tag = 0;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index a319954f9fd..b3e275ca5c8 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -286,7 +286,7 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
return ent;
}
-static int add_one_refname(const char *refname,
+static int add_one_refname(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
@@ -1459,6 +1459,7 @@ static void set_option(struct transport *transport, const char *name, const char
static int add_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 2c0ac6653ca..650dd0d839d 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -521,7 +521,7 @@ static int fsck_handle_reflog(const char *logname, void *cb_data)
return 0;
}
-static int fsck_handle_ref(const char *refname, const struct object_id *oid,
+static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object *obj;
@@ -576,7 +576,7 @@ static void get_default_heads(void)
strbuf_worktree_ref(wt, &ref, "HEAD");
fsck_head_link(ref.buf, &head_points_at, &head_oid);
if (head_points_at && !is_null_oid(&head_oid))
- fsck_handle_ref(ref.buf, &head_oid, 0, NULL);
+ fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL);
strbuf_release(&ref);
if (include_reflogs)
diff --git a/builtin/gc.c b/builtin/gc.c
index 72bac2554fc..65be7c31b33 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -836,6 +836,7 @@ struct cg_auto_data {
};
static int dfs_on_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 70e9ec4e477..52016f1cf7d 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -337,7 +337,7 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_)
return a->taggerdate != b->taggerdate;
}
-static int name_ref(const char *path, const struct object_id *oid,
+static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
struct object *o = parse_object(the_repository, oid);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 638f5c57f0d..a593fbfb3a3 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -771,7 +771,7 @@ static enum write_one_status write_one(struct hashfile *f,
return WRITE_ONE_WRITTEN;
}
-static int mark_tagged(const char *path UNUSED, const struct object_id *oid,
+static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -3127,7 +3127,7 @@ static void add_tag_chain(const struct object_id *oid)
}
}
-static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid,
+static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -4074,6 +4074,7 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED)
}
static int mark_bitmap_preferred_tip(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *data UNUSED)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index d9e2c4bbe39..d3307730f39 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -300,7 +300,7 @@ static void show_ref(const char *path, const struct object_id *oid)
}
}
-static int show_ref_cb(const char *path_full, const struct object_id *oid,
+static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *data)
{
struct oidset *seen = data;
diff --git a/builtin/remote.c b/builtin/remote.c
index 039d1d6c55a..fdc5954c6e0 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -543,6 +543,7 @@ struct branches_for_remote {
};
static int add_branch_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -585,7 +586,7 @@ struct rename_info {
uint32_t symrefs_nr;
};
-static int read_remote_branches(const char *refname,
+static int read_remote_branches(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -971,6 +972,7 @@ static void free_remote_ref_states(struct ref_states *states)
}
static int append_ref_to_tracked_list(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
diff --git a/builtin/repack.c b/builtin/repack.c
index 58ad82dd97b..2c1218debcd 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -667,6 +667,7 @@ struct midx_snapshot_ref_data {
};
static int midx_snapshot_ref_one(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *_data)
{
diff --git a/builtin/replace.c b/builtin/replace.c
index ce9f6974d26..ab004979fbb 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -49,6 +49,7 @@ struct show_data {
};
static int show_reference(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 1e2919fd81c..cc1a88cd933 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -211,7 +211,7 @@ static int show_default(void)
return 0;
}
-static int show_reference(const char *refname, const struct object_id *oid,
+static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
if (ref_excluded(&ref_excludes, refname))
@@ -220,7 +220,7 @@ static int show_reference(const char *refname, const struct object_id *oid,
return 0;
}
-static int anti_reference(const char *refname, const struct object_id *oid,
+static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
show_rev(REVERSED, oid, refname);
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index d72f4cb98de..3427c1572e5 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -410,7 +410,7 @@ static int append_ref(const char *refname, const struct object_id *oid,
return 0;
}
-static int append_head_ref(const char *refname, const struct object_id *oid,
+static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -425,7 +425,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid,
return append_ref(refname + ofs, oid, 0);
}
-static int append_remote_ref(const char *refname, const struct object_id *oid,
+static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -451,7 +451,7 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,
static const char *match_ref_pattern = NULL;
static int match_ref_slash = 0;
-static int append_matching_ref(const char *refname, const struct object_id *oid,
+static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
/* we want to allow pattern hold/<asterisk> to show all
@@ -468,7 +468,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid,
if (wildmatch(match_ref_pattern, tail, 0))
return 0;
if (starts_with(refname, "refs/heads/"))
- return append_head_ref(refname, oid, flag, cb_data);
+ return append_head_ref(refname, NULL, oid, flag, cb_data);
if (starts_with(refname, "refs/tags/"))
return append_tag_ref(refname, oid, flag, cb_data);
return append_ref(refname, oid, 0);
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 3114bdc391a..3b9be14b61c 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -63,7 +63,7 @@ struct show_ref_data {
int show_head;
};
-static int show_ref(const char *refname, const struct object_id *oid,
+static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
struct show_ref_data *data = cbdata;
@@ -97,6 +97,7 @@ static int show_ref(const char *refname, const struct object_id *oid,
}
static int add_existing(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cbdata)
{
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e3e1f08a58c..d7c29383ccb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -611,6 +611,7 @@ static void print_status(unsigned int flags, char state, const char *path,
}
static int handle_submodule_head_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 893e973871e..14f9a525d6a 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -626,6 +626,7 @@ static void print_preparing_worktree_line(int detach,
* Returns 0 on failure and non-zero on success.
*/
static int first_valid_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data UNUSED)
diff --git a/commit-graph.c b/commit-graph.c
index e5dd3553dfe..b6906633b1b 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1815,6 +1815,7 @@ struct refs_cb_data {
};
static int add_ref_to_set(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/delta-islands.c b/delta-islands.c
index 4ac3c10551a..8bafa4b807c 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -388,7 +388,7 @@ static void add_ref_to_island(kh_str_t *remote_islands, const char *island_name,
rl->hash += sha_core;
}
-static int find_island_for_ref(const char *refname, const struct object_id *oid,
+static int find_island_for_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct island_load_data *ild = cb;
diff --git a/fetch-pack.c b/fetch-pack.c
index 7d2aef21add..ae9615fad65 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -181,6 +181,7 @@ static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
}
static int rev_list_insert_ref_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
@@ -608,6 +609,7 @@ static int mark_complete(const struct object_id *oid)
}
static int mark_complete_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/help.c b/help.c
index 1d057aa6073..385a98f81fa 100644
--- a/help.c
+++ b/help.c
@@ -789,7 +789,7 @@ struct similar_ref_cb {
struct string_list *similar_refs;
};
-static int append_similar_ref(const char *refname,
+static int append_similar_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
diff --git a/http-backend.c b/http-backend.c
index 20c3ff8fa95..d9ed6405ed4 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -510,7 +510,7 @@ static void run_service(const char **argv, int buffer_input)
exit(1);
}
-static int show_text_ref(const char *name, const struct object_id *oid,
+static int show_text_ref(const char *name, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *name_nons = strip_namespace(name);
@@ -566,7 +566,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
strbuf_release(&buf);
}
-static int show_head_ref(const char *refname, const struct object_id *oid,
+static int show_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct strbuf *buf = cb_data;
diff --git a/log-tree.c b/log-tree.c
index da06c6e982f..06176e34a2c 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -143,7 +143,7 @@ static int ref_filter_match(const char *refname,
return 1;
}
-static int add_ref_decoration(const char *refname, const struct object_id *oid,
+static int add_ref_decoration(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED,
void *cb_data)
{
diff --git a/ls-refs.c b/ls-refs.c
index 3d047bbc64f..f0d9f8864d7 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -75,7 +75,7 @@ struct ls_refs_data {
unsigned unborn : 1;
};
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct ls_refs_data *data = cb_data;
@@ -134,7 +134,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
oid_is_null = is_null_oid(&oid);
if (!oid_is_null ||
(data->unborn && data->symrefs && (flag & REF_ISSYMREF)))
- send_ref(namespaced.buf, oid_is_null ? NULL : &oid, flag, data);
+ send_ref(namespaced.buf, NULL, oid_is_null ? NULL : &oid, flag, data);
strbuf_release(&namespaced);
}
diff --git a/midx-write.c b/midx-write.c
index 4998707eb8b..bac416d5e87 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -651,7 +651,7 @@ static void prepare_midx_packing_data(struct packing_data *pdata,
trace2_region_leave("midx", "prepare_midx_packing_data", the_repository);
}
-static int add_ref_to_pending(const char *refname,
+static int add_ref_to_pending(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag, void *cb_data)
{
diff --git a/negotiator/default.c b/negotiator/default.c
index 518b3c43b28..052c37f4ae2 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -36,7 +36,7 @@ static void rev_list_push(struct negotiation_state *ns,
}
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index b7e008c2fda..0ad76b033ab 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -73,7 +73,7 @@ static struct entry *rev_list_push(struct data *data, struct commit *commit, int
return entry;
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/notes.c b/notes.c
index 53ca25c8147..77ac78ac08e 100644
--- a/notes.c
+++ b/notes.c
@@ -928,7 +928,7 @@ int combine_notes_cat_sort_uniq(struct object_id *cur_oid,
return ret;
}
-static int string_list_add_one_ref(const char *refname,
+static int string_list_add_one_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb)
{
diff --git a/object-name.c b/object-name.c
index 523af6f64f3..68b4105d614 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1363,7 +1363,7 @@ struct handle_one_ref_cb {
struct commit_list **list;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/reachable.c b/reachable.c
index 1224b300086..1f09353bae3 100644
--- a/reachable.c
+++ b/reachable.c
@@ -77,7 +77,7 @@ static void add_rebase_files(struct rev_info *revs)
free_worktrees(worktrees);
}
-static int add_one_ref(const char *path, const struct object_id *oid,
+static int add_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct rev_info *revs = (struct rev_info *)cb_data;
diff --git a/ref-filter.c b/ref-filter.c
index f7fb0c7e0ec..0b4b6bb8d71 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2863,7 +2863,7 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
@@ -2898,7 +2898,7 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
diff --git a/reflog.c b/reflog.c
index 3c80950186b..744e5f2d982 100644
--- a/reflog.c
+++ b/reflog.c
@@ -298,6 +298,7 @@ int should_expire_reflog_ent_verbose(struct object_id *ooid,
}
static int push_tip_to_list(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags, void *cb_data)
{
diff --git a/refs.c b/refs.c
index 2c592a9ae29..f75d6537bc7 100644
--- a/refs.c
+++ b/refs.c
@@ -411,7 +411,7 @@ int refs_ref_exists(struct ref_store *refs, const char *refname)
NULL, NULL);
}
-static int for_each_filter_refs(const char *refname,
+static int for_each_filter_refs(const char *refname, const char *referent,
const struct object_id *oid,
int flags, void *data)
{
@@ -421,7 +421,7 @@ static int for_each_filter_refs(const char *refname,
return 0;
if (filter->prefix)
skip_prefix(refname, filter->prefix, &refname);
- return filter->fn(refname, oid, flags, filter->cb_data);
+ return filter->fn(refname, referent, oid, flags, filter->cb_data);
}
struct warn_if_dangling_data {
@@ -432,7 +432,7 @@ struct warn_if_dangling_data {
const char *msg_fmt;
};
-static int warn_if_dangling_symref(const char *refname,
+static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
@@ -503,7 +503,7 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag))
- ret = fn(buf.buf, &oid, flag, cb_data);
+ ret = fn(buf.buf, NULL, &oid, flag, cb_data);
strbuf_release(&buf);
return ret;
@@ -1524,7 +1524,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
if (refs_resolve_ref_unsafe(refs, "HEAD", NULL, RESOLVE_REF_READING,
&oid, &flag))
- return fn("HEAD", &oid, flag, cb_data);
+ return fn("HEAD", NULL, &oid, flag, cb_data);
return 0;
}
@@ -2360,7 +2360,7 @@ struct do_for_each_reflog_help {
void *cb_data;
};
-static int do_for_each_reflog_helper(const char *refname,
+static int do_for_each_reflog_helper(const char *refname, const char *referent,
const struct object_id *oid UNUSED,
int flags,
void *cb_data)
diff --git a/refs.h b/refs.h
index ea4a3217658..979494ce1f8 100644
--- a/refs.h
+++ b/refs.h
@@ -294,7 +294,7 @@ struct ref_transaction;
* arguments is only guaranteed to be valid for the duration of a
* single callback invocation.
*/
-typedef int each_ref_fn(const char *refname,
+typedef int each_ref_fn(const char *refname, const char *referent,
const struct object_id *oid, int flags, void *cb_data);
/*
diff --git a/refs/files-backend.c b/refs/files-backend.c
index a963d796a29..f4c892422bc 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3002,7 +3002,7 @@ static int files_transaction_abort(struct ref_store *ref_store,
return 0;
}
-static int ref_present(const char *refname,
+static int ref_present(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data)
diff --git a/refs/iterator.c b/refs/iterator.c
index 26acb6bd640..21beeb91e9e 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -451,7 +451,7 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
current_ref_iter = iter;
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
- retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
+ retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
if (retval) {
/*
* If ref_iterator_abort() returns ITER_ERROR,
diff --git a/remote.c b/remote.c
index c9718ee0ca1..071c542ab31 100644
--- a/remote.c
+++ b/remote.c
@@ -2342,7 +2342,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
return 1;
}
-static int one_local_ref(const char *refname, const struct object_id *oid,
+static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
@@ -2427,7 +2427,7 @@ struct stale_heads_info {
struct refspec *rs;
};
-static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
+static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct stale_heads_info *info = cb_data;
diff --git a/replace-object.c b/replace-object.c
index 73f5acbcd9f..8ef561f1455 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -9,6 +9,7 @@
#include "commit.h"
static int register_replace_ref(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
diff --git a/revision.c b/revision.c
index 6aca4f42303..e37346fb52a 100644
--- a/revision.c
+++ b/revision.c
@@ -1627,7 +1627,7 @@ struct all_refs_cb {
struct worktree *wt;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/server-info.c b/server-info.c
index 6feaa457c5c..3a0d6ad39ab 100644
--- a/server-info.c
+++ b/server-info.c
@@ -151,7 +151,7 @@ static int update_info_file(char *path,
return ret;
}
-static int add_info_ref(const char *path, const struct object_id *oid,
+static int add_info_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/shallow.c b/shallow.c
index a0b181ba8a1..a4d2c3e221b 100644
--- a/shallow.c
+++ b/shallow.c
@@ -610,6 +610,7 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
}
static int mark_uninteresting(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data UNUSED)
@@ -725,6 +726,7 @@ struct commit_array {
};
static int add_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/submodule.c b/submodule.c
index 759cf1e1cda..bdba5a1ba11 100644
--- a/submodule.c
+++ b/submodule.c
@@ -951,6 +951,7 @@ static void free_submodules_data(struct string_list *submodules)
}
static int has_remote(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data UNUSED)
{
@@ -1271,6 +1272,7 @@ int push_unpushed_submodules(struct repository *r,
}
static int append_oid_to_array(const char *ref UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *data)
{
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index ef1d6acbfae..78cb873e6a0 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -153,7 +153,7 @@ static int cmd_rename_ref(struct ref_store *refs, const char **argv)
return refs_rename_ref(refs, oldref, newref, logmsg);
}
-static int each_ref(const char *refname, const struct object_id *oid,
+static int each_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data UNUSED)
{
printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
diff --git a/upload-pack.c b/upload-pack.c
index 4fddc081237..e79e77570b7 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -855,7 +855,7 @@ static void send_unshallow(struct upload_pack_data *data)
}
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data);
static void deepen(struct upload_pack_data *data, int depth)
{
@@ -1206,7 +1206,7 @@ static int mark_our_ref(const char *refname, const char *refname_full,
return 0;
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED,const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *refname = strip_namespace(refname_full);
@@ -1274,14 +1274,14 @@ static void write_v0_ref(struct upload_pack_data *data,
return;
}
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
return 0;
}
-static int find_symref(const char *refname,
+static int find_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag, void *cb_data)
{
diff --git a/walker.c b/walker.c
index 946d86b04ee..918693221a9 100644
--- a/walker.c
+++ b/walker.c
@@ -219,6 +219,7 @@ static int interpret_target(struct walker *walker, char *target, struct object_i
}
static int mark_complete(const char *path UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/worktree.c b/worktree.c
index ed89bab481d..9ab7e305d39 100644
--- a/worktree.c
+++ b/worktree.c
@@ -553,7 +553,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
NULL,
RESOLVE_REF_READING,
&oid, &flag))
- ret = fn(refname.buf, &oid, flag, cb_data);
+ ret = fn(refname.buf, NULL, &oid, flag, cb_data);
if (ret)
break;
}
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 4/4] ref-filter: populate symref from iterator
2024-06-06 17:26 [PATCH 0/4] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
` (2 preceding siblings ...)
2024-06-06 17:26 ` [PATCH 3/4] refs: add referent to each_ref_fn John Cai via GitGitGadget
@ 2024-06-06 17:26 ` John Cai via GitGitGadget
2024-08-01 14:58 ` [PATCH v2 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
4 siblings, 0 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-06-06 17:26 UTC (permalink / raw)
To: git; +Cc: Phillip Wood [ ]
From: John Cai <johncai86@gmail.com>
With a previous commit, the reference the symbolic ref points is saved
in the ref iterator records. Instead of making a separate call to
resolve_refdup() each time, we can just populate the ref_array_item with
the value from the iterator.
Signed-off-by: John Cai <johncai86@gmail.com>
---
ref-filter.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index 0b4b6bb8d71..c7c2117f9cd 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2781,7 +2781,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
return ref_kind_from_refname(refname);
}
-static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
+static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
int flag, struct ref_filter *filter)
{
struct ref_array_item *ref;
@@ -2850,6 +2850,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
ref->commit = commit;
ref->flag = flag;
ref->kind = kind;
+ ref->symref = referent;
return ref;
}
@@ -2863,12 +2864,12 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (ref)
ref_array_append(ref_cbdata->array, ref);
@@ -2898,13 +2899,13 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (!ref)
return 0;
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v2 0/3] keep track of unresolved value of symbolic-ref in ref iterators
2024-06-06 17:26 [PATCH 0/4] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
` (3 preceding siblings ...)
2024-06-06 17:26 ` [PATCH 4/4] ref-filter: populate symref from iterator John Cai via GitGitGadget
@ 2024-08-01 14:58 ` John Cai via GitGitGadget
2024-08-01 14:58 ` [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
` (3 more replies)
4 siblings, 4 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-01 14:58 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai
For reftable development, it's useful to be able to print out the direct
value of a symbolic reference before resolution. This is currently possible
with git-for-each-ref, but since the iterators do not keep track of the
value of the symbolic ref, a separate call needs to be made each time making
it inefficient.
Address this inefficiency by keeping track of the value of the symbolic
reference in the ref iterator. This patch series also ends with a commit to
use this value in the iterator through callbacks in ref-filter.c.
This series started with [1] but I decided to send a separate patch series
since it is substantially different.
Benchmarking shows that with these changes, we experience a speedup in
git-for-each-ref(1) on a repository with many symbolic refs:
$ hyperfine --warmup 5 "git for-each-ref --format='%(refname) %(objectname)
%(symref)'" "~/Projects/git/git for-each-ref --format='%(refname)
%(objectname) %(symref)'" Benchmark 1: git for-each-ref --format='%(refname)
%(objectname) %(symref)' Time (mean ± σ): 905.1 ms ± 13.2 ms [User: 56.3 ms,
System: 628.6 ms] Range (min … max): 893.4 ms … 936.9 ms 10 runs
Benchmark 2: ~/Projects/git/git for-each-ref --format='%(refname)
%(objectname) %(symref)' Time (mean ± σ): 482.2 ms ± 26.4 ms [User: 34.7 ms,
System: 410.6 ms] Range (min … max): 459.4 ms … 541.8 ms 10 runs
Summary ~/Projects/git/git for-each-ref --format='%(refname) %(objectname)
%(symref)' ran 1.88 ± 0.11 times faster than git for-each-ref
--format='%(refname) %(objectname) %(symref)'
Changes since V1:
* Use the return value from refs_resolve_ref_unsafe instead of using an out
parameter
1. https://lore.kernel.org/git/pull.1684.git.git.1709592718743.gitgitgadget@gmail.com/
John Cai (3):
refs: keep track of unresolved reference value in iterators
refs: add referent to each_ref_fn
ref-filter: populate symref from iterator
bisect.c | 3 ++-
builtin/bisect.c | 4 +++-
builtin/checkout.c | 2 +-
builtin/describe.c | 2 +-
builtin/fetch.c | 3 ++-
builtin/fsck.c | 4 ++--
builtin/gc.c | 1 +
builtin/name-rev.c | 2 +-
builtin/pack-objects.c | 5 +++--
builtin/receive-pack.c | 2 +-
builtin/remote.c | 4 +++-
builtin/repack.c | 1 +
builtin/replace.c | 1 +
builtin/rev-parse.c | 4 ++--
builtin/show-branch.c | 8 ++++----
builtin/show-ref.c | 3 ++-
builtin/submodule--helper.c | 1 +
builtin/worktree.c | 1 +
commit-graph.c | 1 +
delta-islands.c | 2 +-
fetch-pack.c | 2 ++
help.c | 2 +-
http-backend.c | 4 ++--
log-tree.c | 2 +-
ls-refs.c | 4 ++--
midx-write.c | 2 +-
negotiator/default.c | 2 +-
negotiator/skipping.c | 2 +-
notes.c | 2 +-
object-name.c | 2 +-
pseudo-merge.c | 1 +
reachable.c | 2 +-
ref-filter.c | 12 +++++++-----
reflog.c | 1 +
refs.c | 14 +++++++-------
refs.h | 2 +-
refs/files-backend.c | 16 +++++++++++-----
refs/iterator.c | 5 ++++-
refs/ref-cache.c | 8 ++++++++
refs/ref-cache.h | 2 ++
refs/refs-internal.h | 1 +
refs/reftable-backend.c | 8 ++++++--
remote.c | 4 ++--
replace-object.c | 1 +
revision.c | 2 +-
server-info.c | 2 +-
shallow.c | 2 ++
submodule.c | 2 ++
t/helper/test-ref-store.c | 2 +-
upload-pack.c | 8 ++++----
walker.c | 1 +
worktree.c | 2 +-
52 files changed, 113 insertions(+), 63 deletions(-)
base-commit: 557ae147e6cdc9db121269b058c757ac5092f9c9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1712%2Fjohn-cai%2Fjc%2Fsymbolic-ref-in-iterator-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1712/john-cai/jc/symbolic-ref-in-iterator-v2
Pull-Request: https://github.com/git/git/pull/1712
Range-diff vs v1:
1: 011c10f4886 < -: ----------- refs: add referent parameter to refs_resolve_ref_unsafe
2: 7202ada0542 ! 1: ac0957c9e6a refs: keep track of unresolved reference value in iterators
@@ refs/files-backend.c: static void loose_fill_ref_dir_regular_file(struct files_r
{
struct object_id oid;
int flag;
-+ const char* referent = NULL;
-
-- if (!refs_resolve_ref_unsafe(&refs->base, refname, NULL, RESOLVE_REF_READING,
-+ if (!refs_resolve_ref_unsafe(&refs->base, refname, referent, RESOLVE_REF_READING,
- &oid, &flag)) {
- oidclr(&oid);
+-
+- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
+- &oid, &flag)) {
++ const char* referent = refs_resolve_ref_unsafe(&refs->base,
++ refname,
++ RESOLVE_REF_READING,
++ &oid, &flag);
++ if (!referent) {
+ oidclr(&oid, the_repository->hash_algo);
flag |= REF_ISBROKEN;
+ } else if (is_null_oid(&oid)) {
@@ refs/files-backend.c: static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
- oidclr(&oid);
+ oidclr(&oid, the_repository->hash_algo);
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
- add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
++
+ add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
}
@@ refs/ref-cache.c: struct ref_dir *get_ref_dir(struct ref_entry *entry)
const struct object_id *oid, int flag)
{
struct ref_entry *ref;
-
+@@ refs/ref-cache.c: struct ref_entry *create_ref_entry(const char *refname,
FLEX_ALLOC_STR(ref, name, refname);
oidcpy(&ref->u.value.oid, oid);
-+ if (referent)
-+ ref->u.value.referent = xstrdup(referent);
-+
ref->flag = flag;
++
++ if (flag & REF_ISSYMREF)
++ ref->u.value.referent = xstrdup_or_null(referent);
++
return ref;
}
+
+@@ refs/ref-cache.c: static void free_ref_entry(struct ref_entry *entry)
+ */
+ clear_ref_dir(&entry->u.subdir);
+ }
++ free(entry->u.value.referent);
+ free(entry);
+ }
+
@@ refs/ref-cache.c: static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
level->index = -1;
} else {
@@ refs/ref-cache.h: struct ref_value {
* referred to by the last reference in the symlink chain.
*/
struct object_id oid;
-+ const char *referent;
++ char *referent;
};
/*
@@ refs/refs-internal.h: enum do_for_each_ref_flags {
## refs/reftable-backend.c ##
@@ refs/reftable-backend.c: static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
- oidread(&iter->oid, iter->ref.value.val2.value);
+ the_repository->hash_algo);
break;
case REFTABLE_REF_SYMREF:
-- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname, NULL,
-+ if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname, iter->base.referent,
- RESOLVE_REF_READING, &iter->oid, &flags))
- oidclr(&iter->oid);
+- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
+- RESOLVE_REF_READING, &iter->oid, &flags))
++ iter->base.referent = refs_resolve_ref_unsafe(&iter->refs->base,
++ iter->ref.refname,
++ RESOLVE_REF_READING,
++ &iter->oid,
++ &flags);
++ if (!iter->base.referent)
+ oidclr(&iter->oid, the_repository->hash_algo);
break;
+ default:
3: 33914f84a64 ! 2: 1f3a604fae7 refs: add referent to each_ref_fn
@@ object-name.c: struct handle_one_ref_cb {
void *cb_data)
{
+ ## pseudo-merge.c ##
+@@ pseudo-merge.c: void load_pseudo_merges_from_config(struct string_list *list)
+ }
+
+ static int find_pseudo_merge_group_for_ref(const char *refname,
++ const char *referent UNUSED,
+ const struct object_id *oid,
+ int flags UNUSED,
+ void *_data)
+
## reachable.c ##
@@ reachable.c: static void add_rebase_files(struct rev_info *revs)
free_worktrees(worktrees);
@@ refs.c: int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, voi
return ret;
@@ refs.c: int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
- if (refs_resolve_ref_unsafe(refs, "HEAD", NULL, RESOLVE_REF_READING,
+ if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
&oid, &flag))
- return fn("HEAD", &oid, flag, cb_data);
+ return fn("HEAD", NULL, &oid, flag, cb_data);
@@ refs.c: struct do_for_each_reflog_help {
const struct object_id *oid UNUSED,
int flags,
void *cb_data)
+@@ refs.c: struct migration_data {
+ struct strbuf *errbuf;
+ };
+
+-static int migrate_one_ref(const char *refname, const struct object_id *oid,
++static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
+ int flags, void *cb_data)
+ {
+ struct migration_data *data = cb_data;
## refs.h ##
@@ refs.h: struct ref_transaction;
@@ walker.c: static int interpret_target(struct walker *walker, char *target, struc
## worktree.c ##
@@ worktree.c: int other_head_refs(each_ref_fn fn, void *cb_data)
- NULL,
+ refname.buf,
RESOLVE_REF_READING,
&oid, &flag))
- ret = fn(refname.buf, &oid, flag, cb_data);
4: 6d5b1b62e6c ! 3: 3e147e7d850 ref-filter: populate symref from iterator
@@ Metadata
## Commit message ##
ref-filter: populate symref from iterator
- With a previous commit, the reference the symbolic ref points is saved
+ With a previous commit, the reference the symbolic ref points to is saved
in the ref iterator records. Instead of making a separate call to
resolve_refdup() each time, we can just populate the ref_array_item with
the value from the iterator.
@@ ref-filter.c: static struct ref_array_item *apply_ref_filter(const char *refname
ref->commit = commit;
ref->flag = flag;
ref->kind = kind;
-+ ref->symref = referent;
++ if (flag & REF_ISSYMREF)
++ ref->symref = xstrdup_or_null(referent);
return ref;
}
--
gitgitgadget
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators
2024-08-01 14:58 ` [PATCH v2 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
@ 2024-08-01 14:58 ` John Cai via GitGitGadget
2024-08-01 16:41 ` Junio C Hamano
2024-08-01 14:58 ` [PATCH v2 2/3] refs: add referent to each_ref_fn John Cai via GitGitGadget
` (2 subsequent siblings)
3 siblings, 1 reply; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-01 14:58 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
Since ref iterators do not hold onto the direct value of a reference
without resolving it, the only way to get ahold of a direct value of a
symbolic ref is to make a separate call to refs_read_symbolic_ref.
To make accessing the direct value of a symbolic ref more efficient,
let's save the direct value of the ref in the iterators for both the
files backend and the reftable backend.
Signed-off-by: John Cai <johncai86@gmail.com>
---
refs/files-backend.c | 14 ++++++++++----
refs/iterator.c | 3 +++
refs/ref-cache.c | 8 ++++++++
refs/ref-cache.h | 2 ++
refs/refs-internal.h | 1 +
refs/reftable-backend.c | 8 ++++++--
6 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index aa52d9be7c7..7640318cba8 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -245,9 +245,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
{
struct object_id oid;
int flag;
-
- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
- &oid, &flag)) {
+ const char* referent = refs_resolve_ref_unsafe(&refs->base,
+ refname,
+ RESOLVE_REF_READING,
+ &oid, &flag);
+ if (!referent) {
oidclr(&oid, the_repository->hash_algo);
flag |= REF_ISBROKEN;
} else if (is_null_oid(&oid)) {
@@ -268,7 +270,8 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
oidclr(&oid, the_repository->hash_algo);
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
- add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
+
+ add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
}
/*
@@ -886,6 +889,9 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
iter->base.refname = iter->iter0->refname;
iter->base.oid = iter->iter0->oid;
iter->base.flags = iter->iter0->flags;
+ if (iter->iter0->flags & REF_ISSYMREF)
+ iter->base.referent = iter->iter0->referent;
+
return ITER_OK;
}
diff --git a/refs/iterator.c b/refs/iterator.c
index d355ebf0d59..26acb6bd640 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -7,6 +7,7 @@
#include "refs.h"
#include "refs/refs-internal.h"
#include "iterator.h"
+#include "strbuf.h"
int ref_iterator_advance(struct ref_iterator *ref_iterator)
{
@@ -29,6 +30,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
{
iter->vtable = vtable;
iter->refname = NULL;
+ iter->referent = NULL;
iter->oid = NULL;
iter->flags = 0;
}
@@ -199,6 +201,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
}
if (selection & ITER_YIELD_CURRENT) {
+ iter->base.referent = (*iter->current)->referent;
iter->base.refname = (*iter->current)->refname;
iter->base.oid = (*iter->current)->oid;
iter->base.flags = (*iter->current)->flags;
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index 4ce519bbc85..da946d476cc 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -5,6 +5,7 @@
#include "refs-internal.h"
#include "ref-cache.h"
#include "../iterator.h"
+#include "../strbuf.h"
void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
{
@@ -34,6 +35,7 @@ struct ref_dir *get_ref_dir(struct ref_entry *entry)
}
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag)
{
struct ref_entry *ref;
@@ -41,6 +43,10 @@ struct ref_entry *create_ref_entry(const char *refname,
FLEX_ALLOC_STR(ref, name, refname);
oidcpy(&ref->u.value.oid, oid);
ref->flag = flag;
+
+ if (flag & REF_ISSYMREF)
+ ref->u.value.referent = xstrdup_or_null(referent);
+
return ref;
}
@@ -66,6 +72,7 @@ static void free_ref_entry(struct ref_entry *entry)
*/
clear_ref_dir(&entry->u.subdir);
}
+ free(entry->u.value.referent);
free(entry);
}
@@ -431,6 +438,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
level->index = -1;
} else {
iter->base.refname = entry->name;
+ iter->base.referent = entry->u.value.referent;
iter->base.oid = &entry->u.value.oid;
iter->base.flags = entry->flag;
return ITER_OK;
diff --git a/refs/ref-cache.h b/refs/ref-cache.h
index 31ebe24f6cf..5f04e518c37 100644
--- a/refs/ref-cache.h
+++ b/refs/ref-cache.h
@@ -42,6 +42,7 @@ struct ref_value {
* referred to by the last reference in the symlink chain.
*/
struct object_id oid;
+ char *referent;
};
/*
@@ -173,6 +174,7 @@ struct ref_entry *create_dir_entry(struct ref_cache *cache,
const char *dirname, size_t len);
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag);
/*
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index fa975d69aaa..117ec233848 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -299,6 +299,7 @@ enum do_for_each_ref_flags {
struct ref_iterator {
struct ref_iterator_vtable *vtable;
const char *refname;
+ const char *referent;
const struct object_id *oid;
unsigned int flags;
};
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index fbe74c239d3..9f724c3d632 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -494,8 +494,12 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
the_repository->hash_algo);
break;
case REFTABLE_REF_SYMREF:
- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
- RESOLVE_REF_READING, &iter->oid, &flags))
+ iter->base.referent = refs_resolve_ref_unsafe(&iter->refs->base,
+ iter->ref.refname,
+ RESOLVE_REF_READING,
+ &iter->oid,
+ &flags);
+ if (!iter->base.referent)
oidclr(&iter->oid, the_repository->hash_algo);
break;
default:
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators
2024-08-01 14:58 ` [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-08-01 16:41 ` Junio C Hamano
2024-08-05 10:59 ` Patrick Steinhardt
0 siblings, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2024-08-01 16:41 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, Linus Arver, John Cai
"John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> @@ -245,9 +245,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
> {
> struct object_id oid;
> int flag;
> -
> - if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
> - &oid, &flag)) {
> + const char* referent = refs_resolve_ref_unsafe(&refs->base,
Style. The asterisk sticks to the pointer variable, not the base type.
> + refname,
> + RESOLVE_REF_READING,
> + &oid, &flag);
> + if (!referent) {
> oidclr(&oid, the_repository->hash_algo);
> flag |= REF_ISBROKEN;
> } else if (is_null_oid(&oid)) {
> @@ -268,7 +270,8 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
> oidclr(&oid, the_repository->hash_algo);
> flag |= REF_BAD_NAME | REF_ISBROKEN;
> }
> - add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
> +
> + add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
> }
This is a very straight-forward change, given the matching change to
the ref-entry, which now has a referent member.
> @@ -886,6 +889,9 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
> iter->base.refname = iter->iter0->refname;
> iter->base.oid = iter->iter0->oid;
> iter->base.flags = iter->iter0->flags;
> + if (iter->iter0->flags & REF_ISSYMREF)
> + iter->base.referent = iter->iter0->referent;
Presumably base.referent is initialized to NULL so this "if"
statement does not need an else clause?
I am primarily wondering why this needs to be conditional. We are
making verbatim copy of the flags word from *iter->iter0 to
iter->base; if iter0 is symref we want to mark base also as symref,
If iter0 is not a symref, then we want to mark base also not a
symref, presumably. So wouldn't it make sense to just say
iter->base.referent = iter->iter0->referent;
here, regardless of what iter->iter0->flags say about symref-ness of
the thing? Because ...
> diff --git a/refs/iterator.c b/refs/iterator.c
> index d355ebf0d59..26acb6bd640 100644
> --- a/refs/iterator.c
> +++ b/refs/iterator.c
> @@ -7,6 +7,7 @@
> #include "refs.h"
> #include "refs/refs-internal.h"
> #include "iterator.h"
> +#include "strbuf.h"
>
> int ref_iterator_advance(struct ref_iterator *ref_iterator)
> {
> @@ -29,6 +30,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
> {
> iter->vtable = vtable;
> iter->refname = NULL;
> + iter->referent = NULL;
> iter->oid = NULL;
> iter->flags = 0;
> }
> @@ -199,6 +201,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
> }
>
> if (selection & ITER_YIELD_CURRENT) {
> + iter->base.referent = (*iter->current)->referent;
> iter->base.refname = (*iter->current)->refname;
> iter->base.oid = (*iter->current)->oid;
> iter->base.flags = (*iter->current)->flags;
... other parts of the API seem to follow that philosophy.
In other words, the invariant of this code is that .referent is
non-NULL if and only if the ref is a symref, and that invariant is
trusted without checking with .flags member. But the earlier hunk
that copied iter0 to base did not seem to be using that invariant,
which made it look inconsistent.
> struct ref_entry *create_ref_entry(const char *refname,
> + const char *referent,
> const struct object_id *oid, int flag)
> {
> struct ref_entry *ref;
> @@ -41,6 +43,10 @@ struct ref_entry *create_ref_entry(const char *refname,
> FLEX_ALLOC_STR(ref, name, refname);
> oidcpy(&ref->u.value.oid, oid);
> ref->flag = flag;
> +
> + if (flag & REF_ISSYMREF)
> + ref->u.value.referent = xstrdup_or_null(referent);
OK. ref_value now has referent next to the existing oid, but that
member only makes sense when flag says it is a symref.
Curiously, that information is missing from ref_value struct, so by
looking at a ref_value alone, we cannot tell if we should trust the
value in the .referent member?
Makes me wonder if we should follow the same "ignore what the flag
says when filling the .referent member; if the ref is not a symref,
the referent variable is NULL, and if it is, referent is never NULL"
pattern? Then ref->u.value.referent is _always_ defined---the
current code says "the u.value.referent member is undefined for ref
that is not a symref", but with the suggested change, it will be
"the u.value.referent member is NULL for ref that is not a symref,
and for a symref, it is the value of the symref".
> return ref;
> }
>
> @@ -66,6 +72,7 @@ static void free_ref_entry(struct ref_entry *entry)
> */
> clear_ref_dir(&entry->u.subdir);
> }
> + free(entry->u.value.referent);
And that would match what is done here. We do not say "entry->flag
says it is not a symref, so do not bother freeing u.value.referent".
> @@ -431,6 +438,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
> level->index = -1;
> } else {
> iter->base.refname = entry->name;
> + iter->base.referent = entry->u.value.referent;
> iter->base.oid = &entry->u.value.oid;
> iter->base.flags = entry->flag;
> return ITER_OK;
> diff --git a/refs/ref-cache.h b/refs/ref-cache.h
> index 31ebe24f6cf..5f04e518c37 100644
> --- a/refs/ref-cache.h
> +++ b/refs/ref-cache.h
> @@ -42,6 +42,7 @@ struct ref_value {
> * referred to by the last reference in the symlink chain.
> */
> struct object_id oid;
> + char *referent;
> };
>
> /*
> @@ -173,6 +174,7 @@ struct ref_entry *create_dir_entry(struct ref_cache *cache,
> const char *dirname, size_t len);
>
> struct ref_entry *create_ref_entry(const char *refname,
> + const char *referent,
> const struct object_id *oid, int flag);
>
> /*
> diff --git a/refs/refs-internal.h b/refs/refs-internal.h
> index fa975d69aaa..117ec233848 100644
> --- a/refs/refs-internal.h
> +++ b/refs/refs-internal.h
> @@ -299,6 +299,7 @@ enum do_for_each_ref_flags {
> struct ref_iterator {
> struct ref_iterator_vtable *vtable;
> const char *refname;
> + const char *referent;
> const struct object_id *oid;
> unsigned int flags;
> };
> diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
> index fbe74c239d3..9f724c3d632 100644
> --- a/refs/reftable-backend.c
> +++ b/refs/reftable-backend.c
> @@ -494,8 +494,12 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
> the_repository->hash_algo);
> break;
> case REFTABLE_REF_SYMREF:
> - if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
> - RESOLVE_REF_READING, &iter->oid, &flags))
> + iter->base.referent = refs_resolve_ref_unsafe(&iter->refs->base,
> + iter->ref.refname,
> + RESOLVE_REF_READING,
> + &iter->oid,
> + &flags);
> + if (!iter->base.referent)
> oidclr(&iter->oid, the_repository->hash_algo);
> break;
> default:
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators
2024-08-01 16:41 ` Junio C Hamano
@ 2024-08-05 10:59 ` Patrick Steinhardt
2024-08-05 15:40 ` Junio C Hamano
0 siblings, 1 reply; 44+ messages in thread
From: Patrick Steinhardt @ 2024-08-05 10:59 UTC (permalink / raw)
To: Junio C Hamano
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Jean-Noël Avila,
Linus Arver, John Cai
[-- Attachment #1: Type: text/plain, Size: 4029 bytes --]
On Thu, Aug 01, 2024 at 09:41:03AM -0700, Junio C Hamano wrote:
> "John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> > @@ -886,6 +889,9 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
> > iter->base.refname = iter->iter0->refname;
> > iter->base.oid = iter->iter0->oid;
> > iter->base.flags = iter->iter0->flags;
> > + if (iter->iter0->flags & REF_ISSYMREF)
> > + iter->base.referent = iter->iter0->referent;
>
> Presumably base.referent is initialized to NULL so this "if"
> statement does not need an else clause?
This function typically ends up being called in a loop though. So
without the else clause, wouldn't we potentially leak the value of a
preceding ref into subsequent iterations like this?
> I am primarily wondering why this needs to be conditional. We are
> making verbatim copy of the flags word from *iter->iter0 to
> iter->base; if iter0 is symref we want to mark base also as symref,
> If iter0 is not a symref, then we want to mark base also not a
> symref, presumably. So wouldn't it make sense to just say
>
> iter->base.referent = iter->iter0->referent;
>
> here, regardless of what iter->iter0->flags say about symref-ness of
> the thing? Because ...
> > diff --git a/refs/iterator.c b/refs/iterator.c
> > index d355ebf0d59..26acb6bd640 100644
> > --- a/refs/iterator.c
> > +++ b/refs/iterator.c
> > @@ -7,6 +7,7 @@
> > #include "refs.h"
> > #include "refs/refs-internal.h"
> > #include "iterator.h"
> > +#include "strbuf.h"
> >
> > int ref_iterator_advance(struct ref_iterator *ref_iterator)
> > {
> > @@ -29,6 +30,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
> > {
> > iter->vtable = vtable;
> > iter->refname = NULL;
> > + iter->referent = NULL;
> > iter->oid = NULL;
> > iter->flags = 0;
> > }
> > @@ -199,6 +201,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
> > }
> >
> > if (selection & ITER_YIELD_CURRENT) {
> > + iter->base.referent = (*iter->current)->referent;
> > iter->base.refname = (*iter->current)->refname;
> > iter->base.oid = (*iter->current)->oid;
> > iter->base.flags = (*iter->current)->flags;
>
> ... other parts of the API seem to follow that philosophy.
>
> In other words, the invariant of this code is that .referent is
> non-NULL if and only if the ref is a symref, and that invariant is
> trusted without checking with .flags member. But the earlier hunk
> that copied iter0 to base did not seem to be using that invariant,
> which made it look inconsistent.
Agreed.
> > struct ref_entry *create_ref_entry(const char *refname,
> > + const char *referent,
> > const struct object_id *oid, int flag)
> > {
> > struct ref_entry *ref;
> > @@ -41,6 +43,10 @@ struct ref_entry *create_ref_entry(const char *refname,
> > FLEX_ALLOC_STR(ref, name, refname);
> > oidcpy(&ref->u.value.oid, oid);
> > ref->flag = flag;
> > +
> > + if (flag & REF_ISSYMREF)
> > + ref->u.value.referent = xstrdup_or_null(referent);
>
> OK. ref_value now has referent next to the existing oid, but that
> member only makes sense when flag says it is a symref.
>
> Curiously, that information is missing from ref_value struct, so by
> looking at a ref_value alone, we cannot tell if we should trust the
> value in the .referent member?
>
> Makes me wonder if we should follow the same "ignore what the flag
> says when filling the .referent member; if the ref is not a symref,
> the referent variable is NULL, and if it is, referent is never NULL"
> pattern? Then ref->u.value.referent is _always_ defined---the
> current code says "the u.value.referent member is undefined for ref
> that is not a symref", but with the suggested change, it will be
> "the u.value.referent member is NULL for ref that is not a symref,
> and for a symref, it is the value of the symref".
Yeah, I think that would be preferable indeed.
Patrick
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators
2024-08-05 10:59 ` Patrick Steinhardt
@ 2024-08-05 15:40 ` Junio C Hamano
0 siblings, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-08-05 15:40 UTC (permalink / raw)
To: Patrick Steinhardt
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Jean-Noël Avila,
Linus Arver, John Cai
Patrick Steinhardt <ps@pks.im> writes:
> On Thu, Aug 01, 2024 at 09:41:03AM -0700, Junio C Hamano wrote:
>> "John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
>> > @@ -886,6 +889,9 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
>> > iter->base.refname = iter->iter0->refname;
>> > iter->base.oid = iter->iter0->oid;
>> > iter->base.flags = iter->iter0->flags;
>> > + if (iter->iter0->flags & REF_ISSYMREF)
>> > + iter->base.referent = iter->iter0->referent;
>>
>> Presumably base.referent is initialized to NULL so this "if"
>> statement does not need an else clause?
>
> This function typically ends up being called in a loop though. So
> without the else clause, wouldn't we potentially leak the value of a
> preceding ref into subsequent iterations like this?
OK, so this does need to clear it when we tell the caller we have
non SYMREF, as we do want to show NULL as base.referent to the
caller in such a case. Thanks.
It does reinforce my larger point, which was:
>> Makes me wonder if we should follow the same "ignore what the flag
>> says when filling the .referent member; if the ref is not a symref,
>> the referent variable is NULL, and if it is, referent is never NULL"
>> pattern? Then ref->u.value.referent is _always_ defined---the
>> current code says "the u.value.referent member is undefined for ref
>> that is not a symref", but with the suggested change, it will be
>> "the u.value.referent member is NULL for ref that is not a symref,
>> and for a symref, it is the value of the symref".
>
> Yeah, I think that would be preferable indeed.
In other words, with .referent member introduced, checking for
(.flags & REF_ISSYMREF) becomes a redundant&duplicated bit of
information, as the bit should exactly match the non-NULL ness of
the .referent member.
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v2 2/3] refs: add referent to each_ref_fn
2024-08-01 14:58 ` [PATCH v2 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-08-01 14:58 ` [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-08-01 14:58 ` John Cai via GitGitGadget
2024-08-01 14:58 ` [PATCH v2 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
2024-08-07 19:42 ` [PATCH v3 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
3 siblings, 0 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-01 14:58 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
Add a parameter to each_ref_fn so that callers to the ref APIs
that use this function as a callback can have acess to the
unresolved value of a symbolic ref.
Signed-off-by: John Cai <johncai86@gmail.com>
---
bisect.c | 3 ++-
builtin/bisect.c | 4 +++-
builtin/checkout.c | 2 +-
builtin/describe.c | 2 +-
builtin/fetch.c | 3 ++-
builtin/fsck.c | 4 ++--
builtin/gc.c | 1 +
builtin/name-rev.c | 2 +-
builtin/pack-objects.c | 5 +++--
builtin/receive-pack.c | 2 +-
builtin/remote.c | 4 +++-
builtin/repack.c | 1 +
builtin/replace.c | 1 +
builtin/rev-parse.c | 4 ++--
builtin/show-branch.c | 8 ++++----
builtin/show-ref.c | 3 ++-
builtin/submodule--helper.c | 1 +
builtin/worktree.c | 1 +
commit-graph.c | 1 +
delta-islands.c | 2 +-
fetch-pack.c | 2 ++
help.c | 2 +-
http-backend.c | 4 ++--
log-tree.c | 2 +-
ls-refs.c | 4 ++--
midx-write.c | 2 +-
negotiator/default.c | 2 +-
negotiator/skipping.c | 2 +-
notes.c | 2 +-
object-name.c | 2 +-
pseudo-merge.c | 1 +
reachable.c | 2 +-
ref-filter.c | 4 ++--
reflog.c | 1 +
refs.c | 14 +++++++-------
refs.h | 2 +-
refs/files-backend.c | 2 +-
refs/iterator.c | 2 +-
remote.c | 4 ++--
replace-object.c | 1 +
revision.c | 2 +-
server-info.c | 2 +-
shallow.c | 2 ++
submodule.c | 2 ++
t/helper/test-ref-store.c | 2 +-
upload-pack.c | 8 ++++----
walker.c | 1 +
worktree.c | 2 +-
48 files changed, 78 insertions(+), 54 deletions(-)
diff --git a/bisect.c b/bisect.c
index 135f94ba097..4406fc44cf9 100644
--- a/bisect.c
+++ b/bisect.c
@@ -448,7 +448,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
clear_commit_weight(&commit_weight);
}
-static int register_ref(const char *refname, const struct object_id *oid,
+static int register_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data UNUSED)
{
struct strbuf good_prefix = STRBUF_INIT;
@@ -1170,6 +1170,7 @@ int estimate_bisect_steps(int all)
}
static int mark_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/bisect.c b/builtin/bisect.c
index dabce9b542b..453a6cccd70 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -356,6 +356,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
}
static int inc_nr(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
@@ -545,7 +546,7 @@ finish:
return res;
}
-static int add_bisect_ref(const char *refname, const struct object_id *oid,
+static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct add_bisect_ref_data *data = cb;
@@ -1162,6 +1163,7 @@ static int bisect_visualize(struct bisect_terms *terms, int argc,
}
static int get_first_good(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 3cf44b4683a..562778885e1 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1045,7 +1045,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
report_tracking(new_branch_info);
}
-static int add_pending_uninteresting_ref(const char *refname,
+static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/describe.c b/builtin/describe.c
index e5287eddf2d..d95a9109eed 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -145,7 +145,7 @@ static void add_to_known_names(const char *path,
}
}
-static int get_name(const char *path, const struct object_id *oid,
+static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
int is_tag = 0;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 693f02b9580..c297569a473 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -286,7 +286,7 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
return ent;
}
-static int add_one_refname(const char *refname,
+static int add_one_refname(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
@@ -1464,6 +1464,7 @@ static void set_option(struct transport *transport, const char *name, const char
static int add_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/fsck.c b/builtin/fsck.c
index d13a226c2ed..ef6ee1268bd 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -521,7 +521,7 @@ static int fsck_handle_reflog(const char *logname, void *cb_data)
return 0;
}
-static int fsck_handle_ref(const char *refname, const struct object_id *oid,
+static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object *obj;
@@ -576,7 +576,7 @@ static void get_default_heads(void)
strbuf_worktree_ref(wt, &ref, "HEAD");
fsck_head_link(ref.buf, &head_points_at, &head_oid);
if (head_points_at && !is_null_oid(&head_oid))
- fsck_handle_ref(ref.buf, &head_oid, 0, NULL);
+ fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL);
strbuf_release(&ref);
if (include_reflogs)
diff --git a/builtin/gc.c b/builtin/gc.c
index 72bac2554fc..65be7c31b33 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -836,6 +836,7 @@ struct cg_auto_data {
};
static int dfs_on_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 70e9ec4e477..52016f1cf7d 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -337,7 +337,7 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_)
return a->taggerdate != b->taggerdate;
}
-static int name_ref(const char *path, const struct object_id *oid,
+static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
struct object *o = parse_object(the_repository, oid);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f395488971f..c481feadbfa 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -771,7 +771,7 @@ static enum write_one_status write_one(struct hashfile *f,
return WRITE_ONE_WRITTEN;
}
-static int mark_tagged(const char *path UNUSED, const struct object_id *oid,
+static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -3129,7 +3129,7 @@ static void add_tag_chain(const struct object_id *oid)
}
}
-static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid,
+static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -4076,6 +4076,7 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED)
}
static int mark_bitmap_preferred_tip(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *data UNUSED)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 339524ae2a8..6e0f462efbb 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -300,7 +300,7 @@ static void show_ref(const char *path, const struct object_id *oid)
}
}
-static int show_ref_cb(const char *path_full, const struct object_id *oid,
+static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *data)
{
struct oidset *seen = data;
diff --git a/builtin/remote.c b/builtin/remote.c
index 08292498bde..9a3db1b0f13 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -543,6 +543,7 @@ struct branches_for_remote {
};
static int add_branch_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -585,7 +586,7 @@ struct rename_info {
uint32_t symrefs_nr;
};
-static int read_remote_branches(const char *refname,
+static int read_remote_branches(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -971,6 +972,7 @@ static void free_remote_ref_states(struct ref_states *states)
}
static int append_ref_to_tracked_list(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
diff --git a/builtin/repack.c b/builtin/repack.c
index f0317fa94ad..d9ea6cecbf9 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -667,6 +667,7 @@ struct midx_snapshot_ref_data {
};
static int midx_snapshot_ref_one(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *_data)
{
diff --git a/builtin/replace.c b/builtin/replace.c
index 1ef833c07f5..34cc4672bc1 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -49,6 +49,7 @@ struct show_data {
};
static int show_reference(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 2e64f5bda70..a7084ca157f 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -211,7 +211,7 @@ static int show_default(void)
return 0;
}
-static int show_reference(const char *refname, const struct object_id *oid,
+static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
if (ref_excluded(&ref_excludes, refname))
@@ -220,7 +220,7 @@ static int show_reference(const char *refname, const struct object_id *oid,
return 0;
}
-static int anti_reference(const char *refname, const struct object_id *oid,
+static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
show_rev(REVERSED, oid, refname);
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index d72f4cb98de..3427c1572e5 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -410,7 +410,7 @@ static int append_ref(const char *refname, const struct object_id *oid,
return 0;
}
-static int append_head_ref(const char *refname, const struct object_id *oid,
+static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -425,7 +425,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid,
return append_ref(refname + ofs, oid, 0);
}
-static int append_remote_ref(const char *refname, const struct object_id *oid,
+static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -451,7 +451,7 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,
static const char *match_ref_pattern = NULL;
static int match_ref_slash = 0;
-static int append_matching_ref(const char *refname, const struct object_id *oid,
+static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
/* we want to allow pattern hold/<asterisk> to show all
@@ -468,7 +468,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid,
if (wildmatch(match_ref_pattern, tail, 0))
return 0;
if (starts_with(refname, "refs/heads/"))
- return append_head_ref(refname, oid, flag, cb_data);
+ return append_head_ref(refname, NULL, oid, flag, cb_data);
if (starts_with(refname, "refs/tags/"))
return append_tag_ref(refname, oid, flag, cb_data);
return append_ref(refname, oid, 0);
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 839a5c29f31..04e0db707c6 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -63,7 +63,7 @@ struct show_ref_data {
int show_head;
};
-static int show_ref(const char *refname, const struct object_id *oid,
+static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
struct show_ref_data *data = cbdata;
@@ -97,6 +97,7 @@ match:
}
static int add_existing(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cbdata)
{
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 880ab4456ee..1cdcc465b1c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -609,6 +609,7 @@ static void print_status(unsigned int flags, char state, const char *path,
}
static int handle_submodule_head_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 1d51e54fcdc..2e16218c655 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -626,6 +626,7 @@ static void print_preparing_worktree_line(int detach,
* Returns 0 on failure and non-zero on success.
*/
static int first_valid_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data UNUSED)
diff --git a/commit-graph.c b/commit-graph.c
index 79b0e72cc42..aa6e08eb39c 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1847,6 +1847,7 @@ struct refs_cb_data {
};
static int add_ref_to_set(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/delta-islands.c b/delta-islands.c
index ffe1ca28144..84435512593 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -390,7 +390,7 @@ static void add_ref_to_island(kh_str_t *remote_islands, const char *island_name,
rl->hash += sha_core;
}
-static int find_island_for_ref(const char *refname, const struct object_id *oid,
+static int find_island_for_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct island_load_data *ild = cb;
diff --git a/fetch-pack.c b/fetch-pack.c
index 732511604b1..58b4581ad80 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -183,6 +183,7 @@ static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
}
static int rev_list_insert_ref_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
@@ -610,6 +611,7 @@ static int mark_complete(const struct object_id *oid)
}
static int mark_complete_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/help.c b/help.c
index a6b4d3b1ebd..c03863f2265 100644
--- a/help.c
+++ b/help.c
@@ -804,7 +804,7 @@ struct similar_ref_cb {
struct string_list *similar_refs;
};
-static int append_similar_ref(const char *refname,
+static int append_similar_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
diff --git a/http-backend.c b/http-backend.c
index 461424972b6..79ce097359b 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -512,7 +512,7 @@ static void run_service(const char **argv, int buffer_input)
exit(1);
}
-static int show_text_ref(const char *name, const struct object_id *oid,
+static int show_text_ref(const char *name, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *name_nons = strip_namespace(name);
@@ -568,7 +568,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
strbuf_release(&buf);
}
-static int show_head_ref(const char *refname, const struct object_id *oid,
+static int show_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct strbuf *buf = cb_data;
diff --git a/log-tree.c b/log-tree.c
index 52feec4356a..40306434556 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -145,7 +145,7 @@ static int ref_filter_match(const char *refname,
return 1;
}
-static int add_ref_decoration(const char *refname, const struct object_id *oid,
+static int add_ref_decoration(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED,
void *cb_data)
{
diff --git a/ls-refs.c b/ls-refs.c
index 2dd925b43d0..c824aea7146 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -77,7 +77,7 @@ struct ls_refs_data {
unsigned unborn : 1;
};
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct ls_refs_data *data = cb_data;
@@ -135,7 +135,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
oid_is_null = is_null_oid(&oid);
if (!oid_is_null ||
(data->unborn && data->symrefs && (flag & REF_ISSYMREF)))
- send_ref(namespaced.buf, oid_is_null ? NULL : &oid, flag, data);
+ send_ref(namespaced.buf, NULL, oid_is_null ? NULL : &oid, flag, data);
strbuf_release(&namespaced);
}
diff --git a/midx-write.c b/midx-write.c
index 478b42e7209..56d1717f9f1 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -655,7 +655,7 @@ static void prepare_midx_packing_data(struct packing_data *pdata,
trace2_region_leave("midx", "prepare_midx_packing_data", the_repository);
}
-static int add_ref_to_pending(const char *refname,
+static int add_ref_to_pending(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag, void *cb_data)
{
diff --git a/negotiator/default.c b/negotiator/default.c
index e3fa5c33249..c479da9b091 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -38,7 +38,7 @@ static void rev_list_push(struct negotiation_state *ns,
}
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index f109928ad0b..f65d47858b4 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -75,7 +75,7 @@ static struct entry *rev_list_push(struct data *data, struct commit *commit, int
return entry;
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/notes.c b/notes.c
index 1ba6412aae8..da42df282d5 100644
--- a/notes.c
+++ b/notes.c
@@ -932,7 +932,7 @@ out:
return ret;
}
-static int string_list_add_one_ref(const char *refname,
+static int string_list_add_one_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb)
{
diff --git a/object-name.c b/object-name.c
index 527b853ac45..7cca43020f2 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1365,7 +1365,7 @@ struct handle_one_ref_cb {
struct commit_list **list;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/pseudo-merge.c b/pseudo-merge.c
index f0fde13c471..77a83b9c5ce 100644
--- a/pseudo-merge.c
+++ b/pseudo-merge.c
@@ -201,6 +201,7 @@ void load_pseudo_merges_from_config(struct string_list *list)
}
static int find_pseudo_merge_group_for_ref(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *_data)
diff --git a/reachable.c b/reachable.c
index 46613a6bb6f..3e9b3dd0a46 100644
--- a/reachable.c
+++ b/reachable.c
@@ -79,7 +79,7 @@ static void add_rebase_files(struct rev_info *revs)
free_worktrees(worktrees);
}
-static int add_one_ref(const char *path, const struct object_id *oid,
+static int add_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct rev_info *revs = (struct rev_info *)cb_data;
diff --git a/ref-filter.c b/ref-filter.c
index 8c5e673fc0a..39997890feb 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2865,7 +2865,7 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
@@ -2900,7 +2900,7 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
diff --git a/reflog.c b/reflog.c
index 5ca944529b3..d592c1cfb56 100644
--- a/reflog.c
+++ b/reflog.c
@@ -300,6 +300,7 @@ int should_expire_reflog_ent_verbose(struct object_id *ooid,
}
static int push_tip_to_list(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags, void *cb_data)
{
diff --git a/refs.c b/refs.c
index bb90a188758..0a5c12cf16b 100644
--- a/refs.c
+++ b/refs.c
@@ -414,7 +414,7 @@ int refs_ref_exists(struct ref_store *refs, const char *refname)
NULL, NULL);
}
-static int for_each_filter_refs(const char *refname,
+static int for_each_filter_refs(const char *refname, const char *referent,
const struct object_id *oid,
int flags, void *data)
{
@@ -424,7 +424,7 @@ static int for_each_filter_refs(const char *refname,
return 0;
if (filter->prefix)
skip_prefix(refname, filter->prefix, &refname);
- return filter->fn(refname, oid, flags, filter->cb_data);
+ return filter->fn(refname, referent, oid, flags, filter->cb_data);
}
struct warn_if_dangling_data {
@@ -435,7 +435,7 @@ struct warn_if_dangling_data {
const char *msg_fmt;
};
-static int warn_if_dangling_symref(const char *refname,
+static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
@@ -506,7 +506,7 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag))
- ret = fn(buf.buf, &oid, flag, cb_data);
+ ret = fn(buf.buf, NULL, &oid, flag, cb_data);
strbuf_release(&buf);
return ret;
@@ -1547,7 +1547,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
&oid, &flag))
- return fn("HEAD", &oid, flag, cb_data);
+ return fn("HEAD", NULL, &oid, flag, cb_data);
return 0;
}
@@ -2387,7 +2387,7 @@ struct do_for_each_reflog_help {
void *cb_data;
};
-static int do_for_each_reflog_helper(const char *refname,
+static int do_for_each_reflog_helper(const char *refname, const char *referent,
const struct object_id *oid UNUSED,
int flags,
void *cb_data)
@@ -2593,7 +2593,7 @@ struct migration_data {
struct strbuf *errbuf;
};
-static int migrate_one_ref(const char *refname, const struct object_id *oid,
+static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct migration_data *data = cb_data;
diff --git a/refs.h b/refs.h
index 0ecba21b4a7..158e0a12197 100644
--- a/refs.h
+++ b/refs.h
@@ -298,7 +298,7 @@ struct ref_transaction;
* arguments is only guaranteed to be valid for the duration of a
* single callback invocation.
*/
-typedef int each_ref_fn(const char *refname,
+typedef int each_ref_fn(const char *refname, const char *referent,
const struct object_id *oid, int flags, void *cb_data);
/*
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 7640318cba8..40c88652750 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3041,7 +3041,7 @@ static int files_transaction_abort(struct ref_store *ref_store,
return 0;
}
-static int ref_present(const char *refname,
+static int ref_present(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data)
diff --git a/refs/iterator.c b/refs/iterator.c
index 26acb6bd640..21beeb91e9e 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -451,7 +451,7 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
current_ref_iter = iter;
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
- retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
+ retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
if (retval) {
/*
* If ref_iterator_abort() returns ITER_ERROR,
diff --git a/remote.c b/remote.c
index f43cf5e7a4d..4a1269a47ab 100644
--- a/remote.c
+++ b/remote.c
@@ -2354,7 +2354,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
return 1;
}
-static int one_local_ref(const char *refname, const struct object_id *oid,
+static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
@@ -2439,7 +2439,7 @@ struct stale_heads_info {
struct refspec *rs;
};
-static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
+static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct stale_heads_info *info = cb_data;
diff --git a/replace-object.c b/replace-object.c
index 59252d565ef..9a3cdd809a9 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -9,6 +9,7 @@
#include "commit.h"
static int register_replace_ref(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
diff --git a/revision.c b/revision.c
index 1c0192f5225..6b33bd814f7 100644
--- a/revision.c
+++ b/revision.c
@@ -1648,7 +1648,7 @@ struct all_refs_cb {
struct worktree *wt;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/server-info.c b/server-info.c
index f61296a60d0..1508fa6f825 100644
--- a/server-info.c
+++ b/server-info.c
@@ -147,7 +147,7 @@ out:
return ret;
}
-static int add_info_ref(const char *path, const struct object_id *oid,
+static int add_info_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/shallow.c b/shallow.c
index 31a6ca40fe2..b8cd051e3b6 100644
--- a/shallow.c
+++ b/shallow.c
@@ -612,6 +612,7 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
}
static int mark_uninteresting(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data UNUSED)
@@ -727,6 +728,7 @@ struct commit_array {
};
static int add_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/submodule.c b/submodule.c
index ab99a302530..7c0f5db861d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -953,6 +953,7 @@ static void free_submodules_data(struct string_list *submodules)
}
static int has_remote(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data UNUSED)
{
@@ -1273,6 +1274,7 @@ int push_unpushed_submodules(struct repository *r,
}
static int append_oid_to_array(const char *ref UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *data)
{
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 637b8b294e9..65346dee551 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -156,7 +156,7 @@ static int cmd_rename_ref(struct ref_store *refs, const char **argv)
return refs_rename_ref(refs, oldref, newref, logmsg);
}
-static int each_ref(const char *refname, const struct object_id *oid,
+static int each_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data UNUSED)
{
printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
diff --git a/upload-pack.c b/upload-pack.c
index 0052c6a4dce..f03ba3e98be 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -857,7 +857,7 @@ static void send_unshallow(struct upload_pack_data *data)
}
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data);
static void deepen(struct upload_pack_data *data, int depth)
{
@@ -1208,7 +1208,7 @@ static int mark_our_ref(const char *refname, const char *refname_full,
return 0;
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED,const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *refname = strip_namespace(refname_full);
@@ -1276,14 +1276,14 @@ static void write_v0_ref(struct upload_pack_data *data,
return;
}
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
return 0;
}
-static int find_symref(const char *refname,
+static int find_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag, void *cb_data)
{
diff --git a/walker.c b/walker.c
index 0fafdc97cf1..807a7a38813 100644
--- a/walker.c
+++ b/walker.c
@@ -221,6 +221,7 @@ static int interpret_target(struct walker *walker, char *target, struct object_i
}
static int mark_complete(const char *path UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/worktree.c b/worktree.c
index f3c4c8ec54d..fd05f3741c6 100644
--- a/worktree.c
+++ b/worktree.c
@@ -546,7 +546,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
refname.buf,
RESOLVE_REF_READING,
&oid, &flag))
- ret = fn(refname.buf, &oid, flag, cb_data);
+ ret = fn(refname.buf, NULL, &oid, flag, cb_data);
if (ret)
break;
}
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v2 3/3] ref-filter: populate symref from iterator
2024-08-01 14:58 ` [PATCH v2 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-08-01 14:58 ` [PATCH v2 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
2024-08-01 14:58 ` [PATCH v2 2/3] refs: add referent to each_ref_fn John Cai via GitGitGadget
@ 2024-08-01 14:58 ` John Cai via GitGitGadget
2024-08-01 16:43 ` Junio C Hamano
2024-08-01 16:51 ` Junio C Hamano
2024-08-07 19:42 ` [PATCH v3 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
3 siblings, 2 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-01 14:58 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
With a previous commit, the reference the symbolic ref points to is saved
in the ref iterator records. Instead of making a separate call to
resolve_refdup() each time, we can just populate the ref_array_item with
the value from the iterator.
Signed-off-by: John Cai <johncai86@gmail.com>
---
ref-filter.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index 39997890feb..08997e59662 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2783,7 +2783,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
return ref_kind_from_refname(refname);
}
-static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
+static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
int flag, struct ref_filter *filter)
{
struct ref_array_item *ref;
@@ -2852,6 +2852,8 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
ref->commit = commit;
ref->flag = flag;
ref->kind = kind;
+ if (flag & REF_ISSYMREF)
+ ref->symref = xstrdup_or_null(referent);
return ref;
}
@@ -2865,12 +2867,12 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (ref)
ref_array_append(ref_cbdata->array, ref);
@@ -2900,13 +2902,13 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (!ref)
return 0;
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v2 3/3] ref-filter: populate symref from iterator
2024-08-01 14:58 ` [PATCH v2 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
@ 2024-08-01 16:43 ` Junio C Hamano
2024-08-01 16:51 ` Junio C Hamano
1 sibling, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-08-01 16:43 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, Linus Arver, John Cai
"John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> @@ -2852,6 +2852,8 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
> ref->commit = commit;
> ref->flag = flag;
> ref->kind = kind;
> + if (flag & REF_ISSYMREF)
> + ref->symref = xstrdup_or_null(referent);
The same reaction as [1/3]. Doesn't the null-ness of referent
convey the same information as the ISSYMREF bit in flag? IOW,
can't we do this assignment unconditionally?
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2 3/3] ref-filter: populate symref from iterator
2024-08-01 14:58 ` [PATCH v2 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
2024-08-01 16:43 ` Junio C Hamano
@ 2024-08-01 16:51 ` Junio C Hamano
2024-08-01 16:54 ` Junio C Hamano
1 sibling, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2024-08-01 16:51 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, Linus Arver, John Cai
"John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: John Cai <johncai86@gmail.com>
>
> With a previous commit, the reference the symbolic ref points to is saved
> in the ref iterator records. Instead of making a separate call to
> resolve_refdup() each time, we can just populate the ref_array_item with
> the value from the iterator.
>
> Signed-off-by: John Cai <johncai86@gmail.com>
> ---
> ref-filter.c | 12 +++++++-----
> 1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/ref-filter.c b/ref-filter.c
> index 39997890feb..08997e59662 100644
> --- a/ref-filter.c
> +++ b/ref-filter.c
> @@ -2783,7 +2783,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
> return ref_kind_from_refname(refname);
> }
>
> -static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
> +static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
> int flag, struct ref_filter *filter)
> {
> struct ref_array_item *ref;
> @@ -2852,6 +2852,8 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
> ref->commit = commit;
> ref->flag = flag;
> ref->kind = kind;
> + if (flag & REF_ISSYMREF)
> + ref->symref = xstrdup_or_null(referent);
>
> return ref;
> }
What is curious is that we do not lose any code from
populate_value() with this change.
Is that because of this piece of code near the beginning of it?
CALLOC_ARRAY(ref->value, used_atom_cnt);
if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository),
ref->refname,
RESOLVE_REF_READING,
NULL, NULL);
if (!ref->symref)
ref->symref = xstrdup("");
}
That is, if we somehow know the value of ref->symref for a ref that
is known to be a symbolic ref (and when we know we need symref
information in the output), we do not bother calling refs_resolve
here to obtain the value.
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2 3/3] ref-filter: populate symref from iterator
2024-08-01 16:51 ` Junio C Hamano
@ 2024-08-01 16:54 ` Junio C Hamano
2024-08-06 19:49 ` John Cai
0 siblings, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2024-08-01 16:54 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, Linus Arver, John Cai
Junio C Hamano <gitster@pobox.com> writes:
>> @@ -2852,6 +2852,8 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
>> ref->commit = commit;
>> ref->flag = flag;
>> ref->kind = kind;
>> + if (flag & REF_ISSYMREF)
>> + ref->symref = xstrdup_or_null(referent);
>>
>> return ref;
>> }
>
> What is curious is that we do not lose any code from
> populate_value() with this change.
>
> Is that because of this piece of code near the beginning of it?
>
> CALLOC_ARRAY(ref->value, used_atom_cnt);
>
> if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
> ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository),
> ref->refname,
> RESOLVE_REF_READING,
> NULL, NULL);
> if (!ref->symref)
> ref->symref = xstrdup("");
> }
>
> That is, if we somehow know the value of ref->symref for a ref that
> is known to be a symbolic ref (and when we know we need symref
> information in the output), we do not bother calling refs_resolve
> here to obtain the value.
I forgot to ask the real question. With your change in place, does
this "lazily fill ref->symref if it hasn't been discovered yet" code
still trigger? Under what condition? Or is this now a dead code?
Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2 3/3] ref-filter: populate symref from iterator
2024-08-01 16:54 ` Junio C Hamano
@ 2024-08-06 19:49 ` John Cai
2024-08-06 20:17 ` Junio C Hamano
0 siblings, 1 reply; 44+ messages in thread
From: John Cai @ 2024-08-06 19:49 UTC (permalink / raw)
To: Junio C Hamano
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver
Hi Junio,
On 1 Aug 2024, at 12:54, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
>>> @@ -2852,6 +2852,8 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
>>> ref->commit = commit;
>>> ref->flag = flag;
>>> ref->kind = kind;
>>> + if (flag & REF_ISSYMREF)
>>> + ref->symref = xstrdup_or_null(referent);
>>>
>>> return ref;
>>> }
>>
>> What is curious is that we do not lose any code from
>> populate_value() with this change.
>>
>> Is that because of this piece of code near the beginning of it?
>>
>> CALLOC_ARRAY(ref->value, used_atom_cnt);
>>
>> if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
>> ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository),
>> ref->refname,
>> RESOLVE_REF_READING,
>> NULL, NULL);
>> if (!ref->symref)
>> ref->symref = xstrdup("");
>> }
>>
>> That is, if we somehow know the value of ref->symref for a ref that
>> is known to be a symbolic ref (and when we know we need symref
>> information in the output), we do not bother calling refs_resolve
>> here to obtain the value.
>
> I forgot to ask the real question. With your change in place, does
> this "lazily fill ref->symref if it hasn't been discovered yet" code
> still trigger? Under what condition? Or is this now a dead code?
Yes that's a good question. I took a look and it seems like in *most* cases by
the time populate_value() is called, apply_ref_filter() has already been called that
populates the symref member of ref_array_item.
populate_value() gets called by get_ref_atom_value() which gets called by both
1. format_ref_array_item()
2. cmp_ref_sorting()
In the case of [2], the callchain starts with filter_and_format_refs() which
calls ref_array_sort() that eventually calls populate_value(). Before
ref_array_sort() is called, filter_refs() is called which ends up calling
do_filter_refs() with filter_one(), leading to apply_ref_filter().
In the case of [1] however, there are a couple of code paths that call
populate_value() without apply_ref_filter() ever being called.
pretty_print_ref() directly calls format_ref_array_item() ->
get_ref_atom_value() -> populate_value(). However, apply_ref_filter() is not
called which means the symref will not be populated.
Looking through the codebase, this function is only called in builtin/tag.c and
bulitin/verify-tag.c in the `git tag -v` codepath. So it seems that if we got
rid of this block of code in populate_value(), only in the case where `git
tag -v --format='%(symref)'` on a symbolic ref pointing to a tag would the
symref be missing.
But I don't even know if this is possible. I tried this locally and got the
error:
$ git tag -a -s -m "version 1" v1 refs/heads/master
$ git symbolic-ref refs/tags/symbolic-v1 refs/tags/v1
$ git tag -v --format='(%symref)'
error: tag 'refs/tags/symbolic-v1' not found.
So practically speaking, I think we are safe to remove. However, from a
future-proof point of view, anyone in the future who calls pretty_print_ref() would also need to be sure to populate the symref member in ref_array_item.
So perhaps from a code durability standpoint we should keep that block?
>
> Thanks.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v2 3/3] ref-filter: populate symref from iterator
2024-08-06 19:49 ` John Cai
@ 2024-08-06 20:17 ` Junio C Hamano
0 siblings, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-08-06 20:17 UTC (permalink / raw)
To: John Cai
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver
John Cai <johncai86@gmail.com> writes:
> Yes that's a good question. I took a look and it seems like in *most* cases by
> the time populate_value() is called, apply_ref_filter() has already been called that
> populates the symref member of ref_array_item.
>
> populate_value() gets called by get_ref_atom_value() which gets called by both
>
> 1. format_ref_array_item()
> 2. cmp_ref_sorting()
>
> In the case of [2], the callchain starts with filter_and_format_refs() which
> calls ref_array_sort() that eventually calls populate_value(). Before
> ref_array_sort() is called, filter_refs() is called which ends up calling
> do_filter_refs() with filter_one(), leading to apply_ref_filter().
>
> In the case of [1] however, there are a couple of code paths that call
> populate_value() without apply_ref_filter() ever being called.
>
> pretty_print_ref() directly calls format_ref_array_item() ->
> get_ref_atom_value() -> populate_value(). However, apply_ref_filter() is not
> called which means the symref will not be populated.
I am perfectly OK to keep the "fallback" code, even if you haven't
found a concrete reproduction to trigger it. Removing it is not
part of what this series is trying to do, anyway. The theme of the
topic has always been "optimize when we can", at least to me.
Having said that, if we somehow can give the analysis you did above
as hint to future developers, then they can start from there when
they consider if they can remove the "fallback" code. It would help
even it just said
/*
* NEEDSWORK: this might have become a dead code after
* optimization to grab symref target in apply_ref_filter().
*/
and nothing else.
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v3 0/3] keep track of unresolved value of symbolic-ref in ref iterators
2024-08-01 14:58 ` [PATCH v2 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
` (2 preceding siblings ...)
2024-08-01 14:58 ` [PATCH v2 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
@ 2024-08-07 19:42 ` John Cai via GitGitGadget
2024-08-07 19:42 ` [PATCH v3 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
` (3 more replies)
3 siblings, 4 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-07 19:42 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai
For reftable development, it's useful to be able to print out the direct
value of a symbolic reference before resolution. This is currently possible
with git-for-each-ref, but since the iterators do not keep track of the
value of the symbolic ref, a separate call needs to be made each time making
it inefficient.
Address this inefficiency by keeping track of the value of the symbolic
reference in the ref iterator. This patch series also ends with a commit to
use this value in the iterator through callbacks in ref-filter.c.
This series started with [1] but I decided to send a separate patch series
since it is substantially different.
Benchmarking shows that with these changes, we experience a speedup in
git-for-each-ref(1) on a repository with many symbolic refs:
$ hyperfine --warmup 5 "git for-each-ref --format='%(refname) %(objectname)
%(symref)'" "~/Projects/git/git for-each-ref --format='%(refname)
%(objectname) %(symref)'" Benchmark 1: git for-each-ref --format='%(refname)
%(objectname) %(symref)' Time (mean ± σ): 905.1 ms ± 13.2 ms [User: 56.3 ms,
System: 628.6 ms] Range (min … max): 893.4 ms … 936.9 ms 10 runs
Benchmark 2: ~/Projects/git/git for-each-ref --format='%(refname)
%(objectname) %(symref)' Time (mean ± σ): 482.2 ms ± 26.4 ms [User: 34.7 ms,
System: 410.6 ms] Range (min … max): 459.4 ms … 541.8 ms 10 runs
Summary ~/Projects/git/git for-each-ref --format='%(refname) %(objectname)
%(symref)' ran 1.88 ± 0.11 times faster than git for-each-ref
--format='%(refname) %(objectname) %(symref)'
Changes since V2:
* Style tweaks
* Added a NEEDSWORK comment around fallback code
* Stay consistent in the meaning of a non-NULL referent member in the
iterator
Changes since V1
* Use the return value from refs_resolve_ref_unsafe instead of using an out
parameter
1. https://lore.kernel.org/git/pull.1684.git.git.1709592718743.gitgitgadget@gmail.com/
John Cai (3):
refs: keep track of unresolved reference value in iterators
refs: add referent to each_ref_fn
ref-filter: populate symref from iterator
bisect.c | 3 ++-
builtin/bisect.c | 4 +++-
builtin/checkout.c | 2 +-
builtin/describe.c | 2 +-
builtin/fetch.c | 3 ++-
builtin/fsck.c | 4 ++--
builtin/gc.c | 1 +
builtin/name-rev.c | 2 +-
builtin/pack-objects.c | 5 +++--
builtin/receive-pack.c | 2 +-
builtin/remote.c | 4 +++-
builtin/repack.c | 1 +
builtin/replace.c | 1 +
builtin/rev-parse.c | 4 ++--
builtin/show-branch.c | 8 ++++----
builtin/show-ref.c | 3 ++-
builtin/submodule--helper.c | 1 +
builtin/worktree.c | 1 +
commit-graph.c | 1 +
delta-islands.c | 2 +-
fetch-pack.c | 2 ++
help.c | 2 +-
http-backend.c | 4 ++--
log-tree.c | 2 +-
ls-refs.c | 4 ++--
midx-write.c | 2 +-
negotiator/default.c | 2 +-
negotiator/skipping.c | 2 +-
notes.c | 2 +-
object-name.c | 2 +-
pseudo-merge.c | 1 +
reachable.c | 2 +-
ref-filter.c | 17 ++++++++++++-----
reflog.c | 1 +
refs.c | 14 +++++++-------
refs.h | 2 +-
refs/files-backend.c | 21 ++++++++++++++++-----
refs/iterator.c | 4 +++-
refs/ref-cache.c | 6 ++++++
refs/ref-cache.h | 2 ++
refs/refs-internal.h | 1 +
refs/reftable-backend.c | 10 ++++++++--
remote.c | 4 ++--
replace-object.c | 1 +
revision.c | 2 +-
server-info.c | 2 +-
shallow.c | 2 ++
submodule.c | 2 ++
t/helper/test-ref-store.c | 2 +-
upload-pack.c | 8 ++++----
walker.c | 1 +
worktree.c | 2 +-
52 files changed, 122 insertions(+), 63 deletions(-)
base-commit: 557ae147e6cdc9db121269b058c757ac5092f9c9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1712%2Fjohn-cai%2Fjc%2Fsymbolic-ref-in-iterator-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1712/john-cai/jc/symbolic-ref-in-iterator-v3
Pull-Request: https://github.com/git/git/pull/1712
Range-diff vs v2:
1: ac0957c9e6a ! 1: fc3defd9c47 refs: keep track of unresolved reference value in iterators
@@ refs/files-backend.c: static void loose_fill_ref_dir_regular_file(struct files_r
-
- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
- &oid, &flag)) {
-+ const char* referent = refs_resolve_ref_unsafe(&refs->base,
++ const char *referent = refs_resolve_ref_unsafe(&refs->base,
+ refname,
+ RESOLVE_REF_READING,
+ &oid, &flag);
@@ refs/files-backend.c: static void loose_fill_ref_dir_regular_file(struct files_r
}
- add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
+
++ if (!(flag & REF_ISSYMREF))
++ referent = NULL;
++
+ add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
}
@@ refs/files-backend.c: static int files_ref_iterator_advance(struct ref_iterator
iter->base.flags = iter->iter0->flags;
+ if (iter->iter0->flags & REF_ISSYMREF)
+ iter->base.referent = iter->iter0->referent;
++ else
++ iter->base.referent = NULL;
+
return ITER_OK;
}
## refs/iterator.c ##
-@@
- #include "refs.h"
- #include "refs/refs-internal.h"
- #include "iterator.h"
-+#include "strbuf.h"
-
- int ref_iterator_advance(struct ref_iterator *ref_iterator)
- {
@@ refs/iterator.c: void base_ref_iterator_init(struct ref_iterator *iter,
{
iter->vtable = vtable;
@@ refs/ref-cache.c: struct ref_entry *create_ref_entry(const char *refname,
FLEX_ALLOC_STR(ref, name, refname);
oidcpy(&ref->u.value.oid, oid);
ref->flag = flag;
-+
-+ if (flag & REF_ISSYMREF)
-+ ref->u.value.referent = xstrdup_or_null(referent);
++ ref->u.value.referent = xstrdup_or_null(referent);
+
return ref;
}
@@ refs/refs-internal.h: enum do_for_each_ref_flags {
};
## refs/reftable-backend.c ##
+@@ refs/reftable-backend.c: static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
+ struct reftable_ref_iterator *iter =
+ (struct reftable_ref_iterator *)ref_iterator;
+ struct reftable_ref_store *refs = iter->refs;
++ const char *referent = NULL;
+
+ while (!iter->err) {
+ int flags = 0;
@@ refs/reftable-backend.c: static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
the_repository->hash_algo);
break;
case REFTABLE_REF_SYMREF:
- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
- RESOLVE_REF_READING, &iter->oid, &flags))
-+ iter->base.referent = refs_resolve_ref_unsafe(&iter->refs->base,
++ referent = refs_resolve_ref_unsafe(&iter->refs->base,
+ iter->ref.refname,
+ RESOLVE_REF_READING,
+ &iter->oid,
+ &flags);
-+ if (!iter->base.referent)
++ if (!referent)
oidclr(&iter->oid, the_repository->hash_algo);
break;
default:
+@@ refs/reftable-backend.c: static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
+ continue;
+
+ iter->base.refname = iter->ref.refname;
++ iter->base.referent = referent;
+ iter->base.oid = &iter->oid;
+ iter->base.flags = flags;
+
2: 1f3a604fae7 = 2: 0b6e732ad7e refs: add referent to each_ref_fn
3: 3e147e7d850 ! 3: 83b70ab8287 ref-filter: populate symref from iterator
@@ Commit message
Signed-off-by: John Cai <johncai86@gmail.com>
## ref-filter.c ##
+@@ ref-filter.c: static int populate_value(struct ref_array_item *ref, struct strbuf *err)
+
+ CALLOC_ARRAY(ref->value, used_atom_cnt);
+
++ /**
++ * NEEDSWORK: The following code might be unncessary if all codepaths
++ * that call populate_value() populates the symref member of ref_array_item
++ * like in apply_ref_filter(). Currently pretty_print_ref() is the only codepath
++ * that calls populate_value() without first populating symref.
++ */
+ if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
+ ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository),
+ ref->refname,
@@ ref-filter.c: static int filter_ref_kind(struct ref_filter *filter, const char *refname)
return ref_kind_from_refname(refname);
}
@@ ref-filter.c: static struct ref_array_item *apply_ref_filter(const char *refname
ref->commit = commit;
ref->flag = flag;
ref->kind = kind;
-+ if (flag & REF_ISSYMREF)
-+ ref->symref = xstrdup_or_null(referent);
++ ref->symref = xstrdup_or_null(referent);
return ref;
}
--
gitgitgadget
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v3 1/3] refs: keep track of unresolved reference value in iterators
2024-08-07 19:42 ` [PATCH v3 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
@ 2024-08-07 19:42 ` John Cai via GitGitGadget
2024-08-07 21:40 ` Junio C Hamano
2024-08-07 19:42 ` [PATCH v3 2/3] refs: add referent to each_ref_fn John Cai via GitGitGadget
` (2 subsequent siblings)
3 siblings, 1 reply; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-07 19:42 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
Since ref iterators do not hold onto the direct value of a reference
without resolving it, the only way to get ahold of a direct value of a
symbolic ref is to make a separate call to refs_read_symbolic_ref.
To make accessing the direct value of a symbolic ref more efficient,
let's save the direct value of the ref in the iterators for both the
files backend and the reftable backend.
Signed-off-by: John Cai <johncai86@gmail.com>
---
refs/files-backend.c | 19 +++++++++++++++----
refs/iterator.c | 2 ++
refs/ref-cache.c | 6 ++++++
refs/ref-cache.h | 2 ++
refs/refs-internal.h | 1 +
refs/reftable-backend.c | 10 ++++++++--
6 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index aa52d9be7c7..5ed69c23f74 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -245,9 +245,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
{
struct object_id oid;
int flag;
-
- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
- &oid, &flag)) {
+ const char *referent = refs_resolve_ref_unsafe(&refs->base,
+ refname,
+ RESOLVE_REF_READING,
+ &oid, &flag);
+ if (!referent) {
oidclr(&oid, the_repository->hash_algo);
flag |= REF_ISBROKEN;
} else if (is_null_oid(&oid)) {
@@ -268,7 +270,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
oidclr(&oid, the_repository->hash_algo);
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
- add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
+
+ if (!(flag & REF_ISSYMREF))
+ referent = NULL;
+
+ add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
}
/*
@@ -886,6 +892,11 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
iter->base.refname = iter->iter0->refname;
iter->base.oid = iter->iter0->oid;
iter->base.flags = iter->iter0->flags;
+ if (iter->iter0->flags & REF_ISSYMREF)
+ iter->base.referent = iter->iter0->referent;
+ else
+ iter->base.referent = NULL;
+
return ITER_OK;
}
diff --git a/refs/iterator.c b/refs/iterator.c
index d355ebf0d59..75fbe5d72ab 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -29,6 +29,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
{
iter->vtable = vtable;
iter->refname = NULL;
+ iter->referent = NULL;
iter->oid = NULL;
iter->flags = 0;
}
@@ -199,6 +200,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
}
if (selection & ITER_YIELD_CURRENT) {
+ iter->base.referent = (*iter->current)->referent;
iter->base.refname = (*iter->current)->refname;
iter->base.oid = (*iter->current)->oid;
iter->base.flags = (*iter->current)->flags;
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index 4ce519bbc85..bf80a62af17 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -5,6 +5,7 @@
#include "refs-internal.h"
#include "ref-cache.h"
#include "../iterator.h"
+#include "../strbuf.h"
void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
{
@@ -34,6 +35,7 @@ struct ref_dir *get_ref_dir(struct ref_entry *entry)
}
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag)
{
struct ref_entry *ref;
@@ -41,6 +43,8 @@ struct ref_entry *create_ref_entry(const char *refname,
FLEX_ALLOC_STR(ref, name, refname);
oidcpy(&ref->u.value.oid, oid);
ref->flag = flag;
+ ref->u.value.referent = xstrdup_or_null(referent);
+
return ref;
}
@@ -66,6 +70,7 @@ static void free_ref_entry(struct ref_entry *entry)
*/
clear_ref_dir(&entry->u.subdir);
}
+ free(entry->u.value.referent);
free(entry);
}
@@ -431,6 +436,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
level->index = -1;
} else {
iter->base.refname = entry->name;
+ iter->base.referent = entry->u.value.referent;
iter->base.oid = &entry->u.value.oid;
iter->base.flags = entry->flag;
return ITER_OK;
diff --git a/refs/ref-cache.h b/refs/ref-cache.h
index 31ebe24f6cf..5f04e518c37 100644
--- a/refs/ref-cache.h
+++ b/refs/ref-cache.h
@@ -42,6 +42,7 @@ struct ref_value {
* referred to by the last reference in the symlink chain.
*/
struct object_id oid;
+ char *referent;
};
/*
@@ -173,6 +174,7 @@ struct ref_entry *create_dir_entry(struct ref_cache *cache,
const char *dirname, size_t len);
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag);
/*
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index fa975d69aaa..117ec233848 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -299,6 +299,7 @@ enum do_for_each_ref_flags {
struct ref_iterator {
struct ref_iterator_vtable *vtable;
const char *refname;
+ const char *referent;
const struct object_id *oid;
unsigned int flags;
};
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index fbe74c239d3..50a072b97b0 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -455,6 +455,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
struct reftable_ref_iterator *iter =
(struct reftable_ref_iterator *)ref_iterator;
struct reftable_ref_store *refs = iter->refs;
+ const char *referent = NULL;
while (!iter->err) {
int flags = 0;
@@ -494,8 +495,12 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
the_repository->hash_algo);
break;
case REFTABLE_REF_SYMREF:
- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
- RESOLVE_REF_READING, &iter->oid, &flags))
+ referent = refs_resolve_ref_unsafe(&iter->refs->base,
+ iter->ref.refname,
+ RESOLVE_REF_READING,
+ &iter->oid,
+ &flags);
+ if (!referent)
oidclr(&iter->oid, the_repository->hash_algo);
break;
default:
@@ -523,6 +528,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
continue;
iter->base.refname = iter->ref.refname;
+ iter->base.referent = referent;
iter->base.oid = &iter->oid;
iter->base.flags = flags;
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v3 1/3] refs: keep track of unresolved reference value in iterators
2024-08-07 19:42 ` [PATCH v3 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-08-07 21:40 ` Junio C Hamano
2024-08-08 18:09 ` John Cai
0 siblings, 1 reply; 44+ messages in thread
From: Junio C Hamano @ 2024-08-07 21:40 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, Linus Arver, John Cai
"John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> diff --git a/refs/files-backend.c b/refs/files-backend.c
> index aa52d9be7c7..5ed69c23f74 100644
> --- a/refs/files-backend.c
> +++ b/refs/files-backend.c
> @@ -245,9 +245,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
> {
> struct object_id oid;
> int flag;
> -
> - if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
Here, we had a nice blank line that separated the decls and the
first statement.
> - &oid, &flag)) {
> + const char *referent = refs_resolve_ref_unsafe(&refs->base,
> + refname,
> + RESOLVE_REF_READING,
> + &oid, &flag);
> + if (!referent) {
We lost it here, though.
> oidclr(&oid, the_repository->hash_algo);
> flag |= REF_ISBROKEN;
> } else if (is_null_oid(&oid)) {
> @@ -268,7 +270,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
> oidclr(&oid, the_repository->hash_algo);
> flag |= REF_BAD_NAME | REF_ISBROKEN;
> }
> - add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
> +
> + if (!(flag & REF_ISSYMREF))
> + referent = NULL;
OK, this is new in this round. The idea is that everybody else can
rely on the invariant that the referent being NULL is equivalent to
REF_ISSYMREF bit in flag word being off from here on.
> + add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
> }
>
> /*
> @@ -886,6 +892,11 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
> iter->base.refname = iter->iter0->refname;
> iter->base.oid = iter->iter0->oid;
> iter->base.flags = iter->iter0->flags;
> + if (iter->iter0->flags & REF_ISSYMREF)
> + iter->base.referent = iter->iter0->referent;
> + else
> + iter->base.referent = NULL;
> return ITER_OK;
> }
Hmph, why not an unconditional
iter->base.referent = iter->iter0->referent;
instead? This code is making sure (iter->base.flags & REF_ISSYMREF)
is directly linked to non-NULL-ness or iter->base.referent, and we
want to make everybody take it as invariant. Shouldn't this code
also rely on the same invariant? If iter-iter0->referent is NULL,
iter->iter0->flag has REF_ISSYMREF bit off, and vice versa.
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH v3 1/3] refs: keep track of unresolved reference value in iterators
2024-08-07 21:40 ` Junio C Hamano
@ 2024-08-08 18:09 ` John Cai
0 siblings, 0 replies; 44+ messages in thread
From: John Cai @ 2024-08-08 18:09 UTC (permalink / raw)
To: Junio C Hamano
Cc: John Cai via GitGitGadget, git, Phillip Wood,
Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver
Hi Junio,
On 7 Aug 2024, at 17:40, Junio C Hamano wrote:
> "John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> diff --git a/refs/files-backend.c b/refs/files-backend.c
>> index aa52d9be7c7..5ed69c23f74 100644
>> --- a/refs/files-backend.c
>> +++ b/refs/files-backend.c
>> @@ -245,9 +245,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
>> {
>> struct object_id oid;
>> int flag;
>> -
>> - if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
>
> Here, we had a nice blank line that separated the decls and the
> first statement.
>
>> - &oid, &flag)) {
>> + const char *referent = refs_resolve_ref_unsafe(&refs->base,
>> + refname,
>> + RESOLVE_REF_READING,
>> + &oid, &flag);
>> + if (!referent) {
>
> We lost it here, though.
Ah will restore the blank line.
>
>> oidclr(&oid, the_repository->hash_algo);
>> flag |= REF_ISBROKEN;
>> } else if (is_null_oid(&oid)) {
>> @@ -268,7 +270,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
>> oidclr(&oid, the_repository->hash_algo);
>> flag |= REF_BAD_NAME | REF_ISBROKEN;
>> }
>> - add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
>> +
>> + if (!(flag & REF_ISSYMREF))
>> + referent = NULL;
>
> OK, this is new in this round. The idea is that everybody else can
> rely on the invariant that the referent being NULL is equivalent to
> REF_ISSYMREF bit in flag word being off from here on.
>
>> + add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
>> }
>>
>> /*
>> @@ -886,6 +892,11 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
>> iter->base.refname = iter->iter0->refname;
>> iter->base.oid = iter->iter0->oid;
>> iter->base.flags = iter->iter0->flags;
>> + if (iter->iter0->flags & REF_ISSYMREF)
>> + iter->base.referent = iter->iter0->referent;
>> + else
>> + iter->base.referent = NULL;
>> return ITER_OK;
>> }
>
> Hmph, why not an unconditional
>
> iter->base.referent = iter->iter0->referent;
>
> instead? This code is making sure (iter->base.flags & REF_ISSYMREF)
> is directly linked to non-NULL-ness or iter->base.referent, and we
> want to make everybody take it as invariant. Shouldn't this code
> also rely on the same invariant? If iter-iter0->referent is NULL,
> iter->iter0->flag has REF_ISSYMREF bit off, and vice versa.
That's a good point. Even though this code will be used in a loop, if we just
set it every time unconditionally then we won't end up with leftover values. Wil
l adjust in the next version.
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v3 2/3] refs: add referent to each_ref_fn
2024-08-07 19:42 ` [PATCH v3 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-08-07 19:42 ` [PATCH v3 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-08-07 19:42 ` John Cai via GitGitGadget
2024-08-07 19:42 ` [PATCH v3 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
2024-08-09 15:37 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
3 siblings, 0 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-07 19:42 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
Add a parameter to each_ref_fn so that callers to the ref APIs
that use this function as a callback can have acess to the
unresolved value of a symbolic ref.
Signed-off-by: John Cai <johncai86@gmail.com>
---
bisect.c | 3 ++-
builtin/bisect.c | 4 +++-
builtin/checkout.c | 2 +-
builtin/describe.c | 2 +-
builtin/fetch.c | 3 ++-
builtin/fsck.c | 4 ++--
builtin/gc.c | 1 +
builtin/name-rev.c | 2 +-
builtin/pack-objects.c | 5 +++--
builtin/receive-pack.c | 2 +-
builtin/remote.c | 4 +++-
builtin/repack.c | 1 +
builtin/replace.c | 1 +
builtin/rev-parse.c | 4 ++--
builtin/show-branch.c | 8 ++++----
builtin/show-ref.c | 3 ++-
builtin/submodule--helper.c | 1 +
builtin/worktree.c | 1 +
commit-graph.c | 1 +
delta-islands.c | 2 +-
fetch-pack.c | 2 ++
help.c | 2 +-
http-backend.c | 4 ++--
log-tree.c | 2 +-
ls-refs.c | 4 ++--
midx-write.c | 2 +-
negotiator/default.c | 2 +-
negotiator/skipping.c | 2 +-
notes.c | 2 +-
object-name.c | 2 +-
pseudo-merge.c | 1 +
reachable.c | 2 +-
ref-filter.c | 4 ++--
reflog.c | 1 +
refs.c | 14 +++++++-------
refs.h | 2 +-
refs/files-backend.c | 2 +-
refs/iterator.c | 2 +-
remote.c | 4 ++--
replace-object.c | 1 +
revision.c | 2 +-
server-info.c | 2 +-
shallow.c | 2 ++
submodule.c | 2 ++
t/helper/test-ref-store.c | 2 +-
upload-pack.c | 8 ++++----
walker.c | 1 +
worktree.c | 2 +-
48 files changed, 78 insertions(+), 54 deletions(-)
diff --git a/bisect.c b/bisect.c
index 135f94ba097..4406fc44cf9 100644
--- a/bisect.c
+++ b/bisect.c
@@ -448,7 +448,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
clear_commit_weight(&commit_weight);
}
-static int register_ref(const char *refname, const struct object_id *oid,
+static int register_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data UNUSED)
{
struct strbuf good_prefix = STRBUF_INIT;
@@ -1170,6 +1170,7 @@ int estimate_bisect_steps(int all)
}
static int mark_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/bisect.c b/builtin/bisect.c
index dabce9b542b..453a6cccd70 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -356,6 +356,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
}
static int inc_nr(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
@@ -545,7 +546,7 @@ finish:
return res;
}
-static int add_bisect_ref(const char *refname, const struct object_id *oid,
+static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct add_bisect_ref_data *data = cb;
@@ -1162,6 +1163,7 @@ static int bisect_visualize(struct bisect_terms *terms, int argc,
}
static int get_first_good(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 3cf44b4683a..562778885e1 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1045,7 +1045,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
report_tracking(new_branch_info);
}
-static int add_pending_uninteresting_ref(const char *refname,
+static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/describe.c b/builtin/describe.c
index e5287eddf2d..d95a9109eed 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -145,7 +145,7 @@ static void add_to_known_names(const char *path,
}
}
-static int get_name(const char *path, const struct object_id *oid,
+static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
int is_tag = 0;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 693f02b9580..c297569a473 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -286,7 +286,7 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
return ent;
}
-static int add_one_refname(const char *refname,
+static int add_one_refname(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
@@ -1464,6 +1464,7 @@ static void set_option(struct transport *transport, const char *name, const char
static int add_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/fsck.c b/builtin/fsck.c
index d13a226c2ed..ef6ee1268bd 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -521,7 +521,7 @@ static int fsck_handle_reflog(const char *logname, void *cb_data)
return 0;
}
-static int fsck_handle_ref(const char *refname, const struct object_id *oid,
+static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object *obj;
@@ -576,7 +576,7 @@ static void get_default_heads(void)
strbuf_worktree_ref(wt, &ref, "HEAD");
fsck_head_link(ref.buf, &head_points_at, &head_oid);
if (head_points_at && !is_null_oid(&head_oid))
- fsck_handle_ref(ref.buf, &head_oid, 0, NULL);
+ fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL);
strbuf_release(&ref);
if (include_reflogs)
diff --git a/builtin/gc.c b/builtin/gc.c
index 72bac2554fc..65be7c31b33 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -836,6 +836,7 @@ struct cg_auto_data {
};
static int dfs_on_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 70e9ec4e477..52016f1cf7d 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -337,7 +337,7 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_)
return a->taggerdate != b->taggerdate;
}
-static int name_ref(const char *path, const struct object_id *oid,
+static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
struct object *o = parse_object(the_repository, oid);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f395488971f..c481feadbfa 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -771,7 +771,7 @@ static enum write_one_status write_one(struct hashfile *f,
return WRITE_ONE_WRITTEN;
}
-static int mark_tagged(const char *path UNUSED, const struct object_id *oid,
+static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -3129,7 +3129,7 @@ static void add_tag_chain(const struct object_id *oid)
}
}
-static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid,
+static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -4076,6 +4076,7 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED)
}
static int mark_bitmap_preferred_tip(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *data UNUSED)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 339524ae2a8..6e0f462efbb 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -300,7 +300,7 @@ static void show_ref(const char *path, const struct object_id *oid)
}
}
-static int show_ref_cb(const char *path_full, const struct object_id *oid,
+static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *data)
{
struct oidset *seen = data;
diff --git a/builtin/remote.c b/builtin/remote.c
index 08292498bde..9a3db1b0f13 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -543,6 +543,7 @@ struct branches_for_remote {
};
static int add_branch_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -585,7 +586,7 @@ struct rename_info {
uint32_t symrefs_nr;
};
-static int read_remote_branches(const char *refname,
+static int read_remote_branches(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -971,6 +972,7 @@ static void free_remote_ref_states(struct ref_states *states)
}
static int append_ref_to_tracked_list(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
diff --git a/builtin/repack.c b/builtin/repack.c
index f0317fa94ad..d9ea6cecbf9 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -667,6 +667,7 @@ struct midx_snapshot_ref_data {
};
static int midx_snapshot_ref_one(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *_data)
{
diff --git a/builtin/replace.c b/builtin/replace.c
index 1ef833c07f5..34cc4672bc1 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -49,6 +49,7 @@ struct show_data {
};
static int show_reference(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 2e64f5bda70..a7084ca157f 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -211,7 +211,7 @@ static int show_default(void)
return 0;
}
-static int show_reference(const char *refname, const struct object_id *oid,
+static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
if (ref_excluded(&ref_excludes, refname))
@@ -220,7 +220,7 @@ static int show_reference(const char *refname, const struct object_id *oid,
return 0;
}
-static int anti_reference(const char *refname, const struct object_id *oid,
+static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
show_rev(REVERSED, oid, refname);
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index d72f4cb98de..3427c1572e5 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -410,7 +410,7 @@ static int append_ref(const char *refname, const struct object_id *oid,
return 0;
}
-static int append_head_ref(const char *refname, const struct object_id *oid,
+static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -425,7 +425,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid,
return append_ref(refname + ofs, oid, 0);
}
-static int append_remote_ref(const char *refname, const struct object_id *oid,
+static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -451,7 +451,7 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,
static const char *match_ref_pattern = NULL;
static int match_ref_slash = 0;
-static int append_matching_ref(const char *refname, const struct object_id *oid,
+static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
/* we want to allow pattern hold/<asterisk> to show all
@@ -468,7 +468,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid,
if (wildmatch(match_ref_pattern, tail, 0))
return 0;
if (starts_with(refname, "refs/heads/"))
- return append_head_ref(refname, oid, flag, cb_data);
+ return append_head_ref(refname, NULL, oid, flag, cb_data);
if (starts_with(refname, "refs/tags/"))
return append_tag_ref(refname, oid, flag, cb_data);
return append_ref(refname, oid, 0);
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 839a5c29f31..04e0db707c6 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -63,7 +63,7 @@ struct show_ref_data {
int show_head;
};
-static int show_ref(const char *refname, const struct object_id *oid,
+static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
struct show_ref_data *data = cbdata;
@@ -97,6 +97,7 @@ match:
}
static int add_existing(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cbdata)
{
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 880ab4456ee..1cdcc465b1c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -609,6 +609,7 @@ static void print_status(unsigned int flags, char state, const char *path,
}
static int handle_submodule_head_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 1d51e54fcdc..2e16218c655 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -626,6 +626,7 @@ static void print_preparing_worktree_line(int detach,
* Returns 0 on failure and non-zero on success.
*/
static int first_valid_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data UNUSED)
diff --git a/commit-graph.c b/commit-graph.c
index 79b0e72cc42..aa6e08eb39c 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1847,6 +1847,7 @@ struct refs_cb_data {
};
static int add_ref_to_set(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/delta-islands.c b/delta-islands.c
index ffe1ca28144..84435512593 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -390,7 +390,7 @@ static void add_ref_to_island(kh_str_t *remote_islands, const char *island_name,
rl->hash += sha_core;
}
-static int find_island_for_ref(const char *refname, const struct object_id *oid,
+static int find_island_for_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct island_load_data *ild = cb;
diff --git a/fetch-pack.c b/fetch-pack.c
index 732511604b1..58b4581ad80 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -183,6 +183,7 @@ static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
}
static int rev_list_insert_ref_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
@@ -610,6 +611,7 @@ static int mark_complete(const struct object_id *oid)
}
static int mark_complete_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/help.c b/help.c
index a6b4d3b1ebd..c03863f2265 100644
--- a/help.c
+++ b/help.c
@@ -804,7 +804,7 @@ struct similar_ref_cb {
struct string_list *similar_refs;
};
-static int append_similar_ref(const char *refname,
+static int append_similar_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
diff --git a/http-backend.c b/http-backend.c
index 461424972b6..79ce097359b 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -512,7 +512,7 @@ static void run_service(const char **argv, int buffer_input)
exit(1);
}
-static int show_text_ref(const char *name, const struct object_id *oid,
+static int show_text_ref(const char *name, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *name_nons = strip_namespace(name);
@@ -568,7 +568,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
strbuf_release(&buf);
}
-static int show_head_ref(const char *refname, const struct object_id *oid,
+static int show_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct strbuf *buf = cb_data;
diff --git a/log-tree.c b/log-tree.c
index 52feec4356a..40306434556 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -145,7 +145,7 @@ static int ref_filter_match(const char *refname,
return 1;
}
-static int add_ref_decoration(const char *refname, const struct object_id *oid,
+static int add_ref_decoration(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED,
void *cb_data)
{
diff --git a/ls-refs.c b/ls-refs.c
index 2dd925b43d0..c824aea7146 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -77,7 +77,7 @@ struct ls_refs_data {
unsigned unborn : 1;
};
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct ls_refs_data *data = cb_data;
@@ -135,7 +135,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
oid_is_null = is_null_oid(&oid);
if (!oid_is_null ||
(data->unborn && data->symrefs && (flag & REF_ISSYMREF)))
- send_ref(namespaced.buf, oid_is_null ? NULL : &oid, flag, data);
+ send_ref(namespaced.buf, NULL, oid_is_null ? NULL : &oid, flag, data);
strbuf_release(&namespaced);
}
diff --git a/midx-write.c b/midx-write.c
index 478b42e7209..56d1717f9f1 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -655,7 +655,7 @@ static void prepare_midx_packing_data(struct packing_data *pdata,
trace2_region_leave("midx", "prepare_midx_packing_data", the_repository);
}
-static int add_ref_to_pending(const char *refname,
+static int add_ref_to_pending(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag, void *cb_data)
{
diff --git a/negotiator/default.c b/negotiator/default.c
index e3fa5c33249..c479da9b091 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -38,7 +38,7 @@ static void rev_list_push(struct negotiation_state *ns,
}
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index f109928ad0b..f65d47858b4 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -75,7 +75,7 @@ static struct entry *rev_list_push(struct data *data, struct commit *commit, int
return entry;
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/notes.c b/notes.c
index 1ba6412aae8..da42df282d5 100644
--- a/notes.c
+++ b/notes.c
@@ -932,7 +932,7 @@ out:
return ret;
}
-static int string_list_add_one_ref(const char *refname,
+static int string_list_add_one_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb)
{
diff --git a/object-name.c b/object-name.c
index 527b853ac45..7cca43020f2 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1365,7 +1365,7 @@ struct handle_one_ref_cb {
struct commit_list **list;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/pseudo-merge.c b/pseudo-merge.c
index f0fde13c471..77a83b9c5ce 100644
--- a/pseudo-merge.c
+++ b/pseudo-merge.c
@@ -201,6 +201,7 @@ void load_pseudo_merges_from_config(struct string_list *list)
}
static int find_pseudo_merge_group_for_ref(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *_data)
diff --git a/reachable.c b/reachable.c
index 46613a6bb6f..3e9b3dd0a46 100644
--- a/reachable.c
+++ b/reachable.c
@@ -79,7 +79,7 @@ static void add_rebase_files(struct rev_info *revs)
free_worktrees(worktrees);
}
-static int add_one_ref(const char *path, const struct object_id *oid,
+static int add_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct rev_info *revs = (struct rev_info *)cb_data;
diff --git a/ref-filter.c b/ref-filter.c
index 8c5e673fc0a..39997890feb 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2865,7 +2865,7 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
@@ -2900,7 +2900,7 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
diff --git a/reflog.c b/reflog.c
index 5ca944529b3..d592c1cfb56 100644
--- a/reflog.c
+++ b/reflog.c
@@ -300,6 +300,7 @@ int should_expire_reflog_ent_verbose(struct object_id *ooid,
}
static int push_tip_to_list(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags, void *cb_data)
{
diff --git a/refs.c b/refs.c
index bb90a188758..0a5c12cf16b 100644
--- a/refs.c
+++ b/refs.c
@@ -414,7 +414,7 @@ int refs_ref_exists(struct ref_store *refs, const char *refname)
NULL, NULL);
}
-static int for_each_filter_refs(const char *refname,
+static int for_each_filter_refs(const char *refname, const char *referent,
const struct object_id *oid,
int flags, void *data)
{
@@ -424,7 +424,7 @@ static int for_each_filter_refs(const char *refname,
return 0;
if (filter->prefix)
skip_prefix(refname, filter->prefix, &refname);
- return filter->fn(refname, oid, flags, filter->cb_data);
+ return filter->fn(refname, referent, oid, flags, filter->cb_data);
}
struct warn_if_dangling_data {
@@ -435,7 +435,7 @@ struct warn_if_dangling_data {
const char *msg_fmt;
};
-static int warn_if_dangling_symref(const char *refname,
+static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
@@ -506,7 +506,7 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag))
- ret = fn(buf.buf, &oid, flag, cb_data);
+ ret = fn(buf.buf, NULL, &oid, flag, cb_data);
strbuf_release(&buf);
return ret;
@@ -1547,7 +1547,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
&oid, &flag))
- return fn("HEAD", &oid, flag, cb_data);
+ return fn("HEAD", NULL, &oid, flag, cb_data);
return 0;
}
@@ -2387,7 +2387,7 @@ struct do_for_each_reflog_help {
void *cb_data;
};
-static int do_for_each_reflog_helper(const char *refname,
+static int do_for_each_reflog_helper(const char *refname, const char *referent,
const struct object_id *oid UNUSED,
int flags,
void *cb_data)
@@ -2593,7 +2593,7 @@ struct migration_data {
struct strbuf *errbuf;
};
-static int migrate_one_ref(const char *refname, const struct object_id *oid,
+static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct migration_data *data = cb_data;
diff --git a/refs.h b/refs.h
index 0ecba21b4a7..158e0a12197 100644
--- a/refs.h
+++ b/refs.h
@@ -298,7 +298,7 @@ struct ref_transaction;
* arguments is only guaranteed to be valid for the duration of a
* single callback invocation.
*/
-typedef int each_ref_fn(const char *refname,
+typedef int each_ref_fn(const char *refname, const char *referent,
const struct object_id *oid, int flags, void *cb_data);
/*
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 5ed69c23f74..ad5f0c21771 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3046,7 +3046,7 @@ static int files_transaction_abort(struct ref_store *ref_store,
return 0;
}
-static int ref_present(const char *refname,
+static int ref_present(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data)
diff --git a/refs/iterator.c b/refs/iterator.c
index 75fbe5d72ab..8e999d81fc6 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -450,7 +450,7 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
current_ref_iter = iter;
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
- retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
+ retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
if (retval) {
/*
* If ref_iterator_abort() returns ITER_ERROR,
diff --git a/remote.c b/remote.c
index f43cf5e7a4d..4a1269a47ab 100644
--- a/remote.c
+++ b/remote.c
@@ -2354,7 +2354,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
return 1;
}
-static int one_local_ref(const char *refname, const struct object_id *oid,
+static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
@@ -2439,7 +2439,7 @@ struct stale_heads_info {
struct refspec *rs;
};
-static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
+static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct stale_heads_info *info = cb_data;
diff --git a/replace-object.c b/replace-object.c
index 59252d565ef..9a3cdd809a9 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -9,6 +9,7 @@
#include "commit.h"
static int register_replace_ref(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
diff --git a/revision.c b/revision.c
index 1c0192f5225..6b33bd814f7 100644
--- a/revision.c
+++ b/revision.c
@@ -1648,7 +1648,7 @@ struct all_refs_cb {
struct worktree *wt;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/server-info.c b/server-info.c
index f61296a60d0..1508fa6f825 100644
--- a/server-info.c
+++ b/server-info.c
@@ -147,7 +147,7 @@ out:
return ret;
}
-static int add_info_ref(const char *path, const struct object_id *oid,
+static int add_info_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/shallow.c b/shallow.c
index 31a6ca40fe2..b8cd051e3b6 100644
--- a/shallow.c
+++ b/shallow.c
@@ -612,6 +612,7 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
}
static int mark_uninteresting(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data UNUSED)
@@ -727,6 +728,7 @@ struct commit_array {
};
static int add_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/submodule.c b/submodule.c
index ab99a302530..7c0f5db861d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -953,6 +953,7 @@ static void free_submodules_data(struct string_list *submodules)
}
static int has_remote(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data UNUSED)
{
@@ -1273,6 +1274,7 @@ int push_unpushed_submodules(struct repository *r,
}
static int append_oid_to_array(const char *ref UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *data)
{
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 637b8b294e9..65346dee551 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -156,7 +156,7 @@ static int cmd_rename_ref(struct ref_store *refs, const char **argv)
return refs_rename_ref(refs, oldref, newref, logmsg);
}
-static int each_ref(const char *refname, const struct object_id *oid,
+static int each_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data UNUSED)
{
printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
diff --git a/upload-pack.c b/upload-pack.c
index 0052c6a4dce..f03ba3e98be 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -857,7 +857,7 @@ static void send_unshallow(struct upload_pack_data *data)
}
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data);
static void deepen(struct upload_pack_data *data, int depth)
{
@@ -1208,7 +1208,7 @@ static int mark_our_ref(const char *refname, const char *refname_full,
return 0;
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED,const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *refname = strip_namespace(refname_full);
@@ -1276,14 +1276,14 @@ static void write_v0_ref(struct upload_pack_data *data,
return;
}
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
return 0;
}
-static int find_symref(const char *refname,
+static int find_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag, void *cb_data)
{
diff --git a/walker.c b/walker.c
index 0fafdc97cf1..807a7a38813 100644
--- a/walker.c
+++ b/walker.c
@@ -221,6 +221,7 @@ static int interpret_target(struct walker *walker, char *target, struct object_i
}
static int mark_complete(const char *path UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/worktree.c b/worktree.c
index f3c4c8ec54d..fd05f3741c6 100644
--- a/worktree.c
+++ b/worktree.c
@@ -546,7 +546,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
refname.buf,
RESOLVE_REF_READING,
&oid, &flag))
- ret = fn(refname.buf, &oid, flag, cb_data);
+ ret = fn(refname.buf, NULL, &oid, flag, cb_data);
if (ret)
break;
}
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v3 3/3] ref-filter: populate symref from iterator
2024-08-07 19:42 ` [PATCH v3 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-08-07 19:42 ` [PATCH v3 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
2024-08-07 19:42 ` [PATCH v3 2/3] refs: add referent to each_ref_fn John Cai via GitGitGadget
@ 2024-08-07 19:42 ` John Cai via GitGitGadget
2024-08-09 15:37 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
3 siblings, 0 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-07 19:42 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
With a previous commit, the reference the symbolic ref points to is saved
in the ref iterator records. Instead of making a separate call to
resolve_refdup() each time, we can just populate the ref_array_item with
the value from the iterator.
Signed-off-by: John Cai <johncai86@gmail.com>
---
ref-filter.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index 39997890feb..4d1f3ff3d23 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2343,6 +2343,12 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
CALLOC_ARRAY(ref->value, used_atom_cnt);
+ /**
+ * NEEDSWORK: The following code might be unncessary if all codepaths
+ * that call populate_value() populates the symref member of ref_array_item
+ * like in apply_ref_filter(). Currently pretty_print_ref() is the only codepath
+ * that calls populate_value() without first populating symref.
+ */
if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository),
ref->refname,
@@ -2783,7 +2789,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
return ref_kind_from_refname(refname);
}
-static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
+static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
int flag, struct ref_filter *filter)
{
struct ref_array_item *ref;
@@ -2852,6 +2858,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
ref->commit = commit;
ref->flag = flag;
ref->kind = kind;
+ ref->symref = xstrdup_or_null(referent);
return ref;
}
@@ -2865,12 +2872,12 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (ref)
ref_array_append(ref_cbdata->array, ref);
@@ -2900,13 +2907,13 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (!ref)
return 0;
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators
2024-08-07 19:42 ` [PATCH v3 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
` (2 preceding siblings ...)
2024-08-07 19:42 ` [PATCH v3 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
@ 2024-08-09 15:37 ` John Cai via GitGitGadget
2024-08-09 15:37 ` [PATCH v4 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
` (3 more replies)
3 siblings, 4 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-09 15:37 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai
For reftable development, it's useful to be able to print out the direct
value of a symbolic reference before resolution. This is currently possible
with git-for-each-ref, but since the iterators do not keep track of the
value of the symbolic ref, a separate call needs to be made each time making
it inefficient.
Address this inefficiency by keeping track of the value of the symbolic
reference in the ref iterator. This patch series also ends with a commit to
use this value in the iterator through callbacks in ref-filter.c.
This series started with [1] but I decided to send a separate patch series
since it is substantially different.
Benchmarking shows that with these changes, we experience a speedup in
git-for-each-ref(1) on a repository with many symbolic refs:
$ hyperfine --warmup 5 "git for-each-ref --format='%(refname) %(objectname)
%(symref)'" "~/Projects/git/git for-each-ref --format='%(refname)
%(objectname) %(symref)'" Benchmark 1: git for-each-ref --format='%(refname)
%(objectname) %(symref)' Time (mean ± σ): 905.1 ms ± 13.2 ms [User: 56.3 ms,
System: 628.6 ms] Range (min … max): 893.4 ms … 936.9 ms 10 runs
Benchmark 2: ~/Projects/git/git for-each-ref --format='%(refname)
%(objectname) %(symref)' Time (mean ± σ): 482.2 ms ± 26.4 ms [User: 34.7 ms,
System: 410.6 ms] Range (min … max): 459.4 ms … 541.8 ms 10 runs
Summary ~/Projects/git/git for-each-ref --format='%(refname) %(objectname)
%(symref)' ran 1.88 ± 0.11 times faster than git for-each-ref
--format='%(refname) %(objectname) %(symref)'
Changes since V3:
* Added blank line to separate declarations from statements
* unconditionally set referent member in base iterator in files backend
Changes since V2:
* Style tweaks
* Added a NEEDSWORK comment around fallback code
* Stay consistent in the meaning of a non-NULL referent member in the
iterator
Changes since V1
* Use the return value from refs_resolve_ref_unsafe instead of using an out
parameter
1. https://lore.kernel.org/git/pull.1684.git.git.1709592718743.gitgitgadget@gmail.com/
John Cai (3):
refs: keep track of unresolved reference value in iterators
refs: add referent to each_ref_fn
ref-filter: populate symref from iterator
bisect.c | 3 ++-
builtin/bisect.c | 4 +++-
builtin/checkout.c | 2 +-
builtin/describe.c | 2 +-
builtin/fetch.c | 3 ++-
builtin/fsck.c | 4 ++--
builtin/gc.c | 1 +
builtin/name-rev.c | 2 +-
builtin/pack-objects.c | 5 +++--
builtin/receive-pack.c | 2 +-
builtin/remote.c | 4 +++-
builtin/repack.c | 1 +
builtin/replace.c | 1 +
builtin/rev-parse.c | 4 ++--
builtin/show-branch.c | 8 ++++----
builtin/show-ref.c | 3 ++-
builtin/submodule--helper.c | 1 +
builtin/worktree.c | 1 +
commit-graph.c | 1 +
delta-islands.c | 2 +-
fetch-pack.c | 2 ++
help.c | 2 +-
http-backend.c | 4 ++--
log-tree.c | 2 +-
ls-refs.c | 4 ++--
midx-write.c | 2 +-
negotiator/default.c | 2 +-
negotiator/skipping.c | 2 +-
notes.c | 2 +-
object-name.c | 2 +-
pseudo-merge.c | 1 +
reachable.c | 2 +-
ref-filter.c | 17 ++++++++++++-----
reflog.c | 1 +
refs.c | 14 +++++++-------
refs.h | 2 +-
refs/files-backend.c | 17 +++++++++++++----
refs/iterator.c | 4 +++-
refs/ref-cache.c | 5 +++++
refs/ref-cache.h | 2 ++
refs/refs-internal.h | 1 +
refs/reftable-backend.c | 10 ++++++++--
remote.c | 4 ++--
replace-object.c | 1 +
revision.c | 2 +-
server-info.c | 2 +-
shallow.c | 2 ++
submodule.c | 2 ++
t/helper/test-ref-store.c | 2 +-
upload-pack.c | 8 ++++----
walker.c | 1 +
worktree.c | 2 +-
52 files changed, 118 insertions(+), 62 deletions(-)
base-commit: 557ae147e6cdc9db121269b058c757ac5092f9c9
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1712%2Fjohn-cai%2Fjc%2Fsymbolic-ref-in-iterator-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1712/john-cai/jc/symbolic-ref-in-iterator-v4
Pull-Request: https://github.com/git/git/pull/1712
Range-diff vs v3:
1: fc3defd9c47 ! 1: c4f5f5b7dd8 refs: keep track of unresolved reference value in iterators
@@ refs/files-backend.c: static void loose_fill_ref_dir_regular_file(struct files_r
{
struct object_id oid;
int flag;
--
-- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
-- &oid, &flag)) {
+ const char *referent = refs_resolve_ref_unsafe(&refs->base,
+ refname,
+ RESOLVE_REF_READING,
+ &oid, &flag);
+
+- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
+- &oid, &flag)) {
+ if (!referent) {
oidclr(&oid, the_repository->hash_algo);
flag |= REF_ISBROKEN;
@@ refs/files-backend.c: static int files_ref_iterator_advance(struct ref_iterator
iter->base.refname = iter->iter0->refname;
iter->base.oid = iter->iter0->oid;
iter->base.flags = iter->iter0->flags;
-+ if (iter->iter0->flags & REF_ISSYMREF)
-+ iter->base.referent = iter->iter0->referent;
-+ else
-+ iter->base.referent = NULL;
++ iter->base.referent = iter->iter0->referent;
+
return ITER_OK;
}
@@ refs/iterator.c: static int merge_ref_iterator_advance(struct ref_iterator *ref_
iter->base.flags = (*iter->current)->flags;
## refs/ref-cache.c ##
-@@
- #include "refs-internal.h"
- #include "ref-cache.h"
- #include "../iterator.h"
-+#include "../strbuf.h"
-
- void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
- {
@@ refs/ref-cache.c: struct ref_dir *get_ref_dir(struct ref_entry *entry)
}
2: 0b6e732ad7e = 2: 6cfac5e51f5 refs: add referent to each_ref_fn
3: 83b70ab8287 = 3: 9f609f4d0f5 ref-filter: populate symref from iterator
--
gitgitgadget
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v4 1/3] refs: keep track of unresolved reference value in iterators
2024-08-09 15:37 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
@ 2024-08-09 15:37 ` John Cai via GitGitGadget
2024-11-23 8:24 ` shejialuo
2024-08-09 15:37 ` [PATCH v4 2/3] refs: add referent to each_ref_fn John Cai via GitGitGadget
` (2 subsequent siblings)
3 siblings, 1 reply; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-09 15:37 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
Since ref iterators do not hold onto the direct value of a reference
without resolving it, the only way to get ahold of a direct value of a
symbolic ref is to make a separate call to refs_read_symbolic_ref.
To make accessing the direct value of a symbolic ref more efficient,
let's save the direct value of the ref in the iterators for both the
files backend and the reftable backend.
Signed-off-by: John Cai <johncai86@gmail.com>
---
refs/files-backend.c | 15 ++++++++++++---
refs/iterator.c | 2 ++
refs/ref-cache.c | 5 +++++
refs/ref-cache.h | 2 ++
refs/refs-internal.h | 1 +
refs/reftable-backend.c | 10 ++++++++--
6 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index aa52d9be7c7..210adf644fa 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -245,9 +245,12 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
{
struct object_id oid;
int flag;
+ const char *referent = refs_resolve_ref_unsafe(&refs->base,
+ refname,
+ RESOLVE_REF_READING,
+ &oid, &flag);
- if (!refs_resolve_ref_unsafe(&refs->base, refname, RESOLVE_REF_READING,
- &oid, &flag)) {
+ if (!referent) {
oidclr(&oid, the_repository->hash_algo);
flag |= REF_ISBROKEN;
} else if (is_null_oid(&oid)) {
@@ -268,7 +271,11 @@ static void loose_fill_ref_dir_regular_file(struct files_ref_store *refs,
oidclr(&oid, the_repository->hash_algo);
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
- add_entry_to_dir(dir, create_ref_entry(refname, &oid, flag));
+
+ if (!(flag & REF_ISSYMREF))
+ referent = NULL;
+
+ add_entry_to_dir(dir, create_ref_entry(refname, referent, &oid, flag));
}
/*
@@ -886,6 +893,8 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
iter->base.refname = iter->iter0->refname;
iter->base.oid = iter->iter0->oid;
iter->base.flags = iter->iter0->flags;
+ iter->base.referent = iter->iter0->referent;
+
return ITER_OK;
}
diff --git a/refs/iterator.c b/refs/iterator.c
index d355ebf0d59..75fbe5d72ab 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -29,6 +29,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
{
iter->vtable = vtable;
iter->refname = NULL;
+ iter->referent = NULL;
iter->oid = NULL;
iter->flags = 0;
}
@@ -199,6 +200,7 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
}
if (selection & ITER_YIELD_CURRENT) {
+ iter->base.referent = (*iter->current)->referent;
iter->base.refname = (*iter->current)->refname;
iter->base.oid = (*iter->current)->oid;
iter->base.flags = (*iter->current)->flags;
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index 4ce519bbc85..35bae7e05de 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -34,6 +34,7 @@ struct ref_dir *get_ref_dir(struct ref_entry *entry)
}
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag)
{
struct ref_entry *ref;
@@ -41,6 +42,8 @@ struct ref_entry *create_ref_entry(const char *refname,
FLEX_ALLOC_STR(ref, name, refname);
oidcpy(&ref->u.value.oid, oid);
ref->flag = flag;
+ ref->u.value.referent = xstrdup_or_null(referent);
+
return ref;
}
@@ -66,6 +69,7 @@ static void free_ref_entry(struct ref_entry *entry)
*/
clear_ref_dir(&entry->u.subdir);
}
+ free(entry->u.value.referent);
free(entry);
}
@@ -431,6 +435,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
level->index = -1;
} else {
iter->base.refname = entry->name;
+ iter->base.referent = entry->u.value.referent;
iter->base.oid = &entry->u.value.oid;
iter->base.flags = entry->flag;
return ITER_OK;
diff --git a/refs/ref-cache.h b/refs/ref-cache.h
index 31ebe24f6cf..5f04e518c37 100644
--- a/refs/ref-cache.h
+++ b/refs/ref-cache.h
@@ -42,6 +42,7 @@ struct ref_value {
* referred to by the last reference in the symlink chain.
*/
struct object_id oid;
+ char *referent;
};
/*
@@ -173,6 +174,7 @@ struct ref_entry *create_dir_entry(struct ref_cache *cache,
const char *dirname, size_t len);
struct ref_entry *create_ref_entry(const char *refname,
+ const char *referent,
const struct object_id *oid, int flag);
/*
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index fa975d69aaa..117ec233848 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -299,6 +299,7 @@ enum do_for_each_ref_flags {
struct ref_iterator {
struct ref_iterator_vtable *vtable;
const char *refname;
+ const char *referent;
const struct object_id *oid;
unsigned int flags;
};
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index fbe74c239d3..50a072b97b0 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -455,6 +455,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
struct reftable_ref_iterator *iter =
(struct reftable_ref_iterator *)ref_iterator;
struct reftable_ref_store *refs = iter->refs;
+ const char *referent = NULL;
while (!iter->err) {
int flags = 0;
@@ -494,8 +495,12 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
the_repository->hash_algo);
break;
case REFTABLE_REF_SYMREF:
- if (!refs_resolve_ref_unsafe(&iter->refs->base, iter->ref.refname,
- RESOLVE_REF_READING, &iter->oid, &flags))
+ referent = refs_resolve_ref_unsafe(&iter->refs->base,
+ iter->ref.refname,
+ RESOLVE_REF_READING,
+ &iter->oid,
+ &flags);
+ if (!referent)
oidclr(&iter->oid, the_repository->hash_algo);
break;
default:
@@ -523,6 +528,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
continue;
iter->base.refname = iter->ref.refname;
+ iter->base.referent = referent;
iter->base.oid = &iter->oid;
iter->base.flags = flags;
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v4 1/3] refs: keep track of unresolved reference value in iterators
2024-08-09 15:37 ` [PATCH v4 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-11-23 8:24 ` shejialuo
0 siblings, 0 replies; 44+ messages in thread
From: shejialuo @ 2024-11-23 8:24 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, Linus Arver, John Cai
On Fri, Aug 09, 2024 at 03:37:49PM +0000, John Cai via GitGitGadget wrote:
[snip]
> @@ -66,6 +69,7 @@ static void free_ref_entry(struct ref_entry *entry)
> */
> clear_ref_dir(&entry->u.subdir);
> }
> + free(entry->u.value.referent);
> free(entry);
> }
>
Today, I am learning the source code of the "ref-cache.[ch]". I feel
rather confused here. And I think this usage is wrong.
"free_ref_entry" will do the following things:
1. If "entry" is a directory, it will call "clear_ref_dir" which will
call "free_ref_entry" for every loose ref.
2. If "entry" is a loose ref, it will call `free(entry->u.value.referent)`
and `free(entry)`.
The problem is if "entry" is a directory, we will also execute the
following statement:
free(entry->u.value.referent);
This does not make sense. We should never access the "entry->u.value" if
"entry" is a directory. So, I think the correct usage should be:
if (entry->flag & REF_DIR) {
...
clear_ref_dir(...);
} else {
free(entry->u.value.referent);
}
Thanks,
Jialuo
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH v4 2/3] refs: add referent to each_ref_fn
2024-08-09 15:37 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-08-09 15:37 ` [PATCH v4 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
@ 2024-08-09 15:37 ` John Cai via GitGitGadget
2024-08-09 15:37 ` [PATCH v4 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
2024-08-09 16:51 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators Junio C Hamano
3 siblings, 0 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-09 15:37 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
Add a parameter to each_ref_fn so that callers to the ref APIs
that use this function as a callback can have acess to the
unresolved value of a symbolic ref.
Signed-off-by: John Cai <johncai86@gmail.com>
---
bisect.c | 3 ++-
builtin/bisect.c | 4 +++-
builtin/checkout.c | 2 +-
builtin/describe.c | 2 +-
builtin/fetch.c | 3 ++-
builtin/fsck.c | 4 ++--
builtin/gc.c | 1 +
builtin/name-rev.c | 2 +-
builtin/pack-objects.c | 5 +++--
builtin/receive-pack.c | 2 +-
builtin/remote.c | 4 +++-
builtin/repack.c | 1 +
builtin/replace.c | 1 +
builtin/rev-parse.c | 4 ++--
builtin/show-branch.c | 8 ++++----
builtin/show-ref.c | 3 ++-
builtin/submodule--helper.c | 1 +
builtin/worktree.c | 1 +
commit-graph.c | 1 +
delta-islands.c | 2 +-
fetch-pack.c | 2 ++
help.c | 2 +-
http-backend.c | 4 ++--
log-tree.c | 2 +-
ls-refs.c | 4 ++--
midx-write.c | 2 +-
negotiator/default.c | 2 +-
negotiator/skipping.c | 2 +-
notes.c | 2 +-
object-name.c | 2 +-
pseudo-merge.c | 1 +
reachable.c | 2 +-
ref-filter.c | 4 ++--
reflog.c | 1 +
refs.c | 14 +++++++-------
refs.h | 2 +-
refs/files-backend.c | 2 +-
refs/iterator.c | 2 +-
remote.c | 4 ++--
replace-object.c | 1 +
revision.c | 2 +-
server-info.c | 2 +-
shallow.c | 2 ++
submodule.c | 2 ++
t/helper/test-ref-store.c | 2 +-
upload-pack.c | 8 ++++----
walker.c | 1 +
worktree.c | 2 +-
48 files changed, 78 insertions(+), 54 deletions(-)
diff --git a/bisect.c b/bisect.c
index 135f94ba097..4406fc44cf9 100644
--- a/bisect.c
+++ b/bisect.c
@@ -448,7 +448,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
clear_commit_weight(&commit_weight);
}
-static int register_ref(const char *refname, const struct object_id *oid,
+static int register_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data UNUSED)
{
struct strbuf good_prefix = STRBUF_INIT;
@@ -1170,6 +1170,7 @@ int estimate_bisect_steps(int all)
}
static int mark_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/bisect.c b/builtin/bisect.c
index dabce9b542b..453a6cccd70 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -356,6 +356,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
}
static int inc_nr(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb_data)
{
@@ -545,7 +546,7 @@ finish:
return res;
}
-static int add_bisect_ref(const char *refname, const struct object_id *oid,
+static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct add_bisect_ref_data *data = cb;
@@ -1162,6 +1163,7 @@ static int bisect_visualize(struct bisect_terms *terms, int argc,
}
static int get_first_good(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 3cf44b4683a..562778885e1 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1045,7 +1045,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
report_tracking(new_branch_info);
}
-static int add_pending_uninteresting_ref(const char *refname,
+static int add_pending_uninteresting_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/describe.c b/builtin/describe.c
index e5287eddf2d..d95a9109eed 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -145,7 +145,7 @@ static void add_to_known_names(const char *path,
}
}
-static int get_name(const char *path, const struct object_id *oid,
+static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
int is_tag = 0;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 693f02b9580..c297569a473 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -286,7 +286,7 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
return ent;
}
-static int add_one_refname(const char *refname,
+static int add_one_refname(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
@@ -1464,6 +1464,7 @@ static void set_option(struct transport *transport, const char *name, const char
static int add_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/builtin/fsck.c b/builtin/fsck.c
index d13a226c2ed..ef6ee1268bd 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -521,7 +521,7 @@ static int fsck_handle_reflog(const char *logname, void *cb_data)
return 0;
}
-static int fsck_handle_ref(const char *refname, const struct object_id *oid,
+static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object *obj;
@@ -576,7 +576,7 @@ static void get_default_heads(void)
strbuf_worktree_ref(wt, &ref, "HEAD");
fsck_head_link(ref.buf, &head_points_at, &head_oid);
if (head_points_at && !is_null_oid(&head_oid))
- fsck_handle_ref(ref.buf, &head_oid, 0, NULL);
+ fsck_handle_ref(ref.buf, NULL, &head_oid, 0, NULL);
strbuf_release(&ref);
if (include_reflogs)
diff --git a/builtin/gc.c b/builtin/gc.c
index 72bac2554fc..65be7c31b33 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -836,6 +836,7 @@ struct cg_auto_data {
};
static int dfs_on_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 70e9ec4e477..52016f1cf7d 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -337,7 +337,7 @@ static int cmp_by_tag_and_age(const void *a_, const void *b_)
return a->taggerdate != b->taggerdate;
}
-static int name_ref(const char *path, const struct object_id *oid,
+static int name_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
struct object *o = parse_object(the_repository, oid);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f395488971f..c481feadbfa 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -771,7 +771,7 @@ static enum write_one_status write_one(struct hashfile *f,
return WRITE_ONE_WRITTEN;
}
-static int mark_tagged(const char *path UNUSED, const struct object_id *oid,
+static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -3129,7 +3129,7 @@ static void add_tag_chain(const struct object_id *oid)
}
}
-static int add_ref_tag(const char *tag UNUSED, const struct object_id *oid,
+static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id peeled;
@@ -4076,6 +4076,7 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED)
}
static int mark_bitmap_preferred_tip(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *data UNUSED)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 339524ae2a8..6e0f462efbb 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -300,7 +300,7 @@ static void show_ref(const char *path, const struct object_id *oid)
}
}
-static int show_ref_cb(const char *path_full, const struct object_id *oid,
+static int show_ref_cb(const char *path_full, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *data)
{
struct oidset *seen = data;
diff --git a/builtin/remote.c b/builtin/remote.c
index 08292498bde..9a3db1b0f13 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -543,6 +543,7 @@ struct branches_for_remote {
};
static int add_branch_for_removal(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -585,7 +586,7 @@ struct rename_info {
uint32_t symrefs_nr;
};
-static int read_remote_branches(const char *refname,
+static int read_remote_branches(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
@@ -971,6 +972,7 @@ static void free_remote_ref_states(struct ref_states *states)
}
static int append_ref_to_tracked_list(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
diff --git a/builtin/repack.c b/builtin/repack.c
index f0317fa94ad..d9ea6cecbf9 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -667,6 +667,7 @@ struct midx_snapshot_ref_data {
};
static int midx_snapshot_ref_one(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *_data)
{
diff --git a/builtin/replace.c b/builtin/replace.c
index 1ef833c07f5..34cc4672bc1 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -49,6 +49,7 @@ struct show_data {
};
static int show_reference(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 2e64f5bda70..a7084ca157f 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -211,7 +211,7 @@ static int show_default(void)
return 0;
}
-static int show_reference(const char *refname, const struct object_id *oid,
+static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
if (ref_excluded(&ref_excludes, refname))
@@ -220,7 +220,7 @@ static int show_reference(const char *refname, const struct object_id *oid,
return 0;
}
-static int anti_reference(const char *refname, const struct object_id *oid,
+static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
show_rev(REVERSED, oid, refname);
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index d72f4cb98de..3427c1572e5 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -410,7 +410,7 @@ static int append_ref(const char *refname, const struct object_id *oid,
return 0;
}
-static int append_head_ref(const char *refname, const struct object_id *oid,
+static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -425,7 +425,7 @@ static int append_head_ref(const char *refname, const struct object_id *oid,
return append_ref(refname + ofs, oid, 0);
}
-static int append_remote_ref(const char *refname, const struct object_id *oid,
+static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data UNUSED)
{
struct object_id tmp;
@@ -451,7 +451,7 @@ static int append_tag_ref(const char *refname, const struct object_id *oid,
static const char *match_ref_pattern = NULL;
static int match_ref_slash = 0;
-static int append_matching_ref(const char *refname, const struct object_id *oid,
+static int append_matching_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
/* we want to allow pattern hold/<asterisk> to show all
@@ -468,7 +468,7 @@ static int append_matching_ref(const char *refname, const struct object_id *oid,
if (wildmatch(match_ref_pattern, tail, 0))
return 0;
if (starts_with(refname, "refs/heads/"))
- return append_head_ref(refname, oid, flag, cb_data);
+ return append_head_ref(refname, NULL, oid, flag, cb_data);
if (starts_with(refname, "refs/tags/"))
return append_tag_ref(refname, oid, flag, cb_data);
return append_ref(refname, oid, 0);
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 839a5c29f31..04e0db707c6 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -63,7 +63,7 @@ struct show_ref_data {
int show_head;
};
-static int show_ref(const char *refname, const struct object_id *oid,
+static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cbdata)
{
struct show_ref_data *data = cbdata;
@@ -97,6 +97,7 @@ match:
}
static int add_existing(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cbdata)
{
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 880ab4456ee..1cdcc465b1c 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -609,6 +609,7 @@ static void print_status(unsigned int flags, char state, const char *path,
}
static int handle_submodule_head_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 1d51e54fcdc..2e16218c655 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -626,6 +626,7 @@ static void print_preparing_worktree_line(int detach,
* Returns 0 on failure and non-zero on success.
*/
static int first_valid_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data UNUSED)
diff --git a/commit-graph.c b/commit-graph.c
index 79b0e72cc42..aa6e08eb39c 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1847,6 +1847,7 @@ struct refs_cb_data {
};
static int add_ref_to_set(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *cb_data)
{
diff --git a/delta-islands.c b/delta-islands.c
index ffe1ca28144..84435512593 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -390,7 +390,7 @@ static void add_ref_to_island(kh_str_t *remote_islands, const char *island_name,
rl->hash += sha_core;
}
-static int find_island_for_ref(const char *refname, const struct object_id *oid,
+static int find_island_for_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED, void *cb)
{
struct island_load_data *ild = cb;
diff --git a/fetch-pack.c b/fetch-pack.c
index 732511604b1..58b4581ad80 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -183,6 +183,7 @@ static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
}
static int rev_list_insert_ref_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
@@ -610,6 +611,7 @@ static int mark_complete(const struct object_id *oid)
}
static int mark_complete_oid(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/help.c b/help.c
index a6b4d3b1ebd..c03863f2265 100644
--- a/help.c
+++ b/help.c
@@ -804,7 +804,7 @@ struct similar_ref_cb {
struct string_list *similar_refs;
};
-static int append_similar_ref(const char *refname,
+static int append_similar_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data)
{
diff --git a/http-backend.c b/http-backend.c
index 461424972b6..79ce097359b 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -512,7 +512,7 @@ static void run_service(const char **argv, int buffer_input)
exit(1);
}
-static int show_text_ref(const char *name, const struct object_id *oid,
+static int show_text_ref(const char *name, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *name_nons = strip_namespace(name);
@@ -568,7 +568,7 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
strbuf_release(&buf);
}
-static int show_head_ref(const char *refname, const struct object_id *oid,
+static int show_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct strbuf *buf = cb_data;
diff --git a/log-tree.c b/log-tree.c
index 52feec4356a..40306434556 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -145,7 +145,7 @@ static int ref_filter_match(const char *refname,
return 1;
}
-static int add_ref_decoration(const char *refname, const struct object_id *oid,
+static int add_ref_decoration(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags UNUSED,
void *cb_data)
{
diff --git a/ls-refs.c b/ls-refs.c
index 2dd925b43d0..c824aea7146 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -77,7 +77,7 @@ struct ls_refs_data {
unsigned unborn : 1;
};
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct ls_refs_data *data = cb_data;
@@ -135,7 +135,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
oid_is_null = is_null_oid(&oid);
if (!oid_is_null ||
(data->unborn && data->symrefs && (flag & REF_ISSYMREF)))
- send_ref(namespaced.buf, oid_is_null ? NULL : &oid, flag, data);
+ send_ref(namespaced.buf, NULL, oid_is_null ? NULL : &oid, flag, data);
strbuf_release(&namespaced);
}
diff --git a/midx-write.c b/midx-write.c
index 478b42e7209..56d1717f9f1 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -655,7 +655,7 @@ static void prepare_midx_packing_data(struct packing_data *pdata,
trace2_region_leave("midx", "prepare_midx_packing_data", the_repository);
}
-static int add_ref_to_pending(const char *refname,
+static int add_ref_to_pending(const char *refname, const char *referent UNUSED,
const struct object_id *oid,
int flag, void *cb_data)
{
diff --git a/negotiator/default.c b/negotiator/default.c
index e3fa5c33249..c479da9b091 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -38,7 +38,7 @@ static void rev_list_push(struct negotiation_state *ns,
}
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index f109928ad0b..f65d47858b4 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -75,7 +75,7 @@ static struct entry *rev_list_push(struct data *data, struct commit *commit, int
return entry;
}
-static int clear_marks(const char *refname, const struct object_id *oid,
+static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
{
diff --git a/notes.c b/notes.c
index 1ba6412aae8..da42df282d5 100644
--- a/notes.c
+++ b/notes.c
@@ -932,7 +932,7 @@ out:
return ret;
}
-static int string_list_add_one_ref(const char *refname,
+static int string_list_add_one_ref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag UNUSED, void *cb)
{
diff --git a/object-name.c b/object-name.c
index 527b853ac45..7cca43020f2 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1365,7 +1365,7 @@ struct handle_one_ref_cb {
struct commit_list **list;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/pseudo-merge.c b/pseudo-merge.c
index f0fde13c471..77a83b9c5ce 100644
--- a/pseudo-merge.c
+++ b/pseudo-merge.c
@@ -201,6 +201,7 @@ void load_pseudo_merges_from_config(struct string_list *list)
}
static int find_pseudo_merge_group_for_ref(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *_data)
diff --git a/reachable.c b/reachable.c
index 46613a6bb6f..3e9b3dd0a46 100644
--- a/reachable.c
+++ b/reachable.c
@@ -79,7 +79,7 @@ static void add_rebase_files(struct rev_info *revs)
free_worktrees(worktrees);
}
-static int add_one_ref(const char *path, const struct object_id *oid,
+static int add_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data)
{
struct rev_info *revs = (struct rev_info *)cb_data;
diff --git a/ref-filter.c b/ref-filter.c
index 8c5e673fc0a..39997890feb 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2865,7 +2865,7 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
@@ -2900,7 +2900,7 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
diff --git a/reflog.c b/reflog.c
index 5ca944529b3..d592c1cfb56 100644
--- a/reflog.c
+++ b/reflog.c
@@ -300,6 +300,7 @@ int should_expire_reflog_ent_verbose(struct object_id *ooid,
}
static int push_tip_to_list(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags, void *cb_data)
{
diff --git a/refs.c b/refs.c
index bb90a188758..0a5c12cf16b 100644
--- a/refs.c
+++ b/refs.c
@@ -414,7 +414,7 @@ int refs_ref_exists(struct ref_store *refs, const char *refname)
NULL, NULL);
}
-static int for_each_filter_refs(const char *refname,
+static int for_each_filter_refs(const char *refname, const char *referent,
const struct object_id *oid,
int flags, void *data)
{
@@ -424,7 +424,7 @@ static int for_each_filter_refs(const char *refname,
return 0;
if (filter->prefix)
skip_prefix(refname, filter->prefix, &refname);
- return filter->fn(refname, oid, flags, filter->cb_data);
+ return filter->fn(refname, referent, oid, flags, filter->cb_data);
}
struct warn_if_dangling_data {
@@ -435,7 +435,7 @@ struct warn_if_dangling_data {
const char *msg_fmt;
};
-static int warn_if_dangling_symref(const char *refname,
+static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags, void *cb_data)
{
@@ -506,7 +506,7 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag))
- ret = fn(buf.buf, &oid, flag, cb_data);
+ ret = fn(buf.buf, NULL, &oid, flag, cb_data);
strbuf_release(&buf);
return ret;
@@ -1547,7 +1547,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
&oid, &flag))
- return fn("HEAD", &oid, flag, cb_data);
+ return fn("HEAD", NULL, &oid, flag, cb_data);
return 0;
}
@@ -2387,7 +2387,7 @@ struct do_for_each_reflog_help {
void *cb_data;
};
-static int do_for_each_reflog_helper(const char *refname,
+static int do_for_each_reflog_helper(const char *refname, const char *referent,
const struct object_id *oid UNUSED,
int flags,
void *cb_data)
@@ -2593,7 +2593,7 @@ struct migration_data {
struct strbuf *errbuf;
};
-static int migrate_one_ref(const char *refname, const struct object_id *oid,
+static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct migration_data *data = cb_data;
diff --git a/refs.h b/refs.h
index 0ecba21b4a7..158e0a12197 100644
--- a/refs.h
+++ b/refs.h
@@ -298,7 +298,7 @@ struct ref_transaction;
* arguments is only guaranteed to be valid for the duration of a
* single callback invocation.
*/
-typedef int each_ref_fn(const char *refname,
+typedef int each_ref_fn(const char *refname, const char *referent,
const struct object_id *oid, int flags, void *cb_data);
/*
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 210adf644fa..94d1ed0e1c7 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3044,7 +3044,7 @@ static int files_transaction_abort(struct ref_store *ref_store,
return 0;
}
-static int ref_present(const char *refname,
+static int ref_present(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED,
void *cb_data)
diff --git a/refs/iterator.c b/refs/iterator.c
index 75fbe5d72ab..8e999d81fc6 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -450,7 +450,7 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
current_ref_iter = iter;
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
- retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
+ retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
if (retval) {
/*
* If ref_iterator_abort() returns ITER_ERROR,
diff --git a/remote.c b/remote.c
index f43cf5e7a4d..4a1269a47ab 100644
--- a/remote.c
+++ b/remote.c
@@ -2354,7 +2354,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
return 1;
}
-static int one_local_ref(const char *refname, const struct object_id *oid,
+static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
@@ -2439,7 +2439,7 @@ struct stale_heads_info {
struct refspec *rs;
};
-static int get_stale_heads_cb(const char *refname, const struct object_id *oid,
+static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data)
{
struct stale_heads_info *info = cb_data;
diff --git a/replace-object.c b/replace-object.c
index 59252d565ef..9a3cdd809a9 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -9,6 +9,7 @@
#include "commit.h"
static int register_replace_ref(const char *refname,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data)
diff --git a/revision.c b/revision.c
index 1c0192f5225..6b33bd814f7 100644
--- a/revision.c
+++ b/revision.c
@@ -1648,7 +1648,7 @@ struct all_refs_cb {
struct worktree *wt;
};
-static int handle_one_ref(const char *path, const struct object_id *oid,
+static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/server-info.c b/server-info.c
index f61296a60d0..1508fa6f825 100644
--- a/server-info.c
+++ b/server-info.c
@@ -147,7 +147,7 @@ out:
return ret;
}
-static int add_info_ref(const char *path, const struct object_id *oid,
+static int add_info_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED,
void *cb_data)
{
diff --git a/shallow.c b/shallow.c
index 31a6ca40fe2..b8cd051e3b6 100644
--- a/shallow.c
+++ b/shallow.c
@@ -612,6 +612,7 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
}
static int mark_uninteresting(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data UNUSED)
@@ -727,6 +728,7 @@ struct commit_array {
};
static int add_ref(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
diff --git a/submodule.c b/submodule.c
index ab99a302530..7c0f5db861d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -953,6 +953,7 @@ static void free_submodules_data(struct string_list *submodules)
}
static int has_remote(const char *refname UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flags UNUSED, void *cb_data UNUSED)
{
@@ -1273,6 +1274,7 @@ int push_unpushed_submodules(struct repository *r,
}
static int append_oid_to_array(const char *ref UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flags UNUSED, void *data)
{
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 637b8b294e9..65346dee551 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -156,7 +156,7 @@ static int cmd_rename_ref(struct ref_store *refs, const char **argv)
return refs_rename_ref(refs, oldref, newref, logmsg);
}
-static int each_ref(const char *refname, const struct object_id *oid,
+static int each_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flags, void *cb_data UNUSED)
{
printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
diff --git a/upload-pack.c b/upload-pack.c
index 0052c6a4dce..f03ba3e98be 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -857,7 +857,7 @@ static void send_unshallow(struct upload_pack_data *data)
}
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED, const struct object_id *oid,
int flag, void *cb_data);
static void deepen(struct upload_pack_data *data, int depth)
{
@@ -1208,7 +1208,7 @@ static int mark_our_ref(const char *refname, const char *refname_full,
return 0;
}
-static int check_ref(const char *refname_full, const struct object_id *oid,
+static int check_ref(const char *refname_full, const char *referent UNUSED,const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
const char *refname = strip_namespace(refname_full);
@@ -1276,14 +1276,14 @@ static void write_v0_ref(struct upload_pack_data *data,
return;
}
-static int send_ref(const char *refname, const struct object_id *oid,
+static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
int flag UNUSED, void *cb_data)
{
write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
return 0;
}
-static int find_symref(const char *refname,
+static int find_symref(const char *refname, const char *referent UNUSED,
const struct object_id *oid UNUSED,
int flag, void *cb_data)
{
diff --git a/walker.c b/walker.c
index 0fafdc97cf1..807a7a38813 100644
--- a/walker.c
+++ b/walker.c
@@ -221,6 +221,7 @@ static int interpret_target(struct walker *walker, char *target, struct object_i
}
static int mark_complete(const char *path UNUSED,
+ const char *referent UNUSED,
const struct object_id *oid,
int flag UNUSED,
void *cb_data UNUSED)
diff --git a/worktree.c b/worktree.c
index f3c4c8ec54d..fd05f3741c6 100644
--- a/worktree.c
+++ b/worktree.c
@@ -546,7 +546,7 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
refname.buf,
RESOLVE_REF_READING,
&oid, &flag))
- ret = fn(refname.buf, &oid, flag, cb_data);
+ ret = fn(refname.buf, NULL, &oid, flag, cb_data);
if (ret)
break;
}
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH v4 3/3] ref-filter: populate symref from iterator
2024-08-09 15:37 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
2024-08-09 15:37 ` [PATCH v4 1/3] refs: keep track of unresolved reference value in iterators John Cai via GitGitGadget
2024-08-09 15:37 ` [PATCH v4 2/3] refs: add referent to each_ref_fn John Cai via GitGitGadget
@ 2024-08-09 15:37 ` John Cai via GitGitGadget
2024-08-09 16:51 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators Junio C Hamano
3 siblings, 0 replies; 44+ messages in thread
From: John Cai via GitGitGadget @ 2024-08-09 15:37 UTC (permalink / raw)
To: git
Cc: Phillip Wood, Kristoffer Haugsbakk, Jeff King, Patrick Steinhardt,
Jean-Noël Avila, Linus Arver, John Cai, John Cai
From: John Cai <johncai86@gmail.com>
With a previous commit, the reference the symbolic ref points to is saved
in the ref iterator records. Instead of making a separate call to
resolve_refdup() each time, we can just populate the ref_array_item with
the value from the iterator.
Signed-off-by: John Cai <johncai86@gmail.com>
---
ref-filter.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/ref-filter.c b/ref-filter.c
index 39997890feb..4d1f3ff3d23 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2343,6 +2343,12 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
CALLOC_ARRAY(ref->value, used_atom_cnt);
+ /**
+ * NEEDSWORK: The following code might be unncessary if all codepaths
+ * that call populate_value() populates the symref member of ref_array_item
+ * like in apply_ref_filter(). Currently pretty_print_ref() is the only codepath
+ * that calls populate_value() without first populating symref.
+ */
if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository),
ref->refname,
@@ -2783,7 +2789,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
return ref_kind_from_refname(refname);
}
-static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
+static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
int flag, struct ref_filter *filter)
{
struct ref_array_item *ref;
@@ -2852,6 +2858,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
ref->commit = commit;
ref->flag = flag;
ref->kind = kind;
+ ref->symref = xstrdup_or_null(referent);
return ref;
}
@@ -2865,12 +2872,12 @@ struct ref_filter_cbdata {
* A call-back given to for_each_ref(). Filter refs and keep them for
* later object processing.
*/
-static int filter_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (ref)
ref_array_append(ref_cbdata->array, ref);
@@ -2900,13 +2907,13 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
struct ref_array_item *ref;
struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
- ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
+ ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
if (!ref)
return 0;
--
gitgitgadget
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators
2024-08-09 15:37 ` [PATCH v4 0/3] keep track of unresolved value of symbolic-ref in ref iterators John Cai via GitGitGadget
` (2 preceding siblings ...)
2024-08-09 15:37 ` [PATCH v4 3/3] ref-filter: populate symref from iterator John Cai via GitGitGadget
@ 2024-08-09 16:51 ` Junio C Hamano
3 siblings, 0 replies; 44+ messages in thread
From: Junio C Hamano @ 2024-08-09 16:51 UTC (permalink / raw)
To: John Cai via GitGitGadget
Cc: git, Phillip Wood, Kristoffer Haugsbakk, Jeff King,
Patrick Steinhardt, Jean-Noël Avila, Linus Arver, John Cai
"John Cai via GitGitGadget" <gitgitgadget@gmail.com> writes:
> John Cai (3):
> refs: keep track of unresolved reference value in iterators
> refs: add referent to each_ref_fn
> ref-filter: populate symref from iterator
Looks good. Let me mark the topic for 'next'.
^ permalink raw reply [flat|nested] 44+ messages in thread