Move PackageIdentifier to cmdline

This is necessary to have TargetResolver depend on it without making it depend
on the packages target. First step of #389.

--
MOS_MIGRATED_REVID=101790345
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BuildFileContainsErrorsException.java b/src/main/java/com/google/devtools/build/lib/packages/BuildFileContainsErrorsException.java
index c116898..a6e4c87 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BuildFileContainsErrorsException.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/BuildFileContainsErrorsException.java
@@ -14,6 +14,8 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+
 import javax.annotation.Nullable;
 
 /**
diff --git a/src/main/java/com/google/devtools/build/lib/packages/BuildFileNotFoundException.java b/src/main/java/com/google/devtools/build/lib/packages/BuildFileNotFoundException.java
index e425013..0e5b3e7 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/BuildFileNotFoundException.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/BuildFileNotFoundException.java
@@ -14,6 +14,8 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+
 /**
  *  Exception indicating an attempt to access a package which is not found or
  *  does not exist.
diff --git a/src/main/java/com/google/devtools/build/lib/packages/CachingPackageLocator.java b/src/main/java/com/google/devtools/build/lib/packages/CachingPackageLocator.java
index 3d677990..c8159ae 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/CachingPackageLocator.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/CachingPackageLocator.java
@@ -13,6 +13,7 @@
 // limitations under the License.
 package com.google.devtools.build.lib.packages;
 
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.vfs.Path;
 
diff --git a/src/main/java/com/google/devtools/build/lib/packages/DuplicatePackageException.java b/src/main/java/com/google/devtools/build/lib/packages/DuplicatePackageException.java
index 8dff44f..5f2d22a 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/DuplicatePackageException.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/DuplicatePackageException.java
@@ -14,6 +14,8 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+
 /**
  * Exception indicating that the same package (i.e. BUILD file) can be loaded
  * via different package paths.
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
index f71da8b..2e429ff 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ExternalPackage.java
@@ -18,9 +18,11 @@
 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.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName;
+import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.events.StoredEventHandler;
-import com.google.devtools.build.lib.packages.PackageIdentifier.RepositoryName;
 import com.google.devtools.build.lib.packages.RuleFactory.InvalidRuleException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.Label;
@@ -134,7 +136,11 @@
       Rule tempRule = RuleFactory.createRule(this, ruleClass, kwargs, eventHandler, ast,
           ast.getLocation());
       addEvents(eventHandler.getEvents());
-      repositoryMap.put(RepositoryName.create("@" + tempRule.getName()), tempRule);
+      try {
+        repositoryMap.put(RepositoryName.create("@" + tempRule.getName()), tempRule);
+      } catch (TargetParsingException e) {
+        throw new SyntaxException(e.getMessage());
+      }
       for (Map.Entry<String, Label> entry :
         ruleClass.getExternalBindingsFunction().apply(tempRule).entrySet()) {
         Label nameLabel = Label.parseAbsolute("//external:" + entry.getKey());
diff --git a/src/main/java/com/google/devtools/build/lib/packages/GlobCache.java b/src/main/java/com/google/devtools/build/lib/packages/GlobCache.java
index af596ff..d459bf6 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/GlobCache.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/GlobCache.java
@@ -21,6 +21,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.SettableFuture;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.concurrent.ThreadSafety;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.vfs.Path;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/InvalidPackageNameException.java b/src/main/java/com/google/devtools/build/lib/packages/InvalidPackageNameException.java
index d4ef8ce..0524d9a 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/InvalidPackageNameException.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/InvalidPackageNameException.java
@@ -14,6 +14,8 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+
 /**
  * Exception indicating that a package name was invalid.
  */
