Switch to RunfilesSuppliers for communicating runfiles

ActionSpawn/SpawnAction now deal exclusively in RunfilesSuppliers, manifests
maps are no more.

There is some lingering awkwardness, in particular:
- Manifests still need to be tracked in some places, we can work out if this is
  still necessary on a case by case basis.
- Skylark makes actions' runfiles available via 'resolve_command' where they are
  consumed by 'action'. I've updated the documentation, though the name isn't
  entirely accurate anymore. That being said these interfaces _are_ marked as
  experimental, so we _should_ be able to be flexible here.

Overall, I think the benefits consolidating runfiles into suppliers, from both
code cleanliness and performance perspectives (no longer needing to parse
manifests), outweights the awkwardnesses.

RELNOTES: resolve_command/action's input_manifest return/parameter is now list

--
PiperOrigin-RevId: 145817429
MOS_MIGRATED_REVID=145817429
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupplierImpl.java b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupplierImpl.java
index 474784c..79ecce1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupplierImpl.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupplierImpl.java
@@ -14,7 +14,8 @@
 
 package com.google.devtools.build.lib.analysis;
 
-import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
@@ -22,17 +23,17 @@
 import com.google.devtools.build.lib.actions.BaseSpawn;
 import com.google.devtools.build.lib.actions.RunfilesSupplier;
 import com.google.devtools.build.lib.vfs.PathFragment;
-
 import java.io.IOException;
 import java.util.Map;
-import java.util.Map.Entry;
+import javax.annotation.Nullable;
 
-/**
- * {@link RunfilesSupplier} implementation wrapping directory to {@link Runfiles} objects mappings.
- */
+/** {@link RunfilesSupplier} implementation wrapping a single {@link Runfiles} directory mapping. */
+// TODO(bazel-team): Consider renaming to SingleRunfilesSupplierImpl.
 public class RunfilesSupplierImpl implements RunfilesSupplier {
-
-  private final ImmutableMap<PathFragment, Runfiles> inputRunfiles;
+  private final PathFragment runfilesDir;
+  private final Runfiles runfiles;
+  @Nullable
+  private final Artifact manifest;
 
   /**
    * Create an instance for an executable.
@@ -46,43 +47,48 @@
   }
 
   /**
-   * Create an instance when you have a a single mapping.
-   *
-   * @param runfilesDir the desired runfiles directory. Should be relative.
-   * @param runfiles the runfiles for runfilesDir
+   * Create an instance. When a manifest is available consider using
+   * {@link #RunfilesSupplierImpl(PathFragment, Runfiles, Artifact)} instead.
    */
   public RunfilesSupplierImpl(PathFragment runfilesDir, Runfiles runfiles) {
-    this.inputRunfiles = ImmutableMap.of(runfilesDir, runfiles);
+    this(runfilesDir, runfiles, /*manifest=*/ null);
   }
 
-  @VisibleForTesting
-  public RunfilesSupplierImpl(Map<PathFragment, Runfiles> inputRunfiles) {
-    this.inputRunfiles = ImmutableMap.copyOf(inputRunfiles);
+  /**
+   * Create an instance mapping {@code runfiles} to {@code runfilesDir}.
+   *
+   * @param runfilesDir the desired runfiles directory. Should be relative.
+   * @param runfiles the runfiles for runilesDir.
+   * @param manifest runfiles' associated runfiles manifest artifact, if present.
+   */
+  public RunfilesSupplierImpl(
+      PathFragment runfilesDir,
+      Runfiles runfiles,
+      @Nullable Artifact manifest) {
+    this.runfilesDir = Preconditions.checkNotNull(runfilesDir);
+    this.runfiles = Preconditions.checkNotNull(runfiles);
+    this.manifest = manifest;
   }
 
   @Override
   public Iterable<Artifact> getArtifacts() {
-    ImmutableSet.Builder<Artifact> builder = ImmutableSet.builder();
-    for (Entry<PathFragment, Runfiles> entry : inputRunfiles.entrySet()) {
-      builder.addAll(
-          Iterables.filter(entry.getValue().getAllArtifacts(), Artifact.MIDDLEMAN_FILTER));
-    }
-    return builder.build();
+    return Iterables.filter(runfiles.getAllArtifacts(), Artifact.MIDDLEMAN_FILTER);
   }
 
   @Override
   public ImmutableSet<PathFragment> getRunfilesDirs() {
-    return inputRunfiles.keySet();
+    return ImmutableSet.of(runfilesDir);
   }
 
   @Override
   public ImmutableMap<PathFragment, Map<PathFragment, Artifact>> getMappings() throws IOException {
-    ImmutableMap.Builder<PathFragment, Map<PathFragment, Artifact>> result =
-        ImmutableMap.builder();
-    for (Entry<PathFragment, Runfiles> entry : inputRunfiles.entrySet()) {
-      result.put(entry.getKey(), entry.getValue().getRunfilesInputs(null, null));
-    }
-    return result.build();
+    return ImmutableMap.of(
+        runfilesDir,
+        runfiles.getRunfilesInputs(/*eventHandler=*/ null, /*location=*/ null));
   }
 
+  @Override
+  public ImmutableList<Artifact> getManifests() {
+    return manifest != null ? ImmutableList.of(manifest) : ImmutableList.<Artifact>of();
+  }
 }