diff options
author | 2018-06-12 09:28:45 -0700 | |
---|---|---|
committer | 2018-06-12 09:30:48 -0700 | |
commit | f4b9ff40b8f1612571cc711560177af240d034d0 (patch) | |
tree | 2b2bf5415d7b4a0ab5db78d916cebfec0775f810 /src/main/java/com/google/devtools | |
parent | 1b94e64ee8a1d385e92a8d9f4c9a06e2d99c82bf (diff) |
Remap repository names inside load statements in BUILD files if the repository name is remapped.
For example if main/WORKSPACE contains:
local_repository(
name = "a",
path = "../a",
repo_mapping = {"@x" : "@y"},
)
a/BUILD
load("@x//:sample.bzl", "sample")
Then the load in a/BUILD will be resolved as "@y//:sample.bzl"
RELNOTES: None
PiperOrigin-RevId: 200227431
Diffstat (limited to 'src/main/java/com/google/devtools')
7 files changed, 133 insertions, 36 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java index 2651e65d82..4e1d59e9e3 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java @@ -539,7 +539,9 @@ public class BuildView { } SkylarkImport skylarkImport; try { - skylarkImport = SkylarkImports.create(bzlFileLoadLikeString); + skylarkImport = + SkylarkImports.create( + bzlFileLoadLikeString, /* repositoryMapping= */ ImmutableMap.of()); } catch (SkylarkImportSyntaxException e) { throw new ViewCreationFailedException( String.format("Invalid aspect '%s': %s", aspect, e.getMessage()), e); diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/Label.java b/src/main/java/com/google/devtools/build/lib/cmdline/Label.java index 61805ca5ae..9d14e6d7d8 100644 --- a/src/main/java/com/google/devtools/build/lib/cmdline/Label.java +++ b/src/main/java/com/google/devtools/build/lib/cmdline/Label.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.cmdline; import com.google.common.base.Preconditions; import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Interner; import com.google.devtools.build.lib.actions.CommandLineItem; @@ -115,8 +116,36 @@ public final class Label * * @param defaultToMain Treat labels in the default repository as being in the main one instead. */ + @Deprecated + // TODO(dannark): Remove usages of this method, use other parseAbsolute() instead public static Label parseAbsolute(String absName, boolean defaultToMain) throws LabelSyntaxException { + return parseAbsolute(absName, defaultToMain, /* repositoryMapping= */ ImmutableMap.of()); + } + + /** + * Factory for Labels from absolute string form. e.g. + * + * <pre> + * //foo/bar + * //foo/bar:quux + * {@literal @}foo + * {@literal @}foo//bar + * {@literal @}foo//bar:baz + * </pre> + * + * <p>Labels that begin with a repository name may have the repository name remapped to a + * different name if it appears in {@code repositoryMapping}. This happens if the current + * repository being evaluated is external to the main repository and the main repository set the + * {@code repo_mapping} attribute when declaring this repository. + * + * @param defaultToMain Treat labels in the default repository as being in the main one instead. + */ + public static Label parseAbsolute( + String absName, + boolean defaultToMain, + ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) + throws LabelSyntaxException { String repo = defaultToMain ? "@" : RepositoryName.DEFAULT_REPOSITORY; int packageStartPos = absName.indexOf("//"); if (packageStartPos > 0) { @@ -134,12 +163,21 @@ public final class Label if (repo.isEmpty() && ABSOLUTE_PACKAGE_NAMES.contains(packageFragment)) { repo = "@"; } - return create(PackageIdentifier.create(repo, packageFragment), labelParts.getTargetName()); + RepositoryName globalRepoName = getGlobalRepoName(repo, repositoryMapping); + return create( + PackageIdentifier.create(globalRepoName, packageFragment), labelParts.getTargetName()); } catch (BadLabelException e) { throw new LabelSyntaxException(e.getMessage()); } } + private static RepositoryName getGlobalRepoName( + String repo, ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) + throws LabelSyntaxException { + RepositoryName repoName = RepositoryName.create(repo); + return repositoryMapping.getOrDefault(repoName, repoName); + } + /** * Alternate factory method for Labels from absolute strings. This is a convenience method for * cases when a Label needs to be initialized statically, so the declared exception is diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java index d9da36f945..108a0cf426 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java +++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java @@ -1246,12 +1246,17 @@ public final class PackageFactory { // Run the lexer and parser with a local reporter, so that errors from other threads do not // show up below. BuildFileAST buildFileAST = - parseBuildFile(packageId, input, preludeStatements, localReporterForParsing); + parseBuildFile( + packageId, + input, + preludeStatements, + /* repositoryMapping= */ ImmutableMap.of(), + localReporterForParsing); AstParseResult astParseResult = new AstParseResult(buildFileAST, localReporterForParsing); return createPackageFromAst( workspaceName, - /*repositoryMapping=*/ ImmutableMap.of(), + /* repositoryMapping= */ ImmutableMap.of(), packageId, buildFile, astParseResult, @@ -1266,10 +1271,12 @@ public final class PackageFactory { PackageIdentifier packageId, ParserInputSource in, List<Statement> preludeStatements, + ImmutableMap<RepositoryName, RepositoryName> repositoryMapping, ExtendedEventHandler eventHandler) { // Logged messages are used as a testability hook tracing the parsing progress logger.fine("Starting to parse " + packageId); - BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(in, preludeStatements, eventHandler); + BuildFileAST buildFileAST = + BuildFileAST.parseBuildFile(in, preludeStatements, repositoryMapping, eventHandler); logger.fine("Finished parsing of " + packageId); return buildFileAST; } @@ -1373,10 +1380,10 @@ public final class PackageFactory { packageId, buildFile, input, - /*preludeStatements=*/ ImmutableList.<Statement>of(), - /*imports=*/ ImmutableMap.<String, Extension>of(), - /*skylarkFileDependencies=*/ ImmutableList.<Label>of(), - /*defaultVisibility=*/ ConstantRuleVisibility.PUBLIC, + /* preludeStatements= */ ImmutableList.<Statement>of(), + /* imports= */ ImmutableMap.<String, Extension>of(), + /* skylarkFileDependencies= */ ImmutableList.<Label>of(), + /* defaultVisibility= */ ConstantRuleVisibility.PUBLIC, semantics, globber) .build(); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java index 05189fb12c..ce4116cc57 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java @@ -1220,7 +1220,7 @@ public class PackageFunction implements SkyFunction { StoredEventHandler astParsingEventHandler = new StoredEventHandler(); BuildFileAST ast = PackageFactory.parseBuildFile( - packageId, input, preludeStatements, astParsingEventHandler); + packageId, input, preludeStatements, repositoryMapping, astParsingEventHandler); astParseResult = new AstParseResult(ast, astParsingEventHandler); astCache.put(packageId, astParseResult); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunction.java index a8d14cae61..d2e7ce8741 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceASTFunction.java @@ -15,6 +15,7 @@ package com.google.devtools.build.lib.skyframe; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.FileValue; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException; @@ -73,6 +74,7 @@ public class WorkspaceASTFunction implements SkyFunction { BuildFileAST.parseBuildFile( ParserInputSource.create(bytes, repoWorkspace.asFragment()), ast.getStatements(), + /* repositoryMapping= */ ImmutableMap.of(), env.getListener()); if (ast.containsErrors()) { throw new WorkspaceASTFunctionException( @@ -81,11 +83,14 @@ public class WorkspaceASTFunction implements SkyFunction { Transience.PERSISTENT); } } - ast = BuildFileAST.parseBuildFile( - ParserInputSource.create(ruleClassProvider.getDefaultWorkspaceSuffix(), - PathFragment.create("/DEFAULT.WORKSPACE.SUFFIX")), - ast.getStatements(), - env.getListener()); + ast = + BuildFileAST.parseBuildFile( + ParserInputSource.create( + ruleClassProvider.getDefaultWorkspaceSuffix(), + PathFragment.create("/DEFAULT.WORKSPACE.SUFFIX")), + ast.getStatements(), + /* repositoryMapping= */ ImmutableMap.of(), + env.getListener()); if (ast.containsErrors()) { throw new WorkspaceASTFunctionException( new BuildFileContainsErrorsException( diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java index ca6307fa8a..801013b207 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java @@ -16,7 +16,9 @@ package com.google.devtools.build.lib.syntax; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.hash.HashCode; +import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.events.Location; @@ -68,6 +70,7 @@ public class BuildFileAST extends ASTNode { List<Statement> preludeStatements, ParseResult result, String contentHashCode, + ImmutableMap<RepositoryName, RepositoryName> repositoryMapping, EventHandler eventHandler) { ImmutableList<Statement> statements = ImmutableList.<Statement>builder() @@ -77,7 +80,7 @@ public class BuildFileAST extends ASTNode { boolean containsErrors = result.containsErrors; Pair<Boolean, ImmutableList<SkylarkImport>> skylarkImports = - fetchLoads(statements, eventHandler); + fetchLoads(statements, repositoryMapping, eventHandler); containsErrors |= skylarkImports.first; return new BuildFileAST( statements, @@ -99,7 +102,7 @@ public class BuildFileAST extends ASTNode { if (stmt instanceof LoadStatement) { String str = ((LoadStatement) stmt).getImport().getValue(); try { - imports.add(SkylarkImports.create(str)); + imports.add(SkylarkImports.create(str, /* repositoryMapping= */ ImmutableMap.of())); } catch (SkylarkImportSyntaxException e) { throw new IllegalStateException( "Cannot create SkylarImport for '" + str + "'. This is an internal error."); @@ -120,14 +123,16 @@ public class BuildFileAST extends ASTNode { * imports that could be resolved. */ private static Pair<Boolean, ImmutableList<SkylarkImport>> fetchLoads( - List<Statement> statements, EventHandler eventHandler) { + List<Statement> statements, + ImmutableMap<RepositoryName, RepositoryName> repositoryMapping, + EventHandler eventHandler) { ImmutableList.Builder<SkylarkImport> imports = ImmutableList.builder(); boolean error = false; for (Statement stmt : statements) { if (stmt instanceof LoadStatement) { String importString = ((LoadStatement) stmt).getImport().getValue(); try { - imports.add(SkylarkImports.create(importString)); + imports.add(SkylarkImports.create(importString, repositoryMapping)); } catch (SkylarkImportSyntaxException e) { eventHandler.handle(Event.error(stmt.getLocation(), e.getMessage())); error = true; @@ -272,20 +277,28 @@ public class BuildFileAST extends ASTNode { } /** - * Parse the specified build file, returning its AST. All errors during - * scanning or parsing will be reported to the reporter. + * Parse the specified build file, returning its AST. All errors during scanning or parsing will + * be reported to the reporter. */ - public static BuildFileAST parseBuildFile(ParserInputSource input, - List<Statement> preludeStatements, - EventHandler eventHandler) { + public static BuildFileAST parseBuildFile( + ParserInputSource input, + List<Statement> preludeStatements, + ImmutableMap<RepositoryName, RepositoryName> repositoryMapping, + EventHandler eventHandler) { Parser.ParseResult result = Parser.parseFile(input, eventHandler); - return create(preludeStatements, result, /*contentHashCode=*/ null, eventHandler) + return create( + preludeStatements, result, /* contentHashCode= */ null, repositoryMapping, eventHandler) .validateBuildFile(eventHandler); } public static BuildFileAST parseBuildFile(ParserInputSource input, EventHandler eventHandler) { Parser.ParseResult result = Parser.parseFile(input, eventHandler); - return create(ImmutableList.<Statement>of(), result, /*contentHashCode=*/ null, eventHandler) + return create( + /* preludeStatements= */ ImmutableList.<Statement>of(), + result, + /* contentHashCode= */ null, + /* repositoryMapping= */ ImmutableMap.of(), + eventHandler) .validateBuildFile(eventHandler); } @@ -295,13 +308,21 @@ public class BuildFileAST extends ASTNode { ParserInputSource input = ParserInputSource.create(bytes, path); Parser.ParseResult result = Parser.parseFile(input, eventHandler); return create( - ImmutableList.of(), result, - HashCode.fromBytes(digest).toString(), eventHandler); + /* preludeStatements= */ ImmutableList.of(), + result, + HashCode.fromBytes(digest).toString(), + /* repositoryMapping= */ ImmutableMap.of(), + eventHandler); } public static BuildFileAST parseSkylarkFile(ParserInputSource input, EventHandler eventHandler) { Parser.ParseResult result = Parser.parseFile(input, eventHandler); - return create(ImmutableList.<Statement>of(), result, /*contentHashCode=*/ null, eventHandler); + return create( + /* preludeStatements= */ ImmutableList.<Statement>of(), + result, + /* contentHashCode= */ null, + /* repositoryMapping= */ ImmutableMap.of(), + eventHandler); } /** @@ -320,10 +341,10 @@ public class BuildFileAST extends ASTNode { .addAll(result.statements) .build(), result.containsErrors, - /*contentHashCode=*/null, + /* contentHashCode= */null, result.location, ImmutableList.copyOf(result.comments), - /*imports=*/null); + /* imports= */null); } /** @@ -356,7 +377,12 @@ public class BuildFileAST extends ASTNode { String str = Joiner.on("\n").join(content); ParserInputSource input = ParserInputSource.create(str, PathFragment.EMPTY_FRAGMENT); Parser.ParseResult result = Parser.parseFile(input, eventHandler); - return create(ImmutableList.of(), result, null, eventHandler); + return create( + /* preludeStatements= */ ImmutableList.of(), + result, + /* contentHashCode= */ null, + /* repositoryMapping= */ ImmutableMap.of(), + eventHandler); } public static BuildFileAST parseBuildString(EventHandler eventHandler, String... content) { diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java index 71f1bffc8d..6cedeed40a 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkImports.java @@ -14,10 +14,12 @@ package com.google.devtools.build.lib.syntax; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.cmdline.LabelValidator; import com.google.devtools.build.lib.cmdline.PackageIdentifier; +import com.google.devtools.build.lib.cmdline.RepositoryName; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; import com.google.devtools.build.lib.vfs.PathFragment; @@ -235,18 +237,35 @@ public class SkylarkImports { /** * Creates and syntactically validates a {@link SkylarkImports} instance from a string. - * <p> - * There four syntactic import variants: Absolute paths, relative paths, absolute labels, and - * relative labels + * + * <p>There are four syntactic import variants: Absolute paths, relative paths, absolute labels, + * and relative labels * * @throws SkylarkImportSyntaxException if the string is not a valid Skylark import. */ public static SkylarkImport create(String importString) throws SkylarkImportSyntaxException { + return create(importString, /* repositoryMapping= */ ImmutableMap.of()); + } + + /** + * Creates and syntactically validates a {@link SkylarkImports} instance from a string. + * + * <p>There four syntactic import variants: Absolute paths, relative paths, absolute labels, and + * relative labels + * + * <p>Absolute labels will have the repository portion of the label remapped if it is present in + * {@code repositoryMapping} + * + * @throws SkylarkImportSyntaxException if the string is not a valid Skylark import. + */ + public static SkylarkImport create( + String importString, ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) + throws SkylarkImportSyntaxException { if (importString.startsWith("//") || importString.startsWith("@")) { // Absolute label. Label importLabel; try { - importLabel = Label.parseAbsolute(importString, false); + importLabel = Label.parseAbsolute(importString, false, repositoryMapping); } catch (LabelSyntaxException e) { throw new SkylarkImportSyntaxException(INVALID_LABEL_PREFIX + e.getMessage()); } |