Encode missing input file failures with FailureDetails
Also refactors missing file message functions so that fewer
MissingInputFileExceptions are needlessly constructed.
RELNOTES: None.
PiperOrigin-RevId: 318356644
diff --git a/src/main/java/com/google/devtools/build/lib/actions/MissingInputFileException.java b/src/main/java/com/google/devtools/build/lib/actions/MissingInputFileException.java
index f37cd06..78ed120 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/MissingInputFileException.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/MissingInputFileException.java
@@ -14,27 +14,28 @@
package com.google.devtools.build.lib.actions;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.syntax.Location;
+import com.google.devtools.build.lib.util.DetailedExitCode;
/**
- * This exception is thrown during a build when an input file is missing, but the file
- * is not the input to any action being executed.
+ * This exception is thrown during a build when an input file is missing, but the file is not the
+ * input to any action being executed.
*
- * If a missing input file is an input
- * to an action, an {@link ActionExecutionException} is thrown instead.
+ * <p>If a missing input file is an input to an action, an {@link ActionExecutionException} is
+ * thrown instead.
*/
public class MissingInputFileException extends BuildFailedException {
private final Location location;
- public MissingInputFileException(String message, Location location) {
- super(message);
+ public MissingInputFileException(FailureDetail failureDetail, Location location) {
+ super(failureDetail.getMessage(), DetailedExitCode.of(failureDetail));
this.location = location;
}
/**
- * Return a location where this input file is referenced. If there
- * are multiple such locations, one is chosen arbitrarily. If there
- * are none, return null.
+ * Return a location where this input file is referenced. If there are multiple such locations,
+ * one is chosen arbitrarily. If there are none, return null.
*/
public Location getLocation() {
return location;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
index 7f6d752..bbfb4f5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java
@@ -1051,12 +1051,11 @@
new IllegalStateException("Non-source artifact had IO Exception" + input, e));
}
- MissingFileArtifactValue missingValue =
- ArtifactFunction.makeMissingInputFileValue(input, e);
- MissingInputFileException missingException = missingValue.getException();
skyframeActionExecutor.printError(
String.format(
- "%s: %s", actionForError.getOwner().getLabel(), missingException.getMessage()),
+ "%s: %s",
+ actionForError.getOwner().getLabel(),
+ ArtifactFunction.makeMissingInputFileMessage(input, e)),
actionForError,
null);
// We don't create a specific cause for the artifact as we do in #handleMissingFile because
@@ -1286,7 +1285,7 @@
missingArtifactCauses.add(
handleMissingFile(
input,
- ArtifactFunction.makeMissingInputFileValue(input, e),
+ ArtifactFunction.makeMissingInputFileMessage(input, e),
action.getOwner().getLabel()));
continue;
}
@@ -1447,17 +1446,21 @@
static LabelCause handleMissingFile(
Artifact input, MissingFileArtifactValue missingValue, Label labelInCaseOfBug) {
- MissingInputFileException e = missingValue.getException();
+ return handleMissingFile(input, missingValue.getException().getMessage(), labelInCaseOfBug);
+ }
+
+ static LabelCause handleMissingFile(
+ Artifact input, String missingMessage, Label labelInCaseOfBug) {
Label inputLabel = input.getOwner();
if (inputLabel == null) {
BugReport.sendBugReport(
new IllegalStateException(
String.format(
"Artifact %s with missing value %s should have owner (%s)",
- input, e.getMessage(), labelInCaseOfBug)));
+ input, missingMessage, labelInCaseOfBug)));
inputLabel = labelInCaseOfBug;
}
- return new LabelCause(inputLabel, e.getMessage());
+ return new LabelCause(inputLabel, missingMessage);
}
@Override
@@ -1749,7 +1752,7 @@
missingArtifactCauses.add(
handleMissingFile(
input,
- ArtifactFunction.makeMissingInputFileValue(input, e),
+ ArtifactFunction.makeMissingInputFileMessage(input, e),
action.getOwner().getLabel()));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
index fd5775b..d04081a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactFunction.java
@@ -254,13 +254,13 @@
try {
fileValue = (FileValue) env.getValueOrThrow(fileSkyKey, IOException.class);
} catch (IOException e) {
- return makeMissingInputFileValue(artifact, e);
+ return makeMissingSourceInputFileValue(artifact, e);
}
if (fileValue == null) {
return null;
}
if (!fileValue.exists()) {
- return makeMissingInputFileValue(artifact, null);
+ return makeMissingSourceInputFileValue(artifact, null);
}
// For directory artifacts that are not Filesets, we initiate a directory traversal here, and
@@ -305,17 +305,27 @@
try {
return FileArtifactValue.createForSourceArtifact(artifact, fileValue);
} catch (IOException e) {
- return makeMissingInputFileValue(artifact, e);
+ return makeMissingSourceInputFileValue(artifact, e);
}
}
- static MissingFileArtifactValue makeMissingInputFileValue(Artifact artifact, Exception failure) {
- String extraMsg = (failure == null) ? "" : (": " + failure.getMessage());
+ static MissingFileArtifactValue makeMissingSourceInputFileValue(
+ Artifact artifact, Exception failure) {
MissingInputFileException ex =
- new MissingInputFileException(constructErrorMessage(artifact) + extraMsg, null);
+ new MissingInputFileException(
+ FailureDetail.newBuilder()
+ .setMessage(makeMissingInputFileMessage(artifact, failure))
+ .setExecution(Execution.newBuilder().setCode(Code.SOURCE_INPUT_MISSING))
+ .build(),
+ null);
return new MissingFileArtifactValue(ex);
}
+ static String makeMissingInputFileMessage(Artifact artifact, Exception failure) {
+ return constructErrorMessage(artifact)
+ + ((failure == null) ? "" : (": " + failure.getMessage()));
+ }
+
@Nullable
private static AggregatingArtifactValue createAggregatingValue(
Artifact artifact,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletor.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletor.java
index 56df64e..ed95bde 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectCompletor.java
@@ -27,6 +27,9 @@
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
+import com.google.devtools.build.lib.server.FailureDetails.Execution;
+import com.google.devtools.build.lib.server.FailureDetails.Execution.Code;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.AspectCompletionValue.AspectCompletionKey;
import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey;
import com.google.devtools.build.lib.skyframe.CompletionFunction.Completor;
@@ -59,12 +62,15 @@
public MissingInputFileException getMissingFilesException(
AspectValue value, AspectCompletionKey key, int missingCount, Environment env) {
AspectKey aspectKey = key.actionLookupKey();
+ String message =
+ String.format(
+ "%s, aspect %s %d input file(s) do not exist",
+ aspectKey.getLabel(), aspectKey.getAspectClass().getName(), missingCount);
return new MissingInputFileException(
- aspectKey.getLabel()
- + ", aspect "
- + aspectKey.getAspectClass().getName()
- + missingCount
- + " input file(s) do not exist",
+ FailureDetail.newBuilder()
+ .setMessage(message)
+ .setExecution(Execution.newBuilder().setCode(Code.SOURCE_INPUT_MISSING))
+ .build(),
value.getLocation());
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java
index 555de2f..fef0a70 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/CompletionFunction.java
@@ -229,7 +229,7 @@
missingCount++;
handleMissingFile(
input,
- ArtifactFunction.makeMissingInputFileValue(input, e),
+ ArtifactFunction.makeMissingSourceInputFileValue(input, e),
rootCausesBuilder,
env,
value,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunction.java
index 6242832..2799fcc 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PlatformMappingFunction.java
@@ -26,6 +26,9 @@
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
+import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration;
+import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration.Code;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.syntax.Location;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -79,10 +82,12 @@
if (fileValue.isDirectory()) {
throw new PlatformMappingException(
new MissingInputFileException(
- String.format(
- "--platform_mappings was set to '%s' relative to the top-level workspace '%s'"
- + " but that path refers to a directory, not a file",
- workspaceRelativeMappingPath, root),
+ createFailureDetail(
+ String.format(
+ "--platform_mappings was set to '%s' relative to the top-level workspace"
+ + " '%s' but that path refers to a directory, not a file",
+ workspaceRelativeMappingPath, root),
+ Code.PLATFORM_MAPPINGS_FILE_IS_DIRECTORY),
Location.BUILTIN),
SkyFunctionException.Transience.PERSISTENT);
}
@@ -105,14 +110,23 @@
}
throw new PlatformMappingException(
new MissingInputFileException(
- String.format(
- "--platform_mappings was set to '%s' but no such file exists relative to the "
- + "package path roots, '%s'",
- workspaceRelativeMappingPath, pathEntries),
+ createFailureDetail(
+ String.format(
+ "--platform_mappings was set to '%s' but no such file exists relative to the "
+ + "package path roots, '%s'",
+ workspaceRelativeMappingPath, pathEntries),
+ Code.PLATFORM_MAPPINGS_FILE_NOT_FOUND),
Location.BUILTIN),
SkyFunctionException.Transience.PERSISTENT);
}
+ private static FailureDetail createFailureDetail(String message, Code detailedCode) {
+ return FailureDetail.newBuilder()
+ .setMessage(message)
+ .setBuildConfiguration(BuildConfiguration.newBuilder().setCode(detailedCode))
+ .build();
+ }
+
@Nullable
@Override
public String extractTag(SkyKey skyKey) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletor.java b/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletor.java
index 9a7fef9..6eac1e1 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TargetCompletor.java
@@ -25,6 +25,9 @@
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
+import com.google.devtools.build.lib.server.FailureDetails.Execution;
+import com.google.devtools.build.lib.server.FailureDetails.Execution.Code;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.skyframe.CompletionFunction.Completor;
import com.google.devtools.build.lib.skyframe.TargetCompletionValue.TargetCompletionKey;
import com.google.devtools.build.skyframe.SkyFunction;
@@ -62,10 +65,13 @@
return null;
}
return new MissingInputFileException(
- configuredTargetAndData.getTarget().getLocation()
- + " "
- + missingCount
- + " input file(s) do not exist",
+ FailureDetail.newBuilder()
+ .setMessage(
+ String.format(
+ "%s %d input file(s) do not exist",
+ configuredTargetAndData.getTarget().getLocation(), missingCount))
+ .setExecution(Execution.newBuilder().setCode(Code.SOURCE_INPUT_MISSING))
+ .build(),
configuredTargetAndData.getTarget().getLocation());
}
diff --git a/src/main/protobuf/failure_details.proto b/src/main/protobuf/failure_details.proto
index fb70bbc..23fa1b7 100644
--- a/src/main/protobuf/failure_details.proto
+++ b/src/main/protobuf/failure_details.proto
@@ -407,6 +407,7 @@
[(metadata) = { exit_code: 1 }];
NON_ACTION_EXECUTION_FAILURE = 34 [(metadata) = { exit_code: 1 }];
CYCLE = 35 [(metadata) = { exit_code: 1 }];
+ SOURCE_INPUT_MISSING = 36 [(metadata) = { exit_code: 1 }];
}
Code code = 1;
@@ -541,6 +542,8 @@
enum Code {
BUILD_CONFIGURATION_UNKNOWN = 0 [(metadata) = { exit_code: 2 }];
PLATFORM_MAPPING_EVALUATION_FAILURE = 1 [(metadata) = { exit_code: 2 }];
+ PLATFORM_MAPPINGS_FILE_IS_DIRECTORY = 2 [(metadata) = { exit_code: 1 }];
+ PLATFORM_MAPPINGS_FILE_NOT_FOUND = 3 [(metadata) = { exit_code: 1 }];
}
Code code = 1;