Take #2 of add repo mapping to bazel context.

This is so that @SkylarkCallable methods (Label.relative in particular) can have access to the repository mapping from the context to properly convert labels.

Initial submit broke rules_go in downstream: https://buildkite.com/bazel/bazel-at-head-plus-downstream/builds/725#35b48f7f-3e95-4322-a360-88c6dc7fb748, but unknown commit fixed it.

RELNOTES: None
PiperOrigin-RevId: 228573949
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 800aa08..6a0faef 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -387,6 +387,7 @@
     ],
     deps = [
         ":skylarkinterface",
+        "//src/main/java/com/google/devtools/build/lib/cmdline:RepositoryName",
         "//third_party:guava",
         "//third_party:jsr305",
     ],
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 b24da5e..3b52ea2 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
@@ -39,6 +39,7 @@
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.graph.Digraph;
 import com.google.devtools.build.lib.graph.Node;
@@ -795,9 +796,10 @@
       SkylarkSemantics skylarkSemantics,
       EventHandler eventHandler,
       String astFileContentHashCode,
-      Map<String, Extension> importMap) {
+      Map<String, Extension> importMap,
+      ImmutableMap<RepositoryName, RepositoryName> repoMapping) {
     BazelStarlarkContext context =
-        new BazelStarlarkContext(toolsRepository, configurationFragmentMap);
+        new BazelStarlarkContext(toolsRepository, configurationFragmentMap, repoMapping);
     Environment env =
         Environment.builder(mutability)
             .setGlobals(globals)
@@ -818,14 +820,16 @@
       SkylarkSemantics skylarkSemantics,
       EventHandler eventHandler,
       String astFileContentHashCode,
-      Map<String, Extension> importMap) {
+      Map<String, Extension> importMap,
+      ImmutableMap<RepositoryName, RepositoryName> repoMapping) {
     return createSkylarkRuleClassEnvironment(
         mutability,
         globals.withLabel(extensionLabel),
         skylarkSemantics,
         eventHandler,
         astFileContentHashCode,
-        importMap);
+        importMap,
+        repoMapping);
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelStarlarkContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelStarlarkContext.java
index 7ebf761..682e433 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelStarlarkContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelStarlarkContext.java
@@ -15,6 +15,7 @@
 package com.google.devtools.build.lib.analysis.skylark;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.skylarkinterface.StarlarkContext;
 import java.util.Objects;
 import javax.annotation.Nullable;
@@ -23,21 +24,28 @@
 public class BazelStarlarkContext implements StarlarkContext {
   private final String toolsRepository;
   @Nullable private final ImmutableMap<String, Class<?>> fragmentNameToClass;
+  private final ImmutableMap<RepositoryName, RepositoryName> repoMapping;
 
   /**
-   * @param toolsRepository the name of the tools repository, such as "bazel_tools"
+   * @param toolsRepository the name of the tools repository, such as "@bazel_tools"
    * @param fragmentNameToClass a map from configuration fragment name to configuration fragment
    *     class, such as "apple" to AppleConfiguration.class
+   * @param repoMapping a map from RepositoryName to RepositoryName to be used for external
+   *     repository renaming
    */
   public BazelStarlarkContext(
-      String toolsRepository, ImmutableMap<String, Class<?>> fragmentNameToClass) {
+      String toolsRepository,
+      ImmutableMap<String, Class<?>> fragmentNameToClass,
+      ImmutableMap<RepositoryName, RepositoryName> repoMapping) {
     this.toolsRepository = toolsRepository;
     this.fragmentNameToClass = fragmentNameToClass;
+    this.repoMapping = repoMapping;
   }
 
   /** @param toolsRepository the name of the tools repository, such as "bazel_tools" */
-  public BazelStarlarkContext(String toolsRepository) {
-    this(toolsRepository, null);
+  public BazelStarlarkContext(
+      String toolsRepository, ImmutableMap<RepositoryName, RepositoryName> repoMapping) {
+    this(toolsRepository, null, repoMapping);
   }
 
   @Override
@@ -50,12 +58,13 @@
     }
     BazelStarlarkContext that = (BazelStarlarkContext) obj;
     return Objects.equals(this.toolsRepository, that.toolsRepository)
-        && Objects.equals(this.fragmentNameToClass, that.fragmentNameToClass);
+        && Objects.equals(this.fragmentNameToClass, that.fragmentNameToClass)
+        && Objects.equals(this.repoMapping, that.repoMapping);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(toolsRepository, fragmentNameToClass);
+    return Objects.hash(toolsRepository, fragmentNameToClass, repoMapping);
   }
 
   /** Returns the name of the tools repository, such as "bazel_tools". */