diff --git a/src/main/java/com/google/devtools/build/lib/packages/NoSuchPackageException.java b/src/main/java/com/google/devtools/build/lib/packages/NoSuchPackageException.java
index 8db0db6..9c2316a 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/NoSuchPackageException.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/NoSuchPackageException.java
@@ -14,6 +14,8 @@
 
 package com.google.devtools.build.lib.packages;
 
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+
 import javax.annotation.Nullable;
 
 /**
@@ -22,7 +24,7 @@
  */
 public abstract class NoSuchPackageException extends NoSuchThingException {
 
-  private final PackageIdentifier packageId;
+  private final com.google.devtools.build.lib.cmdline.PackageIdentifier packageId;
 
   public NoSuchPackageException(PackageIdentifier packageId, String message) {
     this(packageId, "no such package", message);
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 1a52b5e..71054a1 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
@@ -25,6 +25,7 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import com.google.devtools.build.lib.Constants;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.collect.CollectionUtils;
 import com.google.devtools.build.lib.collect.ImmutableSortedKeyMap;
 import com.google.devtools.build.lib.events.Event;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java b/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java
index f4898fd..95a928f 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageDeserializer.java
@@ -22,6 +22,8 @@
 import com.google.common.collect.ImmutableList.Builder;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Sets;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.cmdline.TargetParsingException;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.Location;
@@ -480,7 +482,7 @@
     try {
       builder = new Package.Builder(
           new PackageIdentifier(packagePb.getRepository(), new PathFragment(packagePb.getName())));
-    } catch (SyntaxException e) {
+    } catch (TargetParsingException e) {
       throw new PackageDeserializationException(e);
     }
     StoredEventHandler eventHandler = new StoredEventHandler();
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 8fed87b..c0bb03c 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
@@ -22,6 +22,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.devtools.build.lib.cmdline.LabelValidator;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.Location;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageIdentifier.java b/src/main/java/com/google/devtools/build/lib/packages/PackageIdentifier.java
deleted file mode 100644
index f45ecc4..0000000
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageIdentifier.java
+++ /dev/null
@@ -1,355 +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.Throwables;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ComparisonChain;
-import com.google.devtools.build.lib.cmdline.LabelValidator;
-import com.google.devtools.build.lib.syntax.Label;
-import com.google.devtools.build.lib.syntax.Label.SyntaxException;
-import com.google.devtools.build.lib.util.StringCanonicalizer;
-import com.google.devtools.build.lib.util.StringUtilities;
-import com.google.devtools.build.lib.vfs.Canonicalizer;
-import com.google.devtools.build.lib.vfs.PathFragment;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-import java.util.Objects;
-import java.util.concurrent.ExecutionException;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * Uniquely identifies a package, given a repository name and a package's path fragment.
- *
- * <p>The repository the build is happening in is the <i>default workspace</i>, and is identified
- * by the workspace name "". Other repositories can be named in the WORKSPACE file.  These
- * workspaces are prefixed by {@literal @}.</p>
- */
-@Immutable
-public final class PackageIdentifier implements Comparable<PackageIdentifier>, Serializable {
-
-  /**
-   * A human-readable name for the repository.
-   */
-  public static final class RepositoryName {
-    private static final LoadingCache<String, RepositoryName> repositoryNameCache =
-        CacheBuilder.newBuilder()
-          .weakValues()
-          .build(
-              new CacheLoader<String, RepositoryName> () {
-                @Override
-                public RepositoryName load(String name) throws SyntaxException {
-                  String errorMessage = validate(name);
-                  if (errorMessage != null) {
-                    errorMessage = "invalid repository name '"
-                        + StringUtilities.sanitizeControlChars(name) + "': " + errorMessage;
-                    throw new SyntaxException(errorMessage);
-                  }
-                  return new RepositoryName(StringCanonicalizer.intern(name));
-                }
-              });
-
-    /**
-     * Makes sure that name is a valid repository name and creates a new RepositoryName using it.
-     * @throws SyntaxException if the name is invalid.
-     */
-    public static RepositoryName create(String name) throws SyntaxException {
-      try {
-        return repositoryNameCache.get(name);
-      } catch (ExecutionException e) {
-        Throwables.propagateIfInstanceOf(e.getCause(), SyntaxException.class);
-        throw new IllegalStateException("Failed to create RepositoryName from " + name, e);
-      }
-    }
-
-    private final String name;
-
-    private RepositoryName(String name) {
-      this.name = name;
-    }
-
-    /**
-     * Performs validity checking.  Returns null on success, an error message otherwise.
-     */
-    private static String validate(String name) {
-      if (name.isEmpty()) {
-        return null;
-      }
-
-      if (!name.startsWith("@")) {
-        return "workspace name must start with '@'";
-      }
-
-      // "@" isn't a valid workspace name.
-      if (name.length() == 1) {
-        return "empty workspace name";
-      }
-
-      // Check for any character outside of [/0-9A-Z_a-z-._]. Try to evaluate the
-      // conditional quickly (by looking in decreasing order of character class
-      // likelihood).
-      if (name.startsWith("@/") || name.endsWith("/")) {
-        return "workspace names cannot start nor end with '/'";
-      } else if (name.contains("//")) {
-        return "workspace names cannot contain multiple '/'s in a row";
-      }
-
-      for (int i = name.length() - 1; i >= 1; --i) {
-        char c = name.charAt(i);
-        if ((c < 'a' || c > 'z') && c != '_' && c != '-' && c != '/' && c != '.'
-            && (c < '0' || c > '9') && (c < 'A' || c > 'Z')) {
-          return "workspace names may contain only A-Z, a-z, 0-9, '-', '_', '.', and '/'";
-        }
-      }
-      return null;
-    }
-
-    /**
-     * 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);
-    }
-
-    /**
-     * Returns if this is the default repository, that is, {@link #name} is "".
-     */
-    public boolean isDefault() {
-      return name.isEmpty();
-    }
-
-    /**
-     * 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, with leading "{@literal @}" (or "" for the default repository).
-     */
-    @Override
-    public String toString() {
-      return name;
-    }
-
-    @Override
-    public boolean equals(Object object) {
-      if (this == object) {
-        return true;
-      }
-      if (!(object instanceof RepositoryName)) {
-        return false;
-      }
-      return name.equals(((RepositoryName) object).name);
-    }
-
-    @Override
-    public int hashCode() {
-      return name.hashCode();
-    }
-  }
-
-  public static final String DEFAULT_REPOSITORY = "";
-  public static final RepositoryName DEFAULT_REPOSITORY_NAME;
-
-  static {
-    try {
-      DEFAULT_REPOSITORY_NAME = RepositoryName.create(DEFAULT_REPOSITORY);
-    } catch (Label.SyntaxException e) {
-      throw new IllegalStateException(e);
-    }
-  }
-
-  /**
-   * Helper for serializing PackageIdentifiers.
-   *
-   * <p>PackageIdentifier's field should be final, but then it couldn't be deserialized. This
-   * allows the fields to be deserialized and copied into a new PackageIdentifier.</p>
-   */
-  private static final class SerializationProxy implements Serializable {
-    PackageIdentifier packageId;
-
-    public SerializationProxy(PackageIdentifier packageId) {
-      this.packageId = packageId;
-    }
-
-    private void writeObject(ObjectOutputStream out) throws IOException {
-      out.writeObject(packageId.repository.toString());
-      out.writeObject(packageId.pkgName);
-    }
-
-    private void readObject(ObjectInputStream in)
-        throws IOException, ClassNotFoundException {
-      try {
-        packageId = new PackageIdentifier((String) in.readObject(), (PathFragment) in.readObject());
-      } catch (SyntaxException e) {
-        throw new IOException("Error serializing package identifier: " + e.getMessage());
-      }
-    }
-
-    @SuppressWarnings("unused")
-    private void readObjectNoData() throws ObjectStreamException {
-    }
-
-    private Object readResolve() {
-      return packageId;
-    }
-  }
-
-  // Temporary factory for identifiers without explicit repositories.
-  // TODO(bazel-team): remove all usages of this.
-  public static PackageIdentifier createInDefaultRepo(String name) {
-    return createInDefaultRepo(new PathFragment(name));
-  }
-
-  public static PackageIdentifier createInDefaultRepo(PathFragment name) {
-    try {
-      return new PackageIdentifier(DEFAULT_REPOSITORY, name);
-    } catch (SyntaxException e) {
-      throw new IllegalArgumentException("could not create package identifier for " + name
-          + ": " + e.getMessage());
-    }
-  }
-
-  /**
-   * The identifier for this repository. This is either "" or prefixed with an "@",
-   * e.g., "@myrepo".
-   */
-  private final RepositoryName repository;
-
-  /** The name of the package. Canonical (i.e. x.equals(y) <=> x==y). */
-  private final PathFragment pkgName;
-
-  public PackageIdentifier(String repository, PathFragment pkgName) throws SyntaxException {
-    this(RepositoryName.create(repository), pkgName);
-  }
-
-  public PackageIdentifier(RepositoryName repository, PathFragment pkgName) {
-    Preconditions.checkNotNull(repository);
-    Preconditions.checkNotNull(pkgName);
-    this.repository = repository;
-    this.pkgName = Canonicalizer.fragments().intern(pkgName.normalize());
-  }
-
-  public static PackageIdentifier parse(String input) throws SyntaxException {
-    String repo;
-    String packageName;
-    int packageStartPos = input.indexOf("//");
-    if (packageStartPos > 0) {
-      repo = input.substring(0, packageStartPos);
-      packageName = input.substring(packageStartPos + 2);
-    } else if (packageStartPos == 0) {
-      repo = PackageIdentifier.DEFAULT_REPOSITORY;
-      packageName = input.substring(2);
-    } else {
-      repo = PackageIdentifier.DEFAULT_REPOSITORY;
-      packageName = input;
-    }
-
-    String error = RepositoryName.validate(repo);
-    if (error != null) {
-      throw new SyntaxException(error);
-    }
-
-    error = LabelValidator.validatePackageName(packageName);
-    if (error != null) {
-      throw new SyntaxException(error);
-    }
-
-    return new PackageIdentifier(repo, new PathFragment(packageName));
-  }
-
-  private Object writeReplace() throws ObjectStreamException {
-    return new SerializationProxy(this);
-  }
-
-  private void readObject(ObjectInputStream in)
-      throws IOException, ClassNotFoundException {
-    throw new IOException("Serialization is allowed only by proxy");
-  }
-
-  @SuppressWarnings("unused")
-  private void readObjectNoData() throws ObjectStreamException {
-  }
-
-  public RepositoryName getRepository() {
-    return repository;
-  }
-
-  public PathFragment getPackageFragment() {
-    return pkgName;
-  }
-
-  /**
-   * Returns a relative path that should be unique across all remote and packages, based on the
-   * repository and package names.
-   */
-  public PathFragment getPathFragment() {
-    return repository.isDefault() ? pkgName
-        : new PathFragment(ExternalPackage.NAME).getRelative(repository.strippedName())
-            .getRelative(pkgName);
-  }
-
-  /**
-   * Returns the name of this package.
-   *
-   * <p>There are certain places that expect the path fragment as the package name ('foo/bar') as a
-   * package identifier. This isn't specific enough for packages in other repositories, so their
-   * stringified version is '@baz//foo/bar'.</p>
-   */
-  @Override
-  public String toString() {
-    return (repository.isDefault() ? "" : repository + "//") + pkgName;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (this == object) {
-      return true;
-    }
-    if (!(object instanceof PackageIdentifier)) {
-      return false;
-    }
-    PackageIdentifier that = (PackageIdentifier) object;
-    return pkgName.equals(that.pkgName) && repository.equals(that.repository);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(repository, pkgName);
-  }
-
-  @Override
-  public int compareTo(PackageIdentifier that) {
-    return ComparisonChain.start()
-        .compare(repository.toString(), that.repository.toString())
-        .compare(pkgName, that.pkgName)
-        .result();
-  }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RelativePackageNameResolver.java b/src/main/java/com/google/devtools/build/lib/packages/RelativePackageNameResolver.java
index 2cab8a3..30fc815 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RelativePackageNameResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RelativePackageNameResolver.java
@@ -15,6 +15,7 @@
 package com.google.devtools.build.lib.packages;
 
 import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.vfs.PathFragment;
 
 /**