ref-filter: propagate peeled object ID
When queueing a reference in the "ref-filter" subsystem we end up creating a new ref array item that contains the reference's info. One bit of info that we always discard though is the peeled object ID, and because of that we are forced to use `peel_iterated_oid()`. Refactor the code to propagate the peeled object ID via the ref array, if available. This allows us to manually peel tags without having to go through the object database. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Oct 23, 2025 at 09:16 UTC
70b783c3a194746d8b747677615f33b94454146f
5 files changed
+45
-32
builtin/ls-remote.c
+1
-1
@@ -156,7 +156,7 @@ int cmd_ls_remote(int argc,
156
continue;
157
if (!tail_match(&pattern, ref->name))
158
continue;
159
- item = ref_array_push(&ref_array, ref->name, &ref->old_oid);
159
+ item = ref_array_push(&ref_array, ref->name, &ref->old_oid, NULL);
160
item->symref = xstrdup_or_null(ref->symref);
161
}
162
builtin/tag.c
+1
-1
@@ -153,7 +153,7 @@ static int verify_tag(const char *name, const char *ref UNUSED,
153
return -1;
154
155
if (format->format)
156
- pretty_print_ref(name, oid, format);
156
+ pretty_print_ref(name, oid, NULL, format);
157
158
return 0;
159
}
builtin/verify-tag.c
+1
-1
@@ -67,7 +67,7 @@ int cmd_verify_tag(int argc,
67
}
68
69
if (format.format)
70
- pretty_print_ref(name, &oid, &format);
70
+ pretty_print_ref(name, &oid, NULL, &format);
71
}
72
return had_error;
73
}
ref-filter.c
+38
-28
@@ -2578,8 +2578,15 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
2578
* If it is a tag object, see if we use the peeled value. If we do,
2579
* grab the peeled OID.
2580
*/
2581
- if (need_tagged && peel_iterated_oid(the_repository, &obj->oid, &oi_deref.oid))
2582
- die("bad tag");
2581
+ if (need_tagged) {
2582
+ if (!is_null_oid(&ref->peeled_oid)) {
2583
+ oidcpy(&oi_deref.oid, &ref->peeled_oid);
2584
+ } else if (!peel_object(the_repository, &obj->oid, &oi_deref.oid)) {
2585
+ /* We managed to peel the object ourselves. */
2586
+ } else {
2587
+ die("bad tag");
2588
+ }
2589
+ }
2590
2591
return get_object(ref, 1, &obj, &oi_deref, err);
2592
}
@@ -2807,12 +2814,15 @@ static int match_points_at(struct oid_array *points_at,
2814
* Callers can then fill in other struct members at their leisure.
2815
*/
2816
static struct ref_array_item *new_ref_array_item(const char *refname,
2810
- const struct object_id *oid)
2817
+ const struct object_id *oid,
2818
+ const struct object_id *peeled_oid)
2819
{
2820
struct ref_array_item *ref;
2821
2822
FLEX_ALLOC_STR(ref, refname, refname);
2823
oidcpy(&ref->objectname, oid);
2824
+ if (peeled_oid)
2825
+ oidcpy(&ref->peeled_oid, peeled_oid);
2826
ref->rest = NULL;
2827
2828
return ref;
@@ -2826,9 +2836,10 @@ static void ref_array_append(struct ref_array *array, struct ref_array_item *ref
2836
2837
struct ref_array_item *ref_array_push(struct ref_array *array,
2838
const char *refname,
2829
- const struct object_id *oid)
2839
+ const struct object_id *oid,
2840
+ const struct object_id *peeled_oid)
2841
{
2831
- struct ref_array_item *ref = new_ref_array_item(refname, oid);
2842
+ struct ref_array_item *ref = new_ref_array_item(refname, oid, peeled_oid);
2843
ref_array_append(array, ref);
2844
return ref;
2845
}
@@ -2871,25 +2882,25 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
2882
return ref_kind_from_refname(refname);
2883
}
2884
2874
-static struct ref_array_item *apply_ref_filter(const char *refname, const char *referent, const struct object_id *oid,
2875
- int flag, struct ref_filter *filter)
2885
+static struct ref_array_item *apply_ref_filter(const struct reference *ref,
2886
+ struct ref_filter *filter)
2887
{
2877
- struct ref_array_item *ref;
2888
+ struct ref_array_item *item;
2889
struct commit *commit = NULL;
2890
unsigned int kind;
2891
2881
- if (flag & REF_BAD_NAME) {
2882
- warning(_("ignoring ref with broken name %s"), refname);
2892
+ if (ref->flags & REF_BAD_NAME) {
2893
+ warning(_("ignoring ref with broken name %s"), ref->name);
2894
return NULL;
2895
}
2896
2886
- if (flag & REF_ISBROKEN) {
2887
- warning(_("ignoring broken ref %s"), refname);
2897
+ if (ref->flags & REF_ISBROKEN) {
2898
+ warning(_("ignoring broken ref %s"), ref->name);
2899
return NULL;
2900
}
2901
2902
/* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
2892
- kind = filter_ref_kind(filter, refname);
2903
+ kind = filter_ref_kind(filter, ref->name);
2904
2905
/*
2906
* Generally HEAD refs are printed with special description denoting a rebase,
@@ -2902,13 +2913,13 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
2913
else if (!(kind & filter->kind))
2914
return NULL;
2915
2905
- if (!filter_pattern_match(filter, refname))
2916
+ if (!filter_pattern_match(filter, ref->name))
2917
return NULL;
2918
2908
- if (filter_exclude_match(filter, refname))
2919
+ if (filter_exclude_match(filter, ref->name))
2920
return NULL;
2921
2911
- if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
2922
+ if (filter->points_at.nr && !match_points_at(&filter->points_at, ref->oid, ref->name))
2923
return NULL;
2924
2925
/*
@@ -2918,7 +2929,7 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
2929
*/
2930
if (filter->reachable_from || filter->unreachable_from ||
2931
filter->with_commit || filter->no_commit || filter->verbose) {
2921
- commit = lookup_commit_reference_gently(the_repository, oid, 1);
2932
+ commit = lookup_commit_reference_gently(the_repository, ref->oid, 1);
2933
if (!commit)
2934
return NULL;
2935
/* We perform the filtering for the '--contains' option... */
@@ -2936,13 +2947,13 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const char *
2947
* to do its job and the resulting list may yet to be pruned
2948
* by maxcount logic.
2949
*/
2939
- ref = new_ref_array_item(refname, oid);
2940
- ref->commit = commit;
2941
- ref->flag = flag;
2942
- ref->kind = kind;
2943
- ref->symref = xstrdup_or_null(referent);
2950
+ item = new_ref_array_item(ref->name, ref->oid, ref->peeled_oid);
2951
+ item->commit = commit;
2952
+ item->flag = ref->flags;
2953
+ item->kind = kind;
2954
+ item->symref = xstrdup_or_null(ref->target);
2955
2945
- return ref;
2956
+ return item;
2957
}
2958
2959
struct ref_filter_cbdata {
@@ -2959,8 +2970,7 @@ static int filter_one(const struct reference *ref, void *cb_data)
2970
struct ref_filter_cbdata *ref_cbdata = cb_data;
2971
struct ref_array_item *item;
2972
2962
- item = apply_ref_filter(ref->name, ref->target, ref->oid,
2963
- ref->flags, ref_cbdata->filter);
2973
+ item = apply_ref_filter(ref, ref_cbdata->filter);
2974
if (item)
2975
ref_array_append(ref_cbdata->array, item);
2976
@@ -2997,8 +3007,7 @@ static int filter_and_format_one(const struct reference *ref, void *cb_data)
3007
struct ref_array_item *item;
3008
struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
3009
3000
- item = apply_ref_filter(ref->name, ref->target, ref->oid,
3001
- ref->flags, ref_cbdata->filter);
3010
+ item = apply_ref_filter(ref, ref_cbdata->filter);
3011
if (!item)
3012
return 0;
3013
@@ -3585,13 +3594,14 @@ void print_formatted_ref_array(struct ref_array *array, struct ref_format *forma
3594
}
3595
3596
void pretty_print_ref(const char *name, const struct object_id *oid,
3597
+ const struct object_id *peeled_oid,
3598
struct ref_format *format)
3599
{
3600
struct ref_array_item *ref_item;
3601
struct strbuf output = STRBUF_INIT;
3602
struct strbuf err = STRBUF_INIT;
3603
3594
- ref_item = new_ref_array_item(name, oid);
3604
+ ref_item = new_ref_array_item(name, oid, peeled_oid);
3605
ref_item->kind = ref_kind_from_refname(name);
3606
if (format_ref_array_item(ref_item, format, &output, &err))
3607
die("%s", err.buf);
ref-filter.h
+4
-1
@@ -41,6 +41,7 @@ enum ref_sorting_order {
41
42
struct ref_array_item {
43
struct object_id objectname;
44
+ struct object_id peeled_oid;
45
const char *rest;
46
int flag;
47
unsigned int kind;
@@ -187,6 +188,7 @@ void print_formatted_ref_array(struct ref_array *array, struct ref_format *forma
188
* name must be a fully qualified refname.
189
*/
190
void pretty_print_ref(const char *name, const struct object_id *oid,
191
+ const struct object_id *peeled_oid,
192
struct ref_format *format);
193
194
/*
@@ -195,7 +197,8 @@ void pretty_print_ref(const char *name, const struct object_id *oid,
197
*/
198
struct ref_array_item *ref_array_push(struct ref_array *array,
199
const char *refname,
198
- const struct object_id *oid);
200
+ const struct object_id *oid,
201
+ const struct object_id *peeled_oid);
202
203
/*
204
* If the provided format includes ahead-behind atoms, then compute the