@@ -67,4 +76,13 @@
   public ImmutableMap<String, Class<?>> getFragmentNameToClass() {
     return fragmentNameToClass;
   }
+
+  /**
+   * Returns a map of {@code RepositoryName}s where the keys are repository names that are
+   * written in the BUILD files and the values are new repository names chosen by the main
+   * repository.
+   */
+  public ImmutableMap<RepositoryName, RepositoryName> getRepoMapping() {
+    return repoMapping;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
index 1883eba..df064a1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
@@ -103,7 +103,9 @@
               .setCallerLabel(ruleContext.getLabel())
               .setSemantics(skylarkSemantics)
               .setEventHandler(ruleContext.getAnalysisEnvironment().getEventHandler())
-              .setStarlarkContext(new BazelStarlarkContext(toolsRepository))
+              .setStarlarkContext(
+                  new BazelStarlarkContext(
+                      toolsRepository, ruleContext.getTarget().getPackage().getRepositoryMapping()))
               .build(); // NB: loading phase functions are not available: this is analysis already,
       // so we do *not* setLoadingPhase().
 
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/BUILD b/src/main/java/com/google/devtools/build/lib/cmdline/BUILD
index a648ed3..4790cf3 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/BUILD
@@ -18,6 +18,7 @@
     visibility = ["//src:__subpackages__"],
     deps = [
         "//src/main/java/com/google/devtools/build/lib:skylarkinterface",
+        "//src/main/java/com/google/devtools/build/lib:starlark_context",
         "//src/main/java/com/google/devtools/build/lib:util",
         "//src/main/java/com/google/devtools/build/lib/actions:commandline_item",
         "//src/main/java/com/google/devtools/build/lib/concurrent",
@@ -28,3 +29,23 @@
         "//third_party:jsr305",
     ],
 )
+
+java_library(
+    name = "RepositoryName",
+    srcs = [
+        "LabelConstants.java",
+        "LabelSyntaxException.java",
+        "LabelValidator.java",
+        "PackageIdentifier.java",
+        "RepositoryName.java",
+    ],
+    visibility = ["//src:__subpackages__"],
+    deps = [
+        "//src/main/java/com/google/devtools/build/lib:skylarkinterface",
+        "//src/main/java/com/google/devtools/build/lib:util",
+        "//src/main/java/com/google/devtools/build/lib/concurrent",
+        "//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec:autocodec-annotation",
+        "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
+        "//third_party:guava",
+    ],
+)
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 454dfe8..b0151b1 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
@@ -19,6 +19,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Interner;
 import com.google.devtools.build.lib.actions.CommandLineItem;
+import com.google.devtools.build.lib.analysis.skylark.BazelStarlarkContext;
 import com.google.devtools.build.lib.cmdline.LabelValidator.BadLabelException;
 import com.google.devtools.build.lib.concurrent.BlazeInterners;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
@@ -30,6 +31,7 @@
 import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
 import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
+import com.google.devtools.build.lib.skylarkinterface.StarlarkContext;
 import com.google.devtools.build.lib.util.StringUtilities;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import com.google.devtools.build.skyframe.SkyFunctionName;
