Internal change

PiperOrigin-RevId: 417815015
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
index b9a2e0c..f3d11cb 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
@@ -351,7 +351,7 @@
       Label rdeLabel =
           ruleContext.getRule().getRuleClassObject().getRuleDefinitionEnvironmentLabel();
       // only allow native and builtins to override transitive validation propagation
-      if (rdeLabel != null && !"@_builtins".equals(rdeLabel.getRepository().getNameWithAt())) {
+      if (rdeLabel != null && !"@_builtins".equals(rdeLabel.getRepository().getName())) {
         ruleContext.ruleError(rdeLabel + " cannot access the _transitive_validation private API");
         return;
       }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java
index 1133351..64519a9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java
@@ -444,7 +444,7 @@
   }
 
   public String getMainRepositoryName() {
-    return mainRepositoryName.getName();
+    return mainRepositoryName.strippedName();
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java b/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java
index b13e6cc..a245cb3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/OutputDirectories.java
@@ -101,7 +101,7 @@
     public ArtifactRoot getRoot(
         String outputDirName, BlazeDirectories directories, RepositoryName mainRepositoryName) {
       // e.g., execroot/repo1
-      Path execRoot = directories.getExecRoot(mainRepositoryName.getName());
+      Path execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
       // e.g., [[execroot/repo1]/bazel-out/config/bin]
       return ArtifactRoot.asDerivedRoot(
           execRoot,
@@ -160,7 +160,7 @@
 
     this.mergeGenfilesDirectory = options.mergeGenfilesDirectory;
     this.siblingRepositoryLayout = siblingRepositoryLayout;
-    this.execRoot = directories.getExecRoot(mainRepositoryName.getName());
+    this.execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
   }
 
   private static void addMnemonicPart(
@@ -265,7 +265,7 @@
         execRoot,
         rootType,
         directories.getRelativeOutputPath(),
-        repository.getName(),
+        repository.strippedName(),
         outputDirName,
         nameFragment);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/PackageGroupConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/PackageGroupConfiguredTarget.java
index c4427b9..64bfd5d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/PackageGroupConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/PackageGroupConfiguredTarget.java
@@ -151,7 +151,7 @@
         BazelModuleContext.of(ofInnermostEnclosingStarlarkFunction(starlarkThread))
             .label()
             .getRepository();
-    if (!"@_builtins".equals(repository.getNameWithAt())) {
+    if (!"@_builtins".equals(repository.getName())) {
       throw Starlark.errorf("private API only for use by builtins");
     }
     return Allowlist.isAvailableFor(getPackageSpecifications(), label);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
index 47fd125..b0270b5 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttrModule.java
@@ -457,7 +457,7 @@
       Label label =
           ((BazelModuleContext) Module.ofInnermostEnclosingStarlarkFunction(thread).getClientData())
               .label();
-      if (!label.getPackageIdentifier().getRepository().getName().equals("_builtins")) {
+      if (!label.getPackageIdentifier().getRepository().toString().equals("@_builtins")) {
         throw Starlark.errorf("Rule in '%s' cannot use private API", label.getPackageName());
       }
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
index 3eb5c85..c736c88 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
@@ -466,7 +466,7 @@
     }
 
     if (compileOneFiletype instanceof Sequence) {
-      if (!bzlModule.label().getRepository().getNameWithAt().equals("@_builtins")) {
+      if (!bzlModule.label().getRepository().getName().equals("@_builtins")) {
         throw Starlark.errorf(
             "Rule in '%s' cannot use private API", bzlModule.label().getPackageName());
       }
@@ -909,7 +909,7 @@
       }
       // TODO(b/121385274): remove when we stop allowlisting starlark transitions
       if (hasStarlarkDefinedTransition) {
-        if (!starlarkLabel.getRepository().getNameWithAt().equals("@_builtins")) {
+        if (!starlarkLabel.getRepository().getName().equals("@_builtins")) {
           if (!hasFunctionTransitionAllowlist) {
             errorf(
                 handler,
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java
index 1731bbb..6994f6d 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java
@@ -145,7 +145,7 @@
           Set<String> conflicting =
               overrides.keySet().stream()
                   .filter(repositoryNamesWithManagedDirs::contains)
-                  .map(RepositoryName::getNameWithAt)
+                  .map(RepositoryName::getName)
                   .collect(Collectors.toSet());
           if (!conflicting.isEmpty()) {
             String message =
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionFunction.java
index 7f9add4..a01a4a0 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionFunction.java
@@ -156,7 +156,7 @@
     BiMap<String, ModuleExtensionId> extensionUniqueNames = HashBiMap.create();
     for (ModuleExtensionId id : extensionUsagesById.rowKeySet()) {
       String bestName =
-          id.getBzlFileLabel().getRepository().getName() + "." + id.getExtensionName();
+          id.getBzlFileLabel().getRepository().strippedName() + "." + id.getExtensionName();
       if (extensionUniqueNames.putIfAbsent(bestName, id) == null) {
         continue;
       }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionValue.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionValue.java
index f33078a..00dc3929b3 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionValue.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/BazelModuleResolutionValue.java
@@ -99,8 +99,8 @@
         String canonicalRepoName =
             getExtensionUniqueNames().get(extensionId) + "." + entry.getValue();
         mapping.put(
-            RepositoryName.createUnvalidated(entry.getKey()),
-            RepositoryName.createUnvalidated(canonicalRepoName));
+            RepositoryName.createFromValidStrippedName(entry.getKey()),
+            RepositoryName.createFromValidStrippedName(canonicalRepoName));
       }
     }
     return getDepGraph()
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java
index f93c42b..61f44dc 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Module.java
@@ -106,15 +106,15 @@
     // If this is the root module, this perfectly falls into @<module name> => @
     if (!getName().isEmpty()) {
       mapping.put(
-          RepositoryName.createUnvalidated(getName()),
-          RepositoryName.createUnvalidated(getCanonicalRepoName()));
+          RepositoryName.createFromValidStrippedName(getName()),
+          RepositoryName.createFromValidStrippedName(getCanonicalRepoName()));
     }
     for (Map.Entry<String, ModuleKey> dep : getDeps().entrySet()) {
       // Special note: if `dep` is actually the root module, its ModuleKey would be ROOT whose
       // canonicalRepoName is the empty string. This perfectly maps to the main repo ("@").
       mapping.put(
-          RepositoryName.createUnvalidated(dep.getKey()),
-          RepositoryName.createUnvalidated(dep.getValue().getCanonicalRepoName()));
+          RepositoryName.createFromValidStrippedName(dep.getKey()),
+          RepositoryName.createFromValidStrippedName(dep.getValue().getCanonicalRepoName()));
     }
     return RepositoryMapping.create(mapping.build(), getCanonicalRepoName());
   }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileFunction.java
index 8695ae7..ce56034 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/ModuleFileFunction.java
@@ -216,7 +216,7 @@
           (RepositoryDirectoryValue)
               env.getValue(
                   RepositoryDirectoryValue.key(
-                      RepositoryName.createUnvalidated(canonicalRepoName)));
+                      RepositoryName.createFromValidStrippedName(canonicalRepoName)));
       if (repoDir == null) {
         return null;
       }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModule.java b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModule.java
index a0681e6..99e555f 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/bzlmod/StarlarkBazelModule.java
@@ -95,7 +95,8 @@
   static Label createModuleRootLabel(String canonicalRepoName) {
     return Label.createUnvalidated(
         PackageIdentifier.create(
-            RepositoryName.createUnvalidated(canonicalRepoName), PathFragment.EMPTY_FRAGMENT),
+            RepositoryName.createFromValidStrippedName(canonicalRepoName),
+            PathFragment.EMPTY_FRAGMENT),
         "unused_dummy_target_name");
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java b/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java
index 85be023..ea765a6 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/commands/SyncCommand.java
@@ -195,7 +195,7 @@
           // TODO(aehlig): avoid the detour of serializing and then parsing the repository name
           try {
             repositoriesToFetch.add(
-                RepositoryDirectoryValue.key(RepositoryName.create(rule.getName())));
+                RepositoryDirectoryValue.key(RepositoryName.create("@" + rule.getName())));
           } catch (LabelSyntaxException e) {
             String errorMessage =
                 String.format(
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/CacheHitReportingModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/CacheHitReportingModule.java
index bda4c58..7d33c99 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/CacheHitReportingModule.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/CacheHitReportingModule.java
@@ -15,6 +15,7 @@
 
 import com.google.common.eventbus.Subscribe;
 import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCacheHitEvent;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.Reporter;
 import com.google.devtools.build.lib.repository.RepositoryFailedEvent;
@@ -56,7 +57,7 @@
 
   @Subscribe
   public void failed(RepositoryFailedEvent event) {
-    String repo = event.getRepo();
+    String repo = RepositoryName.stripName(event.getRepo());
     Set<Pair<String, URL>> cacheHits = cacheHitsByRepo.get(repo);
     if (cacheHits != null && !cacheHits.isEmpty()) {
       StringBuilder info = new StringBuilder();
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java
index 41f4777..5f28b96 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java
@@ -247,7 +247,7 @@
             "Repository override directory must be an absolute path", input);
       }
       try {
-        return RepositoryOverride.create(RepositoryName.create(pieces[0]), path);
+        return RepositoryOverride.create(RepositoryName.create("@" + pieces[0]), path);
       } catch (LabelSyntaxException e) {
         throw new OptionsParsingException("Invalid repository name given to override", input);
       }
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 d858937..1acdae6 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/BUILD
@@ -71,6 +71,7 @@
         "//src/main/java/com/google/devtools/build/lib/vfs:ospathpolicy",
         "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
         "//third_party:auto_value",
+        "//third_party:caffeine",
         "//third_party:guava",
         "//third_party:jsr305",
     ],
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 e46d0ce..fcc08a1 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
@@ -89,7 +89,9 @@
     Parts parts = Parts.parse(raw);
     parts.checkPkgIsAbsolute();
     RepositoryName repoName =
-        parts.repo == null ? RepositoryName.MAIN : RepositoryName.createUnvalidated(parts.repo);
+        parts.repo == null
+            ? RepositoryName.MAIN
+            : RepositoryName.createFromValidStrippedName(parts.repo);
     return createUnvalidated(
         PackageIdentifier.create(repoName, PathFragment.create(parts.pkg)), parts.target);
   }
@@ -103,7 +105,7 @@
       return ABSOLUTE_PACKAGE_NAMES.contains(parts.pkg) ? RepositoryName.MAIN : currentRepo;
     }
     // TODO(b/200024947): Make repo mapping take a string and return a RepositoryName.
-    return repoMapping.get(RepositoryName.createUnvalidated(parts.repo));
+    return repoMapping.get(RepositoryName.createFromValidStrippedName(parts.repo));
   }
 
   // TODO(b/200024947): Make this public.
@@ -275,7 +277,9 @@
     }
     // TODO(b/200024947): This method will eventually need to take a repo mapping too.
     RepositoryName repoName =
-        parts.repo == null ? RepositoryName.MAIN : RepositoryName.createUnvalidated(parts.repo);
+        parts.repo == null
+            ? RepositoryName.MAIN
+            : RepositoryName.createFromValidStrippedName(parts.repo);
     return create(PackageIdentifier.create(repoName, pathFragment), parts.target);
   }
 
