Always create TreeArtifactValue through a builder.

Ensures that no unnecessary (unsorted) temporary maps are created prior to the ImmutableSortedMap being created for the final TreeArtifactValue.

MetadataInjector becomes aware of TreeArtifactValue now that the dependency cycle is broken after work in b/161911915, so it can take the TreeArtifactValue instead of a map of its children. The method is renamed to injectTree.

RELNOTES: None.
PiperOrigin-RevId: 323080321
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
index afc1562..7c5bdfd 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
@@ -13,6 +13,7 @@
 // limitations under the License.
 package com.google.devtools.build.lib.remote;
 
+import static com.google.common.util.concurrent.Futures.immediateFuture;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
 import static com.google.devtools.build.lib.remote.util.Utils.getFromFuture;
 
@@ -44,7 +45,6 @@
 import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
 import com.google.devtools.build.lib.actions.EnvironmentalExecException;
 import com.google.devtools.build.lib.actions.ExecException;
-import com.google.devtools.build.lib.actions.FileArtifactValue;
 import com.google.devtools.build.lib.actions.FileArtifactValue.RemoteFileArtifactValue;
 import com.google.devtools.build.lib.actions.UserExecException;
 import com.google.devtools.build.lib.actions.cache.MetadataInjector;
@@ -63,6 +63,7 @@
 import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
 import com.google.devtools.build.lib.server.FailureDetails.RemoteExecution;
 import com.google.devtools.build.lib.server.FailureDetails.RemoteExecution.Code;
+import com.google.devtools.build.lib.skyframe.TreeArtifactValue;
 import com.google.devtools.build.lib.util.io.FileOutErr;
 import com.google.devtools.build.lib.util.io.OutErr;
 import com.google.devtools.build.lib.vfs.Dirent;
@@ -98,13 +99,8 @@
     void lock() throws InterruptedException, IOException;
   }
 
-  private static final ListenableFuture<Void> COMPLETED_SUCCESS = SettableFuture.create();
-  private static final ListenableFuture<byte[]> EMPTY_BYTES = SettableFuture.create();
-
-  static {
-    ((SettableFuture<Void>) COMPLETED_SUCCESS).set(null);
-    ((SettableFuture<byte[]>) EMPTY_BYTES).set(new byte[0]);
-  }
+  private static final ListenableFuture<Void> COMPLETED_SUCCESS = immediateFuture(null);
+  private static final ListenableFuture<byte[]> EMPTY_BYTES = immediateFuture(new byte[0]);
 
   protected final RemoteCacheClient cacheProtocol;
   protected final RemoteOptions options;
@@ -440,7 +436,7 @@
     }
   }
 
-  /** Download a file (that is not a directory). The content is fetched from the digest. */
+  /** Downloads a file (that is not a directory). The content is fetched from the digest. */
   public ListenableFuture<Void> downloadFile(Path path, Digest digest) throws IOException {
     Preconditions.checkNotNull(path.getParentDirectory()).createDirectoryAndParents();
     if (digest.getSizeBytes() == 0) {
@@ -621,8 +617,7 @@
                 + "--experimental_remote_download_outputs=minimal");
       }
       SpecialArtifact parent = (SpecialArtifact) output;
-      ImmutableMap.Builder<TreeFileArtifact, FileArtifactValue> childMetadata =
-          ImmutableMap.builderWithExpectedSize(directory.files.size());
+      TreeArtifactValue.Builder tree = TreeArtifactValue.newBuilder(parent);
       for (FileMetadata file : directory.files()) {
         TreeFileArtifact child =
             TreeFileArtifact.createTreeOutput(parent, file.path().relativeTo(parent.getPath()));
@@ -632,9 +627,9 @@
                 file.digest().getSizeBytes(),
                 /*locationIndex=*/ 1,
                 actionId);
-        childMetadata.put(child, value);
+        tree.putChild(child, value);
       }
-      metadataInjector.injectDirectory(parent, childMetadata.build());
+      metadataInjector.injectTree(parent, tree.build());
     } else {
       FileMetadata outputMetadata = metadata.file(execRoot.getRelative(output.getExecPathString()));
       if (outputMetadata == null) {