@@ -506,33 +508,40 @@
    * @param relName the relative label name; must be non-empty.
    */
   @SkylarkCallable(
-    name = "relative",
-    doc =
-        "Resolves a label that is either absolute (starts with <code>//</code>) or relative to the"
-            + " current package. If this label is in a remote repository, the argument will be "
-            + " resolved relative to that repository. If the argument contains a repository, it"
-            + " will be returned as-is. Reserved labels will also be returned as-is.<br>"
-            + "For example:<br>"
-            + "<pre class=language-python>\n"
-            + "Label(\"//foo/bar:baz\").relative(\":quux\") == Label(\"//foo/bar:quux\")\n"
-            + "Label(\"//foo/bar:baz\").relative(\"//wiz:quux\") == Label(\"//wiz:quux\")\n"
-            + "Label(\"@repo//foo/bar:baz\").relative(\"//wiz:quux\") == "
-            + "Label(\"@repo//wiz:quux\")\n"
-            + "Label(\"@repo//foo/bar:baz\").relative(\"//visibility:public\") == "
-            + "Label(\"//visibility:public\")\n"
-            + "Label(\"@repo//foo/bar:baz\").relative(\"@other//wiz:quux\") == "
-            + "Label(\"@other//wiz:quux\")\n"
-            + "</pre>",
-    parameters = {
-      @Param(
-        name = "relName",
-        type = String.class,
-        doc = "The label that will be resolved relative to this one."
-      )
-    }
-  )
-  public Label getRelative(String relName) throws LabelSyntaxException {
-    return getRelativeWithRemapping(relName, /* repositoryMapping= */ ImmutableMap.of());
+      name = "relative",
+      doc =
+          "Resolves a label that is either absolute (starts with <code>//</code>) or relative to "
+              + "the current package. If this label is in a remote repository, the argument will "
+              + "be resolved relative to that repository. If the argument contains a repository "
+              + "name, the current label is ignored and the argument is returned as-is, except "
+              + "that the repository name is rewritten if it is in the current repository mapping. "
+              + "Reserved labels will also be returned as-is.<br>"
+              + "For example:<br>"
+              + "<pre class=language-python>\n"
+              + "Label(\"//foo/bar:baz\").relative(\":quux\") == Label(\"//foo/bar:quux\")\n"
+              + "Label(\"//foo/bar:baz\").relative(\"//wiz:quux\") == Label(\"//wiz:quux\")\n"
+              + "Label(\"@repo//foo/bar:baz\").relative(\"//wiz:quux\") == "
+              + "Label(\"@repo//wiz:quux\")\n"
+              + "Label(\"@repo//foo/bar:baz\").relative(\"//visibility:public\") == "
+              + "Label(\"//visibility:public\")\n"
+              + "Label(\"@repo//foo/bar:baz\").relative(\"@other//wiz:quux\") == "
+              + "Label(\"@other//wiz:quux\")\n"
+              + "</pre>"
+              + "<p>If the repository mapping passed in is <code>{'@other' : '@remapped'}</code>, "
+              + "then the following remapping will take place:<br>"
+              + "<pre class=language-python>\n"
+              + "Label(\"@repo//foo/bar:baz\").relative(\"@other//wiz:quux\") == "
+              + "Label(\"@remapped//wiz:quux\")",
+      parameters = {
+        @Param(
+            name = "relName",
+            type = String.class,
+            doc = "The label that will be resolved relative to this one.")
+      },
+      useContext = true)
+  public Label getRelative(String relName, StarlarkContext context) throws LabelSyntaxException {
+    BazelStarlarkContext bazelStarlarkContext = (BazelStarlarkContext) context;
+    return getRelativeWithRemapping(relName, bazelStarlarkContext.getRepoMapping());
   }
 
   /**
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 a3b02ce..b501ac5 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
@@ -1618,7 +1618,7 @@
 
     try (Mutability mutability = Mutability.create("package %s", packageId)) {
       BazelStarlarkContext starlarkContext =
-          new BazelStarlarkContext(ruleClassProvider.getToolsRepository());
+          new BazelStarlarkContext(ruleClassProvider.getToolsRepository(), repositoryMapping);
       Environment pkgEnv =
           Environment.builder(mutability)
               .setGlobals(BazelLibrary.GLOBALS)
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
index 302b05b..97b8722 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClassProvider.java
@@ -14,7 +14,9 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.Environment.Extension;
@@ -44,15 +46,16 @@
   Map<String, RuleClass> getRuleClassMap();
 
   /**
-   * Returns a new Skylark Environment instance for rule creation.
-   * Implementations need to be thread safe.
-   * Be sure to close() the mutability before you return the results of said evaluation.
+   * Returns a new Skylark Environment instance for rule creation. Implementations need to be thread
+   * safe. Be sure to close() the mutability before you return the results of said evaluation.
    *
    * @param label the location of the rule.
    * @param mutability the Mutability for the current evaluation context
    * @param skylarkSemantics the semantics options that modify the interpreter
    * @param eventHandler the EventHandler for warnings, errors, etc.
    * @param astFileContentHashCode the hash code identifying this environment.
+   * @param importMap map from import string to Extension
+   * @param repoMapping map of RepositoryNames to be remapped
    * @return an Environment, in which to evaluate load time skylark forms.
    */
   Environment createSkylarkRuleClassEnvironment(
@@ -61,7 +64,8 @@
       SkylarkSemantics skylarkSemantics,
       EventHandler eventHandler,
       @Nullable String astFileContentHashCode,
-      @Nullable Map<String, Extension> importMap);
+      @Nullable Map<String, Extension> importMap,
+      ImmutableMap<RepositoryName, RepositoryName> repoMapping);
 
   /**
    * Returns a map from aspect names to aspect factory objects.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java
index 2248c16..4e4a32b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ASTFileLookupFunction.java
@@ -14,6 +14,7 @@
 
 package com.google.devtools.build.lib.skyframe;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.actions.FileValue;
 import com.google.devtools.build.lib.actions.InconsistentFilesystemException;
 import com.google.devtools.build.lib.cmdline.Label;
@@ -120,9 +121,10 @@
                     mutability,
                     skylarkSemantics,
                     env.getListener(),
-                    // the two below don't matter for extracting the ValidationEnvironment:
+                    // the three below don't matter for extracting the ValidationEnvironment:
                     /*astFileContentHashCode=*/ null,
