Automated rollback of commit 445260de835758f2b739d427f2f51a6dffda773b.

*** Reason for rollback ***

Removed the Precondition as it's not strictly necessary.

*** Original change description ***

Automated rollback of commit 75bb7a91724a82e7769af0fb012b24552d00f935.

*** Reason for rollback ***

Apparently it wasn't fixed. Please before rolling forward again, change the precondition to an error if it can be triggered from Starlark and write a test that checks the error

*** Original change description ***

Automated rollback of commit dcf96007e537c8abc497b2fd3c74862bbcc64deb.

*** Reason for rollback ***

The issue was fixed in the depot.

*** Original change description ***

Automated rollback of commit 0a0c96289068507a72cc6e315f27cf129aeef9b2.

*** Reason...

***

ROLLBACK_OF=238686817
RELNOTES: None
PiperOrigin-RevId: 239371968
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java
index c5f15b2..7b9407b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TreeArtifactValue.java
@@ -46,15 +46,25 @@
 @AutoCodec
 public class TreeArtifactValue implements SkyValue {
 
+  private static final TreeArtifactValue EMPTY =
+      new TreeArtifactValue(
+          DigestUtils.fromMetadata(ImmutableMap.of()).getDigestBytesUnsafe(),
+          ImmutableSortedMap.of(),
+          /* remote= */ false);
+
   private final byte[] digest;
   private final ImmutableSortedMap<TreeFileArtifact, FileArtifactValue> childData;
   private BigInteger valueFingerprint;
+  private final boolean remote;
 
   @AutoCodec.VisibleForSerialization
   TreeArtifactValue(
-      byte[] digest, ImmutableSortedMap<TreeFileArtifact, FileArtifactValue> childData) {
+      byte[] digest,
+      ImmutableSortedMap<TreeFileArtifact, FileArtifactValue> childData,
+      boolean remote) {
     this.digest = digest;
     this.childData = childData;
+    this.remote = remote;
   }
 
   /**
@@ -62,15 +72,23 @@
    * corresponding FileArtifactValues.
    */
   static TreeArtifactValue create(Map<TreeFileArtifact, FileArtifactValue> childFileValues) {
+    if (childFileValues.isEmpty()) {
+      return EMPTY;
+    }
     Map<String, FileArtifactValue> digestBuilder =
         Maps.newHashMapWithExpectedSize(childFileValues.size());
+    boolean remote = true;
     for (Map.Entry<TreeFileArtifact, FileArtifactValue> e : childFileValues.entrySet()) {
-      digestBuilder.put(e.getKey().getParentRelativePath().getPathString(), e.getValue());
+      FileArtifactValue value = e.getValue();
+      // TODO(buchgr): Enforce that all children in a tree artifact are either remote or local
+      // once b/70354083 is fixed.
+      remote = remote && value.isRemote();
+      digestBuilder.put(e.getKey().getParentRelativePath().getPathString(), value);
     }
-
     return new TreeArtifactValue(
         DigestUtils.fromMetadata(digestBuilder).getDigestBytesUnsafe(),
-        ImmutableSortedMap.copyOf(childFileValues));
+        ImmutableSortedMap.copyOf(childFileValues),
+        remote);
   }
 
   FileArtifactValue getSelfData() {
@@ -100,6 +118,11 @@
     return childData;
   }
 
+  /** Returns true if the {@link TreeFileArtifact}s are only stored remotely. */
+  public boolean isRemote() {
+    return remote;
+  }
+
   @Override
   public BigInteger getValueFingerprint() {
     if (valueFingerprint == null) {
@@ -146,7 +169,7 @@
    * Java's concurrent collections disallow null members.
    */
   static final TreeArtifactValue MISSING_TREE_ARTIFACT =
-      new TreeArtifactValue(null, ImmutableSortedMap.of()) {
+      new TreeArtifactValue(null, ImmutableSortedMap.of(), /* remote= */ false) {
         @Override
         FileArtifactValue getSelfData() {
           throw new UnsupportedOperationException();
@@ -194,8 +217,10 @@
         }
       };
 
-  private static void explodeDirectory(Path treeArtifactPath,
-      PathFragment pathToExplode, ImmutableSet.Builder<PathFragment> valuesBuilder)
+  private static void explodeDirectory(
+      Path treeArtifactPath,
+      PathFragment pathToExplode,
+      ImmutableSet.Builder<PathFragment> valuesBuilder)
       throws IOException {
     Path dir = treeArtifactPath.getRelative(pathToExplode);
     Collection<Dirent> dirents = dir.readdir(Symlinks.NOFOLLOW);
@@ -221,11 +246,11 @@
         for (String pathSegment : linkTarget.getSegments()) {
           intermediatePath = intermediatePath.getRelative(pathSegment);
           if (intermediatePath.containsUplevelReferences()) {
-            String errorMessage = String.format(
-                "A TreeArtifact may not contain relative symlinks whose target paths traverse "
-                + "outside of the TreeArtifact, found %s pointing to %s.",
-                subpath,
-                linkTarget);
+            String errorMessage =
+                String.format(
+                    "A TreeArtifact may not contain relative symlinks whose target paths traverse "
+                        + "outside of the TreeArtifact, found %s pointing to %s.",
+                    subpath, linkTarget);
             throw new IOException(errorMessage);
           }
         }