Introduce interleaved package and transitive target loading

Adds SkyFunctions and assorted values that implement interleaved
loading of packages and their targets' transitive dependencies.

They are not hooked up to any graph loading components, yet.

--
MOS_MIGRATED_REVID=97278368
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternValue.java
new file mode 100644
index 0000000..638b078
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfPatternValue.java
@@ -0,0 +1,126 @@
+// 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.skyframe;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.cmdline.TargetParsingException;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
+import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
+import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternKey;
+import com.google.devtools.build.lib.skyframe.TargetPatternValue.TargetPatternSkyKeyOrException;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+
+import java.util.List;
+
+/**
+ * The value returned by {@link PrepareDepsOfPatternFunction}. Because that function is
+ * invoked only for its side effect (i.e. ensuring the graph contains targets matching the
+ * pattern and its transitive dependencies), this value carries no information.
+ *
+ * <p>Because the returned value is always the same object, this value and the
+ * {@link PrepareDepsOfPatternFunction} which computes it are incompatible with change pruning. It
+ * should only be requested by consumers who do not require reevaluation when
+ * {@link PrepareDepsOfPatternFunction} is reevaluated. Safe consumers include, e.g., top-level
+ * consumers, and other functions which invoke {@link PrepareDepsOfPatternFunction} solely for its
+ * side-effects.
+ */
+public class PrepareDepsOfPatternValue implements SkyValue {
+  public static final PrepareDepsOfPatternValue INSTANCE = new PrepareDepsOfPatternValue();
+
+  private PrepareDepsOfPatternValue() {
+  }
+
+  /**
+   * Returns an iterable of {@link PrepareDepsOfPatternSkyKeyOrException}, with
+   * {@link TargetPatternKey} arguments. If a provided pattern fails to parse, an element in the
+   * returned iterable will throw when its
+   * {@link PrepareDepsOfPatternSkyKeyOrException#getSkyKey} method is called and will return the
+   * failing pattern when its {@link PrepareDepsOfPatternSkyKeyOrException#getOriginalPattern}
+   * method is called.
+   *
+   * <p>There may be fewer returned elements than patterns provided as input. This function may
+   * combine patterns to return an iterable of SkyKeys that is equivalent but more efficient to
+   * evaluate, and will omit SkyKeys associated with negative patterns.
+   *
+   * @param patterns The list of patterns, e.g. "-foo/biz...". If a pattern's first character is
+   *     "-", it is treated as a negative pattern.
+   * @param policy The filtering policy, e.g. "only return test targets"
+   * @param offset The offset to apply to relative target patterns.
+   */
+  @ThreadSafe
+  public static Iterable<PrepareDepsOfPatternSkyKeyOrException> keys(List<String> patterns,
+      FilteringPolicy policy, String offset) {
+    Iterable<TargetPatternSkyKeyOrException> keysMaybe =
+        TargetPatternValue.keys(patterns, policy, offset);
+    ImmutableList.Builder<PrepareDepsOfPatternSkyKeyOrException> builder = ImmutableList.builder();
+    for (TargetPatternSkyKeyOrException keyMaybe : keysMaybe) {
+      try {
+        SkyKey skyKey = keyMaybe.getSkyKey();
+        if (!((TargetPatternKey) skyKey.argument()).isNegative()) {
+          builder.add(new PrepareDepsOfPatternSkyKeyOrExceptionImpl(keyMaybe));
+        }
+      } catch (TargetParsingException e) {
+        // keyMaybe.getSkyKey() may throw TargetParsingException if its corresponding pattern
+        // failed to parse. If so, wrap the exception-holding TargetPatternSkyKeyOrException and
+        // return it, so that our caller can deal with it.
+        builder.add(new PrepareDepsOfPatternSkyKeyOrExceptionImpl(keyMaybe));
+      }
+    }
+    return builder.build();
+  }
+
+  /**
+   * Wrapper for a prepare deps of pattern {@link SkyKey} or the {@link TargetParsingException}
+   * thrown when trying to create it.
+   */
+  public interface PrepareDepsOfPatternSkyKeyOrException {
+
+    /**
+     * Returns the stored {@link SkyKey} or throws {@link TargetParsingException} if one was thrown
+     * when creating the key.
+     */
+    SkyKey getSkyKey() throws TargetParsingException;
+
+    /**
+     * Returns the pattern that resulted in the stored {@link SkyKey} or {@link
+     * TargetParsingException}.
+     */
+    String getOriginalPattern();
+  }
+
+  /**
+   * Converts from a {@link TargetPatternSkyKeyOrException} to a
+   * {@link PrepareDepsOfPatternSkyKeyOrException}.
+   */
+  private static class PrepareDepsOfPatternSkyKeyOrExceptionImpl implements
+      PrepareDepsOfPatternSkyKeyOrException {
+
+    private final TargetPatternSkyKeyOrException wrapped;
+
+    private PrepareDepsOfPatternSkyKeyOrExceptionImpl(TargetPatternSkyKeyOrException wrapped) {
+      this.wrapped = wrapped;
+    }
+
+    @Override
+    public SkyKey getSkyKey() throws TargetParsingException {
+      return new SkyKey(SkyFunctions.PREPARE_DEPS_OF_PATTERN, wrapped.getSkyKey().argument());
+    }
+
+    @Override
+    public String getOriginalPattern() {
+      return wrapped.getOriginalPattern();
+    }
+  }
+}