Subject: Re: [PATCH v2 00/14] refs: improvements and fixes for peeling tags

From: Patrick Steinhardt <[email-masked]>
Date: Tue, 14 Oct 2025 08:31:39 +0200

On Fri, Oct 10, 2025 at 08:29:32AM -0700, Junio C Hamano wrote:
> Patrick Steinhardt <[email-masked]> writes:
> 
> > So to move forward, how about we land this as-is and I promise to follow
> > up with another series that:
> >
> >   - Renames `struct ref` as proposed.
> >
> >   - Introduces `struct reference` into more of our APIs?
> 
> Sorry, but I am not quite sure why we would want to do so.
> 
> Does "struct reference" sufficiently cover the things we want to do
> with references and "struct ref" is not sufficient for that?
> 
> Comparing what 'struct ref' caters to its users and what 'struct
> reference' offers to its users and declaring that one set of needs
> is more generic to the 'reference API' than the other set risks
> getting blinded by the area we happened to have been focusing on
> recently.
> 
> Apparently, the above proposal is not claiming that what one wants
> to do is a subset of what the other wants to do (if so, you'd rather
> not be introducing a new "struct reference" but extending "struct
> ref" to be usable for more things).
> 
> Or would we add more to it than what we see in this series, such
> that it would no longer be "a subset" of needs various code paths
> would have around the reference API?  If so, is the longer-term plan
> to have callers that use "struct ref" to eventually use "struct
> reference"?
> 
> If not, they are serving different subset of the problem space, and
> they will continue to do so.  In that case, why wouldn't we rename
> "struct reference" to something that is more focused on what it is
> for?  In the context of this topic, would that be "reference found
> during iteration" or something?

I think that `struct ref` and `struct reference` serve quite distinct
use cases. `struct ref` is all around references in the context of a
remote: they are only in our code that interacts with them like for
example "transport.c", "walker.c", "fetch-pack.c" and so on. As such,
this structure naturally contains a ton of fields that are relevant in
this context:

  - It's a linked list that identifies all refs part of such a push.

  - It contains new_old object IDs.

  - It contains information whether or not such a reference should be
    force-updated.

  - It contains information whether the remote side has such a ref in
    the first place.

  - It encodes the FETCH_HEAD status.

There's much more, and nothing of this has anything to do with a plain
reference. As such, this type would be a very bad fit for use in the
"refs.c" subsystem, as the basic concepts are mismatching.

So what I'm proposing here is to introduce a `struct reference` that
really only cares about the specific concept of a plain reference. That
struct would thus only carry information that can be yielded by the ref
backends standalone.

The benefit is that it allows us to have a better abstraction boundary,
and it allows us to achieve things we cannot easily do right now. For
example, if functions like `refs_read_ref()` returned such a structure,
then we can now also peel such a ref with `reference_get_peeled_oid()`,
which is currently only possible when iterating over references. Other
higher-level functions like `reference_is_branch()` or similar things
can also be introduced. Last but not least, it also makes it obvious
what kind of "thing" we're working with in many cases, as a `struct
reference` will always be the fully-qualified and "raw" reference.

Hope that sheds some light on my thinking :)

Thanks!

Patrick