@@ -402,7 +406,7 @@
   }
 
   public String getUnambiguousCanonicalForm() {
-    return packageIdentifier.getRepository().getNameWithAt()
+    return packageIdentifier.getRepository()
         + "//"
         + packageIdentifier.getPackageFragment()
         + ":"
@@ -418,7 +422,7 @@
               + "<pre class=language-python>Label(\"@foo//bar:baz\").workspace_name"
               + " == \"foo\"</pre>")
   public String getWorkspaceName() {
-    return packageIdentifier.getRepository().getName();
+    return packageIdentifier.getRepository().strippedName();
   }
 
   /**
@@ -435,7 +439,7 @@
     if (packageIdentifier.getRepository().isMain()) {
       repository = "";
     } else {
-      repository = packageIdentifier.getRepository().getNameWithAt();
+      repository = packageIdentifier.getRepository().getName();
     }
     return repository + "//" + getPackageFragment();
   }
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/LabelParser.java b/src/main/java/com/google/devtools/build/lib/cmdline/LabelParser.java
index 8af98a0..75afd2f 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/LabelParser.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/LabelParser.java
@@ -117,9 +117,14 @@
       return validateAndCreate(repo, pkgIsAbsolute, pkg, target, rawLabel);
     }
 
+    @Nullable
     private static void validateRepoName(@Nullable String repo) throws LabelSyntaxException {
-      if (repo != null) {
-        RepositoryName.validate(repo);
+      if (repo == null) {
+        return;
+      }
+      String error = RepositoryName.validate('@' + repo);
+      if (error != null) {
+        throw syntaxErrorf("invalid repository name '@%s': %s", repo, error);
       }
     }
 
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 c64f2be..b2eda75 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
@@ -83,7 +83,7 @@
     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));
+      RepositoryName repository = RepositoryName.createFromValidStrippedName(tofind.getSegment(1));
       return PackageIdentifier.create(repository, tofind.subFragment(2));
     } else {
       return PackageIdentifier.createInMainRepo(tofind);
@@ -116,7 +116,9 @@
     }
     LabelParser.Parts parts = LabelParser.Parts.parse(input + ":dummy_target");
     RepositoryName repoName =
-        parts.repo == null ? RepositoryName.MAIN : RepositoryName.createUnvalidated(parts.repo);
+        parts.repo == null
+            ? RepositoryName.MAIN
+            : RepositoryName.createFromValidStrippedName(parts.repo);
     return create(repoName, PathFragment.create(parts.pkg));
   }
 
@@ -146,7 +148,7 @@
     return repository.isMain() || siblingRepositoryLayout
         ? pkgName
         : LabelConstants.EXTERNAL_PATH_PREFIX
-            .getRelative(repository.getName())
+            .getRelative(repository.strippedName())
             .getRelative(pkgName);
   }
 
@@ -169,7 +171,8 @@
    */
   // TODO(bazel-team): Maybe rename to "getDefaultForm"?
   public String getCanonicalForm() {
-    return repository.getCanonicalForm() + "//" + getPackageFragment();
+    String repository = getRepository().getCanonicalForm();
+    return repository + "//" + getPackageFragment();
   }
 
   /**
@@ -182,10 +185,7 @@
   // that disparity?
   @Override
   public String toString() {
-    if (repository.isMain()) {
-      return getPackageFragment().getPathString();
-    }
-    return getCanonicalForm();
+    return (repository.isMain() ? "" : repository + "//") + pkgName;
   }
 
   @Override
@@ -218,7 +218,7 @@
       return pkgName.compareTo(that.pkgName);
     }
     return ComparisonChain.start()
-        .compare(repository.getName(), that.repository.getName())
+        .compare(repository.toString(), that.repository.toString())
         .compare(pkgName, that.pkgName)
         .result();
   }
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java b/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java
index 796247d..4ea2110 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java
@@ -14,33 +14,51 @@
 
 package com.google.devtools.build.lib.cmdline;
 
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Interner;
-import com.google.devtools.build.lib.concurrent.BlazeInterners;
+import com.google.common.base.Throwables;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
 import com.google.devtools.build.lib.util.Pair;
+import com.google.devtools.build.lib.util.StringCanonicalizer;
 import com.google.devtools.build.lib.util.StringUtilities;
 import com.google.devtools.build.lib.vfs.OsPathPolicy;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.Objects;
+import java.util.concurrent.CompletionException;
 import java.util.regex.Pattern;
 import javax.annotation.Nullable;
 
 /** The name of an external repository. */
 public final class RepositoryName {
 
-  private static final Interner<RepositoryName> interner = BlazeInterners.newWeakInterner();
-
   @SerializationConstant
-  public static final RepositoryName BAZEL_TOOLS = createUnvalidated("bazel_tools");
+  public static final RepositoryName BAZEL_TOOLS = new RepositoryName("@bazel_tools");
 
   @SerializationConstant
   public static final RepositoryName LOCAL_CONFIG_PLATFORM =
-      createUnvalidated("local_config_platform");
+      new RepositoryName("@local_config_platform");
 
-  @SerializationConstant public static final RepositoryName MAIN = createUnvalidated("");
+  @SerializationConstant public static final RepositoryName MAIN = new RepositoryName("@");
 
-  private static final Pattern VALID_REPO_NAME = Pattern.compile("[\\w\\-.]*");
+  private static final Pattern VALID_REPO_NAME = Pattern.compile("@[\\w\\-.]*");
+
+  private static final LoadingCache<String, RepositoryName> repositoryNameCache =
+      Caffeine.newBuilder()
+          .weakValues()
+          .build(
+              name -> {
+                String errorMessage = validate(name);
+                if (errorMessage != null) {
+                  errorMessage =
+                      "invalid repository name '"
+                          + StringUtilities.sanitizeControlChars(name)
+                          + "': "
+                          + errorMessage;
+                  throw new LabelSyntaxException(errorMessage);
+                }
+                return new RepositoryName(StringCanonicalizer.intern(name));
+              });
 
   /**
    * Makes sure that name is a valid repository name and creates a new RepositoryName using it.
@@ -48,14 +66,30 @@
    * @throws LabelSyntaxException if the name is invalid
    */
   public static RepositoryName create(String name) throws LabelSyntaxException {
-    validate(name);
-    return createUnvalidated(name);
+    // TODO(b/200024947): Get rid of the '@'.
+    if (name.isEmpty() || name.equals("@")) {
+      return MAIN;
+    }
+    try {
+      return repositoryNameCache.get(name);
+    } catch (CompletionException e) {
+      Throwables.propagateIfPossible(e.getCause(), LabelSyntaxException.class);
+      throw e;
+    }
   }
 
-  /** Creates a RepositoryName from a known-valid string. */
-  public static RepositoryName createUnvalidated(String name) {
-    Preconditions.checkArgument(!name.startsWith("@"), "Do not prefix @ to repo names!");
-    return interner.intern(new RepositoryName(name));
+  /**
+   * Creates a RepositoryName from a known-valid string (not @-prefixed). Generally this is a
+   * directory that has been created via getSourceRoot() or getPathUnderExecRoot().
+   */
+  public static RepositoryName createFromValidStrippedName(String name) {
+    if (name.isEmpty()) {
+      // NOTE(wyv): Without this `if` clause, a lot of Google-internal integration tests would start
+      //   failing. This suggests to me that something is comparing RepositoryName objects using
+      //   reference equality instead of #equals().
+      return MAIN;
+    }
+    return repositoryNameCache.get("@" + name);
   }
 
   /**
@@ -81,7 +115,7 @@
     }
 
     try {
-      RepositoryName repoName = create(path.getSegment(1));
+      RepositoryName repoName = RepositoryName.create("@" + path.getSegment(1));
       PathFragment subPath = path.subFragment(2);
       return Pair.of(repoName, subPath);
     } catch (LabelSyntaxException e) {
@@ -94,7 +128,7 @@
   /**
    * Store the name if the owner repository where this repository name is requested. If this field
    * is not null, it means this instance represents the requested repository name that is actually
-   * not visible from the owner repository and should fail in {@code RepositoryDelegatorFunction}
+   * not visible from the owner repository and should fail in {@link RepositoryDelegatorFunction}
    * when fetching the repository.
    */
   private final String ownerRepoIfNotVisible;
@@ -108,37 +142,44 @@
     this(name, null);
   }
 
-  /**
-   * Performs validity checking, throwing an exception if the given name is invalid. The exception
-   * message is sanitized.
-   */
-  static void validate(String name) throws LabelSyntaxException {
-    if (name.isEmpty()) {
-      return;
+  /** Performs validity checking. Returns null on success, an error message otherwise. */
+  static String validate(String name) {
+    if (name.isEmpty() || name.equals("@")) {
+      return null;
     }
 
     // Some special cases for more user-friendly error messages.
-    if (name.equals(".") || name.equals("..")) {
-      throw LabelParser.syntaxErrorf(
-          "invalid repository name '%s': repo names are not allowed to be '%s'", name, name);
+    if (!name.startsWith("@")) {
+      return "workspace names must start with '@'";
+    }
+    if (name.equals("@.")) {
+      return "workspace names are not allowed to be '@.'";
+    }
+    if (name.equals("@..")) {
+      return "workspace names are not allowed to be '@..'";
     }
 
     if (!VALID_REPO_NAME.matcher(name).matches()) {
-      throw LabelParser.syntaxErrorf(
-          "invalid repository name '%s': repo names may contain only A-Z, a-z, 0-9, '-', '_' and"
-              + " '.'",
-          StringUtilities.sanitizeControlChars(name));
+      return "workspace names may contain only A-Z, a-z, 0-9, '-', '_' and '.'";
     }
+
+    return null;
   }
 
-  /** Returns the bare repository name without the leading "{@literal @}". */
-  public String getName() {
-    return name;
+  /**
+   * Returns the repository name without the leading "{@literal @}".  For the default repository,
+   * returns "".
+   */
+  public String strippedName() {
+    if (name.isEmpty()) {
+      return name;
+    }
+    return name.substring(1);
   }
 
   /**
    * Create a {@link RepositoryName} instance that indicates the requested repository name is
-   * actually not visible from the owner repository and should fail in {@code
+   * actually not visible from the owner repository and should fail in {@link
    * RepositoryDelegatorFunction} when fetching with this {@link RepositoryName} instance.
    */
   public RepositoryName toNonVisible(String ownerRepo) {
@@ -155,23 +196,43 @@
     return ownerRepoIfNotVisible;
   }
 
-  /** Returns if this is the main repository, that is, {@link #name} is empty. */
-  public boolean isMain() {
-    return name.isEmpty();
-  }
-
-  /** Returns the repository name, with leading "{@literal @}". */
-  public String getNameWithAt() {
-    return '@' + name;
+  /**
+   * Returns the repository name without the leading "{@literal @}". For the default repository,
+   * returns "".
+   */
+  public static String stripName(String repoName) {
+    return repoName.startsWith("@") ? repoName.substring(1) : repoName;
   }
 
   /**
-   * Returns the repository name with leading "{@literal @}" except for the main repo, which is just
-   * the empty string.
+   * Returns if this is the default repository, that is, {@link #name} is "".
+   */
+  public boolean isDefault() {
+    return name.isEmpty();
+  }
+
+  /**
+   * Returns if this is the main repository, that is, {@link #name} is "@".
+   */
+  public boolean isMain() {
+    return name.equals("@");
+  }
+
+  /**
+   * Returns the repository name, with leading "{@literal @}" (or "" for the default repository).
+   */
+  // TODO(bazel-team): Use this over toString()- easier to track its usage.
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Returns the repository name, except that the main repo is conflated with the default repo
+   * ({@code "@"} becomes the empty string).
    */
   // TODO(bazel-team): Consider renaming to "getDefaultForm".
   public String getCanonicalForm() {
-    return isMain() ? "" : getNameWithAt();
+    return isMain() ? "" : name;
   }
 
   /**
@@ -189,7 +250,7 @@
         siblingRepositoryLayout
             ? LabelConstants.EXPERIMENTAL_EXTERNAL_PATH_PREFIX
             : LabelConstants.EXTERNAL_PATH_PREFIX;
-    return prefix.getRelative(getName());
+    return prefix.getRelative(strippedName());
   }
 
   /**
@@ -199,13 +260,15 @@
   public PathFragment getRunfilesPath() {
     return isMain()
         ? PathFragment.EMPTY_FRAGMENT
-        : PathFragment.create("..").getRelative(getName());
+        : PathFragment.create("..").getRelative(strippedName());
   }
 
-  /** Returns the repository name, with leading "{@literal @}". */
+  /**
+   * Returns the repository name, with leading "{@literal @}" (or "" for the default repository).
+   */
   @Override
   public String toString() {
-    return getNameWithAt();
+    return name;
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
index 33cbaaf..8cfdf70 100644
--- a/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
+++ b/src/main/java/com/google/devtools/build/lib/cmdline/TargetPattern.java
@@ -912,7 +912,7 @@
               "Couldn't find package in target " + pattern, TargetPatterns.Code.PACKAGE_NOT_FOUND);
         }
         try {
-          repository = repoMapping.get(RepositoryName.create(pattern.substring(1, pkgStart)));
+          repository = repoMapping.get(RepositoryName.create(pattern.substring(0, pkgStart)));
         } catch (LabelSyntaxException e) {
           throw new TargetParsingException(e.getMessage(), TargetPatterns.Code.LABEL_SYNTAX_ERROR);
         }
@@ -920,7 +920,7 @@
           throw new TargetParsingException(
               String.format(
                   "%s is not visible from repository `@%s`",
-                  repository.getNameWithAt(), repository.getOwnerRepoIfNotVisible()),
+                  repository.getName(), repository.getOwnerRepoIfNotVisible()),
               Code.PACKAGE_NOT_FOUND);
         }
 
@@ -965,7 +965,7 @@
         PackageIdentifier packageIdentifier;
         try {
           packageIdentifier =
-              PackageIdentifier.parse(repository.getNameWithAt() + "//" + realPackagePart);
+              PackageIdentifier.parse(repository.getName() + "//" + realPackagePart);
         } catch (LabelSyntaxException e) {
           throw new TargetParsingException(
               "Invalid package name '" + realPackagePart + "': " + e.getMessage(),
@@ -981,8 +981,7 @@
       if (ALL_RULES_IN_SUFFIXES.contains(targetPart)) {
         PackageIdentifier packageIdentifier;
         try {
-          packageIdentifier =
-              PackageIdentifier.parse(repository.getNameWithAt() + "//" + packagePart);
+          packageIdentifier = PackageIdentifier.parse(repository.getName() + "//" + packagePart);
         } catch (LabelSyntaxException e) {
           throw new TargetParsingException(
               "Invalid package name '" + packagePart + "': " + e.getMessage(),
@@ -995,8 +994,7 @@
       if (ALL_TARGETS_IN_SUFFIXES.contains(targetPart)) {
         PackageIdentifier packageIdentifier;
         try {
-          packageIdentifier =
-              PackageIdentifier.parse(repository.getNameWithAt() + "//" + packagePart);
+          packageIdentifier = PackageIdentifier.parse(repository.getName() + "//" + packagePart);
         } catch (LabelSyntaxException e) {
           throw new TargetParsingException(
               "Invalid package name '" + packagePart + "': " + e.getMessage(),
@@ -1008,7 +1006,7 @@
 
       if (includesRepo || wasOriginallyAbsolute || pattern.contains(":")) {
         PackageIdentifier packageIdentifier;
-        String fullLabel = repository.getNameWithAt() + "//" + pattern;
+        String fullLabel = repository.getName() + "//" + pattern;
         try {
           PackageAndTarget packageAndTarget = LabelValidator.validateAbsoluteLabel(fullLabel);
           packageIdentifier =
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java b/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java
index 38b85f4..8189590 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/BuiltinRestriction.java
@@ -27,7 +27,7 @@
         BazelModuleContext.of(Module.ofInnermostEnclosingStarlarkFunction(thread))
             .label()
             .getRepository();
-    if (!"@_builtins".equals(repository.getNameWithAt())) {
+    if (!"@_builtins".equals(repository.getName())) {
       throw Starlark.errorf("private API only for use in builtins");
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
index a3f94da..b18598b 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/StarlarkNativeModule.java
@@ -563,7 +563,7 @@
     BazelStarlarkContext.from(thread).checkLoadingPhase("native.repository_name");
     PackageIdentifier packageId =
         PackageFactory.getContext(thread).getBuilder().getPackageIdentifier();
-    return packageId.getRepository().getNameWithAt();
+    return packageId.getRepository().toString();
   }
 
   private static Dict<String, Object> getRuleDict(Rule rule, Mutability mu) throws EvalException {
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java
index 7f0d951..6e27b10 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactoryHelper.java
@@ -104,8 +104,8 @@
       // Create repository names with validation, LabelSyntaxException is thrown is the name
       // is not valid.
       builder.addRepositoryMappingEntry(
-          RepositoryName.create(externalRepoName),
-          RepositoryName.create(builder.getPackageWorkspaceName()),
+          RepositoryName.create("@" + externalRepoName),
+          RepositoryName.create("@" + builder.getPackageWorkspaceName()),
           RepositoryName.MAIN);
     }
   }
@@ -124,20 +124,10 @@
       for (Map.Entry<String, String> e :
           Dict.cast(repoMapping, String.class, String.class, "repo_mapping").entrySet()) {
         // Create repository names with validation; may throw LabelSyntaxException.
-        // For legacy reasons, the repository names given to the repo_mapping attribute need to be
-        // prefixed with an @.
-        if (!e.getKey().startsWith("@")) {
-          throw new LabelSyntaxException(
-              "invalid repository name '" + e.getKey() + "': repo names must start with '@'");
-        }
-        if (!e.getValue().startsWith("@")) {
-          throw new LabelSyntaxException(
-              "invalid repository name '" + e.getValue() + "': repo names must start with '@'");
-        }
         builder.addRepositoryMappingEntry(
-            RepositoryName.create(externalRepoName),
-            RepositoryName.create(e.getKey().substring(1)),
-            RepositoryName.create(e.getValue().substring(1)));
+            RepositoryName.create("@" + externalRepoName),
+            RepositoryName.create(e.getKey()),
+            RepositoryName.create(e.getValue()));
       }
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
index f29e7ef..a531eb2 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceGlobals.java
@@ -104,7 +104,7 @@
     // Add entry in repository map from "@name" --> "@" to avoid issue where bazel
     // treats references to @name as a separate external repo
     builder.addRepositoryMappingEntry(
-        RepositoryName.MAIN, RepositoryName.createUnvalidated(name), RepositoryName.MAIN);
+        RepositoryName.MAIN, RepositoryName.createFromValidStrippedName(name), RepositoryName.MAIN);
     parseManagedDirectories(
         Dict.cast(managedDirectories, String.class, Object.class, "managed_directories"));
   }
@@ -177,7 +177,7 @@
           "Cannot parse repository name '%s'. Repository name should start with '@'.", key);
     }
     try {
-      return RepositoryName.create(key.substring(1));
+      return RepositoryName.create(key);
     } catch (LabelSyntaxException e) {
       throw Starlark.errorf("%s", e);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/pkgcache/PathPackageLocator.java b/src/main/java/com/google/devtools/build/lib/pkgcache/PathPackageLocator.java
index b2c195a..c5c4be5 100644
--- a/src/main/java/com/google/devtools/build/lib/pkgcache/PathPackageLocator.java
+++ b/src/main/java/com/google/devtools/build/lib/pkgcache/PathPackageLocator.java
@@ -129,7 +129,7 @@
         Path buildFile =
             outputBase
                 .getRelative(LabelConstants.EXTERNAL_REPOSITORY_LOCATION)
-                .getRelative(packageIdentifier.getRepository().getName())
+                .getRelative(packageIdentifier.getRepository().strippedName())
                 .getRelative(packageIdentifier.getSourceRoot())
                 .getRelative(buildFileName.getFilenameFragment());
         try {
diff --git a/src/main/java/com/google/devtools/build/lib/repository/RepositoryFailedEvent.java b/src/main/java/com/google/devtools/build/lib/repository/RepositoryFailedEvent.java
index 719bba8..a6e84f6 100644
--- a/src/main/java/com/google/devtools/build/lib/repository/RepositoryFailedEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/repository/RepositoryFailedEvent.java
@@ -46,13 +46,18 @@
 
   @Override
   public BuildEventId getEventId() {
+    String strippedRepoName = repo;
+    if (strippedRepoName.startsWith("@")) {
+      strippedRepoName = strippedRepoName.substring(1);
+    }
     try {
-      Label label = Label.create(EXTERNAL_PACKAGE_IDENTIFIER, repo);
+      Label label = Label.create(EXTERNAL_PACKAGE_IDENTIFIER, strippedRepoName);
       return BuildEventIdUtil.unconfiguredLabelId(label);
     } catch (LabelSyntaxException e) {
       // As the repository name was accepted earlier, the label construction really shouldn't fail.
       // In any case, return something still referring to the repository.
-      return BuildEventIdUtil.unknownBuildEventId(EXTERNAL_PACKAGE_IDENTIFIER + ":" + repo);
+      return BuildEventIdUtil.unknownBuildEventId(
+          EXTERNAL_PACKAGE_IDENTIFIER + ":" + strippedRepoName);
     }
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
index 8ce68bb..a7a8a3e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/apple/AppleConfiguration.java
@@ -427,7 +427,7 @@
         BazelModuleContext.of(Module.ofInnermostEnclosingStarlarkFunction(thread))
             .label()
             .getRepository();
-    if (!"@_builtins".equals(repository.getNameWithAt())) {
+    if (!"@_builtins".equals(repository.getName())) {
       throw Starlark.errorf("private API only for use by builtins");
     }
     return isMandatoryMinimumVersion();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java
index 17b97dc..467fb28 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigRuleClasses.java
@@ -151,7 +151,7 @@
                       new ComputedDefault() {
                         @Override
                         public Object getDefault(AttributeMap rule) {
-                          return env.getToolsRepository().getName();
+                          return env.getToolsRepository().strippedName();
                         }
                       }))
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java
index 87e0d4a..361bd27 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigSetting.java
@@ -216,7 +216,7 @@
   }
 
   private static RepositoryName getToolsRepository(RuleContext ruleContext) {
-    return RepositoryName.createUnvalidated(
+    return RepositoryName.createFromValidStrippedName(
         ruleContext.attributes().get(ConfigSettingRule.TOOLS_REPOSITORY_ATTRIBUTE, Type.STRING));
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
index 21d0eb6..448b811 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java
@@ -1235,7 +1235,7 @@
 
     RuleClass ruleClass = rule.getRuleClassObject();
     Label label = ruleClass.getRuleDefinitionEnvironmentLabel();
-    if (label.getRepository().getNameWithAt().equals("@_builtins")) {
+    if (label.getRepository().getName().equals("@_builtins")) {
       // always permit builtins
       return true;
     }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
index 84aeb65..f29aff5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcModule.java
@@ -1966,7 +1966,7 @@
     Label label =
         ((BazelModuleContext) Module.ofInnermostEnclosingStarlarkFunction(thread).getClientData())
             .label();
-    return label.getPackageIdentifier().getRepository().getName().equals("_builtins");
+    return label.getPackageIdentifier().getRepository().toString().equals("@_builtins");
   }
 
   protected Language parseLanguage(String string) throws EvalException {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
index c34e389..2c32ffd 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppHelper.java
@@ -899,7 +899,7 @@
         && (!ruleContext.isAttrDefined("win_def_file", LABEL)
             || ruleContext.getPrerequisiteArtifact("win_def_file") == null)) {
       Fingerprint digest = new Fingerprint();
-      digest.addString(ruleContext.getRepository().getNameWithAt());
+      digest.addString(ruleContext.getRepository().getName());
       digest.addPath(ruleContext.getPackageDirectory());
       return "_" + digest.hexDigestAndReset().substring(0, 10);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java
index 423e96b..4ca7a26 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaStarlarkCommon.java
@@ -308,7 +308,7 @@
         ((BazelModuleContext) Module.ofInnermostEnclosingStarlarkFunction(thread).getClientData())
             .label();
     if (!PRIVATE_STARLARKIFACTION_ALLOWLIST.contains(label.getPackageName())
-        && !label.getPackageIdentifier().getRepository().getName().equals("_builtins")) {
+        && !label.getPackageIdentifier().getRepository().toString().equals("@_builtins")) {
       throw Starlark.errorf("Rule in '%s' cannot use private API", label.getPackageName());
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/ManagedDirectoriesKnowledgeImpl.java b/src/main/java/com/google/devtools/build/lib/rules/repository/ManagedDirectoriesKnowledgeImpl.java
index 3abf745..b632b44 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/ManagedDirectoriesKnowledgeImpl.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/ManagedDirectoriesKnowledgeImpl.java
@@ -90,7 +90,7 @@
     }
 
     ImmutableSortedMap.Builder<RepositoryName, ImmutableSet<PathFragment>> reposMapBuilder =
-        new ImmutableSortedMap.Builder<>(Comparator.comparing(RepositoryName::getNameWithAt));
+        new ImmutableSortedMap.Builder<>(Comparator.comparing(RepositoryName::getName));
     for (Map.Entry<RepositoryName, Set<PathFragment>> entry : reposMap.entrySet()) {
       reposMapBuilder.put(entry.getKey(), ImmutableSet.copyOf(entry.getValue()));
     }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
index 2239484..774e240 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorFunction.java
@@ -47,6 +47,7 @@
 import com.google.devtools.build.lib.vfs.Root;
 import com.google.devtools.build.lib.vfs.RootedPath;
 import com.google.devtools.build.skyframe.SkyFunction;
+import com.google.devtools.build.skyframe.SkyFunction.Environment;
 import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
 import com.google.devtools.build.skyframe.SkyKey;
 import com.google.devtools.build.skyframe.SkyValue;
@@ -248,20 +249,20 @@
         DONT_FETCH_UNCONDITIONALLY.equals(DEPENDENCY_FOR_UNCONDITIONAL_FETCHING.get(env));
     boolean needsConfiguring = false;
 
-    Path repoRoot =
-        RepositoryFunction.getExternalRepositoryDirectory(directories)
-            .getRelative(repositoryName.getName());
+    Path repoRoot = RepositoryFunction.getExternalRepositoryDirectory(directories)
+        .getRelative(repositoryName.strippedName());
 
     if (Preconditions.checkNotNull(overrides).containsKey(repositoryName)) {
       DigestWriter.clearMarkerFile(directories, repositoryName);
-      return setupOverride(overrides.get(repositoryName), env, repoRoot, repositoryName.getName());
+      return setupOverride(
+          overrides.get(repositoryName), env, repoRoot, repositoryName.strippedName());
     }
 
     Rule rule = null;
 
     if (Preconditions.checkNotNull(ENABLE_BZLMOD.get(env))) {
       // Trys to get a repository rule instance from Bzlmod generated repos.
-      SkyKey key = BzlmodRepoRuleValue.key(repositoryName.getName());
+      SkyKey key = BzlmodRepoRuleValue.key(repositoryName.strippedName());
       BzlmodRepoRuleValue value = (BzlmodRepoRuleValue) env.getValue(key);
 
       if (env.valuesMissing()) {
@@ -361,10 +362,8 @@
     if (!repoRoot.exists()) {
       // The repository isn't on the file system, there is nothing we can do.
       throw new RepositoryFunctionException(
-          new IOException(
-              "to fix, run\n\tbazel fetch //...\nExternal repository "
-                  + repositoryName.getNameWithAt()
-                  + " not found and fetching repositories is disabled."),
+          new IOException("to fix, run\n\tbazel fetch //...\nExternal repository " + repositoryName
+              + " not found and fetching repositories is disabled."),
           Transience.TRANSIENT);
     }
 
@@ -446,7 +445,7 @@
   private Rule getRepoRuleFromWorkspace(RepositoryName repositoryName, Environment env)
       throws InterruptedException, RepositoryFunctionException, NoSuchRepositoryException {
     try {
-      return externalPackageHelper.getRuleByName(repositoryName.getName(), env);
+      return externalPackageHelper.getRuleByName(repositoryName.strippedName(), env);
     } catch (ExternalRuleNotFoundException e) {
       // This is caught and handled immediately in compute().
       throw new NoSuchRepositoryException();
@@ -524,7 +523,7 @@
         Rule rule,
         ImmutableSet<PathFragment> managedDirectories) {
       ruleKey = computeRuleKey(rule);
-      markerPath = getMarkerPath(directories, repositoryName.getName());
+      markerPath = getMarkerPath(directories, repositoryName.strippedName());
       this.rule = rule;
       markerData = Maps.newHashMap();
 
@@ -644,7 +643,7 @@
     static void clearMarkerFile(BlazeDirectories directories, RepositoryName repoName)
         throws RepositoryFunctionException {
       try {
-        getMarkerPath(directories, repoName.getName()).delete();
+        getMarkerPath(directories, repoName.strippedName()).delete();
       } catch (IOException e) {
         throw new RepositoryFunctionException(e, Transience.TRANSIENT);
       }
@@ -657,11 +656,13 @@
     final String message;
 
     RepositoryFetching(String name, boolean finished) {
-      this(name, finished, finished ? "finished." : "fetching");
+      this.id = name;
+      this.finished = finished;
+      this.message = finished ? "finished." : "fetching";
     }
 
     RepositoryFetching(String name, boolean finished, String message) {
-      this.id = '@' + name;
+      this.id = name;
       this.finished = finished;
       this.message = message;
     }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
index a2adba3..0f14bfd 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/RepositoryFunction.java
@@ -523,7 +523,8 @@
       return;
     }
     String repositoryName = repositoryPath.getSegment(0);
-    env.getValue(RepositoryDirectoryValue.key(RepositoryName.createUnvalidated(repositoryName)));
+    env.getValue(
+        RepositoryDirectoryValue.key(RepositoryName.createFromValidStrippedName(repositoryName)));
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
index accd601..65bbb8c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
@@ -58,7 +58,7 @@
     try {
       return BuildConfigurationValue.create(
           key.getOptions(),
-          RepositoryName.createUnvalidated(workspaceNameValue.getName()),
+          RepositoryName.createFromValidStrippedName(workspaceNameValue.getName()),
           starlarkSemantics.getBool(BuildLanguageOptions.EXPERIMENTAL_SIBLING_REPOSITORY_LAYOUT),
           // Arguments below this are server-global.
           directories,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
index 3537eff..3de8e89 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlLoadFunction.java
@@ -837,7 +837,7 @@
     }
 
     if (key instanceof BzlLoadValue.KeyForBzlmod
-        && enclosingFileLabel.getRepository().getName().equals("bazel_tools")) {
+        && enclosingFileLabel.getRepository().strippedName().equals("bazel_tools")) {
       // Special case: we're only here to get the @bazel_tools repo (for example, for http_archive).
       // This repo shouldn't have visibility into anything else (during repo generation), so we just
       // return an empty repo mapping.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java
index 8c1dcf0..0f3d0e7 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BzlmodRepoRuleFunction.java
@@ -92,7 +92,7 @@
     // 1. Get repo spec for some special repos
     // Keep this in sync with {@RepositoryMappingFunction}
     // @bazel_tools is a special repo that we pull from the extracted install dir.
-    if (repositoryName.equals(RepositoryName.BAZEL_TOOLS.getName())) {
+    if (repositoryName.equals(RepositoryName.BAZEL_TOOLS.strippedName())) {
       RepoSpec repoSpec =
           RepoSpec.builder()
               .setRuleClassName("local_repository")
@@ -115,7 +115,7 @@
     //   - It can't be starlarkified yet because we can't access the cpu value in repository_ctx.
     //   - The canonical name "local_config_platform" is hardcoded in Bazel code.
     //     See {@link PlatformOptions}
-    if (repositoryName.equals(RepositoryName.LOCAL_CONFIG_PLATFORM.getName())) {
+    if (repositoryName.equals(RepositoryName.LOCAL_CONFIG_PLATFORM.strippedName())) {
       RepoSpec repoSpec =
           RepoSpec.builder()
               .setRuleClassName("local_config_platform")
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java
index 79fc1ff..49aade1 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunction.java
@@ -190,7 +190,7 @@
           String path = (String) rule.getAttr("path");
           return Optional.of(
               LocalRepositoryLookupValue.success(
-                  RepositoryName.create(rule.getName()), PathFragment.create(path)));
+                  RepositoryName.create("@" + rule.getName()), PathFragment.create(path)));
         } catch (LabelSyntaxException e) {
           // This shouldn't be possible if the rule name is valid, and it should already have been
           // validated.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupValue.java
index a822a68..c4c784a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupValue.java
@@ -158,7 +158,7 @@
 
     @Override
     public String toString() {
-      return "SuccessfulLocalRepositoryLookupValue(" + repositoryName.getNameWithAt() + ")";
+      return "SuccessfulLocalRepositoryLookupValue(" + repositoryName + ")";
     }
 
     @Override
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java
index a3b5bdd..c1d4e4b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupFunction.java
@@ -161,7 +161,7 @@
       return "BUILD file not found in directory '"
           + packageKey.getPackageFragment()
           + "' of external repository "
-          + packageKey.getRepository().getNameWithAt()
+          + packageKey.getRepository()
           + ". "
           + educationalMessage;
     }
@@ -390,7 +390,7 @@
     }
     if (!repositoryValue.repositoryExists()) {
       return new PackageLookupValue.NoRepositoryPackageLookupValue(
-          id.getRepository().getNameWithAt(), repositoryValue.getErrorMsg());
+          id.getRepository().getName(), repositoryValue.getErrorMsg());
     }
 
     // Check .bazelignore file after fetching the external repository.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java
index a5d749b..9430532 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredExecutionPlatformsFunction.java
@@ -170,7 +170,7 @@
       TargetPattern.Parser parser =
           new TargetPattern.Parser(
               PathFragment.EMPTY_FRAGMENT,
-              RepositoryName.createUnvalidated(module.getCanonicalRepoName()),
+              RepositoryName.createFromValidStrippedName(module.getCanonicalRepoName()),
               bazelModuleResolutionValue.getFullRepoMapping(module.getKey()));
       for (String pattern : module.getExecutionPlatformsToRegister()) {
         try {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java
index db927dc..ce8e041 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RegisteredToolchainsFunction.java
@@ -160,7 +160,7 @@
       TargetPattern.Parser parser =
           new TargetPattern.Parser(
               PathFragment.EMPTY_FRAGMENT,
-              RepositoryName.createUnvalidated(module.getCanonicalRepoName()),
+              RepositoryName.createFromValidStrippedName(module.getCanonicalRepoName()),
               bazelModuleResolutionValue.getFullRepoMapping(module.getKey()));
       for (String pattern : module.getToolchainsToRegister()) {
         try {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java
index 81dc320..594a7a2 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunction.java
@@ -73,8 +73,8 @@
                             && !entry.getValue().getAssociatedRule().getRuleClass().equals("bind"))
                 .collect(
                     Collectors.toMap(
-                        entry -> RepositoryName.createUnvalidated(entry.getKey()),
-                        entry -> RepositoryName.createUnvalidated(entry.getKey())));
+                        entry -> RepositoryName.createFromValidStrippedName(entry.getKey()),
+                        entry -> RepositoryName.createFromValidStrippedName(entry.getKey())));
         return RepositoryMappingValue.withMapping(
             computeForBazelModuleRepo(repositoryName, bazelModuleResolutionValue)
                 .get()
@@ -128,7 +128,7 @@
   private Optional<RepositoryMapping> computeForBazelModuleRepo(
       RepositoryName repositoryName, BazelModuleResolutionValue bazelModuleResolutionValue) {
     ModuleKey moduleKey =
-        bazelModuleResolutionValue.getCanonicalRepoNameLookup().get(repositoryName.getName());
+        bazelModuleResolutionValue.getCanonicalRepoNameLookup().get(repositoryName.strippedName());
     if (moduleKey == null) {
       return Optional.empty();
     }
@@ -150,7 +150,7 @@
     ModuleExtensionId extensionId =
         moduleExtensionResolutionValue
             .getCanonicalRepoNameToExtensionId()
-            .get(repositoryName.getName());
+            .get(repositoryName.strippedName());
     if (extensionId == null) {
       return Optional.empty();
     }
@@ -162,9 +162,9 @@
         moduleExtensionResolutionValue.getExtensionIdToRepoInternalNames().get(extensionId).stream()
             .collect(
                 toImmutableMap(
-                    RepositoryName::createUnvalidated,
+                    RepositoryName::createFromValidStrippedName,
                     internalName ->
-                        RepositoryName.createUnvalidated(
+                        RepositoryName.createFromValidStrippedName(
                             extensionUniqueName + "." + internalName)));
     // Find the key of the module containing this extension. This will be used to compute additional
     // mappings -- any repo generated by an extension contained in the module "foo" can additionally
@@ -172,13 +172,13 @@
     ModuleKey moduleKey =
         bazelModuleResolutionValue
             .getCanonicalRepoNameLookup()
-            .get(extensionId.getBzlFileLabel().getRepository().getName());
+            .get(extensionId.getBzlFileLabel().getRepository().strippedName());
     // NOTE(wyv): This means that if "foo" has a bazel_dep with the repo name "bar", and the
     // extension generates an internal repo name "bar", then within a repo generated by the
     // extension, "bar" will refer to the latter. We should explore a way to differentiate between
     // the two to avoid any surprises.
     return Optional.of(
-        RepositoryMapping.create(internalMapping, repositoryName.getName())
+        RepositoryMapping.create(internalMapping, repositoryName.strippedName())
             .withAdditionalMappings(bazelModuleResolutionValue.getFullRepoMapping(moduleKey)));
   }
 
@@ -208,17 +208,17 @@
               if (toRepo.isMain()) {
                 return toRepo;
               }
-              ModuleKey moduleKey = moduleNameLookup.get(toRepo.getName());
+              ModuleKey moduleKey = moduleNameLookup.get(toRepo.strippedName());
               return moduleKey == null
                   ? toRepo
-                  : RepositoryName.createUnvalidated(moduleKey.getCanonicalRepoName());
+                  : RepositoryName.createFromValidStrippedName(moduleKey.getCanonicalRepoName());
             }));
     // If there's no existing mapping to "foo", we should add a mapping from "foo" to "foo.1.3"
     // anyways.
     for (Map.Entry<String, ModuleKey> entry : moduleNameLookup.entrySet()) {
       mapping.putIfAbsent(
-          RepositoryName.createUnvalidated(entry.getKey()),
-          RepositoryName.createUnvalidated(entry.getValue().getCanonicalRepoName()));
+          RepositoryName.createFromValidStrippedName(entry.getKey()),
+          RepositoryName.createFromValidStrippedName(entry.getValue().getCanonicalRepoName()));
     }
     return RepositoryMappingValue.withMapping(
         RepositoryMapping.createAllowingFallback(ImmutableMap.copyOf(mapping)));
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java
index 51ea44c..bc7cd48 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeDependencyResolver.java
@@ -127,7 +127,7 @@
           Label repositoryLabel;
           try {
             repositoryLabel =
-                Label.create(EXTERNAL_PACKAGE_IDENTIFIER, label.getRepository().getName());
+                Label.create(EXTERNAL_PACKAGE_IDENTIFIER, label.getRepository().strippedName());
           } catch (LabelSyntaxException lse) {
             // We're taking the repository name from something that was already
             // part of a label, so it should be valid. If we really get into this
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsValue.java
index 26c88b8..72eeb76 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsValue.java
@@ -15,6 +15,7 @@
 package com.google.devtools.build.lib.skyframe;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.cmdline.RepositoryName;
 import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
 import com.google.devtools.build.skyframe.SkyFunctionName;
@@ -33,7 +34,7 @@
  */
 public final class StarlarkBuiltinsValue implements SkyValue {
 
-  static final String BUILTINS_NAME = "_builtins";
+  static final String BUILTINS_NAME = "@_builtins";
 
   /**
    * The builtins pseudo-repository.
@@ -46,8 +47,7 @@
    * and must match {@link #BUILTINS_NAME} exactly.
    */
   // TODO(#11437): Add actual enforcement that users cannot define a repo named "@_builtins".
-  @SerializationConstant
-  static final RepositoryName BUILTINS_REPO = RepositoryName.createUnvalidated("_builtins");
+  @SerializationConstant static final RepositoryName BUILTINS_REPO;
 
   /** Reports whether the given repository is the special builtins pseudo-repository. */
   static boolean isBuiltinsRepo(RepositoryName repo) {
@@ -55,6 +55,14 @@
     return repo.getName().equals(BUILTINS_NAME);
   }
 
+  static {
+    try {
+      BUILTINS_REPO = RepositoryName.create(BUILTINS_NAME);
+    } catch (LabelSyntaxException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
   // These are all (except transitiveDigest) deeply immutable since the Starlark values are already
   // frozen, so let's skip the accessors and mutators.
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkModuleCycleReporter.java b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkModuleCycleReporter.java
index 1ad3af2..bcd1afb 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkModuleCycleReporter.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkModuleCycleReporter.java
@@ -57,7 +57,7 @@
       if (repo instanceof RepositoryDirectoryValue.Key) {
         eventHandler.post(
             new RequestRepositoryInformationEvent(
-                ((RepositoryDirectoryValue.Key) repo).argument().getName()));
+                ((RepositoryDirectoryValue.Key) repo).argument().strippedName()));
       }
     }
   }
@@ -126,7 +126,7 @@
       Function<SkyKey, String> printer =
           input -> {
             if (input instanceof RepositoryDirectoryValue.Key) {
-              return ((RepositoryDirectoryValue.Key) input).argument().getNameWithAt();
+              return ((RepositoryDirectoryValue.Key) input).argument().getName();
             } else {
               throw new UnsupportedOperationException();
             }
@@ -159,7 +159,7 @@
         if (repo instanceof RepositoryDirectoryValue.Key) {
           message
               .append(" - ")
-              .append(((RepositoryDirectoryValue.Key) repo).argument().getNameWithAt())
+              .append(((RepositoryDirectoryValue.Key) repo).argument().getName())
               .append("\n");
         }
       }
@@ -167,7 +167,7 @@
       if (missingRepo instanceof RepositoryDirectoryValue.Key) {
         message
             .append("This could either mean you have to add the '")
-            .append(((RepositoryDirectoryValue.Key) missingRepo).argument().getNameWithAt())
+            .append(((RepositoryDirectoryValue.Key) missingRepo).argument().getName())
             .append("' repository with a statement like `http_archive` in your WORKSPACE file")
             .append(" (note that transitive dependencies are not added automatically), or move")
             .append(" an existing definition earlier in your WORKSPACE file.");
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java b/src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java
index 9cb65a9..6d303d0 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ArtifactFactoryTest.java
@@ -87,7 +87,7 @@
     barRelative = barPath.getRelative("barsource.txt");
 
     alienPath = PathFragment.create("external/alien");
-    alienPackage = PackageIdentifier.create("alien", alienPath);
+    alienPackage = PackageIdentifier.create("@alien", alienPath);
     alienRelative = alienPath.getRelative("alien.txt");
 
     artifactFactory = new ArtifactFactory(execRoot.getParentDirectory(), "bazel-out");
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/LocationExpanderTest.java b/src/test/java/com/google/devtools/build/lib/analysis/LocationExpanderTest.java
index dfe77aa..fdf64e6 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/LocationExpanderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/LocationExpanderTest.java
@@ -130,8 +130,9 @@
         .add("@bar//a", "/exec/src/a")
         .build();
 
-    ImmutableMap<RepositoryName, RepositoryName> repositoryMapping =
-        ImmutableMap.of(RepositoryName.create("foo"), RepositoryName.create("bar"));
+    ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(
+        RepositoryName.create("@foo"),
+        RepositoryName.create("@bar"));
 
     LocationExpander locationExpander =
         new LocationExpander(
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java
index 9f9b390..c333ad7 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/LocationFunctionTest.java
@@ -154,8 +154,8 @@
 
   @Test
   public void locationFunctionWithMappingReplace() throws Exception {
-    RepositoryName a = RepositoryName.create("a");
-    RepositoryName b = RepositoryName.create("b");
+    RepositoryName a = RepositoryName.create("@a");
+    RepositoryName b = RepositoryName.create("@b");
     ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(a, b);
     LocationFunction func =
         new LocationFunctionBuilder("//foo", false).add("@b//foo", "/exec/src/bar").build();
@@ -165,8 +165,8 @@
 
   @Test
   public void locationFunctionWithMappingIgnoreRepo() throws Exception {
-    RepositoryName a = RepositoryName.create("a");
-    RepositoryName b = RepositoryName.create("b");
+    RepositoryName a = RepositoryName.create("@a");
+    RepositoryName b = RepositoryName.create("@b");
     ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(a, b);
     LocationFunction func =
         new LocationFunctionBuilder("//foo", false).add("@potato//foo", "/exec/src/bar").build();
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValueTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValueTest.java
index eaea0af..1a8f286 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValueTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValueTest.java
@@ -389,16 +389,16 @@
     // these configurations are never trimmed nor even used to build targets so not an issue.
     new EqualsTester()
         .addEqualityGroup(
-            createRaw(parseBuildOptions("--test_arg=1a"), "testrepo", false),
-            createRaw(parseBuildOptions("--test_arg=1a"), "testrepo", false))
+            createRaw(parseBuildOptions("--test_arg=1a"), "@testrepo", false),
+            createRaw(parseBuildOptions("--test_arg=1a"), "@testrepo", false))
         // Different BuildOptions means non-equal
-        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=1b"), "testrepo", false))
+        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=1b"), "@testrepo", false))
         // Different --experimental_sibling_repository_layout means non-equal
-        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=2"), "testrepo", true))
-        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=2"), "testrepo", false))
+        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=2"), "@testrepo", true))
+        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=2"), "@testrepo", false))
         // Different repositoryName means non-equal
-        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=3"), "testrepo1", false))
-        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=3"), "testrepo2", false))
+        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=3"), "@testrepo1", false))
+        .addEqualityGroup(createRaw(parseBuildOptions("--test_arg=3"), "@testrepo2", false))
         .testEquals();
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodTestUtil.java b/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodTestUtil.java
index d4c6f29..f90f581 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodTestUtil.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/bzlmod/BzlmodTestUtil.java
@@ -40,8 +40,8 @@
     ImmutableMap.Builder<RepositoryName, RepositoryName> mappingBuilder = ImmutableMap.builder();
     for (int i = 0; i < names.length; i += 2) {
       mappingBuilder.put(
-          RepositoryName.createUnvalidated(names[i]),
-          RepositoryName.createUnvalidated(names[i + 1]));
+          RepositoryName.createFromValidStrippedName(names[i]),
+          RepositoryName.createFromValidStrippedName(names[i + 1]));
     }
     return RepositoryMapping.create(mappingBuilder.build(), key.getCanonicalRepoName());
   }
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptionsTest.java b/src/test/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptionsTest.java
index 305622f..7160d46 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptionsTest.java
@@ -41,14 +41,16 @@
   @Test
   public void testOverrideConverter() throws Exception {
     RepositoryOverride actual = converter.convert("foo=/bar");
-    assertThat(actual.repositoryName()).isEqualTo(RepositoryName.createUnvalidated("foo"));
+    assertThat(actual.repositoryName())
+        .isEqualTo(RepositoryName.createFromValidStrippedName("foo"));
     assertThat(actual.path()).isEqualTo(PathFragment.create("/bar"));
   }
 
   @Test
   public void testOverridePathWithEqualsSign() throws Exception {
     RepositoryOverride actual = converter.convert("foo=/bar=/baz");
-    assertThat(actual.repositoryName()).isEqualTo(RepositoryName.createUnvalidated("foo"));
+    assertThat(actual.repositoryName())
+        .isEqualTo(RepositoryName.createFromValidStrippedName("foo"));
     assertThat(actual.path()).isEqualTo(PathFragment.create("/bar=/baz"));
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/blackbox/tests/workspace/WorkspaceBlackBoxTest.java b/src/test/java/com/google/devtools/build/lib/blackbox/tests/workspace/WorkspaceBlackBoxTest.java
index a578a2b..8be762c 100644
--- a/src/test/java/com/google/devtools/build/lib/blackbox/tests/workspace/WorkspaceBlackBoxTest.java
+++ b/src/test/java/com/google/devtools/build/lib/blackbox/tests/workspace/WorkspaceBlackBoxTest.java
@@ -261,7 +261,7 @@
     ProcessResult result = context().bazel().shouldFail().build("//...");
     assertThat(result.errString())
         .contains(
-            "invalid repository name '@a': repo names may contain only A-Z, a-z, 0-9, '-', '_' and"
-                + " '.'");
+            "invalid repository name '@@a': workspace names may contain only "
+                + "A-Z, a-z, 0-9, '-', '_' and '.'");
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java b/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java
index d9f5ac9..de76ec4 100644
--- a/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java
+++ b/src/test/java/com/google/devtools/build/lib/buildtool/SymlinkForestTest.java
@@ -167,7 +167,7 @@
       repoRoot.getRelative(pkg).createDirectoryAndParents();
       FileSystemUtils.createEmptyFile(repoRoot.getRelative(pkg).getChild("file"));
     }
-    return PackageIdentifier.create(RepositoryName.create(repo), PathFragment.create(pkg));
+    return PackageIdentifier.create(RepositoryName.create("@" + repo), PathFragment.create(pkg));
   }
 
   // Create package for main repo
@@ -177,7 +177,7 @@
       repoRoot.getRelative(pkg).createDirectoryAndParents();
       FileSystemUtils.createEmptyFile(repoRoot.getRelative(pkg).getChild("file"));
     }
-    return PackageIdentifier.createInMainRepo(PathFragment.create(pkg));
+    return PackageIdentifier.create(RepositoryName.create("@"), PathFragment.create(pkg));
   }
 
   private static void assertLinksTo(Path fromRoot, Root toRoot, String relpart) throws IOException {
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 a53defb..f4b89c3 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
@@ -54,19 +54,19 @@
     }
     {
       Label l = Label.parseAbsolute("@foo", ImmutableMap.of());
-      assertThat(l.getRepository().getNameWithAt()).isEqualTo("@foo");
+      assertThat(l.getRepository().getName()).isEqualTo("@foo");
       assertThat(l.getPackageName()).isEmpty();
       assertThat(l.getName()).isEqualTo("foo");
     }
     {
       Label l = Label.parseAbsolute("//@foo", ImmutableMap.of());
-      assertThat(l.getRepository().getNameWithAt()).isEqualTo("@");
+      assertThat(l.getRepository().getName()).isEqualTo("@");
       assertThat(l.getPackageName()).isEqualTo("@foo");
       assertThat(l.getName()).isEqualTo("@foo");
     }
     {
       Label l = Label.parseAbsolute("//xyz/@foo:abc", ImmutableMap.of());
-      assertThat(l.getRepository().getNameWithAt()).isEqualTo("@");
+      assertThat(l.getRepository().getName()).isEqualTo("@");
       assertThat(l.getPackageName()).isEqualTo("xyz/@foo");
       assertThat(l.getName()).isEqualTo("abc");
     }
@@ -133,22 +133,22 @@
 
   @Test
   public void testGetRelativeWithDifferentRepo() throws Exception {
-    PackageIdentifier packageId = PackageIdentifier.create("repo", PathFragment.create("foo"));
+    PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo"));
     Label base = Label.create(packageId, "bar");
 
     Label relative = base.getRelativeWithRemapping("@remote//x:y", ImmutableMap.of());
 
-    assertThat(relative.getRepository()).isEqualTo(RepositoryName.create("remote"));
+    assertThat(relative.getRepository()).isEqualTo(RepositoryName.create("@remote"));
     assertThat(relative.getPackageFragment()).isEqualTo(PathFragment.create("x"));
     assertThat(relative.getName()).isEqualTo("y");
   }
 
   @Test
   public void testGetRelativeWithoutRemappingBaseLabel() throws Exception {
-    PackageIdentifier packageId = PackageIdentifier.create("a", PathFragment.create("foo"));
+    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"));
+        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
@@ -159,10 +159,10 @@
 
   @Test
   public void testGetRelativeWithDifferentRepoAndRemapping() throws Exception {
-    PackageIdentifier packageId = PackageIdentifier.create("repo", PathFragment.create("foo"));
+    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"));
+        ImmutableMap.of(RepositoryName.create("@a"), RepositoryName.create("@b"));
     Label relative = base.getRelativeWithRemapping("@a//x:y", repoMapping);
 
     Label actual = Label.parseAbsoluteUnchecked("@b//x:y");
@@ -171,7 +171,7 @@
 
   @Test
   public void testGetRelativeWithRepoLocalAbsoluteLabel() throws Exception {
-    PackageIdentifier packageId = PackageIdentifier.create("repo", PathFragment.create("foo"));
+    PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo"));
     Label base = Label.create(packageId, "bar");
 
     Label relative = base.getRelativeWithRemapping("//x:y", ImmutableMap.of());
@@ -183,7 +183,7 @@
 
   @Test
   public void testGetRelativeWithLocalRepoRelativeLabel() throws Exception {
-    PackageIdentifier packageId = PackageIdentifier.create("repo", PathFragment.create("foo"));
+    PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo"));
     Label base = Label.create(packageId, "bar");
 
     Label relative = base.getRelativeWithRemapping(":y", ImmutableMap.of());
@@ -195,7 +195,7 @@
 
   @Test
   public void testGetRelativeWithRepoAndReservedPackage() throws Exception {
-    PackageIdentifier packageId = PackageIdentifier.create("repo", PathFragment.create("foo"));
+    PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo"));
     Label base = Label.create(packageId, "bar");
 
     Label relative =
@@ -210,12 +210,12 @@
 
   @Test
   public void testGetRelativeWithRemoteRepoToDefaultRepo() throws Exception {
-    PackageIdentifier packageId = PackageIdentifier.create("repo", PathFragment.create("foo"));
+    PackageIdentifier packageId = PackageIdentifier.create("@repo", PathFragment.create("foo"));
     Label base = Label.create(packageId, "bar");
 
     Label relative = base.getRelativeWithRemapping("@//x:y", ImmutableMap.of());
 
-    assertThat(relative.getRepository()).isEqualTo(RepositoryName.MAIN);
+    assertThat(relative.getRepository()).isEqualTo(RepositoryName.create("@"));
     assertThat(relative.getPackageFragment()).isEqualTo(PathFragment.create("x"));
     assertThat(relative.getName()).isEqualTo("y");
   }
@@ -422,7 +422,7 @@
             LabelSyntaxException.class, () -> Label.parseAbsolute("@foo:xyz", ImmutableMap.of()));
     assertThat(e)
         .hasMessageThat()
-        .containsMatch("invalid repository name 'foo:xyz': repo names may contain only");
+        .containsMatch("invalid repository name '@foo:xyz': workspace names may contain only");
   }
 
   @Test
diff --git a/src/test/java/com/google/devtools/build/lib/cmdline/PackageIdentifierTest.java b/src/test/java/com/google/devtools/build/lib/cmdline/PackageIdentifierTest.java
index d781332..94ed237 100644
--- a/src/test/java/com/google/devtools/build/lib/cmdline/PackageIdentifierTest.java
+++ b/src/test/java/com/google/devtools/build/lib/cmdline/PackageIdentifierTest.java
@@ -29,19 +29,19 @@
   @Test
   public void testParsing() throws Exception {
     PackageIdentifier fooA = PackageIdentifier.parse("@foo//a");
-    assertThat(fooA.getRepository().getName()).isEqualTo("foo");
+    assertThat(fooA.getRepository().strippedName()).isEqualTo("foo");
     assertThat(fooA.getPackageFragment().getPathString()).isEqualTo("a");
     assertThat(fooA.getPackagePath(false)).isEqualTo(PathFragment.create("external/foo/a"));
     assertThat(fooA.getPackagePath(true)).isEqualTo(PathFragment.create("a"));
 
     PackageIdentifier absoluteA = PackageIdentifier.parse("//a");
-    assertThat(absoluteA.getRepository().getName()).isEmpty();
+    assertThat(absoluteA.getRepository().strippedName()).isEmpty();
     assertThat(absoluteA.getPackageFragment().getPathString()).isEqualTo("a");
     assertThat(absoluteA.getPackagePath(false)).isEqualTo(PathFragment.create("a"));
     assertThat(absoluteA.getPackagePath(true)).isEqualTo(PathFragment.create("a"));
 
     PackageIdentifier plainA = PackageIdentifier.parse("a");
-    assertThat(plainA.getRepository().getName()).isEmpty();
+    assertThat(plainA.getRepository().strippedName()).isEmpty();
     assertThat(plainA.getPackageFragment().getPathString()).isEqualTo("a");
     assertThat(plainA.getPackagePath(false)).isEqualTo(PathFragment.create("a"));
     assertThat(plainA.getPackagePath(true)).isEqualTo(PathFragment.create("a"));
@@ -57,16 +57,16 @@
   public void testToString() throws Exception {
     PackageIdentifier local = PackageIdentifier.create("", PathFragment.create("bar/baz"));
     assertThat(local.toString()).isEqualTo("bar/baz");
-    PackageIdentifier external = PackageIdentifier.create("foo", PathFragment.create("bar/baz"));
+    PackageIdentifier external = PackageIdentifier.create("@foo", PathFragment.create("bar/baz"));
     assertThat(external.toString()).isEqualTo("@foo//bar/baz");
   }
 
   @Test
   public void testCompareTo() throws Exception {
-    PackageIdentifier foo1 = PackageIdentifier.create("foo", PathFragment.create("bar/baz"));
-    PackageIdentifier foo2 = PackageIdentifier.create("foo", PathFragment.create("bar/baz"));
-    PackageIdentifier foo3 = PackageIdentifier.create("foo", PathFragment.create("bar/bz"));
-    PackageIdentifier bar = PackageIdentifier.create("bar", PathFragment.create("bar/baz"));
+    PackageIdentifier foo1 = PackageIdentifier.create("@foo", PathFragment.create("bar/baz"));
+    PackageIdentifier foo2 = PackageIdentifier.create("@foo", PathFragment.create("bar/baz"));
+    PackageIdentifier foo3 = PackageIdentifier.create("@foo", PathFragment.create("bar/bz"));
+    PackageIdentifier bar = PackageIdentifier.create("@bar", PathFragment.create("bar/baz"));
     assertThat(foo1.compareTo(foo2)).isEqualTo(0);
     assertThat(foo1.compareTo(foo3)).isLessThan(0);
     assertThat(foo1.compareTo(bar)).isGreaterThan(0);
@@ -75,22 +75,22 @@
   @Test
   public void testInvalidPackageName() throws Exception {
     // This shouldn't throw an exception, package names aren't validated.
-    PackageIdentifier.create("foo", PathFragment.create("bar.baz"));
+    PackageIdentifier.create("@foo", PathFragment.create("bar.baz"));
   }
 
   @Test
   public void testPackageFragmentEquality() throws Exception {
     // Make sure package fragments are canonicalized.
-    PackageIdentifier p1 = PackageIdentifier.create("whatever", PathFragment.create("foo/bar"));
-    PackageIdentifier p2 = PackageIdentifier.create("whatever", PathFragment.create("foo/bar"));
+    PackageIdentifier p1 = PackageIdentifier.create("@whatever", PathFragment.create("foo/bar"));
+    PackageIdentifier p2 = PackageIdentifier.create("@whatever", PathFragment.create("foo/bar"));
     assertThat(p1.getPackageFragment()).isSameInstanceAs(p2.getPackageFragment());
   }
 
   @Test
   public void testRunfilesDir() throws Exception {
-    assertThat(PackageIdentifier.create("foo", PathFragment.create("bar/baz")).getRunfilesPath())
+    assertThat(PackageIdentifier.create("@foo", PathFragment.create("bar/baz")).getRunfilesPath())
         .isEqualTo(PathFragment.create("../foo/bar/baz"));
-    assertThat(PackageIdentifier.create("", PathFragment.create("bar/baz")).getRunfilesPath())
+    assertThat(PackageIdentifier.create("@", PathFragment.create("bar/baz")).getRunfilesPath())
         .isEqualTo(PathFragment.create("bar/baz"));
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java b/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java
index e2e8f6c..ec6c179 100644
--- a/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryMappingTest.java
@@ -29,44 +29,45 @@
   public void maybeFallback() throws Exception {
     RepositoryMapping mapping =
         RepositoryMapping.createAllowingFallback(
-            ImmutableMap.of(RepositoryName.create("A"), RepositoryName.create("com_foo_bar_a")));
-    assertThat(mapping.get(RepositoryName.create("A")))
-        .isEqualTo(RepositoryName.create("com_foo_bar_a"));
-    assertThat(mapping.get(RepositoryName.create("B"))).isEqualTo(RepositoryName.create("B"));
+            ImmutableMap.of(RepositoryName.create("@A"), RepositoryName.create("@com_foo_bar_a")));
+    assertThat(mapping.get(RepositoryName.create("@A")))
+        .isEqualTo(RepositoryName.create("@com_foo_bar_a"));
+    assertThat(mapping.get(RepositoryName.create("@B"))).isEqualTo(RepositoryName.create("@B"));
   }
 
   @Test
   public void neverFallback() throws Exception {
     RepositoryMapping mapping =
         RepositoryMapping.create(
-            ImmutableMap.of(RepositoryName.create("A"), RepositoryName.create("com_foo_bar_a")),
+            ImmutableMap.of(RepositoryName.create("@A"), RepositoryName.create("@com_foo_bar_a")),
             "fake_owner_repo");
-    assertThat(mapping.get(RepositoryName.create("A")))
-        .isEqualTo(RepositoryName.create("com_foo_bar_a"));
-    assertThat(mapping.get(RepositoryName.create("B")))
-        .isEqualTo(RepositoryName.create("B").toNonVisible("fake_owner_repo"));
+    assertThat(mapping.get(RepositoryName.create("@A")))
+        .isEqualTo(RepositoryName.create("@com_foo_bar_a"));
+    assertThat(mapping.get(RepositoryName.create("@B")))
+        .isEqualTo(RepositoryName.create("@B").toNonVisible("fake_owner_repo"));
 
     // Special repos should still be visible
-    assertThat(mapping.get(RepositoryName.create("bazel_tools")))
-        .isEqualTo(RepositoryName.create("bazel_tools"));
-    assertThat(mapping.get(RepositoryName.create("local_config_platform")))
-        .isEqualTo(RepositoryName.create("local_config_platform"));
+    assertThat(mapping.get(RepositoryName.create("@bazel_tools")))
+        .isEqualTo(RepositoryName.create("@bazel_tools"));
+    assertThat(mapping.get(RepositoryName.create("@local_config_platform")))
+        .isEqualTo(RepositoryName.create("@local_config_platform"));
   }
 
   @Test
   public void additionalMappings() throws Exception {
     RepositoryMapping mapping =
         RepositoryMapping.create(
-                ImmutableMap.of(RepositoryName.create("A"), RepositoryName.create("com_foo_bar_a")),
+                ImmutableMap.of(
+                    RepositoryName.create("@A"), RepositoryName.create("@com_foo_bar_a")),
                 "fake_owner_repo")
             .withAdditionalMappings(
                 ImmutableMap.of(
-                    RepositoryName.create("B"), RepositoryName.create("com_foo_bar_b")));
-    assertThat(mapping.get(RepositoryName.create("A")))
-        .isEqualTo(RepositoryName.create("com_foo_bar_a"));
-    assertThat(mapping.get(RepositoryName.create("B")))
-        .isEqualTo(RepositoryName.create("com_foo_bar_b"));
-    assertThat(mapping.get(RepositoryName.create("C")))
-        .isEqualTo(RepositoryName.create("C").toNonVisible("fake_owner_repo"));
+                    RepositoryName.create("@B"), RepositoryName.create("@com_foo_bar_b")));
+    assertThat(mapping.get(RepositoryName.create("@A")))
+        .isEqualTo(RepositoryName.create("@com_foo_bar_a"));
+    assertThat(mapping.get(RepositoryName.create("@B")))
+        .isEqualTo(RepositoryName.create("@com_foo_bar_b"));
+    assertThat(mapping.get(RepositoryName.create("@C")))
+        .isEqualTo(RepositoryName.create("@C").toNonVisible("fake_owner_repo"));
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryNameTest.java b/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryNameTest.java
index 2168bb7..fc3141a 100644
--- a/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryNameTest.java
+++ b/src/test/java/com/google/devtools/build/lib/cmdline/RepositoryNameTest.java
@@ -36,33 +36,38 @@
 
   @Test
   public void testValidateRepositoryName() throws Exception {
-    assertThat(RepositoryName.create("foo").getNameWithAt()).isEqualTo("@foo");
-    assertThat(RepositoryName.create("").getNameWithAt()).isEqualTo("@");
+    assertThat(RepositoryName.create("@foo").toString()).isEqualTo("@foo");
+    assertThat(RepositoryName.create("").toString()).isEqualTo("@");
     assertThat(RepositoryName.create("")).isSameInstanceAs(RepositoryName.MAIN);
-    assertThat(RepositoryName.create("foo_bar").getNameWithAt()).isEqualTo("@foo_bar");
-    assertThat(RepositoryName.create("foo-bar").getNameWithAt()).isEqualTo("@foo-bar");
-    assertThat(RepositoryName.create("foo.bar").getNameWithAt()).isEqualTo("@foo.bar");
-    assertThat(RepositoryName.create("..foo").getNameWithAt()).isEqualTo("@..foo");
-    assertThat(RepositoryName.create("foo..").getNameWithAt()).isEqualTo("@foo..");
-    assertThat(RepositoryName.create(".foo").getNameWithAt()).isEqualTo("@.foo");
+    assertThat(RepositoryName.create("@foo_bar").toString()).isEqualTo("@foo_bar");
+    assertThat(RepositoryName.create("@foo-bar").toString()).isEqualTo("@foo-bar");
+    assertThat(RepositoryName.create("@foo.bar").toString()).isEqualTo("@foo.bar");
+    assertThat(RepositoryName.create("@..foo").toString()).isEqualTo("@..foo");
+    assertThat(RepositoryName.create("@foo..").toString()).isEqualTo("@foo..");
+    assertThat(RepositoryName.create("@.foo").toString()).isEqualTo("@.foo");
 
-    assertNotValid(".", "repo names are not allowed to be '.'");
-    assertNotValid("..", "repo names are not allowed to be '..'");
-    assertNotValid("foo/bar", "repo names may contain only A-Z, a-z, 0-9, '-', '_' and '.'");
-    assertNotValid("foo@", "repo names may contain only A-Z, a-z, 0-9, '-', '_' and '.'");
-    assertNotValid("foo\0", "repo names may contain only A-Z, a-z, 0-9, '-', '_' and '.'");
+    assertNotValid("x", "workspace names must start with '@'");
+    assertNotValid("@.", "workspace names are not allowed to be '@.'");
+    assertNotValid("@..", "workspace names are not allowed to be '@..'");
+    assertNotValid("@foo/bar", "workspace names may contain only A-Z, a-z, 0-9, '-', '_' and '.'");
+    assertNotValid("@foo@", "workspace names may contain only A-Z, a-z, 0-9, '-', '_' and '.'");
+    assertNotValid("@foo\0", "workspace names may contain only A-Z, a-z, 0-9, '-', '_' and '.'");
   }
 
   @Test
   public void testRunfilesDir() throws Exception {
-    assertThat(RepositoryName.create("foo").getRunfilesPath())
+    assertThat(RepositoryName.create("@foo").getRunfilesPath())
         .isEqualTo(PathFragment.create("../foo"));
-    assertThat(RepositoryName.create("").getRunfilesPath()).isEqualTo(PathFragment.EMPTY_FRAGMENT);
+    assertThat(RepositoryName.create("@").getRunfilesPath())
+        .isEqualTo(PathFragment.EMPTY_FRAGMENT);
+    assertThat(RepositoryName.create("").getRunfilesPath())
+        .isEqualTo(PathFragment.EMPTY_FRAGMENT);
   }
 
   @Test
   public void testGetDefaultCanonicalForm() throws Exception {
     assertThat(RepositoryName.create("").getCanonicalForm()).isEqualTo("");
-    assertThat(RepositoryName.create("foo").getCanonicalForm()).isEqualTo("@foo");
+    assertThat(RepositoryName.create("@").getCanonicalForm()).isEqualTo("");
+    assertThat(RepositoryName.create("@foo").getCanonicalForm()).isEqualTo("@foo");
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/cmdline/TargetPatternTest.java b/src/test/java/com/google/devtools/build/lib/cmdline/TargetPatternTest.java
index 64963ba..0e50105 100644
--- a/src/test/java/com/google/devtools/build/lib/cmdline/TargetPatternTest.java
+++ b/src/test/java/com/google/devtools/build/lib/cmdline/TargetPatternTest.java
@@ -170,24 +170,28 @@
     RepositoryMapping renaming =
         RepositoryMapping.createAllowingFallback(
             ImmutableMap.of(
-                RepositoryName.create("foo"), RepositoryName.create("bar"),
-                RepositoryName.create("myworkspace"), RepositoryName.create("")));
+                RepositoryName.create("@foo"), RepositoryName.create("@bar"),
+                RepositoryName.create("@myworkspace"), RepositoryName.create("@")));
     TargetPattern.Parser parser =
         new TargetPattern.Parser(
-            PathFragment.EMPTY_FRAGMENT, RepositoryName.createUnvalidated("myrepo"), renaming);
+            PathFragment.EMPTY_FRAGMENT,
+            RepositoryName.createFromValidStrippedName("myrepo"),
+            renaming);
 
     // Expecting renaming
-    assertThat(parser.parse("@foo//package:target").getRepository().getName()).isEqualTo("bar");
+    assertThat(parser.parse("@foo//package:target").getRepository().strippedName())
+        .isEqualTo("bar");
     assertThat(parser.parse("@myworkspace//package:target").getRepository().isMain()).isTrue();
-    assertThat(parser.parse("@foo//foo/...").getRepository().getName()).isEqualTo("bar");
+    assertThat(parser.parse("@foo//foo/...").getRepository().strippedName()).isEqualTo("bar");
     assertThat(parser.parse("@myworkspace//foo/...").getRepository().isMain()).isTrue();
 
     // No renaming should occur
     assertThat(parser.parse("@//package:target").getRepository().isMain()).isTrue();
-    assertThat(parser.parse("@unrelated//package:target").getRepository().getName())
+    assertThat(parser.parse("@unrelated//package:target").getRepository().strippedName())
         .isEqualTo("unrelated");
-    assertThat(parser.parse("foo/package:target").getRepository().getName()).isEqualTo("myrepo");
-    assertThat(parser.parse("foo/...").getRepository().getName()).isEqualTo("myrepo");
+    assertThat(parser.parse("foo/package:target").getRepository().strippedName())
+        .isEqualTo("myrepo");
+    assertThat(parser.parse("foo/...").getRepository().strippedName()).isEqualTo("myrepo");
   }
 
   private static TargetPattern parse(String pattern) throws TargetParsingException {
diff --git a/src/test/java/com/google/devtools/build/lib/packages/BuildTypeTest.java b/src/test/java/com/google/devtools/build/lib/packages/BuildTypeTest.java
index 688dc7c..bf1ee77 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/BuildTypeTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/BuildTypeTest.java
@@ -272,7 +272,7 @@
             currentRule,
             RepositoryMapping.createAllowingFallback(
                 ImmutableMap.of(
-                    RepositoryName.create("orig_repo"), RepositoryName.create("new_repo"))),
+                    RepositoryName.create("@orig_repo"), RepositoryName.create("@new_repo"))),
             /* convertedLabelsInPackage= */ new HashMap<>());
     Label label = BuildType.LABEL.convert("@orig_repo//foo:bar", null, context);
     assertThat(label)
diff --git a/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java b/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java
index 4754764..e48acfc 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/WorkspaceFactoryTest.java
@@ -140,7 +140,7 @@
         "    path = '/foo',",
         "    repo_mapping = {'@x' : '@y'},",
         ")");
-    assertMapping(helper, "foo", "x", "y");
+    assertMapping(helper, "@foo", "@x", "@y");
   }
 
   @Test
@@ -156,8 +156,8 @@
         "    path = '/bar',",
         "    repo_mapping = {'@a' : '@b'},",
         ")");
-    assertMapping(helper, "foo", "x", "y");
-    assertMapping(helper, "bar", "a", "b");
+    assertMapping(helper, "@foo", "@x", "@y");
+    assertMapping(helper, "@bar", "@a", "@b");
   }
 
   @Test
@@ -168,9 +168,9 @@
         "    path = '/foo',",
         "    repo_mapping = {'@a' : '@b', '@c' : '@d', '@e' : '@f'},",
         ")");
-    assertMapping(helper, "foo", "a", "b");
-    assertMapping(helper, "foo", "c", "d");
-    assertMapping(helper, "foo", "e", "f");
+    assertMapping(helper, "@foo", "@a", "@b");
+    assertMapping(helper, "@foo", "@c", "@d");
+    assertMapping(helper, "@foo", "@e", "@f");
   }
 
   @Test
@@ -181,7 +181,7 @@
         "    path = '/foo',",
         "    repo_mapping = {},",
         ")");
-    assertThat(helper.getPackage().getRepositoryMapping(RepositoryName.create("foo"))).isEmpty();
+    assertThat(helper.getPackage().getRepositoryMapping(RepositoryName.create("@foo"))).isEmpty();
   }
 
   @Test
@@ -200,13 +200,13 @@
   @Test
   public void testImplicitMainRepoRename() throws Exception {
     helper.parse("workspace(name = 'foo')");
-    assertMapping(helper, "", "foo", "");
+    assertMapping(helper, "@", "@foo", "@");
   }
 
   @Test
   public void testEmptyRepositoryHasEmptyMap() throws Exception {
     helper.parse("");
-    assertThat(helper.getPackage().getRepositoryMapping(RepositoryName.create(""))).isEmpty();
+    assertThat(helper.getPackage().getRepositoryMapping(RepositoryName.create("@"))).isEmpty();
   }
 
   @Test
@@ -218,8 +218,8 @@
         "    path = '/foo',",
         "    repo_mapping = {'@x' : '@y', '@bar' : '@newname'},",
         ")");
-    assertMapping(helper, "foo", "x", "y");
-    assertMapping(helper, "foo", "bar", "newname");
+    assertMapping(helper, "@foo", "@x", "@y");
+    assertMapping(helper, "@foo", "@bar", "@newname");
   }
 
   private void assertMapping(
diff --git a/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java b/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java
index f6c5b9b..19315ff 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/config/ConfigSettingTest.java
@@ -148,7 +148,7 @@
   /** Checks the behavior of {@link ConfigSetting#isUnderToolsPackage}. */
   @Test
   public void isUnderToolsPackage() throws Exception {
-    RepositoryName toolsRepo = RepositoryName.create("tools");
+    RepositoryName toolsRepo = RepositoryName.create("@tools");
     // Subpackage of the tools package.
     assertThat(
             ConfigSetting.isUnderToolsPackage(
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
index 4ddff1f..05f1ef8 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
@@ -371,7 +371,7 @@
     assertThat(ccCompilationContext.getIncludeDirs())
         .contains(
             getConfiguration(target)
-                .getGenfilesFragment(RepositoryName.create("bla"))
+                .getGenfilesFragment(RepositoryName.create("@bla"))
                 .getRelative("external/bla"));
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java
index 951a1ce..a55418a 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/proto/BazelProtoLibraryTest.java
@@ -381,7 +381,7 @@
     String genfiles =
         getTargetConfiguration()
             .getGenfilesFragment(
-                siblingRepoLayout ? RepositoryName.create("foo") : RepositoryName.MAIN)
+                siblingRepoLayout ? RepositoryName.create("@foo") : RepositoryName.MAIN)
             .toString();
     String fooProtoRoot;
     if (useVirtualImports) {
diff --git a/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java b/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java
index 98edfce..8b59dc2 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/repository/RepositoryDelegatorTest.java
@@ -273,10 +273,11 @@
   public void testOverride() throws Exception {
     RepositoryDelegatorFunction.REPOSITORY_OVERRIDES.set(
         differencer,
-        ImmutableMap.of(RepositoryName.createUnvalidated("foo"), overrideDirectory.asFragment()));
+        ImmutableMap.of(
+            RepositoryName.createFromValidStrippedName("foo"), overrideDirectory.asFragment()));
 
     StoredEventHandler eventHandler = new StoredEventHandler();
-    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createUnvalidated("foo"));
+    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createFromValidStrippedName("foo"));
     EvaluationContext evaluationContext =
         EvaluationContext.newBuilder()
             .setKeepGoing(false)
@@ -300,7 +301,7 @@
 
     RepositoryDirectoryDirtinessChecker checker =
         new RepositoryDirectoryDirtinessChecker(rootPath, knowledge);
-    RepositoryName repositoryName = RepositoryName.create("repo");
+    RepositoryName repositoryName = RepositoryName.create("@repo");
     RepositoryDirectoryValue.Key key = RepositoryDirectoryValue.key(repositoryName);
 
     SuccessfulRepositoryDirectoryValue usual =
@@ -332,7 +333,7 @@
     assertThat(managedDirectoryM.createDirectory()).isTrue();
 
     knowledge.setManagedDirectories(
-        ImmutableMap.of(PathFragment.create("m"), RepositoryName.create("other")));
+        ImmutableMap.of(PathFragment.create("m"), RepositoryName.create("@other")));
     assertThat(checker.check(key, withManagedDirectories, tsgm).isDirty()).isTrue();
 
     knowledge.setManagedDirectories(ImmutableMap.of(PathFragment.create("m"), repositoryName));
@@ -361,7 +362,7 @@
     // That's why we will directly fill managed directories value (the corresponding structure
     // is passed to RepositoryDelegatorFunction during construction).
     managedDirectoriesKnowledge.setManagedDirectories(
-        ImmutableMap.of(PathFragment.create("dir1"), RepositoryName.create("repo1")));
+        ImmutableMap.of(PathFragment.create("dir1"), RepositoryName.create("@repo1")));
 
     loadRepo("repo1");
 
@@ -389,9 +390,9 @@
     managedDirectoriesKnowledge.setManagedDirectories(
         ImmutableMap.of(
             PathFragment.create("dir1"),
-            RepositoryName.create("repo1"),
+            RepositoryName.create("@repo1"),
             PathFragment.create("dir2"),
-            RepositoryName.create("repo1")));
+            RepositoryName.create("@repo1")));
     loadRepo("repo1");
 
     assertThat(testStarlarkRepositoryFunction.isFetchCalled()).isTrue();
