aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-11-08 10:05:34 -0800
committerJunio C Hamano <gitster@pobox.com>2025-11-08 10:05:34 -0800
commit3960ee5e031156c18e89404089d82292f565e6ea (patch)
tree352eda33e25883d7cf2894de379a8324c59bf14a
parentMerge branch 'tc/last-modified-active-paths-optimization' into jch (diff)
parentt7004: do not chdir around in the main process (diff)
downloadgit-3960ee5e031156c18e89404089d82292f565e6ea.tar.gz
git-3960ee5e031156c18e89404089d82292f565e6ea.zip
Merge branch 'ps/ref-peeled-tags' into jch
Some ref backend storage can hold not just the object name of an annotated tag, but the object name of the object the tag points at. The code to handle this information has been streamlined. * ps/ref-peeled-tags: t7004: do not chdir around in the main process ref-filter: fix stale parsed objects ref-filter: parse objects on demand ref-filter: detect broken tags when dereferencing them refs: don't store peeled object IDs for invalid tags object: add flag to `peel_object()` to verify object type refs: drop infrastructure to peel via iterators refs: drop `current_ref_iter` hack builtin/show-ref: convert to use `reference_get_peeled_oid()` ref-filter: propagate peeled object ID upload-pack: convert to use `reference_get_peeled_oid()` refs: expose peeled object ID via the iterator refs: refactor reference status flags refs: fully reset `struct ref_iterator::ref` on iteration refs: introduce `.ref` field for the base iterator refs: introduce wrapper struct for `each_ref_fn`
-rw-r--r--bisect.c24
-rw-r--r--builtin/bisect.c17
-rw-r--r--builtin/checkout.c6
-rw-r--r--builtin/describe.c18
-rw-r--r--builtin/fetch.c13
-rw-r--r--builtin/fsck.c33
-rw-r--r--builtin/gc.c15
-rw-r--r--builtin/ls-remote.c2
-rw-r--r--builtin/name-rev.c17
-rw-r--r--builtin/pack-objects.c28
-rw-r--r--builtin/receive-pack.c13
-rw-r--r--builtin/remote.c44
-rw-r--r--builtin/replace.c21
-rw-r--r--builtin/repo.c9
-rw-r--r--builtin/rev-parse.c12
-rw-r--r--builtin/show-branch.c35
-rw-r--r--builtin/show-ref.c50
-rw-r--r--builtin/submodule--helper.c10
-rw-r--r--builtin/tag.c2
-rw-r--r--builtin/verify-tag.c2
-rw-r--r--builtin/worktree.c6
-rw-r--r--commit-graph.c14
-rw-r--r--delta-islands.c9
-rw-r--r--fetch-pack.c16
-rw-r--r--help.c10
-rw-r--r--http-backend.c20
-rw-r--r--log-tree.c24
-rw-r--r--ls-refs.c36
-rw-r--r--midx-write.c17
-rw-r--r--negotiator/default.c7
-rw-r--r--negotiator/skipping.c7
-rw-r--r--notes.c8
-rw-r--r--object-name.c10
-rw-r--r--object.c20
-rw-r--r--object.h15
-rw-r--r--pseudo-merge.c21
-rw-r--r--reachable.c9
-rw-r--r--ref-filter.c227
-rw-r--r--ref-filter.h5
-rw-r--r--reflog.c9
-rw-r--r--refs.c85
-rw-r--r--refs.h88
-rw-r--r--refs/debug.c17
-rw-r--r--refs/files-backend.c71
-rw-r--r--refs/iterator.c73
-rw-r--r--refs/packed-backend.c71
-rw-r--r--refs/ref-cache.c18
-rw-r--r--refs/refs-internal.h25
-rw-r--r--refs/reftable-backend.c47
-rw-r--r--remote.c27
-rw-r--r--repack-midx.c16
-rw-r--r--replace-object.c16
-rw-r--r--revision.c12
-rw-r--r--server-info.c12
-rw-r--r--shallow.c16
-rw-r--r--submodule.c12
-rw-r--r--t/for-each-ref-tests.sh4
-rw-r--r--t/helper/test-reach.c2
-rw-r--r--t/helper/test-ref-store.c5
-rw-r--r--t/pack-refs-tests.sh32
-rwxr-xr-xt/t0610-reftable-basics.sh28
-rwxr-xr-xt/t7004-tag.sh58
-rw-r--r--tag.c12
-rw-r--r--tag.h1
-rw-r--r--upload-pack.c49
-rw-r--r--walker.c8
-rw-r--r--worktree.c11
67 files changed, 825 insertions, 852 deletions
diff --git a/bisect.c b/bisect.c
index a6dc76b15c..326b59c0dc 100644
--- a/bisect.c
+++ b/bisect.c
@@ -450,21 +450,20 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
clear_commit_weight(&commit_weight);
}
-static int register_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flags UNUSED, void *cb_data UNUSED)
+static int register_ref(const struct reference *ref, void *cb_data UNUSED)
{
struct strbuf good_prefix = STRBUF_INIT;
strbuf_addstr(&good_prefix, term_good);
strbuf_addstr(&good_prefix, "-");
- if (!strcmp(refname, term_bad)) {
+ if (!strcmp(ref->name, term_bad)) {
free(current_bad_oid);
current_bad_oid = xmalloc(sizeof(*current_bad_oid));
- oidcpy(current_bad_oid, oid);
- } else if (starts_with(refname, good_prefix.buf)) {
- oid_array_append(&good_revs, oid);
- } else if (starts_with(refname, "skip-")) {
- oid_array_append(&skipped_revs, oid);
+ oidcpy(current_bad_oid, ref->oid);
+ } else if (starts_with(ref->name, good_prefix.buf)) {
+ oid_array_append(&good_revs, ref->oid);
+ } else if (starts_with(ref->name, "skip-")) {
+ oid_array_append(&skipped_revs, ref->oid);
}
strbuf_release(&good_prefix);
@@ -1178,14 +1177,11 @@ int estimate_bisect_steps(int all)
return (e < 3 * x) ? n : n - 1;
}
-static int mark_for_removal(const char *refname,
- const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flag UNUSED, void *cb_data)
+static int mark_for_removal(const struct reference *ref, void *cb_data)
{
struct string_list *refs = cb_data;
- char *ref = xstrfmt("refs/bisect%s", refname);
- string_list_append(refs, ref);
+ char *bisect_ref = xstrfmt("refs/bisect%s", ref->name);
+ string_list_append(refs, bisect_ref);
return 0;
}
diff --git a/builtin/bisect.c b/builtin/bisect.c
index ccff4e1a1b..4cc118fb57 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -363,10 +363,7 @@ static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
return 0;
}
-static int inc_nr(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flag UNUSED, void *cb_data)
+static int inc_nr(const struct reference *ref UNUSED, void *cb_data)
{
unsigned int *nr = (unsigned int *)cb_data;
(*nr)++;
@@ -554,12 +551,11 @@ finish:
return res;
}
-static int add_bisect_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flags UNUSED, void *cb)
+static int add_bisect_ref(const struct reference *ref, void *cb)
{
struct add_bisect_ref_data *data = cb;
- add_pending_oid(data->revs, refname, oid, data->object_flags);
+ add_pending_oid(data->revs, ref->name, ref->oid, data->object_flags);
return 0;
}
@@ -1170,12 +1166,9 @@ static int bisect_visualize(struct bisect_terms *terms, int argc,
return run_command(&cmd);
}
-static int get_first_good(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flag UNUSED, void *cb_data)
+static int get_first_good(const struct reference *ref, void *cb_data)
{
- oidcpy(cb_data, oid);
+ oidcpy(cb_data, ref->oid);
return 1;
}
diff --git a/builtin/checkout.c b/builtin/checkout.c
index f9453473fe..66b69df6e6 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1063,11 +1063,9 @@ 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, const char *referent UNUSED,
- const struct object_id *oid,
- int flags UNUSED, void *cb_data)
+static int add_pending_uninteresting_ref(const struct reference *ref, void *cb_data)
{
- add_pending_oid(cb_data, refname, oid, UNINTERESTING);
+ add_pending_oid(cb_data, ref->name, ref->oid, UNINTERESTING);
return 0;
}
diff --git a/builtin/describe.c b/builtin/describe.c
index ffaf8d9f0a..443546aaac 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -154,20 +154,19 @@ static void add_to_known_names(const char *path,
}
}
-static int get_name(const char *path, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data UNUSED)
+static int get_name(const struct reference *ref, void *cb_data UNUSED)
{
int is_tag = 0;
struct object_id peeled;
int is_annotated, prio;
const char *path_to_match = NULL;
- if (skip_prefix(path, "refs/tags/", &path_to_match)) {
+ if (skip_prefix(ref->name, "refs/tags/", &path_to_match)) {
is_tag = 1;
} else if (all) {
if ((exclude_patterns.nr || patterns.nr) &&
- !skip_prefix(path, "refs/heads/", &path_to_match) &&
- !skip_prefix(path, "refs/remotes/", &path_to_match)) {
+ !skip_prefix(ref->name, "refs/heads/", &path_to_match) &&
+ !skip_prefix(ref->name, "refs/remotes/", &path_to_match)) {
/* Only accept reference of known type if there are match/exclude patterns */
return 0;
}
@@ -209,10 +208,10 @@ static int get_name(const char *path, const char *referent UNUSED, const struct
}
/* Is it annotated? */
- if (!peel_iterated_oid(the_repository, oid, &peeled)) {
- is_annotated = !oideq(oid, &peeled);
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled)) {
+ is_annotated = !oideq(ref->oid, &peeled);
} else {
- oidcpy(&peeled, oid);
+ oidcpy(&peeled, ref->oid);
is_annotated = 0;
}
@@ -229,7 +228,8 @@ static int get_name(const char *path, const char *referent UNUSED, const struct
else
prio = 0;
- add_to_known_names(all ? path + 5 : path + 10, &peeled, prio, oid);
+ add_to_known_names(all ? ref->name + 5 : ref->name + 10,
+ &peeled, prio, ref->oid);
return 0;
}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index c7ff3480fb..7052e6ff21 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -289,13 +289,11 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
return ent;
}
-static int add_one_refname(const char *refname, const char *referent UNUSED,
- const struct object_id *oid,
- int flag UNUSED, void *cbdata)
+static int add_one_refname(const struct reference *ref, void *cbdata)
{
struct hashmap *refname_map = cbdata;
- (void) refname_hash_add(refname_map, refname, oid);
+ (void) refname_hash_add(refname_map, ref->name, ref->oid);
return 0;
}
@@ -1416,14 +1414,11 @@ 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)
+static int add_oid(const struct reference *ref, void *cb_data)
{
struct oid_array *oids = cb_data;
- oid_array_append(oids, oid);
+ oid_array_append(oids, ref->oid);
return 0;
}
diff --git a/builtin/fsck.c b/builtin/fsck.c
index b1a650c673..c489582faa 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -530,14 +530,13 @@ static int fsck_handle_reflog(const char *logname, void *cb_data)
return 0;
}
-static int fsck_handle_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data UNUSED)
+static int fsck_handle_ref(const struct reference *ref, void *cb_data UNUSED)
{
struct object *obj;
- obj = parse_object(the_repository, oid);
+ obj = parse_object(the_repository, ref->oid);
if (!obj) {
- if (is_promisor_object(the_repository, oid)) {
+ if (is_promisor_object(the_repository, ref->oid)) {
/*
* Increment default_refs anyway, because this is a
* valid ref.
@@ -546,19 +545,19 @@ static int fsck_handle_ref(const char *refname, const char *referent UNUSED, con
return 0;
}
error(_("%s: invalid sha1 pointer %s"),
- refname, oid_to_hex(oid));
+ ref->name, oid_to_hex(ref->oid));
errors_found |= ERROR_REACHABLE;
/* We'll continue with the rest despite the error.. */
return 0;
}
- if (obj->type != OBJ_COMMIT && is_branch(refname)) {
- error(_("%s: not a commit"), refname);
+ if (obj->type != OBJ_COMMIT && is_branch(ref->name)) {
+ error(_("%s: not a commit"), ref->name);
errors_found |= ERROR_REFS;
}
default_refs++;
obj->flags |= USED;
fsck_put_object_name(&fsck_walk_options,
- oid, "%s", refname);
+ ref->oid, "%s", ref->name);
mark_object_reachable(obj);
return 0;
@@ -580,13 +579,19 @@ static void get_default_heads(void)
worktrees = get_worktrees();
for (p = worktrees; *p; p++) {
struct worktree *wt = *p;
- struct strbuf ref = STRBUF_INIT;
+ struct strbuf refname = STRBUF_INIT;
- 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, NULL, &head_oid, 0, NULL);
- strbuf_release(&ref);
+ strbuf_worktree_ref(wt, &refname, "HEAD");
+ fsck_head_link(refname.buf, &head_points_at, &head_oid);
+ if (head_points_at && !is_null_oid(&head_oid)) {
+ struct reference ref = {
+ .name = refname.buf,
+ .oid = &head_oid,
+ };
+
+ fsck_handle_ref(&ref, NULL);
+ }
+ strbuf_release(&refname);
if (include_reflogs)
refs_for_each_reflog(get_worktree_ref_store(wt),
diff --git a/builtin/gc.c b/builtin/gc.c
index d212cbb9b8..aad1496f07 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1103,24 +1103,21 @@ struct cg_auto_data {
int limit;
};
-static int dfs_on_ref(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flags UNUSED,
- void *cb_data)
+static int dfs_on_ref(const struct reference *ref, void *cb_data)
{
struct cg_auto_data *data = (struct cg_auto_data *)cb_data;
int result = 0;
+ const struct object_id *maybe_peeled = ref->oid;
struct object_id peeled;
struct commit_list *stack = NULL;
struct commit *commit;
- if (!peel_iterated_oid(the_repository, oid, &peeled))
- oid = &peeled;
- if (odb_read_object_info(the_repository->objects, oid, NULL) != OBJ_COMMIT)
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled))
+ maybe_peeled = &peeled;
+ if (odb_read_object_info(the_repository->objects, maybe_peeled, NULL) != OBJ_COMMIT)
return 0;
- commit = lookup_commit(the_repository, oid);
+ commit = lookup_commit(the_repository, maybe_peeled);
if (!commit)
return 0;
if (repo_parse_commit(the_repository, commit) ||
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index df09000b30..fe77829557 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -156,7 +156,7 @@ int cmd_ls_remote(int argc,
continue;
if (!tail_match(&pattern, ref->name))
continue;
- item = ref_array_push(&ref_array, ref->name, &ref->old_oid);
+ item = ref_array_push(&ref_array, ref->name, &ref->old_oid, NULL);
item->symref = xstrdup_or_null(ref->symref);
}
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 74512e54a3..615f7d1aae 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -339,10 +339,9 @@ 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 char *referent UNUSED, const struct object_id *oid,
- int flags UNUSED, void *cb_data)
+static int name_ref(const struct reference *ref, void *cb_data)
{
- struct object *o = parse_object(the_repository, oid);
+ struct object *o = parse_object(the_repository, ref->oid);
struct name_ref_data *data = cb_data;
int can_abbreviate_output = data->tags_only && data->name_only;
int deref = 0;
@@ -350,14 +349,14 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct
struct commit *commit = NULL;
timestamp_t taggerdate = TIME_MAX;
- if (data->tags_only && !starts_with(path, "refs/tags/"))
+ if (data->tags_only && !starts_with(ref->name, "refs/tags/"))
return 0;
if (data->exclude_filters.nr) {
struct string_list_item *item;
for_each_string_list_item(item, &data->exclude_filters) {
- if (subpath_matches(path, item->string) >= 0)
+ if (subpath_matches(ref->name, item->string) >= 0)
return 0;
}
}
@@ -378,7 +377,7 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct
* shouldn't stop when seeing 'refs/tags/v1.4' matches
* 'refs/tags/v*'. We should show it as 'v1.4'.
*/
- switch (subpath_matches(path, item->string)) {
+ switch (subpath_matches(ref->name, item->string)) {
case -1: /* did not match */
break;
case 0: /* matched fully */
@@ -406,13 +405,13 @@ static int name_ref(const char *path, const char *referent UNUSED, const struct
}
if (o && o->type == OBJ_COMMIT) {
commit = (struct commit *)o;
- from_tag = starts_with(path, "refs/tags/");
+ from_tag = starts_with(ref->name, "refs/tags/");
if (taggerdate == TIME_MAX)
taggerdate = commit->date;
}
- add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate,
- from_tag, deref);
+ add_to_tip_table(ref->oid, ref->name, can_abbreviate_output,
+ commit, taggerdate, from_tag, deref);
return 0;
}
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 0e4e9f8068..4486b55e6d 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -831,15 +831,14 @@ static enum write_one_status write_one(struct hashfile *f,
return WRITE_ONE_WRITTEN;
}
-static int mark_tagged(const char *path UNUSED, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data UNUSED)
+static int mark_tagged(const struct reference *ref, void *cb_data UNUSED)
{
struct object_id peeled;
- struct object_entry *entry = packlist_find(&to_pack, oid);
+ struct object_entry *entry = packlist_find(&to_pack, ref->oid);
if (entry)
entry->tagged = 1;
- if (!peel_iterated_oid(the_repository, oid, &peeled)) {
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled)) {
entry = packlist_find(&to_pack, &peeled);
if (entry)
entry->tagged = 1;
@@ -3305,13 +3304,13 @@ static void add_tag_chain(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)
+static int add_ref_tag(const struct reference *ref, void *cb_data UNUSED)
{
struct object_id peeled;
- if (!peel_iterated_oid(the_repository, oid, &peeled) && obj_is_packed(&peeled))
- add_tag_chain(oid);
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled) &&
+ obj_is_packed(&peeled))
+ add_tag_chain(ref->oid);
return 0;
}
@@ -4527,19 +4526,16 @@ static void record_recent_commit(struct commit *commit, void *data UNUSED)
oid_array_append(&recent_objects, &commit->object.oid);
}
-static int mark_bitmap_preferred_tip(const char *refname,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flags UNUSED,
- void *data UNUSED)
+static int mark_bitmap_preferred_tip(const struct reference *ref, void *data UNUSED)
{
+ const struct object_id *maybe_peeled = ref->oid;
struct object_id peeled;
struct object *object;
- if (!peel_iterated_oid(the_repository, oid, &peeled))
- oid = &peeled;
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled))
+ maybe_peeled = &peeled;
- object = parse_object_or_die(the_repository, oid, refname);
+ object = parse_object_or_die(the_repository, maybe_peeled, ref->name);
if (object->type == OBJ_COMMIT)
object->flags |= NEEDS_BITMAP;
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c9288a9c7e..e8ee0e7321 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -305,13 +305,12 @@ static void show_ref(const char *path, 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)
+static int show_ref_cb(const struct reference *ref, void *data)
{
struct oidset *seen = data;
- const char *path = strip_namespace(path_full);
+ const char *path = strip_namespace(ref->name);
- if (ref_is_hidden(path, path_full, &hidden_refs))
+ if (ref_is_hidden(path, ref->name, &hidden_refs))
return 0;
/*
@@ -320,13 +319,13 @@ static int show_ref_cb(const char *path_full, const char *referent UNUSED, const
* transfer but will otherwise ignore them.
*/
if (!path) {
- if (oidset_insert(seen, oid))
+ if (oidset_insert(seen, ref->oid))
return 0;
path = ".have";
} else {
- oidset_insert(seen, oid);
+ oidset_insert(seen, ref->oid);
}
- show_ref(path, oid);
+ show_ref(path, ref->oid);
return 0;
}
diff --git a/builtin/remote.c b/builtin/remote.c
index 8a7ed4299a..7ffc14ba15 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -570,17 +570,14 @@ struct branches_for_remote {
struct known_remotes *keep;
};
-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)
+static int add_branch_for_removal(const struct reference *ref, void *cb_data)
{
struct branches_for_remote *branches = cb_data;
struct refspec_item refspec;
struct known_remote *kr;
memset(&refspec, 0, sizeof(refspec));
- refspec.dst = (char *)refname;
+ refspec.dst = (char *)ref->name;
if (remote_find_tracking(branches->remote, &refspec))
return 0;
free(refspec.src);
@@ -588,7 +585,7 @@ static int add_branch_for_removal(const char *refname,
/* don't delete a branch if another remote also uses it */
for (kr = branches->keep->list; kr; kr = kr->next) {
memset(&refspec, 0, sizeof(refspec));
- refspec.dst = (char *)refname;
+ refspec.dst = (char *)ref->name;
if (!remote_find_tracking(kr->remote, &refspec)) {
free(refspec.src);
return 0;
@@ -596,16 +593,16 @@ static int add_branch_for_removal(const char *refname,
}
/* don't delete non-remote-tracking refs */
- if (!starts_with(refname, "refs/remotes/")) {
+ if (!starts_with(ref->name, "refs/remotes/")) {
/* advise user how to delete local branches */
- if (starts_with(refname, "refs/heads/"))
+ if (starts_with(ref->name, "refs/heads/"))
string_list_append(branches->skipped,
- abbrev_branch(refname));
+ abbrev_branch(ref->name));
/* silently skip over other non-remote refs */
return 0;
}
- string_list_append(branches->branches, refname);
+ string_list_append(branches->branches, ref->name);
return 0;
}
@@ -713,18 +710,18 @@ out:
return error;
}
-static int rename_one_ref(const char *old_refname, const char *referent,
- const struct object_id *oid,
- int flags, void *cb_data)
+static int rename_one_ref(const struct reference *ref, void *cb_data)
{
struct strbuf new_referent = STRBUF_INIT;
struct strbuf new_refname = STRBUF_INIT;
struct rename_info *rename = cb_data;
+ const struct object_id *oid = ref->oid;
+ const char *referent = ref->target;
int error;
- compute_renamed_ref(rename, old_refname, &new_refname);
+ compute_renamed_ref(rename, ref->name, &new_refname);
- if (flags & REF_ISSYMREF) {
+ if (ref->flags & REF_ISSYMREF) {
/*
* Stupidly enough `referent` is not pointing to the immediate
* target of a symref, but it's the recursively resolved value.
@@ -732,25 +729,25 @@ static int rename_one_ref(const char *old_refname, const char *referent,
* unborn symrefs don't have any value for the `referent` at all.
*/
referent = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- old_refname, RESOLVE_REF_NO_RECURSE,
+ ref->name, RESOLVE_REF_NO_RECURSE,
NULL, NULL);
compute_renamed_ref(rename, referent, &new_referent);
oid = NULL;
}
- error = ref_transaction_delete(rename->transaction, old_refname,
+ error = ref_transaction_delete(rename->transaction, ref->name,
oid, referent, REF_NO_DEREF, NULL, rename->err);
if (error < 0)
goto out;
error = ref_transaction_update(rename->transaction, new_refname.buf, oid, null_oid(the_hash_algo),
- (flags & REF_ISSYMREF) ? new_referent.buf : NULL, NULL,
+ (ref->flags & REF_ISSYMREF) ? new_referent.buf : NULL, NULL,
REF_SKIP_CREATE_REFLOG | REF_NO_DEREF | REF_SKIP_OID_VERIFICATION,
NULL, rename->err);
if (error < 0)
goto out;
- error = rename_one_reflog(old_refname, oid, rename);
+ error = rename_one_reflog(ref->name, oid, rename);
if (error < 0)
goto out;
@@ -1125,19 +1122,16 @@ static void free_remote_ref_states(struct ref_states *states)
string_list_clear_func(&states->push, clear_push_info);
}
-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)
+static int append_ref_to_tracked_list(const struct reference *ref, void *cb_data)
{
struct ref_states *states = cb_data;
struct refspec_item refspec;
- if (flags & REF_ISSYMREF)
+ if (ref->flags & REF_ISSYMREF)
return 0;
memset(&refspec, 0, sizeof(refspec));
- refspec.dst = (char *)refname;
+ refspec.dst = (char *)ref->name;
if (!remote_find_tracking(states->remote, &refspec)) {
string_list_append(&states->tracked, abbrev_branch(refspec.src));
free(refspec.src);
diff --git a/builtin/replace.c b/builtin/replace.c
index 900b560a77..4c62c5ab58 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -47,30 +47,27 @@ struct show_data {
enum replace_format format;
};
-static int show_reference(const char *refname,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flag UNUSED, void *cb_data)
+static int show_reference(const struct reference *ref, void *cb_data)
{
struct show_data *data = cb_data;
- if (!wildmatch(data->pattern, refname, 0)) {
+ if (!wildmatch(data->pattern, ref->name, 0)) {
if (data->format == REPLACE_FORMAT_SHORT)
- printf("%s\n", refname);
+ printf("%s\n", ref->name);
else if (data->format == REPLACE_FORMAT_MEDIUM)
- printf("%s -> %s\n", refname, oid_to_hex(oid));
+ printf("%s -> %s\n", ref->name, oid_to_hex(ref->oid));
else { /* data->format == REPLACE_FORMAT_LONG */
struct object_id object;
enum object_type obj_type, repl_type;
- if (repo_get_oid(data->repo, refname, &object))
- return error(_("failed to resolve '%s' as a valid ref"), refname);
+ if (repo_get_oid(data->repo, ref->name, &object))
+ return error(_("failed to resolve '%s' as a valid ref"), ref->name);
obj_type = odb_read_object_info(data->repo->objects, &object, NULL);
- repl_type = odb_read_object_info(data->repo->objects, oid, NULL);
+ repl_type = odb_read_object_info(data->repo->objects, ref->oid, NULL);
- printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type),
- oid_to_hex(oid), type_name(repl_type));
+ printf("%s (%s) -> %s (%s)\n", ref->name, type_name(obj_type),
+ oid_to_hex(ref->oid), type_name(repl_type));
}
}
diff --git a/builtin/repo.c b/builtin/repo.c
index 9d4749f79b..f26640bd6e 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -366,16 +366,13 @@ struct count_references_data {
struct progress *progress;
};
-static int count_references(const char *refname,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flags UNUSED, void *cb_data)
+static int count_references(const struct reference *ref, void *cb_data)
{
struct count_references_data *data = cb_data;
struct ref_stats *stats = data->stats;
size_t ref_count;
- switch (ref_kind_from_refname(refname)) {
+ switch (ref_kind_from_refname(ref->name)) {
case FILTER_REFS_BRANCHES:
stats->branches++;
break;
@@ -396,7 +393,7 @@ static int count_references(const char *refname,
* While iterating through references for counting, also add OIDs in
* preparation for the path walk.
*/
- add_pending_oid(data->revs, NULL, oid, 0);
+ add_pending_oid(data->revs, NULL, ref->oid, 0);
ref_count = get_total_reference_count(stats);
display_progress(data->progress, ref_count);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 7b3711cf34..9032cc6327 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -217,19 +217,17 @@ static int show_default(void)
return 0;
}
-static int show_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data UNUSED)
+static int show_reference(const struct reference *ref, void *cb_data UNUSED)
{
- if (ref_excluded(&ref_excludes, refname))
+ if (ref_excluded(&ref_excludes, ref->name))
return 0;
- show_rev(NORMAL, oid, refname);
+ show_rev(NORMAL, ref->oid, ref->name);
return 0;
}
-static int anti_reference(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data UNUSED)
+static int anti_reference(const struct reference *ref, void *cb_data UNUSED)
{
- show_rev(REVERSED, oid, refname);
+ show_rev(REVERSED, ref->oid, ref->name);
return 0;
}
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 441babf2e3..10475a6b5e 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -413,34 +413,32 @@ static int append_ref(const char *refname, const struct object_id *oid,
return 0;
}
-static int append_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data UNUSED)
+static int append_head_ref(const struct reference *ref, void *cb_data UNUSED)
{
struct object_id tmp;
int ofs = 11;
- if (!starts_with(refname, "refs/heads/"))
+ if (!starts_with(ref->name, "refs/heads/"))
return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
*/
- if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid))
+ if (repo_get_oid(the_repository, ref->name + ofs, &tmp) || !oideq(&tmp, ref->oid))
ofs = 5;
- return append_ref(refname + ofs, oid, 0);
+ return append_ref(ref->name + ofs, ref->oid, 0);
}
-static int append_remote_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data UNUSED)
+static int append_remote_ref(const struct reference *ref, void *cb_data UNUSED)
{
struct object_id tmp;
int ofs = 13;
- if (!starts_with(refname, "refs/remotes/"))
+ if (!starts_with(ref->name, "refs/remotes/"))
return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
*/
- if (repo_get_oid(the_repository, refname + ofs, &tmp) || !oideq(&tmp, oid))
+ if (repo_get_oid(the_repository, ref->name + ofs, &tmp) || !oideq(&tmp, ref->oid))
ofs = 5;
- return append_ref(refname + ofs, oid, 0);
+ return append_ref(ref->name + ofs, ref->oid, 0);
}
static int append_tag_ref(const char *refname, const struct object_id *oid,
@@ -454,27 +452,26 @@ 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 char *referent UNUSED, const struct object_id *oid,
- int flag, void *cb_data)
+static int append_matching_ref(const struct reference *ref, void *cb_data)
{
/* we want to allow pattern hold/<asterisk> to show all
* branches under refs/heads/hold/, and v0.99.9? to show
* refs/tags/v0.99.9a and friends.
*/
const char *tail;
- int slash = count_slashes(refname);
- for (tail = refname; *tail && match_ref_slash < slash; )
+ int slash = count_slashes(ref->name);
+ for (tail = ref->name; *tail && match_ref_slash < slash; )
if (*tail++ == '/')
slash--;
if (!*tail)
return 0;
if (wildmatch(match_ref_pattern, tail, 0))
return 0;
- if (starts_with(refname, "refs/heads/"))
- 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);
+ if (starts_with(ref->name, "refs/heads/"))
+ return append_head_ref(ref, cb_data);
+ if (starts_with(ref->name, "refs/tags/"))
+ return append_tag_ref(ref->name, ref->oid, ref->flags, cb_data);
+ return append_ref(ref->name, ref->oid, 0);
}
static void snarf_refs(int head, int remotes)
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 0b6f9edf86..4d4984e4e0 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -31,31 +31,31 @@ struct show_one_options {
};
static void show_one(const struct show_one_options *opts,
- const char *refname, const struct object_id *oid)
+ const struct reference *ref)
{
const char *hex;
struct object_id peeled;
- if (!odb_has_object(the_repository->objects, oid,
+ if (!odb_has_object(the_repository->objects, ref->oid,
HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
- die("git show-ref: bad ref %s (%s)", refname,
- oid_to_hex(oid));
+ die("git show-ref: bad ref %s (%s)", ref->name,
+ oid_to_hex(ref->oid));
if (opts->quiet)
return;
- hex = repo_find_unique_abbrev(the_repository, oid, opts->abbrev);
+ hex = repo_find_unique_abbrev(the_repository, ref->oid, opts->abbrev);
if (opts->hash_only)
printf("%s\n", hex);
else
- printf("%s %s\n", hex, refname);
+ printf("%s %s\n", hex, ref->name);
if (!opts->deref_tags)
return;
- if (!peel_iterated_oid(the_repository, oid, &peeled)) {
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled)) {
hex = repo_find_unique_abbrev(the_repository, &peeled, opts->abbrev);
- printf("%s %s^{}\n", hex, refname);
+ printf("%s %s^{}\n", hex, ref->name);
}
}
@@ -66,26 +66,25 @@ struct show_ref_data {
int show_head;
};
-static int show_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cbdata)
+static int show_ref(const struct reference *ref, void *cbdata)
{
struct show_ref_data *data = cbdata;
- if (data->show_head && !strcmp(refname, "HEAD"))
+ if (data->show_head && !strcmp(ref->name, "HEAD"))
goto match;
if (data->patterns) {
- int reflen = strlen(refname);
+ int reflen = strlen(ref->name);
const char **p = data->patterns, *m;
while ((m = *p++) != NULL) {
int len = strlen(m);
if (len > reflen)
continue;
- if (memcmp(m, refname + reflen - len, len))
+ if (memcmp(m, ref->name + reflen - len, len))
continue;
if (len == reflen)
goto match;
- if (refname[reflen - len - 1] == '/')
+ if (ref->name[reflen - len - 1] == '/')
goto match;
}
return 0;
@@ -94,18 +93,15 @@ static int show_ref(const char *refname, const char *referent UNUSED, const stru
match:
data->found_match++;
- show_one(data->show_one_opts, refname, oid);
+ show_one(data->show_one_opts, ref);
return 0;
}
-static int add_existing(const char *refname,
- const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flag UNUSED, void *cbdata)
+static int add_existing(const struct reference *ref, void *cbdata)
{
struct string_list *list = (struct string_list *)cbdata;
- string_list_insert(list, refname);
+ string_list_insert(list, ref->name);
return 0;
}
@@ -179,12 +175,18 @@ static int cmd_show_ref__verify(const struct show_one_options *show_one_opts,
if ((starts_with(*refs, "refs/") || refname_is_safe(*refs)) &&
!refs_read_ref(get_main_ref_store(the_repository), *refs, &oid)) {
- show_one(show_one_opts, *refs, &oid);
- }
- else if (!show_one_opts->quiet)
+ struct reference ref = {
+ .name = *refs,
+ .oid = &oid,
+ };
+
+ show_one(show_one_opts, &ref);
+ } else if (!show_one_opts->quiet) {
die("'%s' - not a valid ref", *refs);
- else
+ } else {
return 1;
+ }
+
refs++;
}
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index fcd73abe53..35f6cf735e 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -593,16 +593,12 @@ static void print_status(unsigned int flags, char state, const char *path,
printf("\n");
}
-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)
+static int handle_submodule_head_ref(const struct reference *ref, void *cb_data)
{
struct object_id *output = cb_data;
- if (oid)
- oidcpy(output, oid);
+ if (ref->oid)
+ oidcpy(output, ref->oid);
return 0;
}
diff --git a/builtin/tag.c b/builtin/tag.c
index f0665af3ac..01eba90c5c 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -153,7 +153,7 @@ static int verify_tag(const char *name, const char *ref UNUSED,
return -1;
if (format->format)
- pretty_print_ref(name, oid, format);
+ pretty_print_ref(name, oid, NULL, format);
return 0;
}
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index cd6bc11095..558121eaa1 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -67,7 +67,7 @@ int cmd_verify_tag(int argc,
}
if (format.format)
- pretty_print_ref(name, &oid, &format);
+ pretty_print_ref(name, &oid, NULL, &format);
}
return had_error;
}
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 812774a5ca..b7f323b5e4 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -635,11 +635,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)
+static int first_valid_ref(const struct reference *ref UNUSED, void *cb_data UNUSED)
{
return 1;
}
diff --git a/commit-graph.c b/commit-graph.c
index 474454db73..80be2ff2c3 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1851,18 +1851,16 @@ struct refs_cb_data {
struct progress *progress;
};
-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)
+static int add_ref_to_set(const struct reference *ref, void *cb_data)
{
+ const struct object_id *maybe_peeled = ref->oid;
struct object_id peeled;
struct refs_cb_data *data = (struct refs_cb_data *)cb_data;
- if (!peel_iterated_oid(data->repo, oid, &peeled))
- oid = &peeled;
- if (odb_read_object_info(data->repo->objects, oid, NULL) == OBJ_COMMIT)
- oidset_insert(data->commits, oid);
+ if (!reference_get_peeled_oid(data->repo, ref, &peeled))
+ maybe_peeled = &peeled;
+ if (odb_read_object_info(data->repo->objects, maybe_peeled, NULL) == OBJ_COMMIT)
+ oidset_insert(data->commits, maybe_peeled);
display_progress(data->progress, oidset_size(data->commits));
diff --git a/delta-islands.c b/delta-islands.c
index 36c94799d6..7cfebc4162 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -390,8 +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 char *referent UNUSED, const struct object_id *oid,
- int flags UNUSED, void *cb)
+static int find_island_for_ref(const struct reference *ref, void *cb)
{
struct island_load_data *ild = cb;
@@ -406,7 +405,7 @@ static int find_island_for_ref(const char *refname, const char *referent UNUSED,
/* walk backwards to get last-one-wins ordering */
for (i = ild->nr - 1; i >= 0; i--) {
- if (!regexec(&ild->rx[i], refname,
+ if (!regexec(&ild->rx[i], ref->name,
ARRAY_SIZE(matches), matches, 0))
break;
}
@@ -428,10 +427,10 @@ static int find_island_for_ref(const char *refname, const char *referent UNUSED,
if (island_name.len)
strbuf_addch(&island_name, '-');
- strbuf_add(&island_name, refname + match->rm_so, match->rm_eo - match->rm_so);
+ strbuf_add(&island_name, ref->name + match->rm_so, match->rm_eo - match->rm_so);
}
- add_ref_to_island(ild->remote_islands, island_name.buf, oid);
+ add_ref_to_island(ild->remote_islands, island_name.buf, ref->oid);
strbuf_release(&island_name);
return 0;
}
diff --git a/fetch-pack.c b/fetch-pack.c
index fe7a84bf2f..78c45d4a15 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -188,13 +188,9 @@ static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
return 0;
}
-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)
+static int rev_list_insert_ref_oid(const struct reference *ref, void *cb_data)
{
- return rev_list_insert_ref(cb_data, oid);
+ return rev_list_insert_ref(cb_data, ref->oid);
}
enum ack_type {
@@ -616,13 +612,9 @@ static int mark_complete(const struct object_id *oid)
return 0;
}
-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)
+static int mark_complete_oid(const struct reference *ref, void *cb_data UNUSED)
{
- return mark_complete(oid);
+ return mark_complete(ref->oid);
}
static void mark_recent_complete_commits(struct fetch_pack_args *args,
diff --git a/help.c b/help.c
index 5854dd4a7e..20e114432d 100644
--- a/help.c
+++ b/help.c
@@ -851,18 +851,16 @@ struct similar_ref_cb {
struct string_list *similar_refs;
};
-static int append_similar_ref(const char *refname, const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flags UNUSED, void *cb_data)
+static int append_similar_ref(const struct reference *ref, void *cb_data)
{
struct similar_ref_cb *cb = (struct similar_ref_cb *)(cb_data);
- char *branch = strrchr(refname, '/') + 1;
+ char *branch = strrchr(ref->name, '/') + 1;
/* A remote branch of the same name is deemed similar */
- if (starts_with(refname, "refs/remotes/") &&
+ if (starts_with(ref->name, "refs/remotes/") &&
!strcmp(branch, cb->base_ref))
string_list_append_nodup(cb->similar_refs,
- refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), refname, 1));
+ refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), ref->name, 1));
return 0;
}
diff --git a/http-backend.c b/http-backend.c
index 52f0483dd3..273ed7266f 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -513,18 +513,17 @@ static void run_service(const char **argv, int buffer_input)
exit(1);
}
-static int show_text_ref(const char *name, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data)
+static int show_text_ref(const struct reference *ref, void *cb_data)
{
- const char *name_nons = strip_namespace(name);
+ const char *name_nons = strip_namespace(ref->name);
struct strbuf *buf = cb_data;
- struct object *o = parse_object(the_repository, oid);
+ struct object *o = parse_object(the_repository, ref->oid);
if (!o)
return 0;
- strbuf_addf(buf, "%s\t%s\n", oid_to_hex(oid), name_nons);
+ strbuf_addf(buf, "%s\t%s\n", oid_to_hex(ref->oid), name_nons);
if (o->type == OBJ_TAG) {
- o = deref_tag(the_repository, o, name, 0);
+ o = deref_tag(the_repository, o, ref->name, 0);
if (!o)
return 0;
strbuf_addf(buf, "%s\t%s^{}\n", oid_to_hex(&o->oid),
@@ -569,21 +568,20 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
strbuf_release(&buf);
}
-static int show_head_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag, void *cb_data)
+static int show_head_ref(const struct reference *ref, void *cb_data)
{
struct strbuf *buf = cb_data;
- if (flag & REF_ISSYMREF) {
+ if (ref->flags & REF_ISSYMREF) {
const char *target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- refname,
+ ref->name,
RESOLVE_REF_READING,
NULL, NULL);
if (target)
strbuf_addf(buf, "ref: %s\n", strip_namespace(target));
} else {
- strbuf_addf(buf, "%s\n", oid_to_hex(oid));
+ strbuf_addf(buf, "%s\n", oid_to_hex(ref->oid));
}
return 0;
diff --git a/log-tree.c b/log-tree.c
index 7d917f2a83..1729b0c201 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -147,9 +147,7 @@ static int ref_filter_match(const char *refname,
return 1;
}
-static int add_ref_decoration(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flags UNUSED,
- void *cb_data)
+static int add_ref_decoration(const struct reference *ref, void *cb_data)
{
int i;
struct object *obj;
@@ -158,16 +156,16 @@ static int add_ref_decoration(const char *refname, const char *referent UNUSED,
struct decoration_filter *filter = (struct decoration_filter *)cb_data;
const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;
- if (filter && !ref_filter_match(refname, filter))
+ if (filter && !ref_filter_match(ref->name, filter))
return 0;
- if (starts_with(refname, git_replace_ref_base)) {
+ if (starts_with(ref->name, git_replace_ref_base)) {
struct object_id original_oid;
if (!replace_refs_enabled(the_repository))
return 0;
- if (get_oid_hex(refname + strlen(git_replace_ref_base),
+ if (get_oid_hex(ref->name + strlen(git_replace_ref_base),
&original_oid)) {
- warning("invalid replace ref %s", refname);
+ warning("invalid replace ref %s", ref->name);
return 0;
}
obj = parse_object(the_repository, &original_oid);
@@ -176,10 +174,10 @@ static int add_ref_decoration(const char *refname, const char *referent UNUSED,
return 0;
}
- objtype = odb_read_object_info(the_repository->objects, oid, NULL);
+ objtype = odb_read_object_info(the_repository->objects, ref->oid, NULL);
if (objtype < 0)
return 0;
- obj = lookup_object_by_type(the_repository, oid, objtype);
+ obj = lookup_object_by_type(the_repository, ref->oid, objtype);
for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
struct ref_namespace_info *info = &ref_namespace[i];
@@ -187,24 +185,24 @@ static int add_ref_decoration(const char *refname, const char *referent UNUSED,
if (!info->decoration)
continue;
if (info->exact) {
- if (!strcmp(refname, info->ref)) {
+ if (!strcmp(ref->name, info->ref)) {
deco_type = info->decoration;
break;
}
- } else if (starts_with(refname, info->ref)) {
+ } else if (starts_with(ref->name, info->ref)) {
deco_type = info->decoration;
break;
}
}
- add_name_decoration(deco_type, refname, obj);
+ add_name_decoration(deco_type, ref->name, obj);
while (obj->type == OBJ_TAG) {
if (!obj->parsed)
parse_object(the_repository, &obj->oid);
obj = ((struct tag *)obj)->tagged;
if (!obj)
break;
- add_name_decoration(DECORATION_REF_TAG, refname, obj);
+ add_name_decoration(DECORATION_REF_TAG, ref->name, obj);
}
return 0;
}
diff --git a/ls-refs.c b/ls-refs.c
index c47acde07f..8641281b86 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -75,42 +75,42 @@ struct ls_refs_data {
unsigned unborn : 1;
};
-static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag, void *cb_data)
+static int send_ref(const struct reference *ref, void *cb_data)
{
struct ls_refs_data *data = cb_data;
- const char *refname_nons = strip_namespace(refname);
+ const char *refname_nons = strip_namespace(ref->name);
strbuf_reset(&data->buf);
- if (ref_is_hidden(refname_nons, refname, &data->hidden_refs))
+ if (ref_is_hidden(refname_nons, ref->name, &data->hidden_refs))
return 0;
if (!ref_match(&data->prefixes, refname_nons))
return 0;
- if (oid)
- strbuf_addf(&data->buf, "%s %s", oid_to_hex(oid), refname_nons);
+ if (ref->oid)
+ strbuf_addf(&data->buf, "%s %s", oid_to_hex(ref->oid), refname_nons);
else
strbuf_addf(&data->buf, "unborn %s", refname_nons);
- if (data->symrefs && flag & REF_ISSYMREF) {
+ if (data->symrefs && ref->flags & REF_ISSYMREF) {
+ int unused_flag;
struct object_id unused;
const char *symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- refname,
+ ref->name,
0,
&unused,
- &flag);
+ &unused_flag);
if (!symref_target)
- die("'%s' is a symref but it is not?", refname);
+ die("'%s' is a symref but it is not?", ref->name);
strbuf_addf(&data->buf, " symref-target:%s",
strip_namespace(symref_target));
}
- if (data->peel && oid) {
+ if (data->peel && ref->oid) {
struct object_id peeled;
- if (!peel_iterated_oid(the_repository, oid, &peeled))
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled))
strbuf_addf(&data->buf, " peeled:%s", oid_to_hex(&peeled));
}
@@ -131,9 +131,17 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), namespaced.buf, 0, &oid, &flag))
return; /* bad ref */
oid_is_null = is_null_oid(&oid);
+
if (!oid_is_null ||
- (data->unborn && data->symrefs && (flag & REF_ISSYMREF)))
- send_ref(namespaced.buf, NULL, oid_is_null ? NULL : &oid, flag, data);
+ (data->unborn && data->symrefs && (flag & REF_ISSYMREF))) {
+ struct reference ref = {
+ .name = namespaced.buf,
+ .oid = oid_is_null ? NULL : &oid,
+ .flags = flag,
+ };
+
+ send_ref(&ref, data);
+ }
strbuf_release(&namespaced);
}
diff --git a/midx-write.c b/midx-write.c
index c73010df6d..23e61cb000 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -697,28 +697,27 @@ static void prepare_midx_packing_data(struct packing_data *pdata,
trace2_region_leave("midx", "prepare_midx_packing_data", ctx->repo);
}
-static int add_ref_to_pending(const char *refname, const char *referent UNUSED,
- const struct object_id *oid,
- int flag, void *cb_data)
+static int add_ref_to_pending(const struct reference *ref, void *cb_data)
{
struct rev_info *revs = (struct rev_info*)cb_data;
+ const struct object_id *maybe_peeled = ref->oid;
struct object_id peeled;
struct object *object;
- if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) {
- warning("symbolic ref is dangling: %s", refname);
+ if ((ref->flags & REF_ISSYMREF) && (ref->flags & REF_ISBROKEN)) {
+ warning("symbolic ref is dangling: %s", ref->name);
return 0;
}
- if (!peel_iterated_oid(revs->repo, oid, &peeled))
- oid = &peeled;
+ if (!reference_get_peeled_oid(revs->repo, ref, &peeled))
+ maybe_peeled = &peeled;
- object = parse_object_or_die(revs->repo, oid, refname);
+ object = parse_object_or_die(revs->repo, maybe_peeled, ref->name);
if (object->type != OBJ_COMMIT)
return 0;
add_pending_object(revs, object, "");
- if (bitmap_is_preferred_refname(revs->repo, refname))
+ if (bitmap_is_preferred_refname(revs->repo, ref->name))
object->flags |= NEEDS_BITMAP;
return 0;
}
diff --git a/negotiator/default.c b/negotiator/default.c
index c479da9b09..116dedcf83 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -38,11 +38,10 @@ static void rev_list_push(struct negotiation_state *ns,
}
}
-static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED,
- void *cb_data UNUSED)
+static int clear_marks(const struct reference *ref, void *cb_data UNUSED)
{
- struct object *o = deref_tag(the_repository, parse_object(the_repository, oid), refname, 0);
+ struct object *o = deref_tag(the_repository, parse_object(the_repository, ref->oid),
+ ref->name, 0);
if (o && o->type == OBJ_COMMIT)
clear_commit_marks((struct commit *)o,
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index 616df6bf3a..0a272130fb 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -75,11 +75,10 @@ static struct entry *rev_list_push(struct data *data, struct commit *commit, int
return entry;
}
-static int clear_marks(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED,
- void *cb_data UNUSED)
+static int clear_marks(const struct reference *ref, void *cb_data UNUSED)
{
- struct object *o = deref_tag(the_repository, parse_object(the_repository, oid), refname, 0);
+ struct object *o = deref_tag(the_repository, parse_object(the_repository, ref->oid),
+ ref->name, 0);
if (o && o->type == OBJ_COMMIT)
clear_commit_marks((struct commit *)o,
diff --git a/notes.c b/notes.c
index 9a2e9181fe..8e00fd8c47 100644
--- a/notes.c
+++ b/notes.c
@@ -938,13 +938,11 @@ out:
return ret;
}
-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)
+static int string_list_add_one_ref(const struct reference *ref, void *cb)
{
struct string_list *refs = cb;
- if (!unsorted_string_list_has_string(refs, refname))
- string_list_append(refs, refname);
+ if (!unsorted_string_list_has_string(refs, ref->name))
+ string_list_append(refs, ref->name);
return 0;
}
diff --git a/object-name.c b/object-name.c
index 766c757042..72bdf4f86e 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1446,18 +1446,16 @@ struct handle_one_ref_cb {
struct commit_list **list;
};
-static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED,
- void *cb_data)
+static int handle_one_ref(const struct reference *ref, void *cb_data)
{
struct handle_one_ref_cb *cb = cb_data;
struct commit_list **list = cb->list;
- struct object *object = parse_object(cb->repo, oid);
+ struct object *object = parse_object(cb->repo, ref->oid);
if (!object)
return 0;
if (object->type == OBJ_TAG) {
- object = deref_tag(cb->repo, object, path,
- strlen(path));
+ object = deref_tag(cb->repo, object, ref->name,
+ strlen(ref->name));
if (!object)
return 0;
}
diff --git a/object.c b/object.c
index 986114a6db..e72b0ed436 100644
--- a/object.c
+++ b/object.c
@@ -209,11 +209,12 @@ struct object *lookup_object_by_type(struct repository *r,
enum peel_status peel_object(struct repository *r,
const struct object_id *name,
- struct object_id *oid)
+ struct object_id *oid,
+ unsigned flags)
{
struct object *o = lookup_unknown_object(r, name);
- if (o->type == OBJ_NONE) {
+ if (o->type == OBJ_NONE || flags & PEEL_OBJECT_VERIFY_OBJECT_TYPE) {
int type = odb_read_object_info(r->objects, name, NULL);
if (type < 0 || !object_as_type(o, type, 0))
return PEEL_INVALID;
@@ -222,7 +223,20 @@ enum peel_status peel_object(struct repository *r,
if (o->type != OBJ_TAG)
return PEEL_NON_TAG;
- o = deref_tag_noverify(r, o);
+ while (o && o->type == OBJ_TAG) {
+ o = parse_object(r, &o->oid);
+ if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged) {
+ o = ((struct tag *)o)->tagged;
+
+ if (flags & PEEL_OBJECT_VERIFY_OBJECT_TYPE) {
+ int type = odb_read_object_info(r->objects, &o->oid, NULL);
+ if (type < 0 || !object_as_type(o, type, 0))
+ return PEEL_INVALID;
+ }
+ } else {
+ o = NULL;
+ }
+ }
if (!o)
return PEEL_INVALID;
diff --git a/object.h b/object.h
index fa504a09c0..fd15eecce8 100644
--- a/object.h
+++ b/object.h
@@ -288,6 +288,17 @@ enum peel_status {
PEEL_BROKEN = -4
};
+enum peel_object_flags {
+ /*
+ * Always verify the object type, even in the case where the looked-up
+ * object already has an object type. This can be useful when the
+ * stored object type may be invalid. One such case is when looking up
+ * objects via tags, where we blindly trust the object type declared by
+ * the tag.
+ */
+ PEEL_OBJECT_VERIFY_OBJECT_TYPE = (1 << 0),
+};
+
/*
* Peel the named object; i.e., if the object is a tag, resolve the
* tag recursively until a non-tag is found. If successful, store the
@@ -296,7 +307,9 @@ enum peel_status {
* and leave oid unchanged.
*/
enum peel_status peel_object(struct repository *r,
- const struct object_id *name, struct object_id *oid);
+ const struct object_id *name,
+ struct object_id *oid,
+ unsigned flags);
struct object_list *object_list_insert(struct object *item,
struct object_list **list_p);
diff --git a/pseudo-merge.c b/pseudo-merge.c
index 893b763fe4..a2d5bd85f9 100644
--- a/pseudo-merge.c
+++ b/pseudo-merge.c
@@ -221,28 +221,25 @@ void load_pseudo_merges_from_config(struct repository *r,
}
}
-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)
+static int find_pseudo_merge_group_for_ref(const struct reference *ref, void *_data)
{
struct bitmap_writer *writer = _data;
+ const struct object_id *maybe_peeled = ref->oid;
struct object_id peeled;
struct commit *c;
uint32_t i;
int has_bitmap;
- if (!peel_iterated_oid(the_repository, oid, &peeled))
- oid = &peeled;
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled))
+ maybe_peeled = &peeled;
- c = lookup_commit(the_repository, oid);
+ c = lookup_commit(the_repository, maybe_peeled);
if (!c)
return 0;
- if (!packlist_find(writer->to_pack, oid))
+ if (!packlist_find(writer->to_pack, maybe_peeled))
return 0;
- has_bitmap = bitmap_writer_has_bitmapped_object_id(writer, oid);
+ has_bitmap = bitmap_writer_has_bitmapped_object_id(writer, maybe_peeled);
for (i = 0; i < writer->pseudo_merge_groups.nr; i++) {
struct pseudo_merge_group *group;
@@ -252,7 +249,7 @@ static int find_pseudo_merge_group_for_ref(const char *refname,
size_t j;
group = writer->pseudo_merge_groups.items[i].util;
- if (regexec(group->pattern, refname, ARRAY_SIZE(captures),
+ if (regexec(group->pattern, ref->name, ARRAY_SIZE(captures),
captures, 0))
continue;
@@ -269,7 +266,7 @@ static int find_pseudo_merge_group_for_ref(const char *refname,
if (group_name.len)
strbuf_addch(&group_name, '-');
- strbuf_add(&group_name, refname + match->rm_so,
+ strbuf_add(&group_name, ref->name + match->rm_so,
match->rm_eo - match->rm_so);
}
diff --git a/reachable.c b/reachable.c
index 22266db523..b753c39553 100644
--- a/reachable.c
+++ b/reachable.c
@@ -83,18 +83,17 @@ static void add_rebase_files(struct rev_info *revs)
free_worktrees(worktrees);
}
-static int add_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
- int flag, void *cb_data)
+static int add_one_ref(const struct reference *ref, void *cb_data)
{
struct rev_info *revs = (struct rev_info *)cb_data;
struct object *object;
- if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) {
- warning("symbolic ref is dangling: %s", path);
+ if ((ref->flags & REF_ISSYMREF) && (ref->flags & REF_ISBROKEN)) {
+ warning("symbolic ref is dangling: %s", ref->name);
return 0;
}
- object = parse_object_or_die(the_repository, oid, path);
+ object = parse_object_or_die(the_repository, ref->oid, ref->name);
add_pending_object(revs, object, "");
return 0;
diff --git a/ref-filter.c b/ref-filter.c
index 30cc488d8a..d8667c569a 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -91,6 +91,7 @@ static struct expand_data {
struct object_id delta_base_oid;
void *content;
+ struct object *maybe_object;
struct object_info info;
} oi, oi_deref;
@@ -1475,11 +1476,29 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
}
}
+static struct object *get_or_parse_object(struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
+{
+ if (!data->maybe_object) {
+ data->maybe_object = parse_object_buffer(the_repository, &data->oid, data->type,
+ data->size, data->content, eaten);
+ if (!data->maybe_object) {
+ strbuf_addf(err, _("parse_object_buffer failed on %s for %s"),
+ oid_to_hex(&data->oid), refname);
+ return NULL;
+ }
+ }
+
+ return data->maybe_object;
+}
+
/* See grab_values */
-static void grab_tag_values(struct atom_value *val, int deref, struct object *obj)
+static int grab_tag_values(struct atom_value *val, int deref,
+ struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
{
+ struct tag *tag = NULL;
int i;
- struct tag *tag = (struct tag *) obj;
for (i = 0; i < used_atom_cnt; i++) {
const char *name = used_atom[i].name;
@@ -1487,6 +1506,14 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
struct atom_value *v = &val[i];
if (!!deref != (*name == '*'))
continue;
+
+ if (!tag) {
+ tag = (struct tag *) get_or_parse_object(data, refname,
+ err, eaten);
+ if (!tag)
+ return -1;
+ }
+
if (deref)
name++;
if (atom_type == ATOM_TAG)
@@ -1496,22 +1523,35 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
else if (atom_type == ATOM_OBJECT && tag->tagged)
v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
}
+
+ return 0;
}
/* See grab_values */
-static void grab_commit_values(struct atom_value *val, int deref, struct object *obj)
+static int grab_commit_values(struct atom_value *val, int deref,
+ struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
{
int i;
- struct commit *commit = (struct commit *) obj;
+ struct commit *commit = NULL;
for (i = 0; i < used_atom_cnt; i++) {
const char *name = used_atom[i].name;
enum atom_type atom_type = used_atom[i].atom_type;
struct atom_value *v = &val[i];
+
if (!!deref != (*name == '*'))
continue;
if (deref)
name++;
+
+ if (!commit) {
+ commit = (struct commit *) get_or_parse_object(data, refname,
+ err, eaten);
+ if (!commit)
+ return -1;
+ }
+
if (atom_type == ATOM_TREE &&
grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
continue;
@@ -1531,6 +1571,8 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
v->s = strbuf_detach(&s, NULL);
}
}
+
+ return 0;
}
static const char *find_wholine(const char *who, int wholen, const char *buf)
@@ -1759,10 +1801,12 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void
}
}
-static void grab_signature(struct atom_value *val, int deref, struct object *obj)
+static int grab_signature(struct atom_value *val, int deref,
+ struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
{
int i;
- struct commit *commit = (struct commit *) obj;
+ struct commit *commit = NULL;
struct signature_check sigc = { 0 };
int signature_checked = 0;
@@ -1790,6 +1834,13 @@ static void grab_signature(struct atom_value *val, int deref, struct object *obj
continue;
if (!signature_checked) {
+ if (!commit) {
+ commit = (struct commit *) get_or_parse_object(data, refname,
+ err, eaten);
+ if (!commit)
+ return -1;
+ }
+
check_commit_signature(commit, &sigc);
signature_checked = 1;
}
@@ -1843,6 +1894,8 @@ static void grab_signature(struct atom_value *val, int deref, struct object *obj
if (signature_checked)
signature_check_clear(&sigc);
+
+ return 0;
}
static void find_subpos(const char *buf,
@@ -1920,9 +1973,8 @@ static void append_lines(struct strbuf *out, const char *buf, unsigned long size
}
static void grab_describe_values(struct atom_value *val, int deref,
- struct object *obj)
+ struct expand_data *data)
{
- struct commit *commit = (struct commit *)obj;
int i;
for (i = 0; i < used_atom_cnt; i++) {
@@ -1944,7 +1996,7 @@ static void grab_describe_values(struct atom_value *val, int deref,
cmd.git_cmd = 1;
strvec_push(&cmd.args, "describe");
strvec_pushv(&cmd.args, atom->u.describe_args.v);
- strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
+ strvec_push(&cmd.args, oid_to_hex(&data->oid));
if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {
error(_("failed to run 'describe'"));
v->s = xstrdup("");
@@ -2066,24 +2118,36 @@ static void fill_missing_values(struct atom_value *val)
* pointed at by the ref itself; otherwise it is the object the
* ref (which is a tag) refers to.
*/
-static void grab_values(struct atom_value *val, int deref, struct object *obj, struct expand_data *data)
+static int grab_values(struct atom_value *val, int deref, struct expand_data *data,
+ const char *refname, struct strbuf *err, int *eaten)
{
void *buf = data->content;
+ int ret;
- switch (obj->type) {
+ switch (data->type) {
case OBJ_TAG:
- grab_tag_values(val, deref, obj);
+ ret = grab_tag_values(val, deref, data, refname, err, eaten);
+ if (ret < 0)
+ goto out;
+
grab_sub_body_contents(val, deref, data);
grab_person("tagger", val, deref, buf);
- grab_describe_values(val, deref, obj);
+ grab_describe_values(val, deref, data);
break;
case OBJ_COMMIT:
- grab_commit_values(val, deref, obj);
+ ret = grab_commit_values(val, deref, data, refname, err, eaten);
+ if (ret < 0)
+ goto out;
+
grab_sub_body_contents(val, deref, data);
grab_person("author", val, deref, buf);
grab_person("committer", val, deref, buf);
- grab_signature(val, deref, obj);
- grab_describe_values(val, deref, obj);
+
+ ret = grab_signature(val, deref, data, refname, err, eaten);
+ if (ret < 0)
+ goto out;
+
+ grab_describe_values(val, deref, data);
break;
case OBJ_TREE:
/* grab_tree_values(val, deref, obj, buf, sz); */
@@ -2094,8 +2158,12 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, s
grab_sub_body_contents(val, deref, data);
break;
default:
- die("Eh? Object of type %d?", obj->type);
+ die("Eh? Object of type %d?", data->type);
}
+
+ ret = 0;
+out:
+ return ret;
}
static inline char *copy_advance(char *dst, const char *src)
@@ -2292,38 +2360,43 @@ static const char *get_refname(struct used_atom *atom, struct ref_array_item *re
return show_ref(&atom->u.refname, ref->refname);
}
-static int get_object(struct ref_array_item *ref, int deref, struct object **obj,
+static int get_object(struct ref_array_item *ref, int deref,
struct expand_data *oi, struct strbuf *err)
{
- /* parse_object_buffer() will set eaten to 0 if free() will be needed */
- int eaten = 1;
+ /* parse_object_buffer() will set eaten to 1 if free() will be needed */
+ int eaten = 0;
+ int ret;
+
+ oi->maybe_object = NULL;
+
if (oi->info.contentp) {
/* We need to know that to use parse_object_buffer properly */
oi->info.sizep = &oi->size;
oi->info.typep = &oi->type;
}
+
if (odb_read_object_info_extended(the_repository->objects, &oi->oid, &oi->info,
- OBJECT_INFO_LOOKUP_REPLACE))
- return strbuf_addf_ret(err, -1, _("missing object %s for %s"),
- oid_to_hex(&oi->oid), ref->refname);
+ OBJECT_INFO_LOOKUP_REPLACE)) {
+ ret = strbuf_addf_ret(err, -1, _("missing object %s for %s"),
+ oid_to_hex(&oi->oid), ref->refname);
+ goto out;
+ }
if (oi->info.disk_sizep && oi->disk_size < 0)
BUG("Object size is less than zero.");
if (oi->info.contentp) {
- *obj = parse_object_buffer(the_repository, &oi->oid, oi->type, oi->size, oi->content, &eaten);
- if (!*obj) {
- if (!eaten)
- free(oi->content);
- return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
- oid_to_hex(&oi->oid), ref->refname);
- }
- grab_values(ref->value, deref, *obj, oi);
+ ret = grab_values(ref->value, deref, oi, ref->refname, err, &eaten);
+ if (ret < 0)
+ goto out;
}
grab_common_values(ref->value, deref, oi);
+ ret = 0;
+
+out:
if (!eaten)
free(oi->content);
- return 0;
+ return ret;
}
static void populate_worktree_map(struct hashmap *map, struct worktree **worktrees)
@@ -2376,7 +2449,6 @@ static char *get_worktree_path(const struct ref_array_item *ref)
*/
static int populate_value(struct ref_array_item *ref, struct strbuf *err)
{
- struct object *obj;
int i;
struct object_info empty = OBJECT_INFO_INIT;
int ahead_behind_atoms = 0;
@@ -2564,24 +2636,32 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
oi.oid = ref->objectname;
- if (get_object(ref, 0, &obj, &oi, err))
+ if (get_object(ref, 0, &oi, err))
return -1;
/*
* If there is no atom that wants to know about tagged
* object, we are done.
*/
- if (!need_tagged || (obj->type != OBJ_TAG))
+ if (!need_tagged || (oi.type != OBJ_TAG))
return 0;
/*
* If it is a tag object, see if we use the peeled value. If we do,
* grab the peeled OID.
*/
- if (need_tagged && peel_iterated_oid(the_repository, &obj->oid, &oi_deref.oid))
- die("bad tag");
+ if (need_tagged) {
+ if (!is_null_oid(&ref->peeled_oid)) {
+ oidcpy(&oi_deref.oid, &ref->peeled_oid);
+ } else if (!peel_object(the_repository, &oi.oid, &oi_deref.oid,
+ PEEL_OBJECT_VERIFY_OBJECT_TYPE)) {
+ /* We managed to peel the object ourselves. */
+ } else {
+ die("bad tag");
+ }
+ }
- return get_object(ref, 1, &obj, &oi_deref, err);
+ return get_object(ref, 1, &oi_deref, err);
}
/*
@@ -2807,12 +2887,15 @@ static int match_points_at(struct oid_array *points_at,
* Callers can then fill in other struct members at their leisure.
*/
static struct ref_array_item *new_ref_array_item(const char *refname,
- const struct object_id *oid)
+ const struct object_id *oid,
+ const struct object_id *peeled_oid)
{
struct ref_array_item *ref;
FLEX_ALLOC_STR(ref, refname, refname);
oidcpy(&ref->objectname, oid);
+ if (peeled_oid)
+ oidcpy(&ref->peeled_oid, peeled_oid);
ref->rest = NULL;
return ref;
@@ -2826,9 +2909,10 @@ static void ref_array_append(struct ref_array *array, struct ref_array_item *ref
struct ref_array_item *ref_array_push(struct ref_array *array,
const char *refname,
- const struct object_id *oid)
+ const struct object_id *oid,
+ const struct object_id *peeled_oid)
{
- struct ref_array_item *ref = new_ref_array_item(refname, oid);
+ struct ref_array_item *ref = new_ref_array_item(refname, oid, peeled_oid);
ref_array_append(array, ref);
return ref;
}
@@ -2871,25 +2955,25 @@ 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 char *referent, const struct object_id *oid,
- int flag, struct ref_filter *filter)
+static struct ref_array_item *apply_ref_filter(const struct reference *ref,
+ struct ref_filter *filter)
{
- struct ref_array_item *ref;
+ struct ref_array_item *item;
struct commit *commit = NULL;
unsigned int kind;
- if (flag & REF_BAD_NAME) {
- warning(_("ignoring ref with broken name %s"), refname);
+ if (ref->flags & REF_BAD_NAME) {
+ warning(_("ignoring ref with broken name %s"), ref->name);
return NULL;
}
- if (flag & REF_ISBROKEN) {
- warning(_("ignoring broken ref %s"), refname);
+ if (ref->flags & REF_ISBROKEN) {
+ warning(_("ignoring broken ref %s"), ref->name);
return NULL;
}
/* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
- kind = filter_ref_kind(filter, refname);
+ kind = filter_ref_kind(filter, ref->name);
/*
* Generally HEAD refs are printed with special description denoting a rebase,
@@ -2902,13 +2986,13 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
else if (!(kind & filter->kind))
return NULL;
- if (!filter_pattern_match(filter, refname))
+ if (!filter_pattern_match(filter, ref->name))
return NULL;
- if (filter_exclude_match(filter, refname))
+ if (filter_exclude_match(filter, ref->name))
return NULL;
- if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
+ if (filter->points_at.nr && !match_points_at(&filter->points_at, ref->oid, ref->name))
return NULL;
/*
@@ -2918,7 +3002,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
*/
if (filter->reachable_from || filter->unreachable_from ||
filter->with_commit || filter->no_commit || filter->verbose) {
- commit = lookup_commit_reference_gently(the_repository, oid, 1);
+ commit = lookup_commit_reference_gently(the_repository, ref->oid, 1);
if (!commit)
return NULL;
/* We perform the filtering for the '--contains' option... */
@@ -2936,13 +3020,13 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
* to do its job and the resulting list may yet to be pruned
* by maxcount logic.
*/
- ref = new_ref_array_item(refname, oid);
- ref->commit = commit;
- ref->flag = flag;
- ref->kind = kind;
- ref->symref = xstrdup_or_null(referent);
+ item = new_ref_array_item(ref->name, ref->oid, ref->peeled_oid);
+ item->commit = commit;
+ item->flag = ref->flags;
+ item->kind = kind;
+ item->symref = xstrdup_or_null(ref->target);
- return ref;
+ return item;
}
struct ref_filter_cbdata {
@@ -2954,14 +3038,14 @@ 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, const struct object_id *oid, int flag, void *cb_data)
+static int filter_one(const struct reference *ref, void *cb_data)
{
struct ref_filter_cbdata *ref_cbdata = cb_data;
- struct ref_array_item *ref;
+ struct ref_array_item *item;
- ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
- if (ref)
- ref_array_append(ref_cbdata->array, ref);
+ item = apply_ref_filter(ref, ref_cbdata->filter);
+ if (item)
+ ref_array_append(ref_cbdata->array, item);
return 0;
}
@@ -2990,17 +3074,17 @@ struct ref_filter_and_format_cbdata {
} internal;
};
-static int filter_and_format_one(const char *refname, const char *referent, const struct object_id *oid, int flag, void *cb_data)
+static int filter_and_format_one(const struct reference *ref, void *cb_data)
{
struct ref_filter_and_format_cbdata *ref_cbdata = cb_data;
- struct ref_array_item *ref;
+ struct ref_array_item *item;
struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
- ref = apply_ref_filter(refname, referent, oid, flag, ref_cbdata->filter);
- if (!ref)
+ item = apply_ref_filter(ref, ref_cbdata->filter);
+ if (!item)
return 0;
- if (format_ref_array_item(ref, ref_cbdata->format, &output, &err))
+ if (format_ref_array_item(item, ref_cbdata->format, &output, &err))
die("%s", err.buf);
if (output.len || !ref_cbdata->format->array_opts.omit_empty) {
@@ -3010,7 +3094,7 @@ static int filter_and_format_one(const char *refname, const char *referent, cons
strbuf_release(&output);
strbuf_release(&err);
- free_array_item(ref);
+ free_array_item(item);
/*
* Increment the running count of refs that match the filter. If
@@ -3583,13 +3667,14 @@ void print_formatted_ref_array(struct ref_array *array, struct ref_format *forma
}
void pretty_print_ref(const char *name, const struct object_id *oid,
+ const struct object_id *peeled_oid,
struct ref_format *format)
{
struct ref_array_item *ref_item;
struct strbuf output = STRBUF_INIT;
struct strbuf err = STRBUF_INIT;
- ref_item = new_ref_array_item(name, oid);
+ ref_item = new_ref_array_item(name, oid, peeled_oid);
ref_item->kind = ref_kind_from_refname(name);
if (format_ref_array_item(ref_item, format, &output, &err))
die("%s", err.buf);
diff --git a/ref-filter.h b/ref-filter.h
index 235c60f79c..120221b47f 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -41,6 +41,7 @@ enum ref_sorting_order {
struct ref_array_item {
struct object_id objectname;
+ struct object_id peeled_oid;
const char *rest;
int flag;
unsigned int kind;
@@ -187,6 +188,7 @@ void print_formatted_ref_array(struct ref_array *array, struct ref_format *forma
* name must be a fully qualified refname.
*/
void pretty_print_ref(const char *name, const struct object_id *oid,
+ const struct object_id *peeled_oid,
struct ref_format *format);
/*
@@ -195,7 +197,8 @@ void pretty_print_ref(const char *name, const struct object_id *oid,
*/
struct ref_array_item *ref_array_push(struct ref_array *array,
const char *refname,
- const struct object_id *oid);
+ const struct object_id *oid,
+ const struct object_id *peeled_oid);
/*
* If the provided format includes ahead-behind atoms, then compute the
diff --git a/reflog.c b/reflog.c
index 65ef259b4f..ac87e20c4f 100644
--- a/reflog.c
+++ b/reflog.c
@@ -423,16 +423,13 @@ int should_expire_reflog_ent_verbose(struct object_id *ooid,
return expire;
}
-static int push_tip_to_list(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flags, void *cb_data)
+static int push_tip_to_list(const struct reference *ref, void *cb_data)
{
struct commit_list **list = cb_data;
struct commit *tip_commit;
- if (flags & REF_ISSYMREF)
+ if (ref->flags & REF_ISSYMREF)
return 0;
- tip_commit = lookup_commit_reference_gently(the_repository, oid, 1);
+ tip_commit = lookup_commit_reference_gently(the_repository, ref->oid, 1);
if (!tip_commit)
return 0;
commit_list_insert(tip_commit, list);
diff --git a/refs.c b/refs.c
index 965381367e..a41a94ae55 100644
--- a/refs.c
+++ b/refs.c
@@ -426,17 +426,19 @@ int refs_ref_exists(struct ref_store *refs, const char *refname)
NULL, NULL);
}
-static int for_each_filter_refs(const char *refname, const char *referent,
- const struct object_id *oid,
- int flags, void *data)
+static int for_each_filter_refs(const struct reference *ref, void *data)
{
struct for_each_ref_filter *filter = data;
- if (wildmatch(filter->pattern, refname, 0))
+ if (wildmatch(filter->pattern, ref->name, 0))
return 0;
- if (filter->prefix)
- skip_prefix(refname, filter->prefix, &refname);
- return filter->fn(refname, referent, oid, flags, filter->cb_data);
+ if (filter->prefix) {
+ struct reference skipped = *ref;
+ skip_prefix(skipped.name, filter->prefix, &skipped.name);
+ return filter->fn(&skipped, filter->cb_data);
+ } else {
+ return filter->fn(ref, filter->cb_data);
+ }
}
struct warn_if_dangling_data {
@@ -447,17 +449,15 @@ struct warn_if_dangling_data {
int dry_run;
};
-static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flags, void *cb_data)
+static int warn_if_dangling_symref(const struct reference *ref, void *cb_data)
{
struct warn_if_dangling_data *d = cb_data;
const char *resolves_to, *msg;
- if (!(flags & REF_ISSYMREF))
+ if (!(ref->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, ref->name, 0, NULL, NULL);
if (!resolves_to
|| !string_list_has_string(d->refnames, resolves_to)) {
return 0;
@@ -466,7 +466,7 @@ static int warn_if_dangling_symref(const char *refname, const char *referent UNU
msg = d->dry_run
? _("%s%s will become dangling after %s is deleted\n")
: _("%s%s has become dangling after %s was deleted\n");
- fprintf(d->fp, msg, d->indent, refname, resolves_to);
+ fprintf(d->fp, msg, d->indent, ref->name, resolves_to);
return 0;
}
@@ -507,8 +507,15 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da
int flag;
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
- if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag))
- ret = fn(buf.buf, NULL, &oid, flag, cb_data);
+ if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag)) {
+ struct reference ref = {
+ .name = buf.buf,
+ .oid = &oid,
+ .flags = flag,
+ };
+
+ ret = fn(&ref, cb_data);
+ }
strbuf_release(&buf);
return ret;
@@ -1741,8 +1748,15 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
int flag;
if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING,
- &oid, &flag))
- return fn("HEAD", NULL, &oid, flag, cb_data);
+ &oid, &flag)) {
+ struct reference ref = {
+ .name = "HEAD",
+ .oid = &oid,
+ .flags = flag,
+ };
+
+ return fn(&ref, cb_data);
+ }
return 0;
}
@@ -2310,14 +2324,16 @@ int refs_optimize(struct ref_store *refs, struct pack_refs_opts *opts)
return refs->be->optimize(refs, opts);
}
-int peel_iterated_oid(struct repository *r, const struct object_id *base, struct object_id *peeled)
+int reference_get_peeled_oid(struct repository *repo,
+ const struct reference *ref,
+ struct object_id *peeled_oid)
{
- if (current_ref_iter &&
- (current_ref_iter->oid == base ||
- oideq(current_ref_iter->oid, base)))
- return ref_iterator_peel(current_ref_iter, peeled);
+ if (ref->peeled_oid) {
+ oidcpy(peeled_oid, ref->peeled_oid);
+ return 0;
+ }
- return peel_object(r, base, peeled) ? -1 : 0;
+ return peel_object(repo, ref->oid, peeled_oid, 0) ? -1 : 0;
}
int refs_update_symref(struct ref_store *refs, const char *ref,
@@ -2689,7 +2705,7 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
if (skip &&
- string_list_has_string(skip, iter->refname))
+ string_list_has_string(skip, iter->ref.name))
continue;
if (transaction && ref_transaction_maybe_set_rejected(
@@ -2698,7 +2714,7 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs
continue;
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
- iter->refname, refname);
+ iter->ref.name, refname);
goto cleanup;
}
@@ -2753,14 +2769,10 @@ struct do_for_each_reflog_help {
void *cb_data;
};
-static int do_for_each_reflog_helper(const char *refname,
- const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flags UNUSED,
- void *cb_data)
+static int do_for_each_reflog_helper(const struct reference *ref, void *cb_data)
{
struct do_for_each_reflog_help *hp = cb_data;
- return hp->fn(refname, hp->cb_data);
+ return hp->fn(ref->name, hp->cb_data);
}
int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data)
@@ -2976,25 +2988,24 @@ struct migration_data {
uint64_t index;
};
-static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flags, void *cb_data)
+static int migrate_one_ref(const struct reference *ref, void *cb_data)
{
struct migration_data *data = cb_data;
struct strbuf symref_target = STRBUF_INIT;
int ret;
- if (flags & REF_ISSYMREF) {
- ret = refs_read_symbolic_ref(data->old_refs, refname, &symref_target);
+ if (ref->flags & REF_ISSYMREF) {
+ ret = refs_read_symbolic_ref(data->old_refs, ref->name, &symref_target);
if (ret < 0)
goto done;
- ret = ref_transaction_update(data->transaction, refname, NULL, null_oid(the_hash_algo),
+ ret = ref_transaction_update(data->transaction, ref->name, NULL, null_oid(the_hash_algo),
symref_target.buf, NULL,
REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf);
if (ret < 0)
goto done;
} else {
- ret = ref_transaction_create(data->transaction, refname, oid, NULL,
+ ret = ref_transaction_create(data->transaction, ref->name, ref->oid, NULL,
REF_SKIP_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION,
NULL, data->errbuf);
if (ret < 0)
diff --git a/refs.h b/refs.h
index 4e6bd63aa8..2dd7ac1a16 100644
--- a/refs.h
+++ b/refs.h
@@ -333,36 +333,74 @@ struct ref_transaction;
* stored in ref_iterator::flags. Other bits are for internal use
* only:
*/
+enum reference_status {
+ /* Reference is a symbolic reference. */
+ REF_ISSYMREF = (1 << 0),
-/* Reference is a symbolic reference. */
-#define REF_ISSYMREF 0x01
+ /* Reference is a packed reference. */
+ REF_ISPACKED = (1 << 1),
-/* Reference is a packed reference. */
-#define REF_ISPACKED 0x02
+ /*
+ * Reference cannot be resolved to an object name: dangling symbolic
+ * reference (directly or indirectly), corrupt reference file,
+ * reference exists but name is bad, or symbolic reference refers to
+ * ill-formatted reference name.
+ */
+ REF_ISBROKEN = (1 << 2),
-/*
- * Reference cannot be resolved to an object name: dangling symbolic
- * reference (directly or indirectly), corrupt reference file,
- * reference exists but name is bad, or symbolic reference refers to
- * ill-formatted reference name.
- */
-#define REF_ISBROKEN 0x04
+ /*
+ * Reference name is not well formed.
+ *
+ * See git-check-ref-format(1) for the definition of well formed ref names.
+ */
+ REF_BAD_NAME = (1 << 3),
+};
+
+/* A reference passed to `for_each_ref()`-style callbacks. */
+struct reference {
+ /* The fully-qualified name of the reference. */
+ const char *name;
+
+ /* The target of a symbolic ref. `NULL` for direct references. */
+ const char *target;
+
+ /*
+ * The object ID of a reference. Either the direct object ID or the
+ * resolved object ID in the case of a symbolic ref. May be the zero
+ * object ID in case the symbolic ref cannot be resolved.
+ */
+ const struct object_id *oid;
+
+ /*
+ * An optional peeled object ID. This field _may_ be set for tags in
+ * case the peeled value is present in the backend. Please refer to
+ * `reference_get_peeled_oid()`.
+ */
+ const struct object_id *peeled_oid;
+
+ /* A bitfield of `enum reference_status` flags. */
+ unsigned flags;
+};
/*
- * Reference name is not well formed.
+ * Peel the tag to a non-tag commit. If present, this uses the peeled object ID
+ * exposed by the reference backend. Otherwise, the object is peeled via the
+ * object database, which is less efficient.
*
- * See git-check-ref-format(1) for the definition of well formed ref names.
+ * Return `0` if the reference could be peeled, a negative error code
+ * otherwise.
*/
-#define REF_BAD_NAME 0x08
+int reference_get_peeled_oid(struct repository *repo,
+ const struct reference *ref,
+ struct object_id *peeled_oid);
/*
* The signature for the callback function for the for_each_*()
- * functions below. The memory pointed to by the refname and oid
- * arguments is only guaranteed to be valid for the duration of a
+ * functions below. The memory pointed to by the `struct reference`
+ * argument is only guaranteed to be valid for the duration of a
* single callback invocation.
*/
-typedef int each_ref_fn(const char *refname, const char *referent,
- const struct object_id *oid, int flags, void *cb_data);
+typedef int each_ref_fn(const struct reference *ref, void *cb_data);
/*
* The following functions invoke the specified callback function for
@@ -1251,10 +1289,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
* to the next entry, ref_iterator_advance() aborts the iteration,
* frees the ref_iterator, and returns ITER_ERROR.
*
- * The reference currently being looked at can be peeled by calling
- * ref_iterator_peel(). This function is often faster than peel_ref(),
- * so it should be preferred when iterating over references.
- *
* Putting it all together, a typical iteration looks like this:
*
* int ok;
@@ -1269,9 +1303,6 @@ int repo_migrate_ref_storage_format(struct repository *repo,
* // Access information about the current reference:
* if (!(iter->flags & REF_ISSYMREF))
* printf("%s is %s\n", iter->refname, oid_to_hex(iter->oid));
- *
- * // If you need to peel the reference:
- * ref_iterator_peel(iter, &oid);
* }
*
* if (ok != ITER_DONE)
@@ -1362,13 +1393,6 @@ enum ref_iterator_seek_flag {
int ref_iterator_seek(struct ref_iterator *ref_iterator, const char *refname,
unsigned int flags);
-/*
- * If possible, peel the reference currently being viewed by the
- * iterator. Return 0 on success.
- */
-int ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled);
-
/* Free the reference iterator and any associated resources. */
void ref_iterator_free(struct ref_iterator *ref_iterator);
diff --git a/refs/debug.c b/refs/debug.c
index c59c1728a3..f38991c02a 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -168,11 +168,9 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
trace_printf_key(&trace_refs, "iterator_advance: (%d)\n", res);
else
trace_printf_key(&trace_refs, "iterator_advance: %s (0)\n",
- diter->iter->refname);
+ diter->iter->ref.name);
- diter->base.refname = diter->iter->refname;
- diter->base.oid = diter->iter->oid;
- diter->base.flags = diter->iter->flags;
+ diter->base.ref = diter->iter->ref;
return res;
}
@@ -187,16 +185,6 @@ static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator,
return res;
}
-static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct debug_ref_iterator *diter =
- (struct debug_ref_iterator *)ref_iterator;
- int res = diter->iter->vtable->peel(diter->iter, peeled);
- trace_printf_key(&trace_refs, "iterator_peel: %s: %d\n", diter->iter->refname, res);
- return res;
-}
-
static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct debug_ref_iterator *diter =
@@ -208,7 +196,6 @@ static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable debug_ref_iterator_vtable = {
.advance = debug_ref_iterator_advance,
.seek = debug_ref_iterator_seek,
- .peel = debug_ref_iterator_peel,
.release = debug_ref_iterator_release,
};
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 1adc4b5182..d929f88293 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -961,26 +961,23 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
- parse_worktree_ref(iter->iter0->refname, NULL, NULL,
+ parse_worktree_ref(iter->iter0->ref.name, NULL, NULL,
NULL) != REF_WORKTREE_CURRENT)
continue;
if ((iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS) &&
- (iter->iter0->flags & REF_ISSYMREF) &&
- (iter->iter0->flags & REF_ISBROKEN))
+ (iter->iter0->ref.flags & REF_ISSYMREF) &&
+ (iter->iter0->ref.flags & REF_ISBROKEN))
continue;
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
- !ref_resolves_to_object(iter->iter0->refname,
+ !ref_resolves_to_object(iter->iter0->ref.name,
iter->repo,
- iter->iter0->oid,
- iter->iter0->flags))
+ iter->iter0->ref.oid,
+ iter->iter0->ref.flags))
continue;
- iter->base.refname = iter->iter0->refname;
- iter->base.oid = iter->iter0->oid;
- iter->base.flags = iter->iter0->flags;
- iter->base.referent = iter->iter0->referent;
+ iter->base.ref = iter->iter0->ref;
return ITER_OK;
}
@@ -996,15 +993,6 @@ static int files_ref_iterator_seek(struct ref_iterator *ref_iterator,
return ref_iterator_seek(iter->iter0, refname, flags);
}
-static int files_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct files_ref_iterator *iter =
- (struct files_ref_iterator *)ref_iterator;
-
- return ref_iterator_peel(iter->iter0, peeled);
-}
-
static void files_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct files_ref_iterator *iter =
@@ -1015,7 +1003,6 @@ static void files_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable files_ref_iterator_vtable = {
.advance = files_ref_iterator_advance,
.seek = files_ref_iterator_seek,
- .peel = files_ref_iterator_peel,
.release = files_ref_iterator_release,
};
@@ -1367,30 +1354,29 @@ static void prune_refs(struct files_ref_store *refs, struct ref_to_prune **refs_
* Return true if the specified reference should be packed.
*/
static int should_pack_ref(struct files_ref_store *refs,
- const char *refname,
- const struct object_id *oid, unsigned int ref_flags,
+ const struct reference *ref,
struct pack_refs_opts *opts)
{
struct string_list_item *item;
/* Do not pack per-worktree refs: */
- if (parse_worktree_ref(refname, NULL, NULL, NULL) !=
+ if (parse_worktree_ref(ref->name, NULL, NULL, NULL) !=
REF_WORKTREE_SHARED)
return 0;
/* Do not pack symbolic refs: */
- if (ref_flags & REF_ISSYMREF)
+ if (ref->flags & REF_ISSYMREF)
return 0;
/* Do not pack broken refs: */
- if (!ref_resolves_to_object(refname, refs->base.repo, oid, ref_flags))
+ if (!ref_resolves_to_object(ref->name, refs->base.repo, ref->oid, ref->flags))
return 0;
- if (ref_excluded(opts->exclusions, refname))
+ if (ref_excluded(opts->exclusions, ref->name))
return 0;
for_each_string_list_item(item, opts->includes)
- if (!wildmatch(item->string, refname, 0))
+ if (!wildmatch(item->string, ref->name, 0))
return 1;
return 0;
@@ -1443,8 +1429,7 @@ static int should_pack_refs(struct files_ref_store *refs,
iter = cache_ref_iterator_begin(get_loose_ref_cache(refs, 0), NULL,
refs->base.repo, 0);
while ((ret = ref_iterator_advance(iter)) == ITER_OK) {
- if (should_pack_ref(refs, iter->refname, iter->oid,
- iter->flags, opts))
+ if (should_pack_ref(refs, &iter->ref, opts))
refcount++;
if (refcount >= limit) {
ref_iterator_free(iter);
@@ -1489,24 +1474,24 @@ static int files_pack_refs(struct ref_store *ref_store,
* in the packed ref cache. If the reference should be
* pruned, also add it to refs_to_prune.
*/
- if (!should_pack_ref(refs, iter->refname, iter->oid, iter->flags, opts))
+ if (!should_pack_ref(refs, &iter->ref, opts))
continue;
/*
* Add a reference creation for this reference to the
* packed-refs transaction:
*/
- if (ref_transaction_update(transaction, iter->refname,
- iter->oid, NULL, NULL, NULL,
+ if (ref_transaction_update(transaction, iter->ref.name,
+ iter->ref.oid, NULL, NULL, NULL,
REF_NO_DEREF, NULL, &err))
die("failure preparing to create packed reference %s: %s",
- iter->refname, err.buf);
+ iter->ref.name, err.buf);
/* Schedule the loose reference for pruning if requested. */
if ((opts->flags & PACK_REFS_PRUNE)) {
struct ref_to_prune *n;
- FLEX_ALLOC_STR(n, name, iter->refname);
- oidcpy(&n->oid, iter->oid);
+ FLEX_ALLOC_STR(n, name, iter->ref.name);
+ oidcpy(&n->oid, iter->ref.oid);
n->next = refs_to_prune;
refs_to_prune = n;
}
@@ -2394,7 +2379,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
REFNAME_ALLOW_ONELEVEL))
continue;
- iter->base.refname = diter->relative_path;
+ iter->base.ref.name = diter->relative_path;
return ITER_OK;
}
@@ -2408,12 +2393,6 @@ static int files_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
BUG("ref_iterator_seek() called for reflog_iterator");
}
-static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
- struct object_id *peeled UNUSED)
-{
- BUG("ref_iterator_peel() called for reflog_iterator");
-}
-
static void files_reflog_iterator_release(struct ref_iterator *ref_iterator)
{
struct files_reflog_iterator *iter =
@@ -2424,7 +2403,6 @@ static void files_reflog_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable files_reflog_iterator_vtable = {
.advance = files_reflog_iterator_advance,
.seek = files_reflog_iterator_seek,
- .peel = files_reflog_iterator_peel,
.release = files_reflog_iterator_release,
};
@@ -3165,14 +3143,11 @@ static int parse_and_write_reflog(struct files_ref_store *refs,
return 0;
}
-static int ref_present(const char *refname, const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flags UNUSED,
- void *cb_data)
+static int ref_present(const struct reference *ref, void *cb_data)
{
struct string_list *affected_refnames = cb_data;
- return string_list_has_string(affected_refnames, refname);
+ return string_list_has_string(affected_refnames, ref->name);
}
static int files_transaction_finish_initial(struct files_ref_store *refs,
diff --git a/refs/iterator.c b/refs/iterator.c
index 17ef841d8a..d79aa5ec82 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -21,12 +21,6 @@ int ref_iterator_seek(struct ref_iterator *ref_iterator, const char *refname,
return ref_iterator->vtable->seek(ref_iterator, refname, flags);
}
-int ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- return ref_iterator->vtable->peel(ref_iterator, peeled);
-}
-
void ref_iterator_free(struct ref_iterator *ref_iterator)
{
if (ref_iterator) {
@@ -41,10 +35,7 @@ void base_ref_iterator_init(struct ref_iterator *iter,
struct ref_iterator_vtable *vtable)
{
iter->vtable = vtable;
- iter->refname = NULL;
- iter->referent = NULL;
- iter->oid = NULL;
- iter->flags = 0;
+ memset(&iter->ref, 0, sizeof(iter->ref));
}
struct empty_ref_iterator {
@@ -63,12 +54,6 @@ static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
return 0;
}
-static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
- struct object_id *peeled UNUSED)
-{
- BUG("peel called for empty iterator");
-}
-
static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
{
}
@@ -76,7 +61,6 @@ static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
static struct ref_iterator_vtable empty_ref_iterator_vtable = {
.advance = empty_ref_iterator_advance,
.seek = empty_ref_iterator_seek,
- .peel = empty_ref_iterator_peel,
.release = empty_ref_iterator_release,
};
@@ -127,8 +111,8 @@ enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
* latter.
*/
if (iter_worktree) {
- int cmp = strcmp(iter_worktree->refname,
- iter_common->refname);
+ int cmp = strcmp(iter_worktree->ref.name,
+ iter_common->ref.name);
if (cmp < 0)
return ITER_SELECT_0;
else if (!cmp)
@@ -139,7 +123,7 @@ enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
* We now know that the lexicographically-next ref is a common
* ref. When the common ref is a shared one we return it.
*/
- if (parse_worktree_ref(iter_common->refname, NULL, NULL,
+ if (parse_worktree_ref(iter_common->ref.name, NULL, NULL,
NULL) == REF_WORKTREE_SHARED)
return ITER_SELECT_1;
@@ -212,10 +196,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;
+ iter->base.ref = (*iter->current)->ref;
return ITER_OK;
}
}
@@ -246,18 +227,6 @@ static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator,
return 0;
}
-static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct merge_ref_iterator *iter =
- (struct merge_ref_iterator *)ref_iterator;
-
- if (!iter->current) {
- BUG("peel called before advance for merge iterator");
- }
- return ref_iterator_peel(*iter->current, peeled);
-}
-
static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct merge_ref_iterator *iter =
@@ -269,7 +238,6 @@ static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable merge_ref_iterator_vtable = {
.advance = merge_ref_iterator_advance,
.seek = merge_ref_iterator_seek,
- .peel = merge_ref_iterator_peel,
.release = merge_ref_iterator_release,
};
@@ -313,7 +281,7 @@ static enum iterator_selection overlay_iterator_select(
else if (!front)
return ITER_SELECT_1;
- cmp = strcmp(front->refname, back->refname);
+ cmp = strcmp(front->ref.name, back->ref.name);
if (cmp < 0)
return ITER_SELECT_0;
@@ -371,7 +339,7 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
int ok;
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
- int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
+ int cmp = compare_prefix(iter->iter0->ref.name, iter->prefix);
if (cmp < 0)
continue;
/*
@@ -382,6 +350,8 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
if (cmp > 0)
return ITER_DONE;
+ iter->base.ref = iter->iter0->ref;
+
if (iter->trim) {
/*
* It is nonsense to trim off characters that
@@ -392,15 +362,11 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
* one character left in the refname after
* trimming, report it as a bug:
*/
- if (strlen(iter->iter0->refname) <= iter->trim)
+ if (strlen(iter->base.ref.name) <= iter->trim)
BUG("attempt to trim too many characters");
- iter->base.refname = iter->iter0->refname + iter->trim;
- } else {
- iter->base.refname = iter->iter0->refname;
+ iter->base.ref.name += iter->trim;
}
- iter->base.oid = iter->iter0->oid;
- iter->base.flags = iter->iter0->flags;
return ITER_OK;
}
@@ -420,15 +386,6 @@ static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator,
return ref_iterator_seek(iter->iter0, refname, flags);
}
-static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct prefix_ref_iterator *iter =
- (struct prefix_ref_iterator *)ref_iterator;
-
- return ref_iterator_peel(iter->iter0, peeled);
-}
-
static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct prefix_ref_iterator *iter =
@@ -440,7 +397,6 @@ static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
.advance = prefix_ref_iterator_advance,
.seek = prefix_ref_iterator_seek,
- .peel = prefix_ref_iterator_peel,
.release = prefix_ref_iterator_release,
};
@@ -466,23 +422,18 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
return ref_iterator;
}
-struct ref_iterator *current_ref_iter = NULL;
-
int do_for_each_ref_iterator(struct ref_iterator *iter,
each_ref_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);
+ retval = fn(&iter->ref, cb_data);
if (retval)
goto out;
}
out:
- current_ref_iter = old_ref_iter;
if (ok == ITER_ERROR)
retval = -1;
ref_iterator_free(iter);
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index a8c22a0a7f..1ab0c50393 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -882,6 +882,7 @@ static int next_record(struct packed_ref_iterator *iter)
{
const char *p, *eol;
+ memset(&iter->base.ref, 0, sizeof(iter->base.ref));
strbuf_reset(&iter->refname_buf);
/*
@@ -908,7 +909,7 @@ static int next_record(struct packed_ref_iterator *iter)
if (iter->pos == iter->eof)
return ITER_DONE;
- iter->base.flags = REF_ISPACKED;
+ iter->base.ref.flags = REF_ISPACKED;
p = iter->pos;
if (iter->eof - p < snapshot_hexsz(iter->snapshot) + 2 ||
@@ -916,6 +917,7 @@ static int next_record(struct packed_ref_iterator *iter)
!isspace(*p++))
die_invalid_line(iter->snapshot->refs->path,
iter->pos, iter->eof - iter->pos);
+ iter->base.ref.oid = &iter->oid;
eol = memchr(p, '\n', iter->eof - p);
if (!eol)
@@ -923,22 +925,22 @@ static int next_record(struct packed_ref_iterator *iter)
iter->pos, iter->eof - iter->pos);
strbuf_add(&iter->refname_buf, p, eol - p);
- iter->base.refname = iter->refname_buf.buf;
+ iter->base.ref.name = iter->refname_buf.buf;
if (refname_contains_nul(&iter->refname_buf))
- die("packed refname contains embedded NULL: %s", iter->base.refname);
+ die("packed refname contains embedded NULL: %s", iter->base.ref.name);
- if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) {
- if (!refname_is_safe(iter->base.refname))
+ if (check_refname_format(iter->base.ref.name, REFNAME_ALLOW_ONELEVEL)) {
+ if (!refname_is_safe(iter->base.ref.name))
die("packed refname is dangerous: %s",
- iter->base.refname);
+ iter->base.ref.name);
oidclr(&iter->oid, iter->repo->hash_algo);
- iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN;
+ iter->base.ref.flags |= REF_BAD_NAME | REF_ISBROKEN;
}
if (iter->snapshot->peeled == PEELED_FULLY ||
(iter->snapshot->peeled == PEELED_TAGS &&
- starts_with(iter->base.refname, "refs/tags/")))
- iter->base.flags |= REF_KNOWS_PEELED;
+ starts_with(iter->base.ref.name, "refs/tags/")))
+ iter->base.ref.flags |= REF_KNOWS_PEELED;
iter->pos = eol + 1;
@@ -956,11 +958,12 @@ static int next_record(struct packed_ref_iterator *iter)
* definitely know the value of *this* reference. But
* we suppress it if the reference is broken:
*/
- if ((iter->base.flags & REF_ISBROKEN)) {
+ if ((iter->base.ref.flags & REF_ISBROKEN)) {
oidclr(&iter->peeled, iter->repo->hash_algo);
- iter->base.flags &= ~REF_KNOWS_PEELED;
+ iter->base.ref.flags &= ~REF_KNOWS_PEELED;
} else {
- iter->base.flags |= REF_KNOWS_PEELED;
+ iter->base.ref.flags |= REF_KNOWS_PEELED;
+ iter->base.ref.peeled_oid = &iter->peeled;
}
} else {
oidclr(&iter->peeled, iter->repo->hash_algo);
@@ -976,15 +979,15 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
int ok;
while ((ok = next_record(iter)) == ITER_OK) {
- const char *refname = iter->base.refname;
+ const char *refname = iter->base.ref.name;
const char *prefix = iter->prefix;
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
- !is_per_worktree_ref(iter->base.refname))
+ !is_per_worktree_ref(iter->base.ref.name))
continue;
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
- !ref_resolves_to_object(iter->base.refname, iter->repo,
+ !ref_resolves_to_object(iter->base.ref.name, iter->repo,
&iter->oid, iter->flags))
continue;
@@ -1027,22 +1030,6 @@ static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator,
return 0;
}
-static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct packed_ref_iterator *iter =
- (struct packed_ref_iterator *)ref_iterator;
-
- if ((iter->base.flags & REF_KNOWS_PEELED)) {
- oidcpy(peeled, &iter->peeled);
- return is_null_oid(&iter->peeled) ? -1 : 0;
- } else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) {
- return -1;
- } else {
- return peel_object(iter->repo, &iter->oid, peeled) ? -1 : 0;
- }
-}
-
static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct packed_ref_iterator *iter =
@@ -1056,7 +1043,6 @@ static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable packed_ref_iterator_vtable = {
.advance = packed_ref_iterator_advance,
.seek = packed_ref_iterator_seek,
- .peel = packed_ref_iterator_peel,
.release = packed_ref_iterator_release,
};
@@ -1194,7 +1180,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
iter->snapshot = snapshot;
acquire_snapshot(snapshot);
strbuf_init(&iter->refname_buf, 0);
- iter->base.oid = &iter->oid;
iter->repo = ref_store->repo;
iter->flags = flags;
@@ -1436,7 +1421,7 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
if (!iter)
cmp = +1;
else
- cmp = strcmp(iter->refname, update->refname);
+ cmp = strcmp(iter->ref.name, update->refname);
}
if (!cmp) {
@@ -1459,11 +1444,11 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
}
goto error;
- } else if (!oideq(&update->old_oid, iter->oid)) {
+ } else if (!oideq(&update->old_oid, iter->ref.oid)) {
strbuf_addf(err, "cannot update ref '%s': "
"is at %s but expected %s",
update->refname,
- oid_to_hex(iter->oid),
+ oid_to_hex(iter->ref.oid),
oid_to_hex(&update->old_oid));
ret = REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE;
@@ -1523,13 +1508,8 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
if (cmp < 0) {
/* Pass the old reference through. */
-
- struct object_id peeled;
- int peel_error = ref_iterator_peel(iter, &peeled);
-
- if (write_packed_entry(out, iter->refname,
- iter->oid,
- peel_error ? NULL : &peeled))
+ if (write_packed_entry(out, iter->ref.name,
+ iter->ref.oid, iter->ref.peeled_oid))
goto write_error;
if ((ok = ref_iterator_advance(iter)) != ITER_OK) {
@@ -1547,9 +1527,8 @@ static enum ref_transaction_error write_with_updates(struct packed_ref_store *re
i++;
} else {
struct object_id peeled;
- int peel_error = peel_object(refs->base.repo,
- &update->new_oid,
- &peeled);
+ int peel_error = peel_object(refs->base.repo, &update->new_oid,
+ &peeled, PEEL_OBJECT_VERIFY_OBJECT_TYPE);
if (write_packed_entry(out, update->refname,
&update->new_oid,
diff --git a/refs/ref-cache.c b/refs/ref-cache.c
index e5e5df16d8..ffef01a597 100644
--- a/refs/ref-cache.c
+++ b/refs/ref-cache.c
@@ -425,10 +425,11 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
level->prefix_state = entry_prefix_state;
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;
+ memset(&iter->base.ref, 0, sizeof(iter->base.ref));
+ iter->base.ref.name = entry->name;
+ iter->base.ref.target = entry->u.value.referent;
+ iter->base.ref.oid = &entry->u.value.oid;
+ iter->base.ref.flags = entry->flag;
return ITER_OK;
}
}
@@ -545,14 +546,6 @@ static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator,
return 0;
}
-static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct cache_ref_iterator *iter =
- (struct cache_ref_iterator *)ref_iterator;
- return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0;
-}
-
static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct cache_ref_iterator *iter =
@@ -564,7 +557,6 @@ static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable cache_ref_iterator_vtable = {
.advance = cache_ref_iterator_advance,
.seek = cache_ref_iterator_seek,
- .peel = cache_ref_iterator_peel,
.release = cache_ref_iterator_release,
};
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 4ef3bd75c6..4671517dad 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -249,10 +249,7 @@ const char *find_descendant_ref(const char *dirname,
*/
struct ref_iterator {
struct ref_iterator_vtable *vtable;
- const char *refname;
- const char *referent;
- const struct object_id *oid;
- unsigned int flags;
+ struct reference ref;
};
/*
@@ -361,12 +358,6 @@ typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator,
const char *refname, unsigned int flags);
/*
- * Peels the current ref, returning 0 for success or -1 for failure.
- */
-typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator,
- struct object_id *peeled);
-
-/*
* Implementations of this function should free any resources specific
* to the derived class.
*/
@@ -375,23 +366,9 @@ typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator);
struct ref_iterator_vtable {
ref_iterator_advance_fn *advance;
ref_iterator_seek_fn *seek;
- ref_iterator_peel_fn *peel;
ref_iterator_release_fn *release;
};
-/*
- * current_ref_iter is a performance hack: when iterating over
- * references using the for_each_ref*() functions, current_ref_iter is
- * set to the reference iterator before calling the callback function.
- * If the callback function calls peel_ref(), then peel_ref() first
- * checks whether the reference to be peeled is the one referred to by
- * the iterator (it usually is) and if so, asks the iterator for the
- * peeled version of the reference if it is available. This avoids a
- * refname lookup in a common case. current_ref_iter is set to NULL
- * when the iteration is over.
- */
-extern struct ref_iterator *current_ref_iter;
-
struct ref_store;
/* refs backends */
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index eeec64798f..d46287b5ef 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -547,6 +547,7 @@ struct reftable_ref_iterator {
struct reftable_iterator iter;
struct reftable_ref_record ref;
struct object_id oid;
+ struct object_id peeled_oid;
char *prefix;
size_t prefix_len;
@@ -671,6 +672,8 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
case REFTABLE_REF_VAL2:
oidread(&iter->oid, iter->ref.value.val2.value,
refs->base.repo->hash_algo);
+ oidread(&iter->peeled_oid, iter->ref.value.val2.target_value,
+ refs->base.repo->hash_algo);
break;
case REFTABLE_REF_SYMREF:
referent = refs_resolve_ref_unsafe(&iter->refs->base,
@@ -704,10 +707,13 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
&iter->oid, flags))
continue;
- iter->base.refname = iter->ref.refname;
- iter->base.referent = referent;
- iter->base.oid = &iter->oid;
- iter->base.flags = flags;
+ memset(&iter->base.ref, 0, sizeof(iter->base.ref));
+ iter->base.ref.name = iter->ref.refname;
+ iter->base.ref.target = referent;
+ iter->base.ref.oid = &iter->oid;
+ if (iter->ref.value_type == REFTABLE_REF_VAL2)
+ iter->base.ref.peeled_oid = &iter->peeled_oid;
+ iter->base.ref.flags = flags;
break;
}
@@ -738,21 +744,6 @@ static int reftable_ref_iterator_seek(struct ref_iterator *ref_iterator,
return iter->err;
}
-static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator,
- struct object_id *peeled)
-{
- struct reftable_ref_iterator *iter =
- (struct reftable_ref_iterator *)ref_iterator;
-
- if (iter->ref.value_type == REFTABLE_REF_VAL2) {
- oidread(peeled, iter->ref.value.val2.target_value,
- iter->refs->base.repo->hash_algo);
- return 0;
- }
-
- return -1;
-}
-
static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator)
{
struct reftable_ref_iterator *iter =
@@ -770,7 +761,6 @@ static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable reftable_ref_iterator_vtable = {
.advance = reftable_ref_iterator_advance,
.seek = reftable_ref_iterator_seek,
- .peel = reftable_ref_iterator_peel,
.release = reftable_ref_iterator_release,
};
@@ -828,7 +818,7 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
iter = xcalloc(1, sizeof(*iter));
base_ref_iterator_init(&iter->base, &reftable_ref_iterator_vtable);
- iter->base.oid = &iter->oid;
+ iter->base.ref.oid = &iter->oid;
iter->flags = flags;
iter->refs = refs;
iter->exclude_patterns = filter_exclude_patterns(exclude_patterns);
@@ -1642,7 +1632,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
ref.refname = (char *)u->refname;
ref.update_index = ts;
- peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled);
+ peel_error = peel_object(arg->refs->base.repo, &u->new_oid, &peeled,
+ PEEL_OBJECT_VERIFY_OBJECT_TYPE);
if (!peel_error) {
ref.value_type = REFTABLE_REF_VAL2;
memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
@@ -2072,7 +2063,7 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator)
strbuf_reset(&iter->last_name);
strbuf_addstr(&iter->last_name, iter->log.refname);
- iter->base.refname = iter->log.refname;
+ iter->base.ref.name = iter->log.refname;
break;
}
@@ -2092,13 +2083,6 @@ static int reftable_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSE
return -1;
}
-static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
- struct object_id *peeled UNUSED)
-{
- BUG("reftable reflog iterator cannot be peeled");
- return -1;
-}
-
static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator)
{
struct reftable_reflog_iterator *iter =
@@ -2111,7 +2095,6 @@ static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator)
static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
.advance = reftable_reflog_iterator_advance,
.seek = reftable_reflog_iterator_seek,
- .peel = reftable_reflog_iterator_peel,
.release = reftable_reflog_iterator_release,
};
@@ -2515,7 +2498,7 @@ static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_da
ref.refname = (char *)arg->refname;
ref.update_index = ts;
- if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled)) {
+ if (!peel_object(arg->refs->base.repo, &arg->update_oid, &peeled, 0)) {
ref.value_type = REFTABLE_REF_VAL2;
memcpy(ref.value.val2.target_value, peeled.hash, GIT_MAX_RAWSZ);
memcpy(ref.value.val2.value, arg->update_oid.hash, GIT_MAX_RAWSZ);
diff --git a/remote.c b/remote.c
index df9675cd33..59b3715120 100644
--- a/remote.c
+++ b/remote.c
@@ -2315,21 +2315,19 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
return 1;
}
-static int one_local_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED,
- void *cb_data)
+static int one_local_ref(const struct reference *ref, void *cb_data)
{
struct ref ***local_tail = cb_data;
- struct ref *ref;
+ struct ref *local_ref;
/* we already know it starts with refs/ to get here */
- if (check_refname_format(refname + 5, 0))
+ if (check_refname_format(ref->name + 5, 0))
return 0;
- ref = alloc_ref(refname);
- oidcpy(&ref->new_oid, oid);
- **local_tail = ref;
- *local_tail = &ref->next;
+ local_ref = alloc_ref(ref->name);
+ oidcpy(&local_ref->new_oid, ref->oid);
+ **local_tail = local_ref;
+ *local_tail = &local_ref->next;
return 0;
}
@@ -2402,15 +2400,14 @@ struct stale_heads_info {
struct refspec *rs;
};
-static int get_stale_heads_cb(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flags, void *cb_data)
+static int get_stale_heads_cb(const struct reference *ref, void *cb_data)
{
struct stale_heads_info *info = cb_data;
struct string_list matches = STRING_LIST_INIT_DUP;
struct refspec_item query;
int i, stale = 1;
memset(&query, 0, sizeof(struct refspec_item));
- query.dst = (char *)refname;
+ query.dst = (char *)ref->name;
refspec_find_all_matches(info->rs, &query, &matches);
if (matches.nr == 0)
@@ -2423,7 +2420,7 @@ static int get_stale_heads_cb(const char *refname, const char *referent UNUSED,
* overlapping refspecs, we need to go over all of the
* matching refs.
*/
- if (flags & REF_ISSYMREF)
+ if (ref->flags & REF_ISSYMREF)
goto clean_exit;
for (i = 0; stale && i < matches.nr; i++)
@@ -2431,8 +2428,8 @@ static int get_stale_heads_cb(const char *refname, const char *referent UNUSED,
stale = 0;
if (stale) {
- struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
- oidcpy(&ref->new_oid, oid);
+ struct ref *linked_ref = make_linked_ref(ref->name, &info->stale_refs_tail);
+ oidcpy(&linked_ref->new_oid, ref->oid);
}
clean_exit:
diff --git a/repack-midx.c b/repack-midx.c
index 6f6202c5bc..74bdfa3a6e 100644
--- a/repack-midx.c
+++ b/repack-midx.c
@@ -16,25 +16,23 @@ struct midx_snapshot_ref_data {
int preferred;
};
-static int midx_snapshot_ref_one(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flag UNUSED, void *_data)
+static int midx_snapshot_ref_one(const struct reference *ref, void *_data)
{
struct midx_snapshot_ref_data *data = _data;
+ const struct object_id *maybe_peeled = ref->oid;
struct object_id peeled;
- if (!peel_iterated_oid(data->repo, oid, &peeled))
- oid = &peeled;
+ if (!reference_get_peeled_oid(data->repo, ref, &peeled))
+ maybe_peeled = &peeled;
- if (oidset_insert(&data->seen, oid))
+ if (oidset_insert(&data->seen, maybe_peeled))
return 0; /* already seen */
- if (odb_read_object_info(data->repo->objects, oid, NULL) != OBJ_COMMIT)
+ if (odb_read_object_info(data->repo->objects, maybe_peeled, NULL) != OBJ_COMMIT)
return 0;
fprintf(data->f->fp, "%s%s\n", data->preferred ? "+" : "",
- oid_to_hex(oid));
+ oid_to_hex(maybe_peeled));
return 0;
}
diff --git a/replace-object.c b/replace-object.c
index 3eae051074..03d0f1f083 100644
--- a/replace-object.c
+++ b/replace-object.c
@@ -8,31 +8,27 @@
#include "repository.h"
#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)
+static int register_replace_ref(const struct reference *ref, void *cb_data)
{
struct repository *r = cb_data;
/* Get sha1 from refname */
- const char *slash = strrchr(refname, '/');
- const char *hash = slash ? slash + 1 : refname;
+ const char *slash = strrchr(ref->name, '/');
+ const char *hash = slash ? slash + 1 : ref->name;
struct replace_object *repl_obj = xmalloc(sizeof(*repl_obj));
if (get_oid_hex_algop(hash, &repl_obj->original.oid, r->hash_algo)) {
free(repl_obj);
- warning(_("bad replace ref name: %s"), refname);
+ warning(_("bad replace ref name: %s"), ref->name);
return 0;
}
/* Copy sha1 from the read ref */
- oidcpy(&repl_obj->replacement, oid);
+ oidcpy(&repl_obj->replacement, ref->oid);
/* Register new object */
if (oidmap_put(&r->objects->replace_map, repl_obj))
- die(_("duplicate replace ref: %s"), refname);
+ die(_("duplicate replace ref: %s"), ref->name);
return 0;
}
diff --git a/revision.c b/revision.c
index cf5e6c1ec9..5f0850ae5c 100644
--- a/revision.c
+++ b/revision.c
@@ -1644,19 +1644,17 @@ struct all_refs_cb {
struct worktree *wt;
};
-static int handle_one_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED,
- void *cb_data)
+static int handle_one_ref(const struct reference *ref, void *cb_data)
{
struct all_refs_cb *cb = cb_data;
struct object *object;
- if (ref_excluded(&cb->all_revs->ref_excludes, path))
+ if (ref_excluded(&cb->all_revs->ref_excludes, ref->name))
return 0;
- object = get_reference(cb->all_revs, path, oid, cb->all_flags);
- add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
- add_pending_object(cb->all_revs, object, path);
+ object = get_reference(cb->all_revs, ref->name, ref->oid, cb->all_flags);
+ add_rev_cmdline(cb->all_revs, object, ref->name, REV_CMD_REF, cb->all_flags);
+ add_pending_object(cb->all_revs, object, ref->name);
return 0;
}
diff --git a/server-info.c b/server-info.c
index b9a710544a..4243e24edc 100644
--- a/server-info.c
+++ b/server-info.c
@@ -148,23 +148,21 @@ out:
return ret;
}
-static int add_info_ref(const char *path, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED,
- void *cb_data)
+static int add_info_ref(const struct reference *ref, void *cb_data)
{
struct update_info_ctx *uic = cb_data;
- struct object *o = parse_object(uic->repo, oid);
+ struct object *o = parse_object(uic->repo, ref->oid);
if (!o)
return -1;
- if (uic_printf(uic, "%s %s\n", oid_to_hex(oid), path) < 0)
+ if (uic_printf(uic, "%s %s\n", oid_to_hex(ref->oid), ref->name) < 0)
return -1;
if (o->type == OBJ_TAG) {
- o = deref_tag(uic->repo, o, path, 0);
+ o = deref_tag(uic->repo, o, ref->name, 0);
if (o)
if (uic_printf(uic, "%s %s^{}\n",
- oid_to_hex(&o->oid), path) < 0)
+ oid_to_hex(&o->oid), ref->name) < 0)
return -1;
}
return 0;
diff --git a/shallow.c b/shallow.c
index d9cd4e219c..55b9cd9d3f 100644
--- a/shallow.c
+++ b/shallow.c
@@ -626,14 +626,10 @@ static void paint_down(struct paint_info *info, const struct object_id *oid,
free(tmp);
}
-static int mark_uninteresting(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flags UNUSED,
- void *cb_data UNUSED)
+static int mark_uninteresting(const struct reference *ref, void *cb_data UNUSED)
{
struct commit *commit = lookup_commit_reference_gently(the_repository,
- oid, 1);
+ ref->oid, 1);
if (!commit)
return 0;
commit->object.flags |= UNINTERESTING;
@@ -742,16 +738,12 @@ struct commit_array {
size_t nr, alloc;
};
-static int add_ref(const char *refname UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flags UNUSED,
- void *cb_data)
+static int add_ref(const struct reference *ref, void *cb_data)
{
struct commit_array *ca = cb_data;
ALLOC_GROW(ca->commits, ca->nr + 1, ca->alloc);
ca->commits[ca->nr] = lookup_commit_reference_gently(the_repository,
- oid, 1);
+ ref->oid, 1);
if (ca->commits[ca->nr])
ca->nr++;
return 0;
diff --git a/submodule.c b/submodule.c
index 35c55155f7..40a5c6fb9d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -934,10 +934,7 @@ static void free_submodules_data(struct string_list *submodules)
string_list_clear(submodules, 1);
}
-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)
+static int has_remote(const struct reference *ref UNUSED, void *cb_data UNUSED)
{
return 1;
}
@@ -1255,13 +1252,10 @@ int push_unpushed_submodules(struct repository *r,
return ret;
}
-static int append_oid_to_array(const char *ref UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flags UNUSED, void *data)
+static int append_oid_to_array(const struct reference *ref, void *data)
{
struct oid_array *array = data;
- oid_array_append(array, oid);
+ oid_array_append(array, ref->oid);
return 0;
}
diff --git a/t/for-each-ref-tests.sh b/t/for-each-ref-tests.sh
index e3ad19298a..4593be5fd5 100644
--- a/t/for-each-ref-tests.sh
+++ b/t/for-each-ref-tests.sh
@@ -1809,7 +1809,9 @@ test_expect_success "${git_for_each_ref} reports broken tags" '
bad=$(git hash-object -w -t tag bad) &&
git update-ref refs/tags/broken-tag-bad $bad &&
test_must_fail ${git_for_each_ref} --format="%(*objectname)" \
- refs/tags/broken-tag-*
+ refs/tags/broken-tag-* &&
+ test_must_fail ${git_for_each_ref} --format="%(*objectname)" \
+ refs/tags/broken-tag-bad
'
test_expect_success 'set up tag with signature and no blank lines' '
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 028ec00306..c58c93800f 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -63,7 +63,7 @@ int cmd__reach(int ac, const char **av)
die("failed to resolve %s", buf.buf + 2);
orig = parse_object(r, &oid);
- peeled = deref_tag_noverify(the_repository, orig);
+ peeled = deref_tag(the_repository, orig, NULL, 0);
if (!peeled)
die("failed to load commit for input %s resulting in oid %s",
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 83b06d39a3..b1215947c5 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -154,10 +154,9 @@ 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 char *referent UNUSED, const struct object_id *oid,
- int flags, void *cb_data UNUSED)
+static int each_ref(const struct reference *ref, void *cb_data UNUSED)
{
- printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
+ printf("%s %s 0x%x\n", oid_to_hex(ref->oid), ref->name, ref->flags);
return 0;
}
diff --git a/t/pack-refs-tests.sh b/t/pack-refs-tests.sh
index 3dbcc01718..095823d915 100644
--- a/t/pack-refs-tests.sh
+++ b/t/pack-refs-tests.sh
@@ -428,4 +428,36 @@ do
'
done
+test_expect_success 'pack-refs does not store invalid peeled tag value' '
+ test_when_finished rm -rf repo &&
+ git init repo &&
+ (
+ cd repo &&
+ git commit --allow-empty --message initial &&
+
+ echo garbage >blob-content &&
+ blob_id=$(git hash-object -w -t blob blob-content) &&
+
+ # Write an invalid tag into the object database. The tag itself
+ # is well-formed, but the tagged object is a blob while we
+ # claim that it is a commit.
+ cat >tag-content <<-EOF &&
+ object $blob_id
+ type commit
+ tag bad-tag
+ tagger C O Mitter <committer@example.com> 1112354055 +0200
+
+ annotated
+ EOF
+ tag_id=$(git hash-object -w -t tag tag-content) &&
+ git update-ref refs/tags/bad-tag "$tag_id" &&
+
+ # The packed-refs file should not contain the peeled object ID.
+ # If it did this would cause commands that use the peeled value
+ # to not notice this corrupted tag.
+ git pack-refs --all &&
+ test_grep ! "^\^" .git/packed-refs
+ )
+'
+
test_done
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index 3ea5d51532..6575528f21 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -1135,4 +1135,32 @@ test_expect_success 'fetch: accessing FETCH_HEAD special ref works' '
test_cmp expect actual
'
+test_expect_success 'writes do not persist peeled value for invalid tags' '
+ test_when_finished rm -rf repo &&
+ git init repo &&
+ (
+ cd repo &&
+ git commit --allow-empty --message initial &&
+
+ # We cannot easily verify that the peeled value is not stored
+ # in the tables. Instead, we test this indirectly: we create
+ # two tags that both point to the same object, but they claim
+ # different object types. If we parse both tags we notice that
+ # the parsed tagged object has a mismatch between the two tags
+ # and bail out.
+ #
+ # If we instead use the persisted peeled value we would not
+ # even parse the tags. As such, we would not notice the
+ # discrepancy either and thus listing these tags would succeed.
+ git tag tag-1 -m "tag 1" &&
+ git cat-file tag tag-1 >raw-tag &&
+ sed "s/^type commit$/type blob/" <raw-tag >broken-tag &&
+ broken_tag_id=$(git hash-object -w -t tag broken-tag) &&
+ git update-ref refs/tags/tag-2 $broken_tag_id &&
+
+ test_must_fail git for-each-ref --format="%(*objectname)" refs/tags/ 2>err &&
+ test_grep "bad tag pointer" err
+ )
+'
+
test_done
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 10835631ca..ce2ff2a28a 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -2293,24 +2293,26 @@ test_expect_success '--contains combined with --no-contains' '
# don't recurse down to tags for trees or blobs pointed to by *those*
# commits.
test_expect_success 'Does --[no-]contains stop at commits? Yes!' '
- cd no-contains &&
- blob=$(git rev-parse v0.3:v0.3.t) &&
- tree=$(git rev-parse v0.3^{tree}) &&
- git tag tag-blob $blob &&
- git tag tag-tree $tree &&
- git tag --contains v0.3 >actual &&
- cat >expected <<-\EOF &&
- v0.3
- v0.4
- v0.5
- EOF
- test_cmp expected actual &&
- git tag --no-contains v0.3 >actual &&
- cat >expected <<-\EOF &&
- v0.1
- v0.2
- EOF
- test_cmp expected actual
+ (
+ cd no-contains &&
+ blob=$(git rev-parse v0.3:v0.3.t) &&
+ tree=$(git rev-parse v0.3^{tree}) &&
+ git tag tag-blob $blob &&
+ git tag tag-tree $tree &&
+ git tag --contains v0.3 >actual &&
+ cat >expected <<-\EOF &&
+ v0.3
+ v0.4
+ v0.5
+ EOF
+ test_cmp expected actual &&
+ git tag --no-contains v0.3 >actual &&
+ cat >expected <<-\EOF &&
+ v0.1
+ v0.2
+ EOF
+ test_cmp expected actual
+ )
'
test_expect_success 'If tag is created then tag message file is unlinked' '
@@ -2332,4 +2334,24 @@ test_expect_success 'If tag cannot be created then tag message file is not unlin
test_path_exists .git/TAG_EDITMSG
'
+test_expect_success 'annotated tag version sort' '
+ git tag -a -m "sample 1.0" vsample-1.0 &&
+ git tag -a -m "sample 2.0" vsample-2.0 &&
+ git tag -a -m "sample 10.0" vsample-10.0 &&
+ cat >expect <<-EOF &&
+ vsample-1.0
+ vsample-2.0
+ vsample-10.0
+ EOF
+
+ git tag --list --sort=version:tag vsample-\* >actual &&
+ test_cmp expect actual &&
+
+ # Ensure that we also handle this case alright in the case we have the
+ # peeled values cached e.g. via the packed-refs file.
+ git pack-refs --all &&
+ git tag --list --sort=version:tag vsample-\* &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/tag.c b/tag.c
index 1d52686ee1..f5c232d2f1 100644
--- a/tag.c
+++ b/tag.c
@@ -94,18 +94,6 @@ struct object *deref_tag(struct repository *r, struct object *o, const char *war
return o;
}
-struct object *deref_tag_noverify(struct repository *r, struct object *o)
-{
- while (o && o->type == OBJ_TAG) {
- o = parse_object(r, &o->oid);
- if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
- o = ((struct tag *)o)->tagged;
- else
- o = NULL;
- }
- return o;
-}
-
struct tag *lookup_tag(struct repository *r, const struct object_id *oid)
{
struct object *obj = lookup_object(r, oid);
diff --git a/tag.h b/tag.h
index c49d7c19ad..ef12a61037 100644
--- a/tag.h
+++ b/tag.h
@@ -16,7 +16,6 @@ int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, u
int parse_tag(struct tag *item);
void release_tag_memory(struct tag *t);
struct object *deref_tag(struct repository *r, struct object *, const char *, int);
-struct object *deref_tag_noverify(struct repository *r, struct object *);
int gpg_verify_tag(const struct object_id *oid,
const char *name_to_report, unsigned flags);
struct object_id *get_tagged_oid(struct tag *tag);
diff --git a/upload-pack.c b/upload-pack.c
index 1e87ae9559..2d2b70cbf2 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -870,8 +870,8 @@ static void send_unshallow(struct upload_pack_data *data)
}
}
-static int check_ref(const char *refname_full, const char *referent UNUSED, const struct object_id *oid,
- int flag, void *cb_data);
+static int check_ref(const struct reference *ref, void *cb_data);
+
static void deepen(struct upload_pack_data *data, int depth)
{
if (depth == INFINITE_DEPTH && !is_repository_shallow(the_repository)) {
@@ -1224,13 +1224,12 @@ static int mark_our_ref(const char *refname, const char *refname_full,
return 0;
}
-static int check_ref(const char *refname_full, const char *referent UNUSED,const struct object_id *oid,
- int flag UNUSED, void *cb_data)
+static int check_ref(const struct reference *ref, void *cb_data)
{
- const char *refname = strip_namespace(refname_full);
+ const char *refname = strip_namespace(ref->name);
struct upload_pack_data *data = cb_data;
- mark_our_ref(refname, refname_full, oid, &data->hidden_refs);
+ mark_our_ref(refname, ref->name, ref->oid, &data->hidden_refs);
return 0;
}
@@ -1250,15 +1249,15 @@ static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
}
static void write_v0_ref(struct upload_pack_data *data,
- const char *refname, const char *refname_nons,
- const struct object_id *oid)
+ const struct reference *ref,
+ const char *refname_nons)
{
static const char *capabilities = "multi_ack thin-pack side-band"
" side-band-64k ofs-delta shallow deepen-since deepen-not"
" deepen-relative no-progress include-tag multi_ack_detailed";
struct object_id peeled;
- if (mark_our_ref(refname_nons, refname, oid, &data->hidden_refs))
+ if (mark_our_ref(refname_nons, ref->name, ref->oid, &data->hidden_refs))
return;
if (capabilities) {
@@ -1268,7 +1267,7 @@ static void write_v0_ref(struct upload_pack_data *data,
format_symref_info(&symref_info, &data->symref);
format_session_id(&session_id, data);
packet_fwrite_fmt(stdout, "%s %s%c%s%s%s%s%s%s%s object-format=%s agent=%s\n",
- oid_to_hex(oid), refname_nons,
+ oid_to_hex(ref->oid), refname_nons,
0, capabilities,
(data->allow_uor & ALLOW_TIP_SHA1) ?
" allow-tip-sha1-in-want" : "",
@@ -1284,35 +1283,33 @@ static void write_v0_ref(struct upload_pack_data *data,
strbuf_release(&session_id);
data->sent_capabilities = 1;
} else {
- packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
+ packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(ref->oid), refname_nons);
}
capabilities = NULL;
- if (!peel_iterated_oid(the_repository, oid, &peeled))
+ if (!reference_get_peeled_oid(the_repository, ref, &peeled))
packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
return;
}
-static int send_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid,
- int flag UNUSED, void *cb_data)
+static int send_ref(const struct reference *ref, void *cb_data)
{
- write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
+ write_v0_ref(cb_data, ref, strip_namespace(ref->name));
return 0;
}
-static int find_symref(const char *refname, const char *referent UNUSED,
- const struct object_id *oid UNUSED,
- int flag, void *cb_data)
+static int find_symref(const struct reference *ref, void *cb_data)
{
const char *symref_target;
struct string_list_item *item;
+ int flag;
- if ((flag & REF_ISSYMREF) == 0)
+ if ((ref->flags & REF_ISSYMREF) == 0)
return 0;
symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
- refname, 0, NULL, &flag);
+ ref->name, 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));
+ die("'%s' is a symref but it is not?", ref->name);
+ item = string_list_append(cb_data, strip_namespace(ref->name));
item->util = xstrdup(strip_namespace(symref_target));
return 0;
}
@@ -1445,8 +1442,12 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
send_ref, &data);
for_each_namespaced_ref_1(send_ref, &data);
if (!data.sent_capabilities) {
- const char *refname = "capabilities^{}";
- write_v0_ref(&data, refname, refname, null_oid(the_hash_algo));
+ struct reference ref = {
+ .name = "capabilities^{}",
+ .oid = null_oid(the_hash_algo),
+ };
+
+ write_v0_ref(&data, &ref, ref.name);
}
/*
* fflush stdout before calling advertise_shallow_grafts because send_ref
diff --git a/walker.c b/walker.c
index 8073754517..409b646578 100644
--- a/walker.c
+++ b/walker.c
@@ -226,14 +226,10 @@ static int interpret_target(struct walker *walker, char *target, struct object_i
return -1;
}
-static int mark_complete(const char *path UNUSED,
- const char *referent UNUSED,
- const struct object_id *oid,
- int flag UNUSED,
- void *cb_data UNUSED)
+static int mark_complete(const struct reference *ref, void *cb_data UNUSED)
{
struct commit *commit = lookup_commit_reference_gently(the_repository,
- oid, 1);
+ ref->oid, 1);
if (commit) {
commit->object.flags |= COMPLETE;
diff --git a/worktree.c b/worktree.c
index a2a5f51f29..9308389cb6 100644
--- a/worktree.c
+++ b/worktree.c
@@ -595,8 +595,15 @@ int other_head_refs(each_ref_fn fn, void *cb_data)
if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
refname.buf,
RESOLVE_REF_READING,
- &oid, &flag))
- ret = fn(refname.buf, NULL, &oid, flag, cb_data);
+ &oid, &flag)) {
+ struct reference ref = {
+ .name = refname.buf,
+ .oid = &oid,
+ .flags = flag,
+ };
+
+ ret = fn(&ref, cb_data);
+ }
if (ret)
break;
}