Remove WalkableGraph#exists and allow WalkableGraph#getValue and WalkableGraph#getException to be given non-existent keys without crashing. Add WalkableGraph#isCycle to fill the gap in testing for the difference between non-existence and depending on a cycle.

--
PiperOrigin-RevId: 143205289
MOS_MIGRATED_REVID=143205289
diff --git a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
index ae7aa9d..551b098 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/SkyQueryEnvironment.java
@@ -43,6 +43,7 @@
 import com.google.devtools.build.lib.graph.Digraph;
 import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
 import com.google.devtools.build.lib.packages.DependencyFilter;
+import com.google.devtools.build.lib.packages.NoSuchPackageException;
 import com.google.devtools.build.lib.packages.NoSuchTargetException;
 import com.google.devtools.build.lib.packages.NoSuchThingException;
 import com.google.devtools.build.lib.packages.Package;
@@ -728,9 +729,6 @@
   public Target getTarget(Label label)
       throws TargetNotFoundException, QueryException, InterruptedException {
     SkyKey packageKey = PackageValue.key(label.getPackageIdentifier());
-    if (!graph.exists(packageKey)) {
-      throw new QueryException(packageKey + " does not exist in graph");
-    }
     try {
       PackageValue packageValue = (PackageValue) graph.getValue(packageKey);
       if (packageValue != null) {
@@ -740,8 +738,16 @@
         }
         return packageValue.getPackage().getTarget(label.getName());
       } else {
-        throw (NoSuchThingException) Preconditions.checkNotNull(
-            graph.getException(packageKey), label);
+        NoSuchThingException exception = (NoSuchThingException) graph.getException(packageKey);
+        if (exception != null) {
+          throw exception;
+        }
+        if (graph.isCycle(packageKey)) {
+          throw new NoSuchPackageException(
+              label.getPackageIdentifier(), "Package depends on a cycle");
+        } else {
+          throw new QueryException(packageKey + " does not exist in graph");
+        }
       }
     } catch (NoSuchThingException e) {
       throw new TargetNotFoundException(e);