On Thu, Oct 04, 2018 at 02:48:33AM -0400, Jeff King wrote:

> On Thu, Oct 04, 2018 at 07:56:44AM +0200, René Scharfe wrote:
> 
> > > As the comment above notes, I think we're really looking at the case
> > > where this gets populated on the first call, but not subsequent ones. It
> > > might be less hacky to use a "static int initialized" here. Or if we
> > > want to avoid hidden globals, put the logic into filter_refs() to decide
> > > when to populate.
> > 
> > Right.  I'd prefer the latter, but was unable to find a nice way that
> > still populates the oidset lazily.  It's certainly worth another look,
> > and a separate series.
> 
> It's a little awkward because the lazy load happens in a conditional.
> You can fully encapsulate it like the patch below, but I actually don't
> think it's really helping readability.

I forgot the patch, of course. ;)

I'm not really proposing this, just illustrating one direction (that I
think is kind of ugly). Notably it doesn't get rid of the tricky comment
in tip_oids_contain(), because that is explaining why the single load
works even on a list we're still adding to.

diff --git a/fetch-pack.c b/fetch-pack.c
index a839315726..a6212c8758 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -526,8 +526,14 @@ static void add_refs_to_oidset(struct oidset *oids, struct 
ref *refs)
                oidset_insert(oids, &refs->old_oid);
 }
 
-static int tip_oids_contain(struct oidset *tip_oids,
-                           struct ref *unmatched, struct ref *newlist,
+struct lazy_tip_oids {
+       int loaded;
+       struct oidset oids;
+       struct ref *unmatched;
+       struct ref *newlist;
+};
+
+static int tip_oids_contain(struct lazy_tip_oids *tip_oids,
                            const struct object_id *id)
 {
        /*
@@ -536,11 +542,12 @@ static int tip_oids_contain(struct oidset *tip_oids,
         * add to "newlist" between calls, the additions will always be for
         * oids that are already in the set.
         */
-       if (!tip_oids->set.n_buckets) {
-               add_refs_to_oidset(tip_oids, unmatched);
-               add_refs_to_oidset(tip_oids, newlist);
+       if (!tip_oids->loaded) {
+               add_refs_to_oidset(&tip_oids->oids, tip_oids->unmatched);
+               add_refs_to_oidset(&tip_oids->oids, tip_oids->newlist);
+               tip_oids->loaded = 1;
        }
-       return oidset_contains(tip_oids, id);
+       return oidset_contains(&tip_oids->oids, id);
 }
 
 static void filter_refs(struct fetch_pack_args *args,
@@ -551,7 +558,7 @@ static void filter_refs(struct fetch_pack_args *args,
        struct ref **newtail = &newlist;
        struct ref *unmatched = NULL;
        struct ref *ref, *next;
-       struct oidset tip_oids = OIDSET_INIT;
+       struct lazy_tip_oids tip_oids = { 0 };
        int i;
 
        i = 0;
@@ -589,6 +596,9 @@ static void filter_refs(struct fetch_pack_args *args,
                }
        }
 
+       tip_oids.unmatched = unmatched;
+       tip_oids.newlist = newlist;
+
        /* Append unmatched requests to the list */
        for (i = 0; i < nr_sought; i++) {
                struct object_id oid;
@@ -604,8 +614,7 @@ static void filter_refs(struct fetch_pack_args *args,
 
                if ((allow_unadvertised_object_request &
                     (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1)) ||
-                   tip_oids_contain(&tip_oids, unmatched, newlist,
-                                    &ref->old_oid)) {
+                   tip_oids_contain(&tip_oids, &ref->old_oid)) {
                        ref->match_status = REF_MATCHED;
                        *newtail = copy_ref(ref);
                        newtail = &(*newtail)->next;
@@ -614,7 +623,7 @@ static void filter_refs(struct fetch_pack_args *args,
                }
        }
 
-       oidset_clear(&tip_oids);
+       oidset_clear(&tip_oids.oids);
        for (ref = unmatched; ref; ref = next) {
                next = ref->next;
                free(ref);

Reply via email to