@@ -431,7 +432,7 @@
         "broken_repo(name = 'broken')");
 
     StoredEventHandler eventHandler = new StoredEventHandler();
-    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createUnvalidated("broken"));
+    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createFromValidStrippedName("broken"));
     // Make it be evaluated every time, as we are testing evaluation.
     differencer.invalidate(ImmutableSet.of(key));
     EvaluationContext evaluationContext =
@@ -455,7 +456,7 @@
     scratch.overwriteFile(rootPath.getRelative("WORKSPACE").getPathString(), "");
 
     StoredEventHandler eventHandler = new StoredEventHandler();
-    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createUnvalidated("foo"));
+    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createFromValidStrippedName("foo"));
     // Make it be evaluated every time, as we are testing evaluation.
     differencer.invalidate(ImmutableSet.of(key));
     EvaluationContext evaluationContext =
@@ -500,7 +501,7 @@
         "fictive_repo_rule(name = 'B.1.0')");
 
     StoredEventHandler eventHandler = new StoredEventHandler();
-    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createUnvalidated("B.1.0"));
+    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createFromValidStrippedName("B.1.0"));
     EvaluationContext evaluationContext =
         EvaluationContext.newBuilder()
             .setKeepGoing(false)
@@ -527,7 +528,7 @@
     StoredEventHandler eventHandler = new StoredEventHandler();
     SkyKey key =
         RepositoryDirectoryValue.key(
-            RepositoryName.createUnvalidated("foo").toNonVisible("fake_owner_repo"));
+            RepositoryName.createFromValidStrippedName("foo").toNonVisible("fake_owner_repo"));
     EvaluationContext evaluationContext =
         EvaluationContext.newBuilder()
             .setKeepGoing(false)
