git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 06/13] ref-filter: propagate peeled object ID

From
Patrick Steinhardt <ps@pks.im>
Date
Oct 7, 2025, 10:58 UTC
Message-ID
<20251007-b4-pks-ref-filter-skip-parsing-objects-v1-6-916cc7c6886b@pks.im>
In-Reply-To
<20251007-b4-pks-ref-filter-skip-parsing-objects-v1-0-916cc7c6886b@pks.im>

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>
---
 builtin/ls-remote.c  |  2 +-
 builtin/tag.c        |  2 +-
 builtin/verify-tag.c |  2 +-
 ref-filter.c         | 66 ++++++++++++++++++++++++++++++----------------------
 ref-filter.h         |  5 +++-
 5 files changed, 45 insertions(+), 32 deletions(-)
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/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/ref-filter.c b/ref-filter.c
index 7740f35e93..b18a032e57 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -2578,8 +2578,15 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
 	 * 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, &obj->oid, &oi_deref.oid)) {
+			/* We managed to peel the object ourselves. */
+		} else {
+			die("bad tag");
+		}
+	}
 
 	return get_object(ref, 1, &obj, &oi_deref, err);
 }
@@ -2807,12 +2814,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 +2836,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 +2882,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 +2913,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 +2929,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 +2947,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 {
@@ -2959,8 +2970,7 @@ static int filter_one(const struct reference *ref, void *cb_data)
 	struct ref_filter_cbdata *ref_cbdata = cb_data;
 	struct ref_array_item *item;
 
-	item = apply_ref_filter(ref->name, ref->target, ref->oid,
-				ref->flags, ref_cbdata->filter);
+	item = apply_ref_filter(ref, ref_cbdata->filter);
 	if (item)
 		ref_array_append(ref_cbdata->array, item);
 
@@ -2997,8 +3007,7 @@ static int filter_and_format_one(const struct reference *ref, void *cb_data)
 	struct ref_array_item *item;
 	struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
 
-	item = apply_ref_filter(ref->name, ref->target, ref->oid,
-				ref->flags, ref_cbdata->filter);
+	item = apply_ref_filter(ref, ref_cbdata->filter);
 	if (!item)
 		return 0;
 
@@ -3585,13 +3594,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 81f2c229a9..1126826201 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;
@@ -185,6 +186,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);
 
 /*
@@ -193,7 +195,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
-- 
2.51.0.764.g787ff6f08a.dirty
Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 24 of 106 in “refs: improvements and fixes for peeling tags”
  1. 00/13 refs: improvements and fixes for peeling tagsPatrick Steinhardt, Oct 7, 2025
  2. 01/13 refs: introduce wrapper struct for `each_ref_fn`Patrick Steinhardt, Oct 7, 2025
  3. Justin ToblerOct 7, 2025
  4. Patrick SteinhardtOct 8, 2025
  5. Taylor BlauOct 7, 2025
  6. shejialuoOct 8, 2025
  7. Patrick SteinhardtOct 9, 2025
  8. 02/13 refs: introduce `.ref` field for the base iteratorPatrick Steinhardt, Oct 7, 2025
  9. Karthik NayakOct 7, 2025
  10. Patrick SteinhardtOct 8, 2025
  11. Patrick SteinhardtOct 8, 2025
  12. Justin ToblerOct 7, 2025
  13. Taylor BlauOct 7, 2025
  14. 03/13 refs: refactor reference status flagsPatrick Steinhardt, Oct 7, 2025
  15. Karthik NayakOct 7, 2025
  16. Patrick SteinhardtOct 8, 2025
  17. 04/13 refs: expose peeled object ID via the iteratorPatrick Steinhardt, Oct 7, 2025
  18. Karthik NayakOct 7, 2025
  19. Patrick SteinhardtOct 8, 2025
  20. Karthik NayakOct 15, 2025
  21. 05/13 upload-pack: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 7, 2025
  22. Karthik NayakOct 7, 2025
  23. Patrick SteinhardtOct 8, 2025
  24. 06/13 ref-filter: propagate peeled object IDPatrick Steinhardt, Oct 7, 2025
  25. 07/13 builtin/show-ref: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 7, 2025
  26. 08/13 refs: drop `current_ref_iter` hackPatrick Steinhardt, Oct 7, 2025
  27. 09/13 refs: drop infrastructure to peel via iteratorsPatrick Steinhardt, Oct 7, 2025
  28. 10/13 object: add flag to `peel_object()` to verify object typePatrick Steinhardt, Oct 7, 2025
  29. Kristoffer HaugsbakkOct 8, 2025
  30. 11/13 refs: don't store peeled object IDs for invalid tagsPatrick Steinhardt, Oct 7, 2025
  31. 12/13 ref-filter: detect broken tags when dereferencing themPatrick Steinhardt, Oct 7, 2025
  32. 13/13 ref-filter: parse objects on demandPatrick Steinhardt, Oct 7, 2025
  33. Kristoffer HaugsbakkOct 8, 2025
  34. Patrick SteinhardtOct 8, 2025
  35. Junio C HamanoOct 7, 2025
  36. Taylor BlauOct 7, 2025
  37. Junio C HamanoOct 7, 2025
  38. 00/14 refs: improvements and fixes for peeling tagsPatrick Steinhardt, Oct 8, 2025
  39. 01/14 refs: introduce wrapper struct for `each_ref_fn`Patrick Steinhardt, Oct 8, 2025
  40. 02/14 refs: introduce `.ref` field for the base iteratorPatrick Steinhardt, Oct 8, 2025
  41. 03/14 refs: fully reset `struct ref_iterator::ref` on iterationPatrick Steinhardt, Oct 8, 2025
  42. 04/14 refs: refactor reference status flagsPatrick Steinhardt, Oct 8, 2025
  43. 05/14 refs: expose peeled object ID via the iteratorPatrick Steinhardt, Oct 8, 2025
  44. 06/14 upload-pack: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 8, 2025
  45. 07/14 ref-filter: propagate peeled object IDPatrick Steinhardt, Oct 8, 2025
  46. 08/14 builtin/show-ref: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 8, 2025
  47. 09/14 refs: drop `current_ref_iter` hackPatrick Steinhardt, Oct 8, 2025
  48. 10/14 refs: drop infrastructure to peel via iteratorsPatrick Steinhardt, Oct 8, 2025
  49. 11/14 object: add flag to `peel_object()` to verify object typePatrick Steinhardt, Oct 8, 2025
  50. 12/14 refs: don't store peeled object IDs for invalid tagsPatrick Steinhardt, Oct 8, 2025
  51. shejialuoOct 8, 2025
  52. Patrick SteinhardtOct 9, 2025
  53. 13/14 ref-filter: detect broken tags when dereferencing themPatrick Steinhardt, Oct 8, 2025
  54. 14/14 ref-filter: parse objects on demandPatrick Steinhardt, Oct 8, 2025
  55. Jeff KingOct 9, 2025
  56. Patrick SteinhardtOct 9, 2025
  57. Jeff KingOct 9, 2025
  58. Patrick SteinhardtOct 9, 2025
  59. Jeff KingOct 10, 2025
  60. Patrick SteinhardtOct 10, 2025
  61. Jeff KingOct 10, 2025
  62. Junio C HamanoOct 10, 2025
  63. Patrick SteinhardtOct 14, 2025
  64. Junio C HamanoOct 14, 2025
  65. Toon ClaesOct 9, 2025
  66. Junio C HamanoOct 9, 2025
  67. 00/14 refs: improvements and fixes for peeling tagsPatrick Steinhardt, Oct 22, 2025
  68. 01/14 refs: introduce wrapper struct for `each_ref_fn`Patrick Steinhardt, Oct 22, 2025
  69. 02/14 refs: introduce `.ref` field for the base iteratorPatrick Steinhardt, Oct 22, 2025
  70. 03/14 refs: fully reset `struct ref_iterator::ref` on iterationPatrick Steinhardt, Oct 22, 2025
  71. 04/14 refs: refactor reference status flagsPatrick Steinhardt, Oct 22, 2025
  72. 05/14 refs: expose peeled object ID via the iteratorPatrick Steinhardt, Oct 22, 2025
  73. 06/14 upload-pack: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 22, 2025
  74. 07/14 ref-filter: propagate peeled object IDPatrick Steinhardt, Oct 22, 2025
  75. 08/14 builtin/show-ref: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 22, 2025
  76. 09/14 refs: drop `current_ref_iter` hackPatrick Steinhardt, Oct 22, 2025
  77. 10/14 refs: drop infrastructure to peel via iteratorsPatrick Steinhardt, Oct 22, 2025
  78. 11/14 object: add flag to `peel_object()` to verify object typePatrick Steinhardt, Oct 22, 2025
  79. 12/14 refs: don't store peeled object IDs for invalid tagsPatrick Steinhardt, Oct 22, 2025
  80. 13/14 ref-filter: detect broken tags when dereferencing themPatrick Steinhardt, Oct 22, 2025
  81. 14/14 ref-filter: parse objects on demandPatrick Steinhardt, Oct 22, 2025
  82. Junio C HamanoOct 22, 2025
  83. Patrick SteinhardtOct 23, 2025
  84. Karthik NayakOct 22, 2025
  85. Junio C HamanoOct 22, 2025
  86. Patrick SteinhardtOct 23, 2025
  87. 00/14 refs: improvements and fixes for peeling tagsPatrick Steinhardt, Oct 23, 2025
  88. 01/14 refs: introduce wrapper struct for `each_ref_fn`Patrick Steinhardt, Oct 23, 2025
  89. 02/14 refs: introduce `.ref` field for the base iteratorPatrick Steinhardt, Oct 23, 2025
  90. 03/14 refs: fully reset `struct ref_iterator::ref` on iterationPatrick Steinhardt, Oct 23, 2025
  91. 04/14 refs: refactor reference status flagsPatrick Steinhardt, Oct 23, 2025
  92. 05/14 refs: expose peeled object ID via the iteratorPatrick Steinhardt, Oct 23, 2025
  93. 06/14 upload-pack: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 23, 2025
  94. 07/14 ref-filter: propagate peeled object IDPatrick Steinhardt, Oct 23, 2025
  95. 08/14 builtin/show-ref: convert to use `reference_get_peeled_oid()`Patrick Steinhardt, Oct 23, 2025
  96. 09/14 refs: drop `current_ref_iter` hackPatrick Steinhardt, Oct 23, 2025
  97. 10/14 refs: drop infrastructure to peel via iteratorsPatrick Steinhardt, Oct 23, 2025
  98. 11/14 object: add flag to `peel_object()` to verify object typePatrick Steinhardt, Oct 23, 2025
  99. 12/14 refs: don't store peeled object IDs for invalid tagsPatrick Steinhardt, Oct 23, 2025
  100. 13/14 ref-filter: detect broken tags when dereferencing themPatrick Steinhardt, Oct 23, 2025
  101. 14/14 ref-filter: parse objects on demandPatrick Steinhardt, Oct 23, 2025
  102. Jeff KingNov 4, 2025
  103. Junio C HamanoNov 4, 2025
  104. Jeff KingNov 4, 2025
  105. Junio C HamanoOct 23, 2025
  106. Patrick SteinhardtOct 24, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.