[7.3.0] Be resilient to outdated exec paths in action cache entries (#23230)
https://github.com/bazelbuild/bazel/commit/60924fdc2972184494f6382d39e8c786aa14b9a9
changed the canonical repo name separator from `~` to `+`. Older repo
names containing `~` now trigger a syntax error. If an action cache
entry refers to an exec path from a previous version of Bazel that used
`~`, we need to be resilient and treat the cache entry as corrupted,
rather than just crash.
Fixes https://github.com/bazelbuild/bazel/issues/23180.
Closes #23227.
PiperOrigin-RevId: 660105601
Change-Id: Iea5d86c635056d12ba20598383da463bdde03ab0
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java b/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
index 6e814e1..6f8d153 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/PackageIdentifier.java
@@ -23,6 +23,7 @@
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyKey.SkyKeyInterner;
+import java.util.Optional;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@@ -77,8 +78,11 @@
*
* In this case, this method returns a package identifier for foo/bar, even though that is not a
* package. Callers need to look up the actual package if needed.
+ *
+ * <p>Returns {@link Optional#empty()} if the path corresponds to an invalid label (e.g. with a
+ * malformed repo name).
*/
- public static PackageIdentifier discoverFromExecPath(
+ public static Optional<PackageIdentifier> discoverFromExecPath(
PathFragment execPath, boolean forFiles, boolean siblingRepositoryLayout) {
Preconditions.checkArgument(!execPath.isAbsolute(), execPath);
PathFragment tofind =
@@ -93,10 +97,15 @@
if (tofind.startsWith(prefix)) {
// Using the path prefix can be either "external" or "..", depending on whether the sibling
// repository layout is used.
- RepositoryName repository = RepositoryName.createUnvalidated(tofind.getSegment(1));
- return PackageIdentifier.create(repository, tofind.subFragment(2));
+ try {
+ RepositoryName repository = RepositoryName.create(tofind.getSegment(1));
+ return Optional.of(PackageIdentifier.create(repository, tofind.subFragment(2)));
+ } catch (LabelSyntaxException e) {
+ // The path corresponds to an invalid label.
+ return Optional.empty();
+ }
} else {
- return PackageIdentifier.createInMainRepo(tofind);
+ return Optional.of(PackageIdentifier.createInMainRepo(tofind));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/HeaderDiscovery.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/HeaderDiscovery.java
index 40f1f71..bb3d068 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/HeaderDiscovery.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/HeaderDiscovery.java
@@ -22,7 +22,6 @@
import com.google.devtools.build.lib.actions.PathMapper;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
-import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
@@ -32,6 +31,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import javax.annotation.Nullable;
/**
@@ -178,10 +178,13 @@
}
Artifact artifact = regularDerivedArtifacts.get(execPathFragment);
if (artifact == null) {
- RepositoryName repository =
- PackageIdentifier.discoverFromExecPath(execPathFragment, false, siblingRepositoryLayout)
- .getRepository();
- artifact = artifactResolver.resolveSourceArtifact(execPathFragment, repository);
+ Optional<PackageIdentifier> pkgId =
+ PackageIdentifier.discoverFromExecPath(
+ execPathFragment, false, siblingRepositoryLayout);
+ if (pkgId.isPresent()) {
+ artifact =
+ artifactResolver.resolveSourceArtifact(execPathFragment, pkgId.get().getRepository());
+ }
}
if (artifact != null) {
// We don't need to add the sourceFile itself as it is a mandatory input.
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 eef14e8..5958e27 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
@@ -116,6 +116,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
@@ -686,11 +687,13 @@
PathFragment parent =
checkNotNull(path.getParentDirectory(), "Must pass in files, not root directory");
checkArgument(!parent.isAbsolute(), path);
- ContainingPackageLookupValue.Key depKey =
- ContainingPackageLookupValue.key(
- PackageIdentifier.discoverFromExecPath(path, true, siblingRepositoryLayout));
- depKeys.put(path, depKey);
- packageLookupsRequested.add(depKey);
+ Optional<PackageIdentifier> pkgId =
+ PackageIdentifier.discoverFromExecPath(path, true, siblingRepositoryLayout);
+ if (pkgId.isPresent()) {
+ ContainingPackageLookupValue.Key depKey = ContainingPackageLookupValue.key(pkgId.get());
+ depKeys.put(path, depKey);
+ packageLookupsRequested.add(depKey);
+ }
}
SkyframeLookupResult values = env.getValuesAndExceptions(depKeys.values());