-                    /*importMap=*/ null)
+                    /*importMap=*/ null,
+                    /*repoMapping=*/ ImmutableMap.of())
                 .setupDynamic(Runtime.PKG_NAME, Runtime.NONE)
                 .setupDynamic(Runtime.REPOSITORY_NAME, Runtime.NONE);
         byte[] bytes = FileSystemUtils.readWithKnownFileSize(path, astFileSize);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
index 6de65cf..c6d05e1 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkylarkImportLookupFunction.java
@@ -266,13 +266,16 @@
 
     // Process the load statements in the file.
     ImmutableList<SkylarkImport> unRemappedImports = ast.getImports();
-    ImmutableList<SkylarkImport> imports =
-        remapImports(unRemappedImports, workspaceChunk, workspacePath, fileLabel, env);
-    // We do a skykey lookup in remapImports that might not be completed yet so if it returns null
-    // we need to stop the current computation
-    if (imports == null) {
+    ImmutableMap<RepositoryName, RepositoryName> repositoryMapping =
+        getRepositoryMapping(workspaceChunk, workspacePath, fileLabel, env);
+
+    if (repositoryMapping == null) {
       return null;
     }
+
+    ImmutableList<SkylarkImport> imports =
+        remapImports(unRemappedImports, workspaceChunk, repositoryMapping);
+
     ImmutableMap<String, Label> labelsForImports = getLabelsForLoadStatements(imports, fileLabel);
     ImmutableCollection<Label> importLabels = labelsForImports.values();
 
@@ -371,52 +374,30 @@
     // #createExtension does not request values from the Environment. It may post events to the
     // Environment, but events do not matter when caching SkylarkImportLookupValues.
     Extension extension =
-        createExtension(ast, fileLabel, extensionsForImports, skylarkSemantics, env, inWorkspace);
+        createExtension(
+            ast,
+            fileLabel,
+            extensionsForImports,
+            skylarkSemantics,
+            env,
+            inWorkspace,
+            repositoryMapping);
     SkylarkImportLookupValue result =
         new SkylarkImportLookupValue(
             extension, new SkylarkFileDependency(fileLabel, fileDependencies.build()));
     return result;
   }
 