@@ -545,7 +546,8 @@
 
   private void loadRepo(String strippedRepoName) throws InterruptedException {
     StoredEventHandler eventHandler = new StoredEventHandler();
-    SkyKey key = RepositoryDirectoryValue.key(RepositoryName.createUnvalidated(strippedRepoName));
+    SkyKey key =
+        RepositoryDirectoryValue.key(RepositoryName.createFromValidStrippedName(strippedRepoName));
     // Make it be evaluated every time, as we are testing evaluation.
     differencer.invalidate(ImmutableSet.of(key));
     EvaluationContext evaluationContext =
diff --git a/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java b/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
index bf1cbc2..efec6b3 100644
--- a/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
@@ -944,7 +944,7 @@
     BuildConfigurationValue configuration =
         BuildConfigurationValue.create(
             defaultBuildOptions,
-            RepositoryName.createUnvalidated("workspace"),
+            RepositoryName.createFromValidStrippedName("workspace"),
             /*siblingRepositoryLayout=*/ false,
             new BlazeDirectories(
                 new ServerDirectories(outputBase, outputBase, outputBase),
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java
index 86b4465..c05f551 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ContainingPackageLookupFunctionTest.java
@@ -251,10 +251,10 @@
     scratch.file("a/b/BUILD");
     ContainingPackageLookupValue value =
         lookupContainingPackage(
-            PackageIdentifier.create(RepositoryName.create("a"), PathFragment.create("b")));
+            PackageIdentifier.create(RepositoryName.create("@a"), PathFragment.create("b")));
     assertThat(value.hasContainingPackage()).isTrue();
     assertThat(value.getContainingPackageName())
-        .isEqualTo(PackageIdentifier.create(RepositoryName.create("a"), PathFragment.create("b")));
+        .isEqualTo(PackageIdentifier.create(RepositoryName.create("@a"), PathFragment.create("b")));
   }
 
   @Test
@@ -268,7 +268,7 @@
     ContainingPackageLookupValue value = lookupContainingPackage("a/b");
     assertThat(value.hasContainingPackage()).isTrue();
     assertThat(value.getContainingPackageName())
-        .isEqualTo(PackageIdentifier.create(RepositoryName.create("a"), PathFragment.create("b")));
+        .isEqualTo(PackageIdentifier.create(RepositoryName.create("@a"), PathFragment.create("b")));
   }
 
   @Test
