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);