Make selected variant known to artifact resolving This will allow us to use different resolving strategies depending on the variant that carries the artifact(s). We need this to allow modules with variants from mixed origins. For example, a module with only pom metadata, which carries additional variants added by component metadata rules.
Rework exclude rule merging As a follow-up to #9197, this commit properly fixes the exclude rule merging algorithm, by completely rewriting it. The new merging algorithm works by implementing the minimal set of algebra operations that make sense to minimize computation durations. In order to do this, this commit introduces a number of exclude specs (found in their own package) and factories to create actual implementation of those specs.
Specs represent the different kind of excludes we can find:
- excluding a group - excluding a module (no group defined) - excluding a group+module - excluding an artifact of a group+module - pattern-matching excludes - unions of excludes - intersections of excludes
With all those minimal bricks, factories are responsible of generating consistent specs. The dumbest factory will just generate new instances for everything. This is the default factory.
Minimally, this factory has to be backed by an optimizing factory, which will take care of handling special cases:
- union or intersection of a single spec - union or intersection of 2 specs - when one of them is null - when both are equal
Then we have a factory which performs the minimal algebra to minimize specs:
- unions of unions - intersections of intersections - union of a union and individual specs - insection of an intersection and individual spec - ...
This factory can be as smart as it can, but one must be careful that it's worth it: some previously implemented optimizations (like (A+B).A = A turned out to be costly to detect, and didn't make it the final cut.
Last but not least, a caching factory is there to avoid recomputing the same intersections and unions of specs when we have already done the job. This is efficient if the underlying (delegate) specs are easily compared, which is the case thanks to the interning factory.
All in all, the delegation chain allows us to make the algorithm fast and hopefully reliable, while making it easier to debug.