Stop throwing an exception if a Package was successfully created but contains errors. Instead, require callers to process the package and throw if they need to.
This allows us to avoid embedding a Package in an exception, which is icky. This also allows us to remove Package#containsTemporaryErrors.
Most callers' changes are fairly straightforward. The exception is EnvironmentBackedRecursivePackageProvider, which cannot throw an exception of its own in case of a package with errors (because it doesn't do that in keep_going mode), but whose request for a package with errors *should* shut down the build in case of nokeep_going mode. To do this in Skyframe, we have a new PackageErrorFunction which is to be called only in this situation, and will unconditionally throw. EnvironmentBackedRecursivePackageProvider can then catch this exception and continue on as usual, except that the exception will shut down the thread pool in a nokeep_going build.
--
MOS_MIGRATED_REVID=103247761
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java
index 63e8e1d..4d2413a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/EnvironmentBackedRecursivePackageProvider.java
@@ -13,11 +13,13 @@
// 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.common.collect.Iterables;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Package;
@@ -46,21 +48,26 @@
public Package getPackage(EventHandler eventHandler, PackageIdentifier packageName)
throws NoSuchPackageException, MissingDepException {
SkyKey pkgKey = PackageValue.key(packageName);
- Package pkg;
- try {
- PackageValue pkgValue =
- (PackageValue) env.getValueOrThrow(pkgKey, NoSuchPackageException.class);
- if (pkgValue == null) {
+ PackageValue pkgValue =
+ (PackageValue) env.getValueOrThrow(pkgKey, NoSuchPackageException.class);
+ if (pkgValue == null) {
+ throw new MissingDepException();
+ }
+ Package pkg = pkgValue.getPackage();
+ if (pkg.containsErrors()) {
+ // If this is a nokeep_going build, we must shut the build down by throwing an exception. To
+ // do that, we request a node that will throw an exception, and then try to catch it and
+ // continue. This gives the framework notification to shut down the build if it should.
+ try {
+ env.getValueOrThrow(
+ PackageErrorFunction.key(packageName), BuildFileContainsErrorsException.class);
+ Preconditions.checkState(env.valuesMissing(), "Should have thrown for %s", packageName);
throw new MissingDepException();
- }
- pkg = pkgValue.getPackage();
- } catch (NoSuchPackageException e) {
- pkg = e.getPackage();
- if (pkg == null) {
- throw e;
+ } catch (BuildFileContainsErrorsException e) {
+ // Expected.
}
}
- return pkg;
+ return pkgValue.getPackage();
}
@Override