@@ -300,7 +300,7 @@
   @Test
   public void testNonExistentExternalRepositoryErrorReason() throws Exception {
     PackageIdentifier identifier =
-        PackageIdentifier.create("some_repo", PathFragment.create(":atarget"));
+        PackageIdentifier.create("@some_repo", PathFragment.create(":atarget"));
     ContainingPackageLookupValue value = lookupContainingPackage(identifier);
     assertThat(value.hasContainingPackage()).isFalse();
     assertThat(value.getClass()).isEqualTo(NoContainingPackage.class);
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java
index ad10bd4..7eac47f 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/GlobDescriptorTest.java
@@ -34,13 +34,13 @@
     SerializationTester serializationTester =
         new SerializationTester(
                 GlobDescriptor.create(
-                    PackageIdentifier.create("foo", PathFragment.create("//bar")),
+                    PackageIdentifier.create("@foo", PathFragment.create("//bar")),
                     Root.fromPath(FsUtils.TEST_FILESYSTEM.getPath("/packageRoot")),
                     PathFragment.create("subdir"),
                     "pattern",
                     /*excludeDirs=*/ false),
                 GlobDescriptor.create(
-                    PackageIdentifier.create("bar", PathFragment.create("//foo")),
+                    PackageIdentifier.create("@bar", PathFragment.create("//foo")),
                     Root.fromPath(FsUtils.TEST_FILESYSTEM.getPath("/anotherPackageRoot")),
                     PathFragment.create("anotherSubdir"),
                     "pattern",
@@ -58,7 +58,7 @@
   public void testCreateReturnsInternedInstances() throws LabelSyntaxException {
     GlobDescriptor original =
         GlobDescriptor.create(
-            PackageIdentifier.create("foo", PathFragment.create("//bar")),
+            PackageIdentifier.create("@foo", PathFragment.create("//bar")),
             Root.fromPath(FsUtils.TEST_FILESYSTEM.getPath("/packageRoot")),
             PathFragment.create("subdir"),
             "pattern",
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunctionTest.java
index 77cc3bb..32a0a51 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/LocalRepositoryLookupFunctionTest.java
@@ -193,7 +193,7 @@
             RootedPath.toRootedPath(
                 Root.fromPath(rootDirectory), PathFragment.create("local/repo")));
     assertThat(repositoryLookupValue).isNotNull();
-    assertThat(repositoryLookupValue.getRepository().getNameWithAt()).isEqualTo("@local");
+    assertThat(repositoryLookupValue.getRepository().getName()).isEqualTo("@local");
     assertThat(repositoryLookupValue.getPath()).isEqualTo(PathFragment.create("local/repo"));
   }
 
@@ -209,7 +209,7 @@
                 Root.fromPath(rootDirectory.getRelative("/abs")),
                 PathFragment.create("local/repo")));
     assertThat(repositoryLookupValue).isNotNull();
-    assertThat(repositoryLookupValue.getRepository().getNameWithAt()).isEqualTo("@local");
+    assertThat(repositoryLookupValue.getRepository().getName()).isEqualTo("@local");
     assertThat(repositoryLookupValue.getPath()).isEqualTo(PathFragment.create("/abs/local/repo"));
   }
 
