diff --git a/tools/java/runfiles/Runfiles.java b/tools/java/runfiles/Runfiles.java index 81fa0b37e3481f..b704847b5a784e 100644 --- a/tools/java/runfiles/Runfiles.java +++ b/tools/java/runfiles/Runfiles.java @@ -78,67 +78,84 @@ * Process p = pb.start(); * */ -public abstract class Runfiles { +public final class Runfiles { - private static final String MAIN_REPOSITORY_NAME = ""; + public abstract static class Preloaded { - /** - * See {@link com.google.devtools.build.lib.analysis.RepoMappingManifestAction.Entry}. - */ - private static class RepoMappingKey { + /** + * See {@link com.google.devtools.build.lib.analysis.RepoMappingManifestAction.Entry}. + */ + static class RepoMappingKey { - public final String sourceRepo; - public final String targetRepoApparentName; + public final String sourceRepo; + public final String targetRepoApparentName; - public RepoMappingKey(String sourceRepo, String targetRepoApparentName) { - this.sourceRepo = sourceRepo; - this.targetRepoApparentName = targetRepoApparentName; - } + public RepoMappingKey(String sourceRepo, String targetRepoApparentName) { + this.sourceRepo = sourceRepo; + this.targetRepoApparentName = targetRepoApparentName; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RepoMappingKey that = (RepoMappingKey) o; + return sourceRepo.equals(that.sourceRepo) && targetRepoApparentName.equals( + that.targetRepoApparentName); } - if (o == null || getClass() != o.getClass()) { - return false; + + @Override + public int hashCode() { + return Objects.hash(sourceRepo, targetRepoApparentName); } - RepoMappingKey that = (RepoMappingKey) o; - return sourceRepo.equals(that.sourceRepo) && targetRepoApparentName.equals( - that.targetRepoApparentName); } - @Override - public int hashCode() { - return Objects.hash(sourceRepo, targetRepoApparentName); + /** + * Returns a new instance that uses the provided source repository as a default for all calls to + * {@link #rlocation(String)}. + * + *

This is useful when receiving a {@link Runfiles} instance from a different Bazel + * repository. In this case, while the runfiles manifest or directory encoded in the instance + * should be used for runfiles lookups, the repository from which apparent repository names + * should be resolved needs to change. + * + * @param sourceRepository the canonical name of the Bazel repository relative to which apparent + * repository names should be resolved + * @return a new {@link Runfiles} instance identical to this one, except that calls to + * {@link #rlocation(String)} use the provided source repository. + */ + public final Runfiles withSourceRepository(String sourceRepository) { + Util.checkArgument(sourceRepository != null); + return new Runfiles(this, sourceRepository); } - } - private final Map repoMapping; - private final String sourceRepository; + public final Runfiles unmapped() { + return new Runfiles(this, null); + } - // Package-private constructor, so only package-private classes may extend it. - private Runfiles(String repoMappingPath, String sourceRepository) throws IOException { - this.repoMapping = loadRepositoryMapping(repoMappingPath); - this.sourceRepository = sourceRepository; - } + protected abstract Map getEnvVars(); - protected Runfiles(Runfiles runfiles, String sourceRepository) { - this.repoMapping = runfiles.repoMapping; - this.sourceRepository = sourceRepository; + protected abstract String rlocationChecked(String path); + + protected abstract Map getRepoMapping(); + + // Private constructor, so only nested classes may extend it. + private Preloaded() { + } } - /** - * Returns a new {@link Runfiles} instance. - * - *

Deprecated: With {@code --enable_bzlmod}, this function can only resolve runfiles - * correctly if called from the main repository. Use {@link #create(String)} instead. - * - *

This method passes the JVM's environment variable map to {@link #create(Map)}. - */ - @Deprecated - public static Runfiles create() throws IOException { - return create(System.getenv()); + private static final String MAIN_REPOSITORY = ""; + + private final Preloaded preloadedRunfiles; + private final String sourceRepository; + + private Runfiles(Preloaded preloadedRunfiles, String sourceRepository) { + this.preloadedRunfiles = preloadedRunfiles; + this.sourceRepository = sourceRepository; } /** @@ -150,17 +167,13 @@ public static Runfiles create() throws IOException { * lookups should be performed. This can be obtained using * {@link AutoBazelRepository} (see class documentation). */ - public static Runfiles create(String sourceRepository) throws IOException { - return create(System.getenv(), sourceRepository); + public static Preloaded preload() throws IOException { + return preload(System.getenv()); } /** * Returns a new {@link Runfiles} instance. * - *

Deprecated: With {@code --enable_bzlmod}, this function can only resolve runfiles - * correctly if called from the main repository. Use {@link #create(Map, String)} instead. - * - * *

The returned object is either: * *