aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyConfiguration.java72
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyLoader.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyOptions.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntry.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntryConverter.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/whitelisting/BUILD26
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/whitelisting/Whitelist.java80
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java42
8 files changed, 202 insertions, 50 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyConfiguration.java
index 96d3431836..37adc1a0b1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyConfiguration.java
@@ -33,52 +33,58 @@ import com.google.devtools.build.lib.util.Preconditions;
* should be limited to specified packages. Because this is part of the configuration, it can only
* be accessed during the analysis phase; decisions which are made during the loading phase can't
* use this information. Some examples of use cases for this fragment:
+ *
* <ul>
- * <li>A new rule class which could have a major impact on Blaze's memory usage is added. To
- * limit this impact during the experimental phase, a feature policy is added which makes it
- * an error for rules of that class to be created - or used by other rules - in any package
- * other than those defined by the policy. The policy is populated with projects who are
- * doing guided experimentation with the feature, and gradually expands as the feature rolls
- * out. Then the feature's policy can be removed, making it generally available.
- * <li>An attribute is being deprecated. To prevent rollback, a feature policy is added which
- * makes it an error for rules in packages other than those defined by the policy to specify
- * a value for that attribute. The policy is populated with existing users, and as those
- * users are migrated, they are removed from the policy until it is completely empty. Then
- * the attribute can be removed entirely.
+ * <li>A new rule class which could have a major impact on Blaze's memory usage is added. To limit
+ * this impact during the experimental phase, a feature policy is added which makes it an
+ * error for rules of that class to be created - or used by other rules - in any package other
+ * than those defined by the policy. The policy is populated with projects who are doing
+ * guided experimentation with the feature, and gradually expands as the feature rolls out.
+ * Then the feature's policy can be removed, making it generally available.
+ * <li>An attribute is being deprecated. To prevent rollback, a feature policy is added which
+ * makes it an error for rules in packages other than those defined by the policy to specify a
+ * value for that attribute. The policy is populated with existing users, and as those users
+ * are migrated, they are removed from the policy until it is completely empty. Then the
+ * attribute can be removed entirely.
* </ul>
*
* <p>To use this package:
+ *
* <ol>
- * <li>Define a feature ID in the {@link FeaturePolicyLoader}'s constructor (in the
- * RuleClassProvider). This is the string that will be used when checking for the feature in
- * rule code, as well as the string used in the flag value for {@link FeaturePolicyOptions}.
- * <li>In the RuleClass(es) which will change based on the feature's state, declare
- * {@link FeaturePolicyConfiguration} as a required configuration fragment.
- * <li>In the ConfiguredTargetFactory of those rules, get the FeaturePolicyConfiguration and
- * check {@link #isFeatureEnabledForRule(String,Label)} with the feature ID created in
- * step 1 and the label of the current rule. In the event that an error needs to be
- * displayed, use {@link #getPolicyForFeature(String)} to show the user where the policy is.
- * <li>Create a package_group containing the list of packages which should have access to this
- * feature. It can be empty (no packages can access the feature) or contain //... (all
- * packages can access the feature) to begin with.
- * <li>After the a release containing the feature ID has been pushed, update the global RC file
- * with a --feature_control_policy=(your_feature)=(your_package_group) flag. You can now
- * alter access to your feature by changing the package_group.
+ * <li>Define a feature ID in the {@link FeaturePolicyLoader}'s constructor (in the
+ * RuleClassProvider). This is the string that will be used when checking for the feature in
+ * rule code, as well as the string used in the flag value for {@link FeaturePolicyOptions}.
+ * <li>In the RuleClass(es) which will change based on the feature's state, declare {@link
+ * FeaturePolicyConfiguration} as a required configuration fragment.
+ * <li>In the ConfiguredTargetFactory of those rules, get the FeaturePolicyConfiguration and check
+ * {@link #isFeatureEnabledForRule(String,Label)} with the feature ID created in step 1 and
+ * the label of the current rule. In the event that an error needs to be displayed, use {@link
+ * #getPolicyForFeature(String)} to show the user where the policy is.
+ * <li>Create a package_group containing the list of packages which should have access to this
+ * feature. It can be empty (no packages can access the feature) or contain //... (all
+ * packages can access the feature) to begin with.
+ * <li>After the a release containing the feature ID has been pushed, update the global RC file
+ * with a --feature_control_policy=(your_feature)=(your_package_group) flag. You can now alter
+ * access to your feature by changing the package_group.
* </ol>
*
* <p>To stop using this package:
+ *
* <ol>
- * <li>Your policy should be at an end state - containing all packages (a rollout which has
- * become generally available) or no packages (a deprecated feature which has been totally
- * cleaned up).
- * <li>Make the behavior the policy controlled permanent - remove a deprecated feature, or
- * remove the check on a feature which is being rolled out.
- * <li>After this new version is released, remove the flag from the global rc file, and remove
- * the feature ID from the constructor for {@link FeaturePolicyLoader}.
+ * <li>Your policy should be at an end state - containing all packages (a rollout which has become
+ * generally available) or no packages (a deprecated feature which has been totally cleaned
+ * up).
+ * <li>Make the behavior the policy controlled permanent - remove a deprecated feature, or remove
+ * the check on a feature which is being rolled out.
+ * <li>After this new version is released, remove the flag from the global rc file, and remove the
+ * feature ID from the constructor for {@link FeaturePolicyLoader}.
* </ol>
*
* @see FeaturePolicyLoader
+ * @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 FeaturePolicyConfiguration extends BuildConfiguration.Fragment {
private final ImmutableSetMultimap<String, PackageSpecification> features;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyLoader.java b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyLoader.java
index 9e2c856835..7704c8c6cd 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyLoader.java
@@ -37,7 +37,13 @@ import java.util.Queue;
import java.util.Set;
import javax.annotation.Nullable;
-/** A loader for the FeaturePolicyConfiguration fragment. */
+/**
+ * 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<String> permittedFeatures;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyOptions.java
index b0036d5f23..737c1c878c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/FeaturePolicyOptions.java
@@ -21,7 +21,13 @@ import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import java.util.List;
-/** The options fragment which defines {@link FeaturePolicyConfiguration}. */
+/**
+ * The options fragment which defines {@link FeaturePolicyConfiguration}.
+ *
+ * @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 FeaturePolicyOptions extends FragmentOptions {
/** The mapping from features to their associated package groups. */
@Option(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntry.java b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntry.java
index e0982a25df..b871637d17 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntry.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntry.java
@@ -17,7 +17,13 @@ package com.google.devtools.build.lib.analysis.featurecontrol;
import com.google.auto.value.AutoValue;
import com.google.devtools.build.lib.cmdline.Label;
-/** Policy value object encoding the package group which can access a given feature. */
+/**
+ * Policy value object encoding the package group which can access a given feature.
+ *
+ * @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
@AutoValue
public abstract class PolicyEntry {
/** Creates a new PolicyEntry for the given feature and package_group label. */
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntryConverter.java b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntryConverter.java
index a8f997b76b..ec245313a9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntryConverter.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/featurecontrol/PolicyEntryConverter.java
@@ -19,7 +19,13 @@ import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.OptionsParsingException;
-/** A converter which creates a PolicyEntry from a flag value. */
+/**
+ * A converter which creates a PolicyEntry from a flag value.
+ *
+ * @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 PolicyEntryConverter implements Converter<PolicyEntry> {
@Override
public PolicyEntry convert(String input) throws OptionsParsingException {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/whitelisting/BUILD b/src/main/java/com/google/devtools/build/lib/analysis/whitelisting/BUILD
new file mode 100644
index 0000000000..b31e3c224b
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/whitelisting/BUILD
@@ -0,0 +1,26 @@
+# Description:
+# Whitelisting mechanism for rolling out and deprecating pieces of Bazel functionality.
+
+package(
+ default_visibility = ["//src:__subpackages__"],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
+
+java_library(
+ name = "whitelisting",
+ srcs = glob(["*.java"]),
+ deps = [
+ "//src/main/java/com/google/devtools/build/lib:build-base",
+ "//src/main/java/com/google/devtools/build/lib:packages-internal",
+ "//src/main/java/com/google/devtools/build/lib:preconditions",
+ "//src/main/java/com/google/devtools/build/lib/cmdline",
+ "//src/main/java/com/google/devtools/common/options",
+ "//third_party:auto_value",
+ "//third_party:guava",
+ "//third_party:jsr305",
+ ],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/whitelisting/Whitelist.java b/src/main/java/com/google/devtools/build/lib/analysis/whitelisting/Whitelist.java
new file mode 100644
index 0000000000..0da6e4d362
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/whitelisting/Whitelist.java
@@ -0,0 +1,80 @@
+// 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.whitelisting;
+
+import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST;
+import static com.google.devtools.build.lib.packages.Attribute.attr;
+import static com.google.devtools.build.lib.packages.BuildType.LABEL;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.util.Preconditions;
+
+/**
+ * Class used for implementing whitelists using package groups.
+ *
+ * <p>To use add an attribute {@link getAttributeFromWhitelistName(String,Label) to the rule class
+ * which needs the whitelisting mechanism and use {@link isAvailable(RuleContext,String)} to check
+ * during analysis if a rule is present
+ */
+public final class Whitelist {
+
+ private Whitelist() {}
+
+ /**
+ * Returns an Attribute.Builder that can be used to add an implicit attribute to a rule containing
+ * a package group whitelist.
+ *
+ * @param whitelistName The name of the whitelist. This has to comply with attribute naming
+ * standards and will be used as a suffix for the attribute name.
+ * @param packageGroupWhitelist Label for the package group with the whitelist.
+ */
+ public static Attribute.Builder<Label> getAttributeFromWhitelistName(
+ String whitelistName, Label packageGroupWhitelist) {
+ String attributeName = getAttributeNameFromWhitelistName(whitelistName);
+ return attr(attributeName, LABEL)
+ .value(packageGroupWhitelist)
+ .cfg(HOST)
+ .mandatoryNativeProviders(ImmutableList.of(PackageSpecificationProvider.class));
+ }
+
+ /**
+ * Returns whether the rule in the given RuleContext is in a whitelist.
+ *
+ * @param ruleContext The context in which this check is being executed.
+ * @param whitelistName The name of the whitelist being used.
+ */
+ public static boolean isAvailable(RuleContext ruleContext, String whitelistName) {
+ String attributeName = getAttributeNameFromWhitelistName(whitelistName);
+ Preconditions.checkArgument(ruleContext.isAttrDefined(attributeName, LABEL));
+ TransitiveInfoCollection packageGroup = ruleContext.getPrerequisite(attributeName, Mode.HOST);
+ Label label = ruleContext.getLabel();
+ return packageGroup
+ .getProvider(PackageSpecificationProvider.class)
+ .getPackageSpecifications()
+ .toList()
+ .stream()
+ .anyMatch(p -> p.containsPackage(label.getPackageIdentifier()));
+ }
+
+ private static String getAttributeNameFromWhitelistName(String whitelistName) {
+ return String.format("$whitelist_%s", whitelistName);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java
index 81c097f19e..bb2456c08e 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelPrerequisiteValidator.java
@@ -14,12 +14,16 @@
package com.google.devtools.build.lib.bazel.rules;
+import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.PackageGroup;
+import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.rules.AliasProvider;
@@ -72,19 +76,31 @@ public class BazelPrerequisiteValidator
new VisibilityErrorEvent(context.getConfiguration(), rule.getLabel(), errorMessage));
}
- if (prerequisiteTarget instanceof PackageGroup && !attrName.equals("visibility")) {
- context.reportError(
- rule.getAttributeLocation(attrName),
- "in "
- + attrName
- + " attribute of "
- + rule.getRuleClass()
- + " rule "
- + rule.getLabel()
- + ": package group "
- + AliasProvider.printLabelWithAliasChain(prerequisite)
- + " is misplaced here "
- + "(they are only allowed in the visibility attribute)");
+ if (prerequisiteTarget instanceof PackageGroup) {
+ ImmutableList<ImmutableList<Class<? extends TransitiveInfoProvider>>>
+ mandatoryNativeProviders =
+ RawAttributeMapper.of(rule)
+ .getAttributeDefinition(attrName)
+ .getMandatoryNativeProvidersList();
+ boolean containsPackageSpecificationProvider =
+ mandatoryNativeProviders
+ .stream()
+ .anyMatch(list -> list.contains(PackageSpecificationProvider.class));
+ // TODO(plf): Add the PackageSpecificationProvider to the 'visibility' attribute.
+ if (!attrName.equals("visibility") && !containsPackageSpecificationProvider) {
+ context.reportError(
+ rule.getAttributeLocation(attrName),
+ "in "
+ + attrName
+ + " attribute of "
+ + rule.getRuleClass()
+ + " rule "
+ + rule.getLabel()
+ + ": package group "
+ + AliasProvider.printLabelWithAliasChain(prerequisite)
+ + " is misplaced here "
+ + "(they are only allowed in the visibility attribute)");
+ }
}
}