-  /**
-   * This method takes in a list of {@link SkylarkImport}s (load statements) as they appear in the
-   * BUILD, bzl, or WORKSPACE file they originated from and optionally remaps the load statements
-   * using the repository mappings provided in the WORKSPACE file.
-   *
-   * <p>If the {@link SkylarkImport}s originated from a WORKSPACE file, then the repository mappings
-   * are pulled from the previous {@link WorkspaceFileValue}. If they didn't originate from a
-   * WORKSPACE file then the repository mappings are pulled from the fully computed {@link
-   * RepositoryMappingValue}.
-   *
-   * <p>There is a chance that SkyValues requested are not yet computed and so SkyFunction callers
-   * of this method need to check if the return value is null and then return null themselves.
-   *
-   * @param unRemappedImports the list of load statements to be remapped
-   * @param workspaceChunk the workspaceChunk we are currently evaluating that this load statement
-   *     originated from. WORKSPACE files are chunked at every non-consecutive load statement and
-   *     evaluated separately. See {@link WorkspaceFileValue} for more information.
-   * @param workspacePath the path of the project's WORKSPACE file
-   * @param enclosingFileLabel the label of the file (bzl, WORKSPACE, BUILD) that this load
-   *     statement appeared in
-   * @param env the Skyframe used to ask for additional SkyValues
-   * @return a list of remapped {@link SkylarkImport}s or null if any SkyValue requested wasn't
-   *     fully computed yet
-   * @throws InterruptedException
-   */
-  private ImmutableList<SkylarkImport> remapImports(
-      ImmutableList<SkylarkImport> unRemappedImports,
-      int workspaceChunk,
-      RootedPath workspacePath,
-      Label enclosingFileLabel,
-      Environment env)
+  private ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping(
+      int workspaceChunk, RootedPath workspacePath, Label enclosingFileLabel, Environment env)
       throws InterruptedException {
 
     // There is no previous workspace chunk
     if (workspaceChunk == 0) {
-      return unRemappedImports;
+      return ImmutableMap.of();
     }
-    ImmutableMap<RepositoryName, RepositoryName> repositoryMapping;
 
+    ImmutableMap<RepositoryName, RepositoryName> repositoryMapping;
     // We are fully done with workspace evaluation so we should get the mappings from the
     // final RepositoryMappingValue
     if (workspaceChunk == -1) {
@@ -439,6 +420,41 @@
               .getOrDefault(
                   enclosingFileLabel.getPackageIdentifier().getRepository(), ImmutableMap.of());
     }
+    return repositoryMapping;
+  }
+
+  /**
+   * This method takes in a list of {@link SkylarkImport}s (load statements) as they appear in the
+   * BUILD, bzl, or WORKSPACE file they originated from and optionally remaps the load statements
+   * using the repository mappings provided in the WORKSPACE file.
+   *
+   * <p>If the {@link SkylarkImport}s originated from a WORKSPACE file, then the repository mappings
+   * are pulled from the previous {@link WorkspaceFileValue}. If they didn't originate from a
+   * WORKSPACE file then the repository mappings are pulled from the fully computed {@link
+   * RepositoryMappingValue}.
+   *
+   * <p>There is a chance that SkyValues requested are not yet computed and so SkyFunction callers
+   * of this method need to check if the return value is null and then return null themselves.
+   *
+   * @param unRemappedImports the list of load statements to be remapped
+   * @param workspaceChunk the workspaceChunk we are currently evaluating that this load statement
+   *     originated from. WORKSPACE files are chunked at every non-consecutive load statement and
+   *     evaluated separately. See {@link WorkspaceFileValue} for more information.
+   * @param repositoryMapping map from original repository names to new repository names given
+   *     by the main repository
+   * @return a list of remapped {@link SkylarkImport}s or null if any SkyValue requested wasn't
+   *     fully computed yet
+   * @throws InterruptedException
+   */
+  private ImmutableList<SkylarkImport> remapImports(
+      ImmutableList<SkylarkImport> unRemappedImports,
+      int workspaceChunk,
+      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) {
+
+    // There is no previous workspace chunk
+    if (workspaceChunk == 0) {
+      return unRemappedImports;
+    }
 
     ImmutableList.Builder<SkylarkImport> builder = ImmutableList.builder();
     for (SkylarkImport notRemappedImport : unRemappedImports) {
@@ -475,16 +491,15 @@
                 (oldLabel, newLabel) -> oldLabel));
   }
 
