Do not store a separate map for external package data. This ensures that serialization works correctly.

Removes ExternalPackage as Package specialization.

--
MOS_MIGRATED_REVID=103395682
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java
index 2c324c1..6dcfc6c 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/MavenServerFunction.java
@@ -18,7 +18,7 @@
 import com.google.devtools.build.lib.analysis.RuleDefinition;
 import com.google.devtools.build.lib.bazel.rules.workspace.MavenServerRule;
 import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
-import com.google.devtools.build.lib.packages.ExternalPackage;
+import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.skyframe.FileValue;
 import com.google.devtools.build.lib.syntax.Type;
@@ -57,7 +57,7 @@
   @Override
   public SkyValue compute(SkyKey skyKey, Environment env) throws RepositoryFunctionException {
     String repository = skyKey.argument().toString();
-    ExternalPackage externalPackage = RepositoryFunction.getExternalPackage(env);
+    Package externalPackage = RepositoryFunction.getExternalPackage(env);
     Rule repositoryRule = externalPackage.getRule(repository);
 
     boolean foundRepoRule = repositoryRule != null
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryFunction.java
index 479b3c0..0b52ba7 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryFunction.java
@@ -22,8 +22,8 @@
 import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
 import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
 import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
-import com.google.devtools.build.lib.packages.ExternalPackage;
 import com.google.devtools.build.lib.packages.NoSuchPackageException;
+import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.skyframe.FileSymlinkException;
 import com.google.devtools.build.lib.skyframe.FileValue;
@@ -245,9 +245,9 @@
   }
 
   @Nullable
-  public static ExternalPackage getExternalPackage(Environment env)
+  public static Package getExternalPackage(Environment env)
       throws RepositoryFunctionException {
-    SkyKey packageKey = PackageValue.key(ExternalPackage.PACKAGE_IDENTIFIER);
+    SkyKey packageKey = PackageValue.key(Package.EXTERNAL_PACKAGE_IDENTIFIER);
     PackageValue packageValue;
     try {
       packageValue = (PackageValue) env.getValueOrThrow(packageKey,
@@ -255,17 +255,18 @@
     } catch (NoSuchPackageException e) {
       throw new RepositoryFunctionException(
           new BuildFileNotFoundException(
-              ExternalPackage.PACKAGE_IDENTIFIER, "Could not load //external package"),
+              Package.EXTERNAL_PACKAGE_IDENTIFIER, "Could not load //external package"),
           Transience.PERSISTENT);
     }
     if (packageValue == null) {
       return null;
     }
-    ExternalPackage externalPackage = (ExternalPackage) packageValue.getPackage();
+
+    Package externalPackage = packageValue.getPackage();
     if (externalPackage.containsErrors()) {
       throw new RepositoryFunctionException(
           new BuildFileContainsErrorsException(
-              ExternalPackage.PACKAGE_IDENTIFIER, "Could not load //external package"),
+              Package.EXTERNAL_PACKAGE_IDENTIFIER, "Could not load //external package"),
           Transience.PERSISTENT);
     }
     return externalPackage;