@@ -224,7 +224,7 @@
             RootedPath.toRootedPath(
                 Root.fromPath(rootDirectory), PathFragment.create("local/repo")));
     assertThat(repositoryLookupValue).isNotNull();
-    assertThat(repositoryLookupValue.getRepository().getNameWithAt()).isEqualTo("@local");
+    assertThat(repositoryLookupValue.getRepository().getName()).isEqualTo("@local");
     assertThat(repositoryLookupValue.getPath()).isEqualTo(PathFragment.create("local/repo"));
   }
 
@@ -240,7 +240,7 @@
                 Root.fromPath(rootDirectory.getRelative("/abs")),
                 PathFragment.create("local/repo")));
     assertThat(repositoryLookupValue).isNotNull();
-    assertThat(repositoryLookupValue.getRepository().getNameWithAt()).isEqualTo("@local");
+    assertThat(repositoryLookupValue.getRepository().getName()).isEqualTo("@local");
     assertThat(repositoryLookupValue.getPath()).isEqualTo(PathFragment.create("/abs/local/repo"));
   }
 
@@ -256,7 +256,7 @@
             RootedPath.toRootedPath(
                 Root.fromPath(rootDirectory), PathFragment.create("local/repo/sub/package")));
     assertThat(repositoryLookupValue).isNotNull();
