Add BundledFileSystem
This is an InMemoryFileSystem whose contents are guaranteed to not change during Skyframe evaluation. It produces fake, constant digest values, and ExternalFilesHelper identifies its files as FileType.BUNDLED rather than as external files.
Work toward #11437.
PiperOrigin-RevId: 363245300
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
index fc0e83a..7ad8850 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
@@ -56,6 +56,7 @@
import com.google.devtools.build.lib.starlarkbuildapi.core.Bootstrap;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.common.options.Option;
@@ -103,6 +104,31 @@
ImmutableList<RuleSet> requires();
}
+ /** An InMemoryFileSystem for bundled builtins .bzl files. */
+ public static class BundledFileSystem extends InMemoryFileSystem {
+
+ private static final byte[] EMPTY_DIGEST = new byte[0];
+
+ public BundledFileSystem() {
+ super(DigestHashFunction.SHA256);
+ }
+
+ // Bundled files are guaranteed to not change throughout the lifetime of the Bazel server, so it
+ // is permissible to use a fake digest. This helps avoid peculiarities in the interaction of
+ // InMemoryFileSystem and Skyframe. See cl/354809138 for further discussion, including of
+ // possible (but unlikely) future caveats of this approach.
+
+ @Override
+ protected synchronized byte[] getFastDigest(PathFragment path) throws IOException {
+ return EMPTY_DIGEST;
+ }
+
+ @Override
+ protected synchronized byte[] getDigest(PathFragment path) throws IOException {
+ return EMPTY_DIGEST;
+ }
+ }
+
/** Builder for {@link ConfiguredRuleClassProvider}. */
public static class Builder implements RuleDefinitionEnvironment {
private final StringBuilder defaultWorkspaceFilePrefix = new StringBuilder();
@@ -503,7 +529,7 @@
// Use of --experimental_builtins_bzl_path=%bundled% is disallowed.
builtinsRoot = null;
} else {
- InMemoryFileSystem fs = new InMemoryFileSystem(DigestHashFunction.SHA256);
+ BundledFileSystem fs = new BundledFileSystem();
Path builtinsPath = fs.getPath("/virtual_builtins_bzl");
if (builtinsBzlZipResource != null) {
// Production case.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
index c4e85d1..da07b4d 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
@@ -16,6 +16,7 @@
import com.google.common.base.Preconditions;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
+import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider.BundledFileSystem;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
@@ -151,6 +152,13 @@
/** Classification of a path encountered by Bazel. */
public enum FileType {
+ /**
+ * A path to a file located inside of Bazel, e.g. the bundled builtins_bzl root (for {@code
+ * --experimental_builtins_bzl_root=%bundled%}) that live in an InMemoryFileSystem. These files
+ * must not change throughout the lifetime of the server.
+ */
+ BUNDLED,
+
/** A path inside the package roots. */
INTERNAL,
@@ -259,7 +267,14 @@
return Pair.of(fileType, null);
}
+ /**
+ * Returns the classification of a path, and updates this instance's state regarding what kinds of
+ * paths have been seen.
+ */
private FileType detectFileType(RootedPath rootedPath) {
+ if (rootedPath.getRoot().getFileSystem() instanceof BundledFileSystem) {
+ return FileType.BUNDLED;
+ }
PathPackageLocator packageLocator = pkgLocator.get();
if (packageLocator.getPathEntries().contains(rootedPath.getRoot())) {
return FileType.INTERNAL;
@@ -305,6 +320,7 @@
externalFileAction);
RepositoryFunction.addManagedDirectoryDependencies(pair.getSecond(), env);
break;
+ case BUNDLED:
case INTERNAL:
break;
case EXTERNAL: