// Copyright 2017 The Bazel Authors. All rights reserved. // // 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 com.google.devtools.build.lib.analysis.featurecontrol; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.devtools.build.lib.analysis.RedirectChaser; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.BuildOptions; import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment; import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory; import com.google.devtools.build.lib.analysis.config.FragmentOptions; import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.NoSuchPackageException; import com.google.devtools.build.lib.packages.NoSuchTargetException; import com.google.devtools.build.lib.packages.PackageGroup; import com.google.devtools.build.lib.packages.PackageSpecification; import com.google.devtools.build.lib.packages.Target; import com.google.devtools.build.lib.util.Preconditions; import java.util.ArrayDeque; import java.util.LinkedHashSet; import java.util.Queue; import java.util.Set; import javax.annotation.Nullable; /** * A loader for the FeaturePolicyConfiguration fragment. * * @deprecated This is deprecated because the dependency on the package group used to hold the * whitelist is not accessible through blaze query. Use {@link Whitelist}. */ @Deprecated public final class FeaturePolicyLoader implements ConfigurationFragmentFactory { private final ImmutableSet permittedFeatures; public FeaturePolicyLoader(Iterable permittedFeatures) { this.permittedFeatures = ImmutableSet.copyOf(permittedFeatures); for (String permittedFeature : this.permittedFeatures) { Preconditions.checkArgument( !permittedFeature.contains("="), "Feature names cannot contain ="); } } @Override @Nullable public BuildConfiguration.Fragment create(ConfigurationEnvironment env, BuildOptions buildOptions) throws InvalidConfigurationException, InterruptedException { ImmutableSetMultimap.Builder features = new ImmutableSetMultimap.Builder<>(); ImmutableMap.Builder policies = new ImmutableMap.Builder<>(); LinkedHashSet unseenFeatures = new LinkedHashSet<>(permittedFeatures); for (PolicyEntry entry : buildOptions.get(FeaturePolicyOptions.class).policies) { if (!permittedFeatures.contains(entry.getFeature())) { // It would be so nice to be able to do this during parsing... but because options are // parsed statically through reflection, we have no way of doing this until we get to the // configuration loader. throw new InvalidConfigurationException("No such feature: " + entry.getFeature()); } if (!unseenFeatures.remove(entry.getFeature())) { // TODO(mstaib): Perhaps we should allow for overriding or concatenation here? throw new InvalidConfigurationException( "Multiple definitions of the rollout policy for feature " + entry.getFeature() + ". To use multiple package_groups, use a package_group with the includes " + "attribute instead."); } Iterable packageSpecifications = getAllPackageSpecificationsForPackageGroup( env, entry.getPackageGroupLabel(), entry.getFeature()); if (packageSpecifications == null) { return null; } features.putAll(entry.getFeature(), packageSpecifications); policies.put(entry.getFeature(), entry.getPackageGroupLabel().toString()); } // Default to universal access for all features not declared. for (String unseenFeature : unseenFeatures) { features.put(unseenFeature, PackageSpecification.everything()); policies.put(unseenFeature, "//..."); } return new FeaturePolicyConfiguration(features.build(), policies.build()); } /** * Evaluates, recursively, the given package group. Returns {@code null} in the case of missing * Skyframe dependencies. */ @Nullable private static Iterable getAllPackageSpecificationsForPackageGroup( ConfigurationEnvironment env, Label packageGroupLabel, String feature) throws InvalidConfigurationException, InterruptedException { String context = feature + " feature policy"; Label actualPackageGroupLabel = RedirectChaser.followRedirects(env, packageGroupLabel, context); if (actualPackageGroupLabel == null) { return null; } ImmutableSet.Builder packages = new ImmutableSet.Builder<>(); Set