All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gradle.api.internalivyservice.resolveengine.graph.selectors.SelectorStateResolverResults Maven / Gradle / Ivy

There is a newer version: 8.6
Show newest version
/*
 * Copyright 2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.selectors;

import com.google.common.collect.Lists;
import org.gradle.api.internal.artifacts.ResolvedVersionConstraint;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.DefaultVersionComparator;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.LatestVersionSelector;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.Version;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelector;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.ComponentResolutionState;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.VirtualPlatformState;
import org.gradle.internal.resolve.ModuleVersionResolveException;
import org.gradle.internal.resolve.result.ComponentIdResolveResult;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

class SelectorStateResolverResults {
    private static final VersionParser VERSION_PARSER = new VersionParser();
    private static final Comparator VERSION_COMPARATOR = new DefaultVersionComparator().asVersionComparator();
    private final List results;

    public SelectorStateResolverResults(int size) {
        results = Lists.newArrayListWithCapacity(size);
    }

    public  List getResolved(ComponentStateFactory componentFactory) {
        ModuleVersionResolveException failure = null;
        List resolved = null;
        boolean hasSoftForce = hasSoftForce();
        for (Registration entry : results) {
            ResolvableSelectorState selectorState = entry.selector;
            ComponentIdResolveResult idResolveResult = entry.result;

            if (selectorState.isForce() && !hasSoftForce) {
                T forcedComponent = componentForIdResolveResult(componentFactory, idResolveResult, selectorState);
                return Collections.singletonList(forcedComponent);
            }

            if (idResolveResult.mark(this)) {
                if (idResolveResult.getFailure() == null) {
                    T componentState = componentForIdResolveResult(componentFactory, idResolveResult, selectorState);
                    if (resolved == null) {
                        resolved = Lists.newArrayList();
                    }
                    resolved.add(componentState);
                } else {
                    if (failure == null) {
                        failure = idResolveResult.getFailure();
                    }
                }
            }
        }

        if (resolved == null && failure != null) {
            throw failure;
        }

        return resolved == null ? Collections.emptyList() : resolved;
    }

    static  boolean isVersionAllowedByPlatform(T componentState) {
        Set platformOwners = componentState.getPlatformOwners();
        if (!platformOwners.isEmpty()) {
            for (VirtualPlatformState platformOwner : platformOwners) {
                if (platformOwner.isGreaterThanForcedVersion(componentState.getVersion())) {
                    return false;
                }
            }
        } else {
            VirtualPlatformState platform = componentState.getPlatformState();
            if (platform != null && platform.isGreaterThanForcedVersion(componentState.getVersion())) {
                // the platform itself is greater than the forced version
                return false;
            }
        }
        return true;
    }

    private boolean hasSoftForce() {
        for (Registration entry : results) {
            ResolvableSelectorState selectorState = entry.selector;
            if (selectorState.isSoftForce()) {
                return true;
            }
        }
        return false;
    }

    public static  T componentForIdResolveResult(ComponentStateFactory componentFactory, ComponentIdResolveResult idResolveResult, ResolvableSelectorState selector) {
        T component = componentFactory.getRevision(idResolveResult.getId(), idResolveResult.getModuleVersionId(), idResolveResult.getMetadata());
        component.selectedBy(selector);
        if (idResolveResult.isRejected()) {
            component.reject();
        }
        return component;
    }

    /**
     * Check already resolved results for a compatible version, and use it for this dependency rather than re-resolving.
     */
    boolean alreadyHaveResolutionForSelector(ResolvableSelectorState selector) {
        for (Registration registration : results) {
            ComponentIdResolveResult discovered = registration.result;
            if (selectorAcceptsCandidate(selector, discovered, registration.selector.isFromLock())) {
                register(selector, discovered);
                selector.markResolved();
                return true;
            }
        }
        return false;
    }

    boolean replaceExistingResolutionsWithBetterResult(ComponentIdResolveResult candidate, boolean isFromLock) {
        // Check already-resolved dependencies and use this version if it's compatible
        boolean replaces = false;
        for (Registration registration : results) {
            ComponentIdResolveResult previous = registration.result;
            ResolvableSelectorState previousSelector = registration.selector;
            if (emptyVersion(previous) || sameVersion(previous, candidate) ||
                    (selectorAcceptsCandidate(previousSelector, candidate, isFromLock) && lowerVersion(previous, candidate))) {
                registration.result = candidate;
                replaces = true;
            }
        }
        return replaces;
    }

    void register(ResolvableSelectorState selector, ComponentIdResolveResult resolveResult) {
        results.add(new Registration(selector, resolveResult));
    }

    private static boolean emptyVersion(ComponentIdResolveResult existing) {
        if (existing.getFailure() == null) {
            return existing.getModuleVersionId().getVersion().isEmpty();
        }
        return false;
    }

    private static boolean sameVersion(ComponentIdResolveResult existing, ComponentIdResolveResult resolveResult) {
        if (existing.getFailure() == null && resolveResult.getFailure() == null) {
            return existing.getId().equals(resolveResult.getId());
        }
        return false;
    }

    private static boolean lowerVersion(ComponentIdResolveResult existing, ComponentIdResolveResult resolveResult) {
        if (existing.getFailure() == null && resolveResult.getFailure() == null) {
            Version existingVersion = VERSION_PARSER.transform(existing.getModuleVersionId().getVersion());
            Version candidateVersion = VERSION_PARSER.transform(resolveResult.getModuleVersionId().getVersion());

            int comparison = VERSION_COMPARATOR.compare(candidateVersion, existingVersion);
            return comparison < 0;
        }
        return false;
    }

    private static boolean selectorAcceptsCandidate(ResolvableSelectorState dep, ComponentIdResolveResult candidate, boolean candidateIsFromLock) {
        if (hasFailure(candidate)) {
            return false;
        }
        ResolvedVersionConstraint versionConstraint = dep.getVersionConstraint();
        if (versionConstraint == null) {
            return dep.getSelector().matchesStrictly(candidate.getId());
        }
        VersionSelector versionSelector = versionConstraint.getRequiredSelector();
        if (versionSelector != null &&
                (candidateIsFromLock || versionSelector.canShortCircuitWhenVersionAlreadyPreselected())) {

            if (candidateIsFromLock && versionSelector instanceof LatestVersionSelector) {
                // Always assume a candidate from a lock will satisfy the latest version selector
                return true;
            }

            return versionSelector.accept(candidate.getModuleVersionId().getVersion());
        }
        return false;
    }

    private static boolean hasFailure(ComponentIdResolveResult candidate) {
        return candidate.getFailure() != null;
    }

    public boolean isEmpty() {
        return results.isEmpty();
    }

    private static class Registration {
        private final ResolvableSelectorState selector;
        private ComponentIdResolveResult result;

        private Registration(ResolvableSelectorState selector, ComponentIdResolveResult result) {
            this.selector = selector;
            this.result = result;
        }

        @Override
        public String toString() {
            return selector.toString() + " -> " + result.getModuleVersionId();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy