Allow package blacklisting to be done via a file checked into the depot. By default this is disabled. -- MOS_MIGRATED_REVID=107644420
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BlacklistedPackagePrefixesFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BlacklistedPackagePrefixesFunction.java new file mode 100644 index 0000000..11c78ae --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BlacklistedPackagePrefixesFunction.java
@@ -0,0 +1,110 @@ +// Copyright 2015 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.skyframe; + +import com.google.common.collect.ImmutableSet; +import com.google.common.io.CharStreams; +import com.google.common.io.LineProcessor; +import com.google.devtools.build.lib.pkgcache.PathPackageLocator; +import com.google.devtools.build.lib.vfs.Path; +import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.lib.vfs.RootedPath; +import com.google.devtools.build.skyframe.SkyFunction; +import com.google.devtools.build.skyframe.SkyFunctionException; +import com.google.devtools.build.skyframe.SkyKey; +import com.google.devtools.build.skyframe.SkyValue; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +import javax.annotation.Nullable; + +/** + * A function that retrieves a set of blacklisted package pattern prefixes from the file given by + * PrecomputedValue.BLACKLISTED_PACKAGE_PREFIXES_FILE. + */ +public class BlacklistedPackagePrefixesFunction implements SkyFunction { + @Nullable + @Override + public SkyValue compute(SkyKey key, Environment env) + throws SkyFunctionException, InterruptedException { + PathPackageLocator pkgLocator = PrecomputedValue.PATH_PACKAGE_LOCATOR.get(env); + PathFragment patternsFile = PrecomputedValue.BLACKLISTED_PACKAGE_PREFIXES_FILE.get(env); + if (env.valuesMissing()) { + return null; + } + + if (patternsFile.equals(PathFragment.EMPTY_FRAGMENT)) { + return new BlacklistedPackagePrefixesValue(ImmutableSet.<PathFragment>of()); + } + + for (Path packagePathEntry : pkgLocator.getPathEntries()) { + RootedPath rootedPatternFile = RootedPath.toRootedPath(packagePathEntry, patternsFile); + FileValue patternFileValue = (FileValue) env.getValue(FileValue.key(rootedPatternFile)); + if (patternFileValue == null) { + return null; + } + if (patternFileValue.isFile()) { + try { + try (InputStreamReader reader = + new InputStreamReader(rootedPatternFile.asPath().getInputStream(), + StandardCharsets.UTF_8)) { + return new BlacklistedPackagePrefixesValue( + CharStreams.readLines(reader, new PathFragmentLineProcessor())); + } + } catch (IOException e) { + String errorMessage = e.getMessage() != null + ? "error '" + e.getMessage() + "'" : "an error"; + throw new BlacklistedPatternsFunctionException( + new InconsistentFilesystemException( + rootedPatternFile.asPath() + " is not readable because: " + errorMessage + + ". Was it modified mid-build?")); + } + } + } + + return new BlacklistedPackagePrefixesValue(ImmutableSet.<PathFragment>of()); + } + + private static final class PathFragmentLineProcessor + implements LineProcessor<ImmutableSet<PathFragment>> { + private final ImmutableSet.Builder<PathFragment> fragments = ImmutableSet.builder(); + + @Override + public boolean processLine(String line) throws IOException { + if (!line.isEmpty()) { + fragments.add(new PathFragment(line)); + } + return true; + } + + @Override + public ImmutableSet<PathFragment> getResult() { + return fragments.build(); + } + } + + @Nullable + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + + private static final class BlacklistedPatternsFunctionException extends SkyFunctionException { + public BlacklistedPatternsFunctionException(InconsistentFilesystemException e) { + super(e, Transience.TRANSIENT); + } + } +}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BlacklistedPackagePrefixesValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/BlacklistedPackagePrefixesValue.java new file mode 100644 index 0000000..036f055 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/BlacklistedPackagePrefixesValue.java
@@ -0,0 +1,56 @@ +// Copyright 2014 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.skyframe; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.skyframe.SkyKey; +import com.google.devtools.build.skyframe.SkyValue; + +/** + * An immutable set of package name prefixes that should be blacklisted. + */ +public class BlacklistedPackagePrefixesValue implements SkyValue { + private final ImmutableSet<PathFragment> patterns; + + private static final SkyKey BLACKLIST_KEY = + new SkyKey(SkyFunctions.BLACKLISTED_PACKAGE_PREFIXES, ""); + + public BlacklistedPackagePrefixesValue(ImmutableSet<PathFragment> exclusions) { + this.patterns = Preconditions.checkNotNull(exclusions); + } + + public static SkyKey key() { + return BLACKLIST_KEY; + } + + public ImmutableSet<PathFragment> getPatterns() { + return patterns; + } + + @Override + public int hashCode() { + return patterns.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BlacklistedPackagePrefixesValue) { + BlacklistedPackagePrefixesValue other = (BlacklistedPackagePrefixesValue) obj; + return this.patterns.equals(other.patterns); + } + return false; + } +}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java index 3a4f7d6..28557d1 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java
@@ -73,13 +73,14 @@ return PackageLookupValue.DELETED_PACKAGE_VALUE; } - ImmutableSet<PathFragment> patterns = PrecomputedValue.BLACKLISTED_PKG_PREFIXES.get(env); - if (patterns == null) { + BlacklistedPackagePrefixesValue blacklistedPatternsValue = + (BlacklistedPackagePrefixesValue) env.getValue(BlacklistedPackagePrefixesValue.key()); + if (blacklistedPatternsValue == null) { return null; } PathFragment buildFileFragment = packageKey.getPackageFragment(); - for (PathFragment pattern : patterns) { + for (PathFragment pattern : blacklistedPatternsValue.getPatterns()) { if (buildFileFragment.startsWith(pattern)) { return PackageLookupValue.DELETED_PACKAGE_VALUE; }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java index 518b538..0e17d97 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java
@@ -19,7 +19,6 @@ import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.TopLevelArtifactContext; @@ -77,8 +76,9 @@ public static final Precomputed<String> DEFAULTS_PACKAGE_CONTENTS = new Precomputed<>(new SkyKey(SkyFunctions.PRECOMPUTED, "default_pkg")); - public static final Precomputed<ImmutableSet<PathFragment>> BLACKLISTED_PKG_PREFIXES = - new Precomputed<>(new SkyKey(SkyFunctions.PRECOMPUTED, "blacklisted_pkg_patterns")); + public static final Precomputed<PathFragment> BLACKLISTED_PACKAGE_PREFIXES_FILE = + new Precomputed<>( + new SkyKey(SkyFunctions.PRECOMPUTED, "blacklisted_package_prefixes_file")); public static final Precomputed<RuleVisibility> DEFAULT_VISIBILITY = new Precomputed<>(new SkyKey(SkyFunctions.PRECOMPUTED, "default_visibility"));
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java index 3286908..4ee7430 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveDirectoryTraversalFunction.java
@@ -113,11 +113,13 @@ */ TReturn visitDirectory(RecursivePkgKey recursivePkgKey, Environment env) { RootedPath rootedPath = recursivePkgKey.getRootedPath(); - ImmutableSet<PathFragment> blacklist = PrecomputedValue.BLACKLISTED_PKG_PREFIXES.get(env); + BlacklistedPackagePrefixesValue blacklist = + (BlacklistedPackagePrefixesValue) env.getValue(BlacklistedPackagePrefixesValue.key()); if (blacklist == null) { return null; } - Set<PathFragment> excludedPaths = Sets.union(recursivePkgKey.getExcludedPaths(), blacklist); + Set<PathFragment> excludedPaths = + Sets.union(recursivePkgKey.getExcludedPaths(), blacklist.getPatterns()); Path root = rootedPath.getRoot(); PathFragment rootRelativePath = rootedPath.getRelativePath();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java index b041211..3ed5488 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java
@@ -51,6 +51,8 @@ SkyFunctionName.create("PREPARE_DEPS_OF_PATTERN"); public static final SkyFunctionName PREPARE_DEPS_OF_TARGETS_UNDER_DIRECTORY = SkyFunctionName.create("PREPARE_DEPS_OF_TARGETS_UNDER_DIRECTORY"); + public static final SkyFunctionName BLACKLISTED_PACKAGE_PREFIXES = + SkyFunctionName.create("BLACKLISTED_PACKAGE_PREFIXES"); public static final SkyFunctionName TEST_SUITE_EXPANSION = SkyFunctionName.create("TEST_SUITE_EXPANSION"); public static final SkyFunctionName TESTS_IN_SUITE = SkyFunctionName.create("TESTS_IN_SUITE");
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java index 76ad0e7..c21a416 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -344,6 +344,7 @@ map.put(SkyFunctions.PREPARE_DEPS_OF_PATTERN, new PrepareDepsOfPatternFunction(pkgLocator)); map.put(SkyFunctions.PREPARE_DEPS_OF_TARGETS_UNDER_DIRECTORY, new PrepareDepsOfTargetsUnderDirectoryFunction()); + map.put(SkyFunctions.BLACKLISTED_PACKAGE_PREFIXES, new BlacklistedPackagePrefixesFunction()); map.put(SkyFunctions.TESTS_IN_SUITE, new TestsInSuiteFunction()); map.put(SkyFunctions.TEST_SUITE_EXPANSION, new TestSuiteExpansionFunction()); map.put(SkyFunctions.TARGET_PATTERN_PHASE, new TargetPatternPhaseFunction()); @@ -499,8 +500,8 @@ } } - protected ImmutableSet<PathFragment> getBlacklistedPkgPrefixes() { - return ImmutableSet.of(); + protected PathFragment getBlacklistedPackagePrefixesFile() { + return PathFragment.EMPTY_FRAGMENT; } class BuildViewProvider { @@ -861,8 +862,8 @@ public abstract void setDeletedPackages(Iterable<PackageIdentifier> pkgs); @VisibleForTesting - public final void setBlacklistedPkgPrefixes(ImmutableSet<PathFragment> blacklist) { - PrecomputedValue.BLACKLISTED_PKG_PREFIXES.set(injectable(), blacklist); + public final void setBlacklistedPackagePrefixesFile(PathFragment blacklistedPkgFile) { + PrecomputedValue.BLACKLISTED_PACKAGE_PREFIXES_FILE.set(injectable(), blacklistedPkgFile); } /** @@ -879,7 +880,7 @@ maybeInjectPrecomputedValuesForAnalysis(); setCommandId(commandId); - setBlacklistedPkgPrefixes(getBlacklistedPkgPrefixes()); + setBlacklistedPackagePrefixesFile(getBlacklistedPackagePrefixesFile()); setShowLoadingProgress(showLoadingProgress); setDefaultVisibility(defaultVisibility); setupDefaultPackage(defaultsPackageContents);