@@ -293,15 +294,16 @@
   public static Rule getRule(
       RepositoryName repositoryName, @Nullable String ruleClassName, Environment env)
       throws RepositoryFunctionException {
-    ExternalPackage externalPackage = getExternalPackage(env);
+    Package externalPackage = getExternalPackage(env);
     if (externalPackage == null) {
       return null;
     }
-    Rule rule = externalPackage.getRepositoryInfo(repositoryName);
+
+    Rule rule = externalPackage.getRule(repositoryName.strippedName());
     if (rule == null) {
       throw new RepositoryFunctionException(
           new BuildFileContainsErrorsException(
-              ExternalPackage.PACKAGE_IDENTIFIER,
+              Package.EXTERNAL_PACKAGE_IDENTIFIER,
               "The repository named '" + repositoryName + "' could not be resolved"),
           Transience.PERSISTENT);
     }
@@ -353,8 +355,9 @@
   }
 
   public static Path getExternalRepositoryDirectory(BlazeDirectories directories) {
-    return directories.getOutputBase().getRelative(
-        ExternalPackage.PACKAGE_IDENTIFIER.getPackageFragment());
+    return directories
+        .getOutputBase()
+        .getRelative(Package.EXTERNAL_PACKAGE_IDENTIFIER.getPackageFragment());
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java
deleted file mode 100644
index fdb63e2..0000000
--- a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2014 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.packages;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
-import com.google.devtools.build.lib.cmdline.PackageIdentifier;
-import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName;
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.events.StoredEventHandler;
-import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
-import com.google.devtools.build.lib.syntax.Environment;
-import com.google.devtools.build.lib.syntax.FuncallExpression;
-import com.google.devtools.build.lib.syntax.Label;
-import com.google.devtools.build.lib.vfs.Path;
-
-import java.util.Map;
-
-/**
- * This creates the //external package, where targets not homed in this repository can be bound.
- */
-public class ExternalPackage extends Package {
-  public static final PackageIdentifier PACKAGE_IDENTIFIER;
-
-  static {
-    try {
-      PACKAGE_IDENTIFIER = PackageIdentifier.parse("//external");
-    } catch (LabelSyntaxException e) {
-      throw new IllegalStateException();
-    }
-  }
-
-  private Map<RepositoryName, Rule> repositoryMap;
-
-  ExternalPackage(String runfilesPrefix) {
-    super(PACKAGE_IDENTIFIER, runfilesPrefix);
-  }
-
-  /**
-   * Returns a description of the repository with the given name, or null if there's no such
-   * repository.
-   */
-  public Rule getRepositoryInfo(RepositoryName repositoryName) {
-    return repositoryMap.get(repositoryName);
-  }
-
-  /**
-   * Given a workspace file path, creates an ExternalPackage.
-   */
-  public static class Builder extends Package.Builder {
-    private Map<RepositoryName, Rule> repositoryMap = Maps.newLinkedHashMap();
-
-    public Builder(Path workspacePath, String runfilesPrefix) {
-      super(new ExternalPackage(runfilesPrefix));
-      setFilename(workspacePath);
-      setMakeEnv(new MakeEnvironment.Builder());
-    }
-
-    protected ExternalPackage externalPackage() {
-      return (ExternalPackage) pkg;
-    }
-
-    @Override
-    public ExternalPackage build() {
-      for (Rule rule : repositoryMap.values()) {
-        try {
-          addRule(rule);
-        } catch (NameConflictException e) {
-          throw new IllegalStateException("Got a name conflict for " + rule
-              + ", which can't happen: " + e.getMessage());
-        }
-      }
-      externalPackage().repositoryMap = ImmutableMap.copyOf(repositoryMap);
-
-      Package base = super.build();
-      return (ExternalPackage) base;
-    }
-
-    /**
-     * Sets the name for this repository.
-     */
-    @Override
-    public Builder setWorkspaceName(String workspaceName) {
-      pkg.workspaceName = workspaceName;
-      return this;
-    }
-
-    private void overwriteRule(Rule rule) throws NameConflictException {
-      Preconditions.checkArgument(rule.getOutputFiles().isEmpty());
-      Target old = targets.get(rule.getName());
-      if (old != null) {
-        if (old instanceof Rule) {
-          Verify.verify(((Rule) old).getOutputFiles().isEmpty());
-        }
-
-        targets.remove(rule.getName());
-      }
-
-      addRule(rule);
-    }
-
-    public void addBindRule(
-        RuleClass bindRuleClass, Label virtual, Label actual, Location location)
-        throws InvalidRuleException, NameConflictException, InterruptedException {
-
-      Map<String, Object> attributes = Maps.newHashMap();
-      // Bound rules don't have a name field, but this works because we don't want more than one
-      // with the same virtual name.
-      attributes.put("name", virtual.getName());
-      if (actual != null) {
-        attributes.put("actual", actual);
-      }
-      StoredEventHandler handler = new StoredEventHandler();
-      Rule rule = RuleFactory.createRule(
-          this, bindRuleClass, attributes, handler, null, location, null);
-      overwriteRule(rule);
-      rule.setVisibility(ConstantRuleVisibility.PUBLIC);
-    }
-
-    /**
-     * Adds the rule to the map of rules. Overwrites rules that are already there, to allow "later"
-     * WORKSPACE files to overwrite "earlier" ones.
-     */
-    public Builder createAndAddRepositoryRule(RuleClass ruleClass, RuleClass bindRuleClass,
-        Map<String, Object> kwargs, FuncallExpression ast, Environment env)
-        throws InvalidRuleException, NameConflictException, LabelSyntaxException,
-            InterruptedException {
-      StoredEventHandler eventHandler = new StoredEventHandler();
-      Rule tempRule = RuleFactory.createRule(
-          this, ruleClass, kwargs, eventHandler, ast, ast.getLocation(), env);
-      addEvents(eventHandler.getEvents());
-      try {
-        repositoryMap.put(RepositoryName.create("@" + tempRule.getName()), tempRule);
-      } catch (LabelSyntaxException e) {
-        throw new LabelSyntaxException(e.getMessage());
-      }
-      for (Map.Entry<String, Label> entry :
-        ruleClass.getExternalBindingsFunction().apply(tempRule).entrySet()) {
-        Label nameLabel = Label.parseAbsolute("//external:" + entry.getKey());
-        addBindRule(bindRuleClass, nameLabel, entry.getValue(), tempRule.getLocation());
-      }
-      return this;
-    }
-  }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java
new file mode 100644
index 0000000..7f6de05
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackageBuilder.java
@@ -0,0 +1,100 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.packages;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Verify;
+import com.google.common.collect.Maps;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.events.StoredEventHandler;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
+import com.google.devtools.build.lib.syntax.Label;
+
+import java.util.Map;
+
+/**
+ * A builder that helps constructing the //external package.
+ */
+public class ExternalPackageBuilder {
+
+  private Map<PackageIdentifier.RepositoryName, Rule> repositoryMap = Maps.newLinkedHashMap();
+
+  void build(Package.Builder pkg) {
+    for (Rule rule : repositoryMap.values()) {
+      try {
+        pkg.addRule(rule);
+      } catch (Package.NameConflictException e) {
+        throw new IllegalStateException(
+            "Got a name conflict for " + rule + ", which can't happen: " + e.getMessage(), e);
+      }
+    }
+  }
+
+  public ExternalPackageBuilder createAndAddRepositoryRule(
+      Package.Builder pkg,
+      RuleClass ruleClass,
+      RuleClass bindRuleClass,
+      Map<String, Object> kwargs,
+      FuncallExpression ast)
+      throws RuleFactory.InvalidRuleException, Package.NameConflictException, LabelSyntaxException,
+          InterruptedException {
+
+    StoredEventHandler eventHandler = new StoredEventHandler();
+    Rule tempRule =
+        RuleFactory.createRule(pkg, ruleClass, kwargs, eventHandler, ast, ast.getLocation(), null);
+    pkg.addEvents(eventHandler.getEvents());
+    repositoryMap.put(PackageIdentifier.RepositoryName.create("@" + tempRule.getName()), tempRule);
+    for (Map.Entry<String, Label> entry :
+        ruleClass.getExternalBindingsFunction().apply(tempRule).entrySet()) {
+      Label nameLabel = Label.parseAbsolute("//external:" + entry.getKey());
+      addBindRule(pkg, bindRuleClass, nameLabel, entry.getValue(), tempRule.getLocation());
+    }
+    return this;
+  }
+
+  public void addBindRule(
+      Package.Builder pkg, RuleClass bindRuleClass, Label virtual, Label actual, Location location)
+      throws RuleFactory.InvalidRuleException, Package.NameConflictException, InterruptedException {
+
+    Map<String, Object> attributes = Maps.newHashMap();
+    // Bound rules don't have a name field, but this works because we don't want more than one
+    // with the same virtual name.
+    attributes.put("name", virtual.getName());
+    if (actual != null) {
+      attributes.put("actual", actual);
+    }
+    StoredEventHandler handler = new StoredEventHandler();
+    Rule rule =
+        RuleFactory.createRule(pkg, bindRuleClass, attributes, handler, null, location, null);
+    overwriteRule(pkg, rule);
+    rule.setVisibility(ConstantRuleVisibility.PUBLIC);
+  }
+
+  private void overwriteRule(Package.Builder pkg, Rule rule) throws Package.NameConflictException {
+    Preconditions.checkArgument(rule.getOutputFiles().isEmpty());
+    Target old = pkg.targets.get(rule.getName());
+    if (old != null) {
+      if (old instanceof Rule) {
+        Verify.verify(((Rule) old).getOutputFiles().isEmpty());
+      }
+
+      pkg.targets.remove(rule.getName());
+    }
+
+    pkg.addRule(rule);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java
index 41224e0..12b0a26 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Package.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java
@@ -67,6 +67,16 @@
  */
 public class Package implements Serializable {
 
+  public static PackageIdentifier EXTERNAL_PACKAGE_IDENTIFIER;
+
+  static {
+    try {
+      Package.EXTERNAL_PACKAGE_IDENTIFIER = PackageIdentifier.parse("//external");
+    } catch (LabelSyntaxException e) {
+      throw new IllegalStateException();
+    }
+  }
+
   /**
    * Common superclass for all name-conflict exceptions.
    */
@@ -744,7 +754,14 @@
     }
   }
 
-  static class Builder {
+  public static Builder newExternalPackageBuilder(Path workspacePath, String runfilesPrefix) {
+    Builder b = new Builder(new Package(EXTERNAL_PACKAGE_IDENTIFIER, runfilesPrefix));
+    b.setFilename(workspacePath);
+    b.setMakeEnv(new MakeEnvironment.Builder());
+    return b;
+  }
+
+  public static class Builder {
     protected static Package newPackage(PackageIdentifier packageId, String runfilesPrefix) {
       return new Package(packageId, runfilesPrefix);
     }
@@ -777,6 +794,8 @@
     protected Map<Label, Path> subincludes = null;
     protected ImmutableList<Label> skylarkFileDependencies = ImmutableList.of();
 
+    protected ExternalPackageBuilder externalPackageData = new ExternalPackageBuilder();
+
     /**
      * True iff the "package" function has already been called in this package.
      */
@@ -809,7 +828,7 @@
       }
     }
 
-    Builder(PackageIdentifier id, String runfilesPrefix) {
+    public Builder(PackageIdentifier id, String runfilesPrefix) {
       this(newPackage(id, runfilesPrefix));
     }
 
@@ -1294,6 +1313,9 @@
       if (alreadyBuilt) {
         return pkg;
       }
+
+      externalPackageData.build(this);
+
       // Freeze targets and distributions.
       targets = ImmutableMap.copyOf(targets);
       defaultDistributionSet =
@@ -1314,6 +1336,10 @@
       return pkg;
     }
 
+    protected ExternalPackageBuilder externalPackageData() {
+      return externalPackageData;
+    }
+
     public Package build() {
       if (alreadyBuilt) {
         return pkg;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index 55046a6..378db51 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -1022,16 +1022,32 @@
     }
   }
 
+  @VisibleForTesting
+  public Package createPackageForTesting(
+      PackageIdentifier packageId,
+      Path buildFile,
+      CachingPackageLocator locator,
+      EventHandler eventHandler)
+      throws NoSuchPackageException, InterruptedException {
+    Package externalPkg =
+        Package.newExternalPackageBuilder(buildFile.getRelative("WORKSPACE"), "TESTING").build();
+    return createPackageForTesting(packageId, externalPkg, buildFile, locator, eventHandler);
+  }
+
   /**
    * Same as {@link #createPackage}, but does the required validation of "packageName" first,
    * throwing a {@link NoSuchPackageException} if the name is invalid.
    */
   @VisibleForTesting
-  public Package createPackageForTesting(PackageIdentifier packageId,
-      Path buildFile, CachingPackageLocator locator, EventHandler eventHandler)
-          throws NoSuchPackageException, InterruptedException {
-    String error = LabelValidator.validatePackageName(
-        packageId.getPackageFragment().getPathString());
+  public Package createPackageForTesting(
+      PackageIdentifier packageId,
+      Package externalPkg,
+      Path buildFile,
+      CachingPackageLocator locator,
+      EventHandler eventHandler)
+      throws NoSuchPackageException, InterruptedException {
+    String error =
+        LabelValidator.validatePackageName(packageId.getPackageFragment().getPathString());
     if (error != null) {
       throw new BuildFileNotFoundException(
           packageId, "illegal package name: '" + packageId + "' (" + error + ")");
@@ -1050,9 +1066,6 @@
           Event.error(Location.fromFile(buildFile), "preprocessing failed: " + e.getMessage()));
       throw new BuildFileContainsErrorsException(packageId, "preprocessing failed", e);
     }
-    ExternalPackage externalPkg =
-        new ExternalPackage.Builder(
-            buildFile.getRelative("WORKSPACE"), ruleClassProvider.getRunfilesPrefix()).build();
 
     Package result =
         createPackageFromPreprocessingResult(
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index 22df6d7..887f684 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -21,7 +21,7 @@
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.events.StoredEventHandler;
-import com.google.devtools.build.lib.packages.ExternalPackage.Builder;
+import com.google.devtools.build.lib.packages.Package.Builder;
 import com.google.devtools.build.lib.syntax.BaseFunction;
 import com.google.devtools.build.lib.syntax.BuildFileAST;
 import com.google.devtools.build.lib.syntax.BuiltinFunction;
@@ -108,8 +108,8 @@
 
   private static BuiltinFunction newBindFunction(
       final RuleFactory ruleFactory, final Builder builder) {
-    return new BuiltinFunction("bind",
-        FunctionSignature.namedOnly(1, "name", "actual"), BuiltinFunction.USE_LOC) {
+    return new BuiltinFunction(
+        "bind", FunctionSignature.namedOnly(1, "name", "actual"), BuiltinFunction.USE_LOC) {
       public Object invoke(String name, String actual, Location loc)
           throws EvalException, InterruptedException {
         Label nameLabel = null;
@@ -117,10 +117,18 @@
           nameLabel = Label.parseAbsolute("//external:" + name);
           try {
             RuleClass ruleClass = ruleFactory.getRuleClass("bind");
-            builder.addBindRule(ruleClass, nameLabel,
-                actual == null ? null : Label.parseAbsolute(actual), loc);
-          } catch (RuleFactory.InvalidRuleException | Package.NameConflictException |
-              LabelSyntaxException e) {
+            builder
+                .externalPackageData()
+                .addBindRule(
+                    builder,
+                    ruleClass,
+                    nameLabel,
+                    actual == null ? null : Label.parseAbsolute(actual),
+                    loc);
+          } catch (
+              RuleFactory.InvalidRuleException | Package.NameConflictException
+                      | LabelSyntaxException
+                  e) {
             throw new EvalException(loc, e.getMessage());
           }
 
@@ -138,16 +146,19 @@
    */
   private static BuiltinFunction newRuleFunction(
       final RuleFactory ruleFactory, final Builder builder, final String ruleClassName) {
-    return new BuiltinFunction(ruleClassName,
-        FunctionSignature.KWARGS, BuiltinFunction.USE_AST_ENV) {
+    return new BuiltinFunction(
+        ruleClassName, FunctionSignature.KWARGS, BuiltinFunction.USE_AST_ENV) {
       public Object invoke(Map<String, Object> kwargs, FuncallExpression ast, Environment env)
           throws EvalException, InterruptedException {
         try {
           RuleClass ruleClass = ruleFactory.getRuleClass(ruleClassName);
           RuleClass bindRuleClass = ruleFactory.getRuleClass("bind");
-          builder.createAndAddRepositoryRule(ruleClass, bindRuleClass, kwargs, ast, env);
-        } catch (RuleFactory.InvalidRuleException | Package.NameConflictException |
-            LabelSyntaxException e) {
+          builder
+              .externalPackageData()
+              .createAndAddRepositoryRule(builder, ruleClass, bindRuleClass, kwargs, ast);
+        } catch (
+            RuleFactory.InvalidRuleException | Package.NameConflictException | LabelSyntaxException
+                e) {
           throw new EvalException(ast.getLocation(), e.getMessage());
         }
         return NONE;
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
index 6dd38da..e2fccb0 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExternalFilesHelper.java
@@ -16,7 +16,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableSet;
-import com.google.devtools.build.lib.packages.ExternalPackage;
+import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.RootedPath;
@@ -134,7 +134,7 @@
       PackageValue pkgValue =
           (PackageValue)
               Preconditions.checkNotNull(
-                  env.getValue(PackageValue.key(ExternalPackage.PACKAGE_IDENTIFIER)));
+                  env.getValue(PackageValue.key(Package.EXTERNAL_PACKAGE_IDENTIFIER)));
       Preconditions.checkState(!pkgValue.getPackage().containsErrors());
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index 427e758..6fc4bf3 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -31,7 +31,6 @@
 import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
 import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
 import com.google.devtools.build.lib.packages.CachingPackageLocator;
-import com.google.devtools.build.lib.packages.ExternalPackage;
 import com.google.devtools.build.lib.packages.InvalidPackageNameException;
 import com.google.devtools.build.lib.packages.NoSuchPackageException;
 import com.google.devtools.build.lib.packages.Package;
@@ -386,10 +385,10 @@
       }
     }
 
-    if (packageId.equals(ExternalPackage.PACKAGE_IDENTIFIER)) {
+    if (packageId.equals(Package.EXTERNAL_PACKAGE_IDENTIFIER)) {
       return getExternalPackage(env, packageLookupValue.getRoot());
     }
-    SkyKey externalPackageKey = PackageValue.key(ExternalPackage.PACKAGE_IDENTIFIER);
+    SkyKey externalPackageKey = PackageValue.key(Package.EXTERNAL_PACKAGE_IDENTIFIER);
     PackageValue externalPackage = (PackageValue) env.getValue(externalPackageKey);
     if (externalPackage == null) {
       return null;
@@ -397,7 +396,7 @@
     Package externalPkg = externalPackage.getPackage();
     if (externalPkg.containsErrors()) {
       throw new PackageFunctionException(
-          new BuildFileContainsErrorsException(ExternalPackage.PACKAGE_IDENTIFIER),
+          new BuildFileContainsErrorsException(Package.EXTERNAL_PACKAGE_IDENTIFIER),
           Transience.PERSISTENT);
     }
 
@@ -859,7 +858,8 @@
 
   private static class BadWorkspaceFileException extends NoSuchPackageException {
     private BadWorkspaceFileException(String message) {
-      super(ExternalPackage.PACKAGE_IDENTIFIER,
+      super(
+          Package.EXTERNAL_PACKAGE_IDENTIFIER,
           "Error encountered while dealing with the WORKSPACE file: " + message);
     }
   }
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 610971d..af4489a 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
@@ -18,8 +18,8 @@
 import com.google.devtools.build.lib.cmdline.LabelValidator;
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.packages.BuildFileNotFoundException;
-import com.google.devtools.build.lib.packages.ExternalPackage;
 import com.google.devtools.build.lib.packages.NoSuchPackageException;
+import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.vfs.Path;
@@ -54,7 +54,7 @@
     if (!packageKey.getRepository().equals(PackageIdentifier.MAIN_REPOSITORY_NAME)
         && !packageKey.getRepository().isDefault()) {
       return computeExternalPackageLookupValue(skyKey, env, packageKey);
-    } else if (packageKey.equals(ExternalPackage.PACKAGE_IDENTIFIER)) {
+    } else if (packageKey.equals(Package.EXTERNAL_PACKAGE_IDENTIFIER)) {
       return computeWorkspaceLookupValue(env, packageKey);
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
index 14a40da..d613819 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/WorkspaceFileFunction.java
@@ -15,7 +15,7 @@
 package com.google.devtools.build.lib.skyframe;
 
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
-import com.google.devtools.build.lib.packages.ExternalPackage.Builder;
+import com.google.devtools.build.lib.packages.Package.Builder;
 import com.google.devtools.build.lib.packages.PackageFactory;
 import com.google.devtools.build.lib.packages.RuleClassProvider;
 import com.google.devtools.build.lib.packages.WorkspaceFactory;
@@ -61,8 +61,9 @@
     }
 
     Path repoWorkspace = workspaceRoot.getRoot().getRelative(workspaceRoot.getRelativePath());
-    Builder builder = new Builder(repoWorkspace,
-        packageFactory.getRuleClassProvider().getRunfilesPrefix());
+    Builder builder =
+        com.google.devtools.build.lib.packages.Package.newExternalPackageBuilder(
+            repoWorkspace, packageFactory.getRuleClassProvider().getRunfilesPrefix());
     try (Mutability mutability = Mutability.create("workspace %s", repoWorkspace)) {
       WorkspaceFactory parser =
           new WorkspaceFactory(
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
index 82c6aa5..e4275c9 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
@@ -21,7 +21,6 @@
 import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
 import com.google.devtools.build.lib.packages.CachingPackageLocator;
 import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
-import com.google.devtools.build.lib.packages.ExternalPackage;
 import com.google.devtools.build.lib.packages.GlobCache;
 import com.google.devtools.build.lib.packages.MakeEnvironment;
 import com.google.devtools.build.lib.packages.Package;
@@ -128,8 +127,10 @@
     GlobCache globCache = new GlobCache(
         buildFile.getParentDirectory(), packageId, locator, null, TestUtils.getPool());
     LegacyGlobber globber = new LegacyGlobber(globCache);
-    ExternalPackage externalPkg = new ExternalPackage.Builder(
-        buildFile.getParentDirectory().getRelative("WORKSPACE"), "TESTING").build();
+    Package externalPkg =
+        Package.newExternalPackageBuilder(
+                buildFile.getParentDirectory().getRelative("WORKSPACE"), "TESTING")
+            .build();
     LegacyBuilder resultBuilder =
         factory.evaluateBuildFile(
             externalPkg,
diff --git a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java
index 93313da..ec3e903 100644
--- a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java
+++ b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/GenerateWorkspace.java
@@ -17,7 +17,7 @@
 import com.google.common.io.Files;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.StoredEventHandler;
-import com.google.devtools.build.lib.packages.ExternalPackage;
+import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.vfs.FileSystem;
 import com.google.devtools.build.lib.vfs.JavaIoFileSystem;
@@ -95,8 +95,7 @@
     for (String project : projects) {
       Resolver workspaceResolver = new Resolver(resolver, handler);
       Path projectPath = fileSystem.getPath(getAbsolute(project));
-      ExternalPackage externalPackage =
-          workspaceResolver.parse(projectPath.getRelative("WORKSPACE"));
+      Package externalPackage = workspaceResolver.parse(projectPath.getRelative("WORKSPACE"));
       workspaceResolver.resolveTransitiveDependencies(externalPackage);
     }
   }
diff --git a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java
index 957f43a..b775de7 100644
--- a/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java
+++ b/src/tools/generate_workspace/src/main/java/com/google/devtools/build/workspace/Resolver.java
@@ -23,7 +23,7 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
 import com.google.devtools.build.lib.packages.AttributeMap;
-import com.google.devtools.build.lib.packages.ExternalPackage;
+import com.google.devtools.build.lib.packages.Package;
 import com.google.devtools.build.lib.packages.RuleClassProvider;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.packages.WorkspaceFactory;
@@ -66,10 +66,10 @@
   /**
    * Converts the WORKSPACE file content into an ExternalPackage.
    */
-  public ExternalPackage parse(Path workspacePath) {
+  public Package parse(Path workspacePath) {
     resolver.addHeader(workspacePath.getPathString());
-    ExternalPackage.Builder builder = new ExternalPackage.Builder(workspacePath,
-        ruleClassProvider.getRunfilesPrefix());
+    Package.Builder builder =
+        Package.newExternalPackageBuilder(workspacePath, ruleClassProvider.getRunfilesPrefix());
     try (Mutability mutability = Mutability.create("External Package %s", workspacePath)) {
       new WorkspaceFactory(builder, ruleClassProvider, mutability)
           .parse(ParserInputSource.create(workspacePath));
@@ -83,7 +83,7 @@
   /**
    * Calculates transitive dependencies of the given //external package.
    */
-  public void resolveTransitiveDependencies(ExternalPackage externalPackage) {
+  public void resolveTransitiveDependencies(Package externalPackage) {
     Location location = Location.fromFile(externalPackage.getFilename());
     for (Target target : externalPackage.getTargets()) {
       // Targets are //external:foo.
@@ -100,7 +100,7 @@
           return;
         }
         com.google.devtools.build.lib.packages.Rule workspaceRule =
-            externalPackage.getRepositoryInfo(repositoryName);
+            externalPackage.getRule(repositoryName.strippedName());
 
         DefaultModelResolver modelResolver = resolver.getModelResolver();
         AttributeMap attributeMap = AggregatingAttributeMapper.of(workspaceRule);