aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupValue.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupValue.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupValue.java249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupValue.java
new file mode 100644
index 0000000000..c877d38263
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageLookupValue.java
@@ -0,0 +1,249 @@
+// 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.skyframe;
+
+import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.packages.PackageIdentifier;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+
+/**
+ * A value that represents a package lookup result.
+ *
+ * <p>Package lookups will always produce a value. On success, the {@code #getRoot} returns the
+ * package path root under which the package resides and the package's BUILD file is guaranteed to
+ * exist; on failure, {@code #getErrorReason} and {@code #getErrorMsg} describe why the package
+ * doesn't exist.
+ *
+ * <p>Implementation detail: we use inheritance here to optimize for memory usage.
+ */
+abstract class PackageLookupValue implements SkyValue {
+
+ enum ErrorReason {
+ // There is no BUILD file.
+ NO_BUILD_FILE,
+
+ // The package name is invalid.
+ INVALID_PACKAGE_NAME,
+
+ // The package is considered deleted because of --deleted_packages.
+ DELETED_PACKAGE,
+
+ // The //external package could not be loaded, either because the WORKSPACE file could not be
+ // parsed or the packages it references cannot be loaded.
+ NO_EXTERNAL_PACKAGE
+ }
+
+ protected PackageLookupValue() {
+ }
+
+ public static PackageLookupValue success(Path root) {
+ return new SuccessfulPackageLookupValue(root);
+ }
+
+ public static PackageLookupValue noBuildFile() {
+ return NoBuildFilePackageLookupValue.INSTANCE;
+ }
+
+ public static PackageLookupValue noExternalPackage() {
+ return NoExternalPackageLookupValue.INSTANCE;
+ }
+
+ public static PackageLookupValue invalidPackageName(String errorMsg) {
+ return new InvalidNamePackageLookupValue(errorMsg);
+ }
+
+ public static PackageLookupValue deletedPackage() {
+ return DeletedPackageLookupValue.INSTANCE;
+ }
+
+ /**
+ * For a successful package lookup, returns the root (package path entry) that the package
+ * resides in.
+ */
+ public abstract Path getRoot();
+
+ /**
+ * Returns whether the package lookup was successful.
+ */
+ public abstract boolean packageExists();
+
+ /**
+ * For an unsuccessful package lookup, gets the reason why {@link #packageExists} returns
+ * {@code false}.
+ */
+ abstract ErrorReason getErrorReason();
+
+ /**
+ * For an unsuccessful package lookup, gets a detailed error message for {@link #getErrorReason}
+ * that is suitable for reporting to a user.
+ */
+ abstract String getErrorMsg();
+
+ static SkyKey key(PathFragment directory) {
+ Preconditions.checkArgument(!directory.isAbsolute(), directory);
+ return key(PackageIdentifier.createInDefaultRepo(directory));
+ }
+
+ static SkyKey key(PackageIdentifier pkgIdentifier) {
+ return new SkyKey(SkyFunctions.PACKAGE_LOOKUP, pkgIdentifier);
+ }
+
+ private static class SuccessfulPackageLookupValue extends PackageLookupValue {
+
+ private final Path root;
+
+ private SuccessfulPackageLookupValue(Path root) {
+ this.root = root;
+ }
+
+ @Override
+ public boolean packageExists() {
+ return true;
+ }
+
+ @Override
+ public Path getRoot() {
+ return root;
+ }
+
+ @Override
+ ErrorReason getErrorReason() {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ String getErrorMsg() {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof SuccessfulPackageLookupValue)) {
+ return false;
+ }
+ SuccessfulPackageLookupValue other = (SuccessfulPackageLookupValue) obj;
+ return root.equals(other.root);
+ }
+
+ @Override
+ public int hashCode() {
+ return root.hashCode();
+ }
+ }
+
+ private abstract static class UnsuccessfulPackageLookupValue extends PackageLookupValue {
+
+ @Override
+ public boolean packageExists() {
+ return false;
+ }
+
+ @Override
+ public Path getRoot() {
+ throw new IllegalStateException();
+ }
+ }
+
+ private static class NoBuildFilePackageLookupValue extends UnsuccessfulPackageLookupValue {
+
+ public static final NoBuildFilePackageLookupValue INSTANCE =
+ new NoBuildFilePackageLookupValue();
+
+ private NoBuildFilePackageLookupValue() {
+ }
+
+ @Override
+ ErrorReason getErrorReason() {
+ return ErrorReason.NO_BUILD_FILE;
+ }
+
+ @Override
+ String getErrorMsg() {
+ return "BUILD file not found on package path";
+ }
+ }
+
+ private static class NoExternalPackageLookupValue extends UnsuccessfulPackageLookupValue {
+
+ public static final NoExternalPackageLookupValue INSTANCE =
+ new NoExternalPackageLookupValue();
+
+ private NoExternalPackageLookupValue() {
+ }
+
+ @Override
+ ErrorReason getErrorReason() {
+ return ErrorReason.NO_EXTERNAL_PACKAGE;
+ }
+
+ @Override
+ String getErrorMsg() {
+ return "Error loading the //external package";
+ }
+ }
+
+ private static class InvalidNamePackageLookupValue extends UnsuccessfulPackageLookupValue {
+
+ private final String errorMsg;
+
+ private InvalidNamePackageLookupValue(String errorMsg) {
+ this.errorMsg = errorMsg;
+ }
+
+ @Override
+ ErrorReason getErrorReason() {
+ return ErrorReason.INVALID_PACKAGE_NAME;
+ }
+
+ @Override
+ String getErrorMsg() {
+ return errorMsg;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof InvalidNamePackageLookupValue)) {
+ return false;
+ }
+ InvalidNamePackageLookupValue other = (InvalidNamePackageLookupValue) obj;
+ return errorMsg.equals(other.errorMsg);
+ }
+
+ @Override
+ public int hashCode() {
+ return errorMsg.hashCode();
+ }
+ }
+
+ private static class DeletedPackageLookupValue extends UnsuccessfulPackageLookupValue {
+
+ public static final DeletedPackageLookupValue INSTANCE = new DeletedPackageLookupValue();
+
+ private DeletedPackageLookupValue() {
+ }
+
+ @Override
+ ErrorReason getErrorReason() {
+ return ErrorReason.DELETED_PACKAGE;
+ }
+
+ @Override
+ String getErrorMsg() {
+ return "Package is considered deleted due to --deleted_packages";
+ }
+ }
+}