-  /**
-   * Creates the Extension to be imported.
-   */
+  /** Creates the Extension to be imported. */
   private Extension createExtension(
       BuildFileAST ast,
       Label extensionLabel,
       Map<String, Extension> importMap,
       SkylarkSemantics skylarkSemantics,
       Environment env,
-      boolean inWorkspace)
+      boolean inWorkspace,
+      ImmutableMap<RepositoryName, RepositoryName> repositoryMapping)
       throws SkylarkImportFailedException, InterruptedException {
     StoredEventHandler eventHandler = new StoredEventHandler();
     // TODO(bazel-team): this method overestimates the changes which can affect the
@@ -494,10 +509,14 @@
     PathFragment extensionFile = extensionLabel.toPathFragment();
     try (Mutability mutability = Mutability.create("importing %s", extensionFile)) {
       com.google.devtools.build.lib.syntax.Environment extensionEnv =
-          ruleClassProvider
-              .createSkylarkRuleClassEnvironment(
-                  extensionLabel, mutability, skylarkSemantics,
-                  eventHandler, ast.getContentHashCode(), importMap);
+          ruleClassProvider.createSkylarkRuleClassEnvironment(
+              extensionLabel,
+              mutability,
+              skylarkSemantics,
+              eventHandler,
+              ast.getContentHashCode(),
+              importMap,
+              repositoryMapping);
       extensionEnv.setupOverride("native", packageFactory.getNativeModule(inWorkspace));
       execAndExport(ast, extensionLabel, eventHandler, extensionEnv);
 
diff --git a/src/main/java/com/google/devtools/build/skydoc/BUILD b/src/main/java/com/google/devtools/build/skydoc/BUILD
index 869ea9b..c6e3688 100644
--- a/src/main/java/com/google/devtools/build/skydoc/BUILD
+++ b/src/main/java/com/google/devtools/build/skydoc/BUILD
@@ -51,6 +51,7 @@
     srcs = glob(["*.java"]),
     visibility = ["//src/test:__subpackages__"],
     deps = [
+        "//src/main/java/com/google/devtools/build/lib:build-base",
         "//src/main/java/com/google/devtools/build/lib:events",
         "//src/main/java/com/google/devtools/build/lib:skylark_semantics",
         "//src/main/java/com/google/devtools/build/lib:skylark_semantics_options",
diff --git a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
index f298430..bb64b94 100644
--- a/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
+++ b/src/main/java/com/google/devtools/build/skydoc/SkydocMain.java
@@ -19,6 +19,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.analysis.skylark.BazelStarlarkContext;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.events.EventHandler;
@@ -384,7 +385,9 @@
 
     Map<String, Extension> imports = new HashMap<>();
     for (SkylarkImport anImport : buildFileAST.getImports()) {
-      Label relativeLabel = label.getRelative(anImport.getImportString());
+      BazelStarlarkContext context =
+          new BazelStarlarkContext("", ImmutableMap.of(), ImmutableMap.of());
+      Label relativeLabel = label.getRelative(anImport.getImportString(), context);
 
       try {
         Environment importEnv =
diff --git a/src/test/java/com/google/devtools/build/lib/cmdline/LabelTest.java b/src/test/java/com/google/devtools/build/lib/cmdline/LabelTest.java
index ea74305..c5ad4da 100644
--- a/src/test/java/com/google/devtools/build/lib/cmdline/LabelTest.java
+++ b/src/test/java/com/google/devtools/build/lib/cmdline/LabelTest.java
@@ -167,6 +167,32 @@
   }
 
   @Test
+  public void testGetRelativeWithoutRemappingBaseLabel() throws Exception {
+    PackageIdentifier packageId = PackageIdentifier.create("@a", PathFragment.create("foo"));
+    Label base = Label.create(packageId, "bar");
+    ImmutableMap<RepositoryName, RepositoryName> repoMapping =
+        ImmutableMap.of(RepositoryName.create("@a"), RepositoryName.create("@b"));
+    Label relative = base.getRelativeWithRemapping(":y", repoMapping);
+
+    // getRelative should only remap repositories passed in the string arg and not
+    // make changes to existing Labels
+    Label actual = Label.parseAbsoluteUnchecked("@a//foo:y");
+    assertThat(relative).isEqualTo(actual);
+  }
+
+  @Test
+  public void testGetRelativeWithDifferentRepoAndRemapping() throws Exception {
+    PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo"));
+    Label base = Label.create(packageId, "bar");
+    ImmutableMap<RepositoryName, RepositoryName> repoMapping =
+        ImmutableMap.of(RepositoryName.create("@a"), RepositoryName.create("@b"));
+    Label relative = base.getRelativeWithRemapping("@a//x:y", repoMapping);
+
+    Label actual = Label.parseAbsoluteUnchecked("@b//x:y");
+    assertThat(relative).isEqualTo(actual);
+  }
+
+  @Test
   public void testGetRelativeWithRepoLocalAbsoluteLabel() throws Exception {
     PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo"));
     Label base = Label.create(packageId, "bar");
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java b/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java
index 94043f5..e12e982 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java
@@ -68,7 +68,9 @@
     return new EvaluationTestCase() {
       @Override
       public Environment newEnvironment() throws Exception {
-        BazelStarlarkContext context = new BazelStarlarkContext(TestConstants.TOOLS_REPOSITORY);
+        BazelStarlarkContext context =
+            new BazelStarlarkContext(
+                TestConstants.TOOLS_REPOSITORY, /*repoMapping=*/ ImmutableMap.of());
         Environment env =
             Environment.builder(mutability)
                 .setSemantics(semantics)
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java b/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java
index f7f8ee8..4da0657 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/util/EvaluationTestCase.java
@@ -64,7 +64,9 @@
    * No PythonPreprocessing, mostly empty mutable Environment.
    */
   public Environment newBuildEnvironment() {
-    BazelStarlarkContext context = new BazelStarlarkContext(TestConstants.TOOLS_REPOSITORY);
+    BazelStarlarkContext context =
+        new BazelStarlarkContext(
+            TestConstants.TOOLS_REPOSITORY, /* repoMapping= */ ImmutableMap.of());
     Environment env =
         Environment.builder(mutability)
             .useDefaultSemantics()
diff --git a/src/test/shell/bazel/workspace_test.sh b/src/test/shell/bazel/workspace_test.sh
index 43bf32e..59e4dff 100755
--- a/src/test/shell/bazel/workspace_test.sh
+++ b/src/test/shell/bazel/workspace_test.sh
@@ -574,6 +574,40 @@
       || fail "Expected srcs to contain '@b//:x.txt'"
 }
 
+function test_remapping_with_label_relative() {
+  # create foo repository
+  mkdir foo
+  touch foo/WORKSPACE
+  cat >foo/foo.bzl <<EOF
+x = Label("//blah:blah").relative("@a//:baz")
+print(x)
+EOF
+  cat >foo/BUILD <<EOF
+load(":foo.bzl", "x")
+genrule(
+  name = "bar",
+  outs = ["xyz"],
+  cmd = "touch \$(location xyz)",
+  visibility = ["//visibility:public"]
+)
+EOF
+
+  # Main repo assigns @a to @b within @foo
+  mkdir -p main
+  cat >main/WORKSPACE <<EOF
+workspace(name = "main")
+local_repository(name = "foo", path="../foo", repo_mapping = {"@a" : "@b"})
+local_repository(name = "b", path="../b")
+EOF
+  touch main/BUILD
+
+  cd main
+  bazel build --experimental_enable_repo_mapping @foo//:bar \
+      >& "$TEST_log" || fail "Expected build to succeed"
+  expect_log "@b//:baz"
+  expect_not_log "@a//:baz"
+}
+
 function test_workspace_addition_change_aspect() {
   mkdir -p repo_one
   mkdir -p repo_two