-    assertThat(repositoryLookupValue.getRepository().getNameWithAt()).isEqualTo("@local");
+    assertThat(repositoryLookupValue.getRepository().getName()).isEqualTo("@local");
     assertThat(repositoryLookupValue.getPath()).isEqualTo(PathFragment.create("local/repo"));
   }
 
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java
index 24fc055..baca435 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/PackageLookupFunctionTest.java
@@ -382,7 +382,7 @@
 
     // First, use the correct label.
     PackageLookupValue packageLookupValue =
-        lookupPackage(PackageIdentifier.create("local", PathFragment.EMPTY_FRAGMENT));
+        lookupPackage(PackageIdentifier.create("@local", PathFragment.EMPTY_FRAGMENT));
     assertThat(packageLookupValue.packageExists()).isTrue();
 
     // Then, use the incorrect label.
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java
index 5c426d2..b6030c7 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/RepositoryMappingFunctionTest.java
@@ -86,7 +86,7 @@
   public static RepositoryMappingValue withMapping(
       ImmutableMap<RepositoryName, RepositoryName> repositoryMapping, RepositoryName ownerRepo) {
     return RepositoryMappingValue.withMapping(
-        RepositoryMapping.create(repositoryMapping, ownerRepo.getName()));
+        RepositoryMapping.create(repositoryMapping, ownerRepo.strippedName()));
   }
 
   public RepositoryMappingValue withMappingForRootModule(
@@ -94,11 +94,11 @@
     ImmutableMap.Builder<RepositoryName, RepositoryName> allMappings = ImmutableMap.builder();
     allMappings.putAll(repositoryMapping);
     for (String name : analysisMock.getWorkspaceRepos()) {
-      RepositoryName repoName = RepositoryName.createUnvalidated(name);
+      RepositoryName repoName = RepositoryName.createFromValidStrippedName(name);
       allMappings.put(repoName, repoName);
     }
     return RepositoryMappingValue.withMapping(
-        RepositoryMapping.create(allMappings.build(), ownerRepo.getName()));
+        RepositoryMapping.create(allMappings.build(), ownerRepo.strippedName()));
   }
 
   @Test
@@ -111,7 +111,7 @@
         "    path = '/a_remote_repo',",
         "    repo_mapping = {'@a' : '@b'},",
         ")");
-    RepositoryName name = RepositoryName.create("a_remote_repo");
+    RepositoryName name = RepositoryName.create("@a_remote_repo");
     SkyKey skyKey = RepositoryMappingValue.key(name);
     EvaluationResult<RepositoryMappingValue> result = eval(skyKey);
 
@@ -121,10 +121,10 @@
         .isEqualTo(
             withMappingAllowingFallback(
                 ImmutableMap.of(
-                    RepositoryName.create("a"),
-                    RepositoryName.create("b"),
-                    RepositoryName.create("good"),
-                    RepositoryName.create(""))));
+                    RepositoryName.create("@a"),
+                    RepositoryName.create("@b"),
+                    RepositoryName.create("@good"),
+                    RepositoryName.create("@"))));
   }
 
   @Test
@@ -145,12 +145,12 @@
         .isEqualTo(
             withMappingForRootModule(
                 ImmutableMap.of(
-                    RepositoryName.create(""),
-                    RepositoryName.create(""),
-                    RepositoryName.create("A"),
-                    RepositoryName.create(""),
-                    RepositoryName.create("com_foo_bar_b"),
-                    RepositoryName.create("B.1.0")),
+                    RepositoryName.create("@"),
+                    RepositoryName.create("@"),
+                    RepositoryName.create("@A"),
+                    RepositoryName.create("@"),
+                    RepositoryName.create("@com_foo_bar_b"),
+                    RepositoryName.create("@B.1.0")),
                 name));
   }
 
@@ -168,7 +168,7 @@
             "module(name='C', version='1.0')",
             "bazel_dep(name='B', version='1.0', repo_name='com_foo_bar_b')");
 
-    RepositoryName name = RepositoryName.create("C.1.0");
+    RepositoryName name = RepositoryName.create("@C.1.0");
     SkyKey skyKey = RepositoryMappingValue.key(name);
     EvaluationResult<RepositoryMappingValue> result = eval(skyKey);
 
@@ -178,10 +178,10 @@
         .isEqualTo(
             withMapping(
                 ImmutableMap.of(
-                    RepositoryName.create("C"),
-                    RepositoryName.create("C.1.0"),
-                    RepositoryName.create("com_foo_bar_b"),
-                    RepositoryName.create("B.1.0")),
+                    RepositoryName.create("@C"),
+                    RepositoryName.create("@C.1.0"),
+                    RepositoryName.create("@com_foo_bar_b"),
+                    RepositoryName.create("@B.1.0")),
                 name));
   }
 
@@ -194,7 +194,7 @@
         "module(name='B', version='1.0')",
         "bazel_dep(name='A',version='3.0')");
 
-    RepositoryName name = RepositoryName.create("B.1.0");
+    RepositoryName name = RepositoryName.create("@B.1.0");
     SkyKey skyKey = RepositoryMappingValue.key(name);
     EvaluationResult<RepositoryMappingValue> result = eval(skyKey);
 
@@ -204,10 +204,10 @@
         .isEqualTo(
             withMapping(
                 ImmutableMap.of(
-                    RepositoryName.create("B"),
-                    RepositoryName.create("B.1.0"),
-                    RepositoryName.create("A"),
-                    RepositoryName.create("")),
+                    RepositoryName.create("@B"),
+                    RepositoryName.create("@B.1.0"),
+                    RepositoryName.create("@A"),
+                    RepositoryName.create("@")),
                 name));
   }
 
@@ -235,14 +235,14 @@
         .isEqualTo(
             withMappingForRootModule(
                 ImmutableMap.of(
-                    RepositoryName.create(""),
-                    RepositoryName.create(""),
-                    RepositoryName.create("A"),
-                    RepositoryName.create(""),
-                    RepositoryName.create("B1"),
-                    RepositoryName.create("B.1.0"),
-                    RepositoryName.create("B2"),
-                    RepositoryName.create("B.2.0")),
+                    RepositoryName.create("@"),
+                    RepositoryName.create("@"),
+                    RepositoryName.create("@A"),
+                    RepositoryName.create("@"),
+                    RepositoryName.create("@B1"),
+                    RepositoryName.create("@B.1.0"),
+                    RepositoryName.create("@B2"),
+                    RepositoryName.create("@B.2.0")),
                 name));
   }
 
@@ -264,7 +264,7 @@
         .addModule(createModuleKey("D", "1.0"), "module(name='D', version='1.0')")
         .addModule(createModuleKey("D", "2.0"), "module(name='D', version='2.0')");
 
-    RepositoryName name = RepositoryName.create("B.1.0");
+    RepositoryName name = RepositoryName.create("@B.1.0");
     SkyKey skyKey = RepositoryMappingValue.key(name);
     EvaluationResult<RepositoryMappingValue> result = eval(skyKey);
 
@@ -276,8 +276,8 @@
         .isEqualTo(
             withMapping(
                 ImmutableMap.of(
-                    RepositoryName.create("B"), RepositoryName.create("B.1.0"),
-                    RepositoryName.create("D"), RepositoryName.create("D.1.0")),
+                    RepositoryName.create("@B"), RepositoryName.create("@B.1.0"),
+                    RepositoryName.create("@D"), RepositoryName.create("@D.1.0")),
                 name));
   }
 
@@ -297,7 +297,7 @@
         .addModule(createModuleKey("B", "2.0"), "module(name='B', version='2.0')")
         .addModule(createModuleKey("C", "1.0"), "module(name='C', version='1.0')");
 
-    RepositoryName name = RepositoryName.create("B.1.0");
+    RepositoryName name = RepositoryName.create("@B.1.0");
     SkyKey skyKey = RepositoryMappingValue.key(name);
     EvaluationResult<RepositoryMappingValue> result = eval(skyKey);
 
