Remote API v2 migration.

Major differences between v1test and v2 that are implemented here:
- Execute call streams Operation updates
- WaitExecution call replaces Watcher API
- Action is no longer part of the Execute request, and must be uploaded separately
- output spec and platform moved from Action to Command

Also, adding retries to operations lost on the server, resolving a TODO.

TESTED=unit tests, LRE, RBE.
TYPE_CHANGE_OK=this is a breaking change by design, will update proto parsing tool as well
TAG_CHANGE_OK=this way give us flexibility to update the parsing tool to support both versions
PiperOrigin-RevId: 208990450
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java
index a97d277..7c6cc50 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteSpawnCache.java
@@ -15,6 +15,9 @@
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 
+import build.bazel.remote.execution.v2.Action;
+import build.bazel.remote.execution.v2.ActionResult;
+import build.bazel.remote.execution.v2.Command;
 import com.google.devtools.build.lib.actions.ActionInput;
 import com.google.devtools.build.lib.actions.ExecException;
 import com.google.devtools.build.lib.actions.ExecutionStrategy;
@@ -36,9 +39,6 @@
 import com.google.devtools.build.lib.remote.util.TracingMetadataUtils;
 import com.google.devtools.build.lib.vfs.Path;
 import com.google.devtools.build.lib.vfs.PathFragment;
-import com.google.devtools.remoteexecution.v1test.Action;
-import com.google.devtools.remoteexecution.v1test.ActionResult;
-import com.google.devtools.remoteexecution.v1test.Command;
 import io.grpc.Context;
 import java.io.IOException;
 import java.util.Collection;
@@ -99,13 +99,16 @@
     SortedMap<PathFragment, ActionInput> inputMap = context.getInputMapping();
     TreeNode inputRoot = repository.buildFromActionInputs(inputMap);
     repository.computeMerkleDigests(inputRoot);
-    Command command = RemoteSpawnRunner.buildCommand(spawn.getArguments(), spawn.getEnvironment());
+    Command command =
+        RemoteSpawnRunner.buildCommand(
+            spawn.getOutputFiles(),
+            spawn.getArguments(),
+            spawn.getEnvironment(),
+            spawn.getExecutionPlatform());
     Action action =
         RemoteSpawnRunner.buildAction(
-            spawn.getOutputFiles(),
             digestUtil.compute(command),
             repository.getMerkleDigest(inputRoot),
-            spawn.getExecutionPlatform(),
             context.getTimeout(),
             Spawns.mayBeCached(spawn));
     // Look up action cache, and reuse the action output if it is found.
@@ -183,7 +186,8 @@
           Collection<Path> files =
               RemoteSpawnRunner.resolveActionInputs(execRoot, spawn.getOutputFiles());
           try {
-            remoteCache.upload(actionKey, execRoot, files, context.getFileOutErr(), uploadAction);
+            remoteCache.upload(
+                actionKey, action, command, execRoot, files, context.getFileOutErr(), uploadAction);
           } catch (IOException e) {
             String errorMsg = e.getMessage();
             if (isNullOrEmpty(errorMsg)) {
@@ -205,12 +209,9 @@
               continue;
             }
             FileArtifactValue metadata = context.getMetadataProvider().getMetadata(input);
-            if (metadata instanceof FileArtifactValue) {
-              FileArtifactValue artifactValue = (FileArtifactValue) metadata;
-              Path path = execRoot.getRelative(input.getExecPath());
-              if (artifactValue.wasModifiedSinceDigest(path)) {
-                throw new IOException(path + " was modified during execution");
-              }
+            Path path = execRoot.getRelative(input.getExecPath());
+            if (metadata.wasModifiedSinceDigest(path)) {
+              throw new IOException(path + " was modified during execution");
             }
           }
         }