On Thu, Jun 15, 2017 at 10:50:46AM -0700, Junio C Hamano wrote:
> > if (!find_pack_entry(real, &e)) {
> > /* Most likely it's a loose object. */
> > - if (!sha1_loose_object_info(real, oi, flags)) {
> > + if (oi && !sha1_loose_object_info(real, oi, flags)) {
> > oi->whence = OI_LOOSE;
> > return 0;
> > }
> > + if (!oi && has_loose_object(real))
> > + return 0;
>
> This conversion is not incorrect per-se.
>
> We can see that has_sha1_file_with_flags() after this patch still
> calls has_loose_object(). But it bothers me that there is no hint
> to future developers to warn that a rewrite of the above like this
> is incorrect:
>
> if (!find_pack_entry(read, &e)) {
> /* Most likely it's a loose object. */
> + struct object_info dummy_oi;
> + if (!oi) {
> + memset(&dummy_oi, 0, sizeof(dummy_oi);
> + oi = &dummy_oi;
> + }
> - if (oi && !sha1_loose_object_info(real, oi, flags)) {
> + if (!sha1_loose_object_info(real, oi, flags)) {
> oi->whence = OI_LOOSE;
> return 0;
> }
> - if (!oi && has_loose_object(real))
> - return 0;
>
> It used to be very easy to see that has_sha1_file_with_flags() will
> call has_loose_object() when it does not find the object in a pack,
> which will result in the loose object file freshened. In the new
> code, it is very subtle to see that---it will happen when the caller
> passes oi == NULL, and has_sha1_file_with_flags() is such a caller,
> but it is unclear if there are other callers of this "consolidated"
> sha1_object_info_extended() that passes oi == NULL, and if they do
> also want to freshen the loose object file when they do so.
I also found this quite subtle. However, I don't think that
has_sha1_file() actually freshens. It's a bit confusing because
has_loose_object() reuses the check_and_freshen() function to do the
lookup, but it actually sets the "freshen" flag to false.
That's why in 33d4221c7 (write_sha1_file: freshen existing objects,
2014-10-15), which introduced the freshening functions and converted
has_loose_object(), the actual write_sha1_file() function switched to
using the freshening functions directly (and obviously sets the freshen
parameter to true).
I actually think all of that infrastructure could become part of
Jonathan's consolidated lookup, too. We would just need:
1. A QUICK flag to avoid re-reading objects/pack when we don't find
anything (which it looks like he already has).
2. A FRESHEN flag to update the mtime of any item that we do find.
I suspect we may also need something like ONLY_LOOSE and ONLY_NONLOCAL
to meet all the callers (e.g., has_loose_object_nonlocal). Those should
be easy to implement, I'd think.
> I would have preferred to see the new variable not to be called 'f',
> as that makes it unclear what it is (is that a callback function
> pointer?). In this case, uyou are forcing the flag bits passed
> down, so perhaps you can reuse the same variable?
>
> If you allocated a separate variable because
> has_sha1_file_with_flags() and sha1_object_info_extended() take flag
> bits from two separate vocabularies, that is a valid reasoning, but
> if that is the case, then I would have named 'f' to reflect that
> fact that this is different from parameter 'flag' that is defined in
> the has_sha1_file_with_flags() world, but a different thing that is
> defined in sha1_object_info_extended() world, e.g. "soie_flag" or
> something like that.
I had the same thoughts (both on the name and the "vocabularies"). IMHO
we should consider allocating the bits from the same set. There's only
one HAS_SHA1 flag, and it has an exact match in OBJECT_INFO_QUICK.
I think this patch might be a bit easier to review if it were broken
down more in a sequence of:
1. Add features to the consolidated function to support everything
that function X supports.
2. Preparatory cleanup around X (e.g., pointing HAS_SHA1_QUICK at
OBJECT_INFO_QUICK).
3. Convert X to use the consolidated function.
4. Repeat for each X we wish to consolidate.
That's going to end up with probably 12 patches instead of one, but I
think it may be a lot easier to communicate the reason for the various
design decisions.
-Peff