@@ -309,8 +309,8 @@
         .isEqualTo(
             withMapping(
                 ImmutableMap.of(
-                    RepositoryName.create("B"), RepositoryName.create("B.1.0"),
-                    RepositoryName.create("com_foo_bar_c"), RepositoryName.create("C.1.0")),
+                    RepositoryName.create("@B"), RepositoryName.create("@B.1.0"),
+                    RepositoryName.create("@com_foo_bar_c"), RepositoryName.create("@C.1.0")),
                 name));
   }
 
@@ -329,9 +329,9 @@
         "    path = '/other_remote_repo',",
         "    repo_mapping = {'@x' : '@y'},",
         ")");
-    RepositoryName name1 = RepositoryName.create("a_remote_repo");
+    RepositoryName name1 = RepositoryName.create("@a_remote_repo");
     SkyKey skyKey1 = RepositoryMappingValue.key(name1);
-    RepositoryName name2 = RepositoryName.create("other_remote_repo");
+    RepositoryName name2 = RepositoryName.create("@other_remote_repo");
     SkyKey skyKey2 = RepositoryMappingValue.key(name2);
 
     assertThatEvaluationResult(eval(skyKey1))
@@ -339,19 +339,19 @@
         .isEqualTo(
             withMappingAllowingFallback(
                 ImmutableMap.of(
-                    RepositoryName.create("a"),
-                    RepositoryName.create("b"),
-                    RepositoryName.create("good"),
-                    RepositoryName.create(""))));
+                    RepositoryName.create("@a"),
+                    RepositoryName.create("@b"),
+                    RepositoryName.create("@good"),
+                    RepositoryName.create("@"))));
     assertThatEvaluationResult(eval(skyKey2))
         .hasEntryThat(skyKey2)
         .isEqualTo(
             withMappingAllowingFallback(
                 ImmutableMap.of(
-                    RepositoryName.create("x"),
-                    RepositoryName.create("y"),
-                    RepositoryName.create("good"),
-                    RepositoryName.create(""))));
+                    RepositoryName.create("@x"),
+                    RepositoryName.create("@y"),
+                    RepositoryName.create("@good"),
+                    RepositoryName.create("@"))));
   }
 
   @Test
@@ -364,7 +364,7 @@
         "    path = '/a_remote_repo',",
         "    repo_mapping = {'@a' : '@b', '@x' : '@y'},",
         ")");
-    RepositoryName name = RepositoryName.create("a_remote_repo");
+    RepositoryName name = RepositoryName.create("@a_remote_repo");
     SkyKey skyKey = RepositoryMappingValue.key(name);
 
     assertThatEvaluationResult(eval(skyKey))
@@ -372,12 +372,12 @@
         .isEqualTo(
             withMappingAllowingFallback(
                 ImmutableMap.of(
-                    RepositoryName.create("a"),
-                    RepositoryName.create("b"),
-                    RepositoryName.create("x"),
-                    RepositoryName.create("y"),
-                    RepositoryName.create("good"),
-                    RepositoryName.create(""))));
+                    RepositoryName.create("@a"),
+                    RepositoryName.create("@b"),
+                    RepositoryName.create("@x"),
+                    RepositoryName.create("@y"),
+                    RepositoryName.create("@good"),
+                    RepositoryName.create("@"))));
   }
 
   @Test
@@ -411,25 +411,25 @@
         .addModule(createModuleKey("D", "1.0"), "module(name='D', version='1.0')")
         .addModule(createModuleKey("D", "2.0"), "module(name='D', version='2.0')");
 
-    RepositoryName name = RepositoryName.create("ws_repo");
+    RepositoryName name = RepositoryName.create("@ws_repo");
     SkyKey skyKey = RepositoryMappingValue.key(name);
     assertThatEvaluationResult(eval(skyKey))
         .hasEntryThat(skyKey)
         .isEqualTo(
             withMappingAllowingFallback(
                 ImmutableMap.<RepositoryName, RepositoryName>builder()
-                    .put(RepositoryName.create("root"), RepositoryName.MAIN)
+                    .put(RepositoryName.create("@root"), RepositoryName.MAIN)
                     // mappings to @B get remapped to @B.1.0 because of module B@1.0
-                    .put(RepositoryName.create("B_alias"), RepositoryName.create("B.1.0"))
-                    .put(RepositoryName.create("B_alias2"), RepositoryName.create("B.1.0"))
+                    .put(RepositoryName.create("@B_alias"), RepositoryName.create("@B.1.0"))
+                    .put(RepositoryName.create("@B_alias2"), RepositoryName.create("@B.1.0"))
                     // mapping from @B to @B.1.0 is also created
-                    .put(RepositoryName.create("B"), RepositoryName.create("B.1.0"))
+                    .put(RepositoryName.create("@B"), RepositoryName.create("@B.1.0"))
                     // mapping from @C to @C.2.0 is created despite not being mentioned
-                    .put(RepositoryName.create("C"), RepositoryName.create("C.2.0"))
+                    .put(RepositoryName.create("@C"), RepositoryName.create("@C.2.0"))
                     // mapping to @D is untouched because D has a multiple-version override
-                    .put(RepositoryName.create("D_alias"), RepositoryName.create("D"))
+                    .put(RepositoryName.create("@D_alias"), RepositoryName.create("@D"))
                     // mapping to @E is untouched because E is not a module
-                    .put(RepositoryName.create("E_alias"), RepositoryName.create("E"))
+                    .put(RepositoryName.create("@E_alias"), RepositoryName.create("@E"))
                     .build()));
   }
 
@@ -444,14 +444,14 @@
         "    path = '/a_remote_repo',",
         "    repo_mapping = {'x' : '@b'},",
         ")");
-    RepositoryName name = RepositoryName.create("a_remote_repo");
+    RepositoryName name = RepositoryName.create("@a_remote_repo");
     SkyKey skyKey = RepositoryMappingValue.key(name);
 
     assertThatEvaluationResult(eval(skyKey))
         .hasErrorEntryForKeyThat(skyKey)
         .hasExceptionThat()
         .isInstanceOf(NoSuchPackageException.class);
-    assertContainsEvent("invalid repository name 'x': repo names must start with '@'");
+    assertContainsEvent("invalid repository name 'x': workspace names must start with '@'");
   }
 
   @Test
@@ -463,7 +463,7 @@
         "    path = '/a_remote_repo',",
         "    repo_mapping = {},",
         ")");
-    RepositoryName name = RepositoryName.create("a_remote_repo");
+    RepositoryName name = RepositoryName.create("@a_remote_repo");
     SkyKey skyKey = RepositoryMappingValue.key(name);
 
     assertThatEvaluationResult(eval(skyKey))
@@ -471,7 +471,7 @@
         .isEqualTo(
             withMappingAllowingFallback(
                 ImmutableMap.of(
-                    RepositoryName.createUnvalidated(TestConstants.WORKSPACE_NAME),
+                    RepositoryName.createFromValidStrippedName(TestConstants.WORKSPACE_NAME),
                     RepositoryName.MAIN)));
   }
 
@@ -484,14 +484,14 @@
         "    name = 'a_remote_repo',",
         "    path = '/a_remote_repo',",
         ")");
-    RepositoryName name = RepositoryName.create("a_remote_repo");
+    RepositoryName name = RepositoryName.create("@a_remote_repo");
     SkyKey skyKey = RepositoryMappingValue.key(name);
 
     assertThatEvaluationResult(eval(skyKey))
         .hasEntryThat(skyKey)
         .isEqualTo(
             withMappingAllowingFallback(
-                ImmutableMap.of(RepositoryName.create("good"), RepositoryName.MAIN)));
+                ImmutableMap.of(RepositoryName.create("@good"), RepositoryName.MAIN)));
   }
 
   @Test
@@ -499,14 +499,14 @@
     new EqualsTester()
         .addEqualityGroup(
             withMappingAllowingFallback(
-                ImmutableMap.of(RepositoryName.create("foo"), RepositoryName.create("bar"))),
+                ImmutableMap.of(RepositoryName.create("@foo"), RepositoryName.create("@bar"))),
             withMappingAllowingFallback(
-                ImmutableMap.of(RepositoryName.create("foo"), RepositoryName.create("bar"))))
+                ImmutableMap.of(RepositoryName.create("@foo"), RepositoryName.create("@bar"))))
         .addEqualityGroup(
             withMappingAllowingFallback(
-                ImmutableMap.of(RepositoryName.create("fizz"), RepositoryName.create("buzz"))),
+                ImmutableMap.of(RepositoryName.create("@fizz"), RepositoryName.create("@buzz"))),
             withMappingAllowingFallback(
-                ImmutableMap.of(RepositoryName.create("fizz"), RepositoryName.create("buzz"))))
+                ImmutableMap.of(RepositoryName.create("@fizz"), RepositoryName.create("@buzz"))))
         .testEquals();
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
index 95a1acc..0cd0436 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunctionTest.java
@@ -178,12 +178,12 @@
             "local_repository(name = 'a', path = '../a', repo_mapping = {'@x' : '@y'})",
             "load('//:b.bzl', 'b')",
             "local_repository(name = 'b', path = '../b', repo_mapping = {'@x' : '@y'})");
-    RepositoryName a = RepositoryName.create("a");
-    RepositoryName b = RepositoryName.create("b");
-    RepositoryName x = RepositoryName.create("x");
-    RepositoryName y = RepositoryName.create("y");
-    RepositoryName good = RepositoryName.create("good");
-    RepositoryName main = RepositoryName.create("");
+    RepositoryName a = RepositoryName.create("@a");
+    RepositoryName b = RepositoryName.create("@b");
+    RepositoryName x = RepositoryName.create("@x");
+    RepositoryName y = RepositoryName.create("@y");
+    RepositoryName good = RepositoryName.create("@good");
+    RepositoryName main = RepositoryName.create("@");
 
     SkyKey key0 = WorkspaceFileValue.key(workspace, 0);
     EvaluationResult<WorkspaceFileValue> result0 = eval(key0);
@@ -205,9 +205,9 @@
       TestManagedDirectoriesListener listener = new TestManagedDirectoriesListener();
       ManagedDirectoriesKnowledgeImpl knowledge = new ManagedDirectoriesKnowledgeImpl(listener);
 
-      RepositoryName one = RepositoryName.create("repo1");
-      RepositoryName two = RepositoryName.create("repo2");
-      RepositoryName three = RepositoryName.create("repo3");
+      RepositoryName one = RepositoryName.create("@repo1");
+      RepositoryName two = RepositoryName.create("@repo2");
+      RepositoryName three = RepositoryName.create("@repo3");
 
       PathFragment pf1 = PathFragment.create("dir1");
       PathFragment pf2 = PathFragment.create("dir2");
@@ -316,9 +316,9 @@
     assertThat(managedDirectories).hasSize(3);
     assertThat(managedDirectories)
         .containsExactly(
-            PathFragment.create("dir1"), RepositoryName.create("repo1"),
-            PathFragment.create("dir2"), RepositoryName.create("repo1"),
-            PathFragment.create("dir3"), RepositoryName.create("repo2"));
+            PathFragment.create("dir1"), RepositoryName.create("@repo1"),
+            PathFragment.create("dir2"), RepositoryName.create("@repo1"),
+            PathFragment.create("dir3"), RepositoryName.create("@repo2"));
     return workspaceFileValue;
   }
 
@@ -556,9 +556,9 @@
     SkyKey key1 = WorkspaceFileValue.key(workspace, 1);
     EvaluationResult<WorkspaceFileValue> result1 = eval(key1);
     WorkspaceFileValue value1 = result1.get(key1);
-    RepositoryName good = RepositoryName.create("good");
-    RepositoryName main = RepositoryName.create("");
-    RepositoryName secondary = RepositoryName.create("secondary");
+    RepositoryName good = RepositoryName.create("@good");
+    RepositoryName main = RepositoryName.create("@");
+    RepositoryName secondary = RepositoryName.create("@secondary");
     assertThat(value1.getRepositoryMapping()).containsEntry(secondary, ImmutableMap.of(good, main));
     assertNoEvents();
   }
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java
index 1059d30..588f523 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/packages/BazelPackageLoaderTest.java
@@ -56,7 +56,7 @@
     embeddedBinaries.createDirectoryAndParents();
 
     mockEmbeddedTools(embeddedBinaries);
-    fetchExternalRepo(RepositoryName.create("bazel_tools"));
+    fetchExternalRepo(RepositoryName.create("@bazel_tools"));
   }
 
   private static void mockEmbeddedTools(Path embeddedBinaries) throws IOException {
@@ -132,7 +132,7 @@
     file("WORKSPACE", "local_repository(name = 'r', path='r')");
     file("r/WORKSPACE", "workspace(name = 'r')");
     file("r/good/BUILD", "sh_library(name = 'good')");
-    RepositoryName rRepoName = RepositoryName.create("r");
+    RepositoryName rRepoName = RepositoryName.create("@r");
     fetchExternalRepo(rRepoName);
 
     PackageIdentifier pkgId = PackageIdentifier.create(rRepoName, PathFragment.create("good"));
@@ -153,7 +153,7 @@
         "new_local_repository(name = 'r', path = '/r', "
             + "build_file_content = 'sh_library(name = \"good\")')");
     fs.getPath("/r").createDirectoryAndParents();
-    RepositoryName rRepoName = RepositoryName.create("r");
+    RepositoryName rRepoName = RepositoryName.create("@r");
     fetchExternalRepo(rRepoName);
 
     PackageIdentifier pkgId =
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PackageIdentifierCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PackageIdentifierCodecTest.java
index 71e4e81..72bf2fe 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PackageIdentifierCodecTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/PackageIdentifierCodecTest.java
@@ -27,7 +27,7 @@
 
   @Test
   public void testCodec() throws Exception {
-    new SerializationTester(PackageIdentifier.create("foo", PathFragment.create("bar/baz")))
+    new SerializationTester(PackageIdentifier.create("@foo", PathFragment.create("bar/baz")))
         .runTests();
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/RepositoryNameCodecTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/RepositoryNameCodecTest.java
index 06588d6..aeaeeda 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/serialization/RepositoryNameCodecTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/serialization/RepositoryNameCodecTest.java
@@ -27,7 +27,7 @@
   public void testCodec() throws Exception {
     new SerializationTester(
             RepositoryName.create(RepositoryName.MAIN.getName()),
-            RepositoryName.create("externalandshouldntexistinthisworkspace"))
+            RepositoryName.create("@externalandshouldntexistinthisworkspace"))
         .runTests();
   }
 }
diff --git a/src/test/shell/bazel/local_repository_test.sh b/src/test/shell/bazel/local_repository_test.sh
index c889498..4d473d6 100755
--- a/src/test/shell/bazel/local_repository_test.sh
+++ b/src/test/shell/bazel/local_repository_test.sh
@@ -1027,7 +1027,7 @@
 EOF
 
   bazel build @r/a//:bin &> $TEST_log && fail "expected build failure, but succeeded"
-  expect_log "repo names may contain only A-Z, a-z, 0-9, '-', '_' and '.'"
+  expect_log "workspace names may contain only A-Z, a-z, 0-9, '-', '_' and '.'"
 }
 
 function test_remote_includes() {