fix crash for recursive target pattern outside of universe scope
PiperOrigin-RevId: 350560818
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/BUILD b/src/main/java/com/google/devtools/build/lib/pkgcache/BUILD
index b174fd9..cf2dee9 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/BUILD
@@ -31,6 +31,7 @@
"//src/main/java/com/google/devtools/build/lib/concurrent",
"//src/main/java/com/google/devtools/build/lib/events",
"//src/main/java/com/google/devtools/build/lib/packages",
+ "//src/main/java/com/google/devtools/build/lib/query2/engine",
"//src/main/java/com/google/devtools/build/lib/skyframe:detailed_exceptions",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
"//src/main/java/com/google/devtools/build/lib/util:detailed_exit_code",
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java
index 316bd23..378905e 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/RecursivePackageProvider.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
import java.util.Map;
@@ -56,7 +57,7 @@
PathFragment directory,
ImmutableSet<PathFragment> blacklistedSubdirectories,
ImmutableSet<PathFragment> excludedSubdirectories)
- throws InterruptedException;
+ throws InterruptedException, QueryException;
/**
* Returns the {@link Package} corresponding to each Package in "pkgIds". If any of the packages
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
index 4962e08..d5eceb7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
@@ -1575,6 +1575,7 @@
"//src/main/java/com/google/devtools/build/lib/events",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/com/google/devtools/build/lib/pkgcache",
+ "//src/main/java/com/google/devtools/build/lib/query2/engine",
"//src/main/java/com/google/devtools/build/lib/rules:repository/repository_directory_value",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
@@ -2140,6 +2141,7 @@
"//src/main/java/com/google/devtools/build/lib/events",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/com/google/devtools/build/lib/pkgcache",
+ "//src/main/java/com/google/devtools/build/lib/query2/engine",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
"//src/main/protobuf:failure_details_java_proto",
"//third_party:guava",
@@ -2217,9 +2219,11 @@
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/build/lib/concurrent",
"//src/main/java/com/google/devtools/build/lib/events",
+ "//src/main/java/com/google/devtools/build/lib/query2/engine",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
"//src/main/java/com/google/devtools/build/skyframe",
+ "//src/main/protobuf:failure_details_java_proto",
"//third_party:guava",
],
)
@@ -2274,6 +2278,7 @@
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/build/lib/concurrent",
"//src/main/java/com/google/devtools/build/lib/events",
+ "//src/main/java/com/google/devtools/build/lib/query2/engine",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
"//src/main/java/com/google/devtools/build/skyframe",
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
index 1776a29..22bd020 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
@@ -37,6 +37,7 @@
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.pkgcache.AbstractRecursivePackageProvider;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
@@ -207,7 +208,7 @@
PathFragment directory,
ImmutableSet<PathFragment> ignoredSubdirectories,
ImmutableSet<PathFragment> excludedSubdirectories)
- throws InterruptedException {
+ throws InterruptedException, QueryException {
ImmutableList<Root> roots =
checkValidDirectoryAndGetRoots(
repository, directory, ignoredSubdirectories, excludedSubdirectories);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java
index 72b343a..f89e4db 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePackageProviderBackedTargetPatternResolver.java
@@ -44,6 +44,7 @@
import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
import com.google.devtools.build.lib.pkgcache.RecursivePackageProvider;
import com.google.devtools.build.lib.pkgcache.TargetPatternResolverUtil;
+import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
@@ -253,7 +254,7 @@
pathFragment,
blacklistedSubdirectories,
excludedSubdirectories);
- } catch (TargetParsingException e) {
+ } catch (TargetParsingException | QueryException e) {
return Futures.immediateFailedFuture(e);
} catch (InterruptedException e) {
return Futures.immediateCancelledFuture();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java
index ac1ea8a..580105e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursivePkgValueRootPackageExtractor.java
@@ -13,7 +13,6 @@
// limitations under the License.
package com.google.devtools.build.lib.skyframe;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -22,6 +21,8 @@
import com.google.devtools.build.lib.concurrent.BatchCallback;
import com.google.devtools.build.lib.concurrent.ParallelVisitor.UnusedException;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
+import com.google.devtools.build.lib.query2.engine.QueryException;
+import com.google.devtools.build.lib.server.FailureDetails.Query.Code;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
@@ -41,7 +42,7 @@
PathFragment directory,
ImmutableSet<PathFragment> ignoredSubdirectories,
ImmutableSet<PathFragment> excludedSubdirectories)
- throws InterruptedException {
+ throws InterruptedException, QueryException {
ImmutableSet<PathFragment> filteredIgnoredSubdirectories =
ImmutableSet.copyOf(
Iterables.filter(
@@ -49,21 +50,24 @@
path -> !path.equals(directory) && path.startsWith(directory)));
for (Root root : roots) {
- // Note: no need to check if lookup == null because it will never be null.
- // {@link RecursivePkgFunction} handles all errors in a keep_going build.
- // In a nokeep_going build, we would never reach this part of the code.
+ RootedPath rootedPath = RootedPath.toRootedPath(root, directory);
RecursivePkgValue lookup =
(RecursivePkgValue)
graph.getValue(
- RecursivePkgValue.key(
- repository,
- RootedPath.toRootedPath(root, directory),
- filteredIgnoredSubdirectories));
- Preconditions.checkState(
- lookup != null,
- "Root %s in repository %s could not be found in the graph.",
- root.asPath(),
- repository.getName());
+ RecursivePkgValue.key(repository, rootedPath, filteredIgnoredSubdirectories));
+ if (lookup == null) {
+ // A null lookup should only happen during post-analysis queries which have access to
+ // --universe_scope logic. For builds lookup should never be null because {@link
+ // RecursivePkgFunction} handles all errors in a --keep_going build. In a --nokeep_going
+ // build, we should never reach this part of the code.
+ throw new QueryException(
+ String.format(
+ "Unable to load package '%s' because package is not in scope. Check that all"
+ + " target patterns in query expression are within the --universe_scope of this"
+ + " query.",
+ rootedPath),
+ Code.TARGET_NOT_IN_UNIVERSE_SCOPE);
+ }
ImmutableList.Builder<PackageIdentifier> packageIds = ImmutableList.builder();
for (String packageName : lookup.getPackages().toList()) {
// TODO(bazel-team): Make RecursivePkgValue return NestedSet<PathFragment> so this transform
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RootPackageExtractor.java b/src/main/java/com/google/devtools/build/lib/skyframe/RootPackageExtractor.java
index b92e8e1..65a4fa2 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RootPackageExtractor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RootPackageExtractor.java
@@ -19,6 +19,7 @@
import com.google.devtools.build.lib.concurrent.BatchCallback;
import com.google.devtools.build.lib.concurrent.ParallelVisitor.UnusedException;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
+import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.skyframe.WalkableGraph;
@@ -53,5 +54,5 @@
PathFragment directory,
ImmutableSet<PathFragment> blacklistedSubdirectories,
ImmutableSet<PathFragment> excludedSubdirectories)
- throws InterruptedException;
+ throws InterruptedException, QueryException;
}
diff --git a/src/test/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQuerySemanticsTest.java b/src/test/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQuerySemanticsTest.java
index 807c092..4f2988d 100644
--- a/src/test/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQuerySemanticsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/query2/cquery/ConfiguredTargetQuerySemanticsTest.java
@@ -38,7 +38,8 @@
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.build.lib.query2.engine.QueryException;
-import com.google.devtools.build.lib.server.FailureDetails.ConfigurableQuery.Code;
+import com.google.devtools.build.lib.server.FailureDetails.ConfigurableQuery;
+import com.google.devtools.build.lib.server.FailureDetails.Query;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.vfs.Path;
import java.util.Collection;
@@ -161,7 +162,8 @@
// Test that the proper error is thrown when requesting an attribute that doesn't exist.
EvalThrowsResult evalThrowsResult = evalThrows("labels('fake_attr', //test:my_rule)", true);
- assertConfigurableQueryCode(evalThrowsResult.getFailureDetail(), Code.ATTRIBUTE_MISSING);
+ assertConfigurableQueryCode(
+ evalThrowsResult.getFailureDetail(), ConfigurableQuery.Code.ATTRIBUTE_MISSING);
assertThat(evalThrowsResult.getMessage())
.isEqualTo(
"in 'fake_attr' of rule //test:my_rule: configured target of type"
@@ -337,11 +339,13 @@
EvalThrowsResult hostResult = evalThrows("config(//test:host_dep, target)", true);
assertThat(hostResult.getMessage())
.isEqualTo("No target (in) //test:host_dep could be found in the 'target' configuration");
- assertConfigurableQueryCode(hostResult.getFailureDetail(), Code.TARGET_MISSING);
+ assertConfigurableQueryCode(
+ hostResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
EvalThrowsResult execResult = evalThrows("config(//test:exec_dep, target)", true);
assertThat(execResult.getMessage())
.isEqualTo("No target (in) //test:exec_dep could be found in the 'target' configuration");
- assertConfigurableQueryCode(execResult.getFailureDetail(), Code.TARGET_MISSING);
+ assertConfigurableQueryCode(
+ execResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
BuildConfiguration configuration =
getConfiguration(Iterables.getOnlyElement(eval("config(//test:dep, target)")));
@@ -361,12 +365,14 @@
EvalThrowsResult targetResult = evalThrows("config(//test:target_dep, host)", true);
assertThat(targetResult.getMessage())
.isEqualTo("No target (in) //test:target_dep could be found in the 'host' configuration");
- assertConfigurableQueryCode(targetResult.getFailureDetail(), Code.TARGET_MISSING);
+ assertConfigurableQueryCode(
+ targetResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
assertThat(eval("config(//test:host_dep, host)")).isEqualTo(eval("//test:host_dep"));
EvalThrowsResult hostResult = evalThrows("config(//test:exec_dep, host)", true);
assertThat(hostResult.getMessage())
.isEqualTo("No target (in) //test:exec_dep could be found in the 'host' configuration");
- assertConfigurableQueryCode(hostResult.getFailureDetail(), Code.TARGET_MISSING);
+ assertConfigurableQueryCode(
+ hostResult.getFailureDetail(), ConfigurableQuery.Code.TARGET_MISSING);
BuildConfiguration configuration =
getConfiguration(Iterables.getOnlyElement(eval("config(//test:dep, host)")));
@@ -455,7 +461,8 @@
QueryException e =
assertThrows(
QueryException.class, () -> eval("config(//mytest:mytarget," + wrongPrefix + ")"));
- assertConfigurableQueryCode(e.getFailureDetail(), Code.INCORRECT_CONFIG_ARGUMENT_ERROR);
+ assertConfigurableQueryCode(
+ e.getFailureDetail(), ConfigurableQuery.Code.INCORRECT_CONFIG_ARGUMENT_ERROR);
assertThat(e)
.hasMessageThat()
.contains("config()'s second argument must identify a unique configuration");
@@ -492,6 +499,19 @@
+ "find BUILD file /workspace/parent/child/BUILD");
}
+ // Regression test for b/175739699
+ @Test
+ public void testRecursiveTargetPatternOutsideOfScopeFailsGracefully() throws Exception {
+ writeFile("testA/BUILD", "sh_library(name = 'testA')");
+ writeFile("testB/BUILD", "sh_library(name = 'testB')");
+ writeFile("testB/testC/BUILD", "sh_library(name = 'testC')");
+ helper.setUniverseScope("//testA");
+ QueryException e = assertThrows(QueryException.class, () -> eval("//testB/..."));
+ assertThat(e.getFailureDetail().getQuery().getCode())
+ .isEqualTo(Query.Code.TARGET_NOT_IN_UNIVERSE_SCOPE);
+ assertThat(e).hasMessageThat().contains("package is not in scope");
+ }
+
@Override
@Test
public void testMultipleTopLevelConfigurations_nullConfigs() throws Exception {