diff --git a/internal/catalogue/resolve.go b/internal/catalogue/resolve.go index ded00e0..8439f2c 100644 --- a/internal/catalogue/resolve.go +++ b/internal/catalogue/resolve.go @@ -834,6 +834,19 @@ func providersFirst(order []string, shelf map[string]Manifest) []string { // losing the one it depends on. func perConsumer(needs []Needed, order []string, catalogue map[string]Manifest) []Needed { out := make([]Needed, 0, len(needs)) + // Once per (provision, consumer, local name, provider). The walk over names visits a + // same-node provision once per module that mentions it, so two consumers of one produced two + // raw needs and, fanned out below, four — the same credential twice for each. Harmless + // downstream, since a pair is one row however often it is asked for, and wrong all the same. + seen := map[[4]string]bool{} + keep := func(n Needed) { + key := [4]string{n.Name, n.For, n.Local, n.From} + if seen[key] { + return + } + seen[key] = true + out = append(out, n) + } for _, n := range needs { var wanted bool for _, name := range order { @@ -849,13 +862,15 @@ func perConsumer(needs []Needed, order []string, catalogue map[string]Manifest) copied.For = m.Module // And once per file THIS module keeps the credential in, where it keeps several // (ADR 0094) — here, where the consumer is finally known, not on the walk above. - out = eachLocal(out, catalogue, copied) + for _, one := range eachLocal(nil, catalogue, copied) { + keep(one) + } wanted = true break } } if !wanted { - out = append(out, n) + keep(n) } } return out