RecursiveFilesystemTraversalFunction now tracks changes in symlinked directory.
We achieve this by computing the directory symlink's metadata hash, which the
Google-internal Fileset rule writes in the fileset_manifest file, from the
hashes of all files under it. This adds complexity but is necessary, because
the symlink's FileStateValue remains the same even if the directory's contents
change, so the FileStateValue alone is inadequate to compute the metadata for
the fileset_manifest.
--
MOS_MIGRATED_REVID=109577723
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
index adc220e..5b4f17d 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
@@ -294,6 +294,27 @@
}
}
+ private void assertTraversalRootHashesAre(
+ boolean equal, RecursiveFilesystemTraversalValue a, RecursiveFilesystemTraversalValue b)
+ throws Exception {
+ if (equal) {
+ assertThat(a.getResolvedRoot().get().hashCode())
+ .isEqualTo(b.getResolvedRoot().get().hashCode());
+ } else {
+ assertThat(a.getResolvedRoot().get().hashCode())
+ .isNotEqualTo(b.getResolvedRoot().get().hashCode());
+ }
+ }
+
+ private void assertTraversalRootHashesAreEqual(
+ RecursiveFilesystemTraversalValue a, RecursiveFilesystemTraversalValue b) throws Exception {
+ assertTraversalRootHashesAre(true, a, b);
+ }
+
+ private void assertTraversalRootHashesAreNotEqual(
+ RecursiveFilesystemTraversalValue a, RecursiveFilesystemTraversalValue b) throws Exception {
+ assertTraversalRootHashesAre(false, a, b);
+ }
private void assertTraversalOfFile(Artifact rootArtifact) throws Exception {
TraversalRequest traversalRoot = fileLikeRoot(rootArtifact, DONT_CROSS);
@@ -312,6 +333,8 @@
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v2);
assertThat(v2).isNotEqualTo(v1);
+ assertTraversalRootHashesAreNotEqual(v1, v2);
+
progressReceiver.clear();
}
@@ -350,6 +373,7 @@
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v2);
assertThat(v2).isNotEqualTo(v1);
+ assertTraversalRootHashesAreNotEqual(v1, v2);
}
@Test
@@ -406,7 +430,10 @@
traverseAndAssertFiles(traversalRoot, expected1, expected2, expected3);
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v2);
+ // Directories always have the same hash code, but that is fine because their contents are also
+ // part of the RecursiveFilesystemTraversalValue, so v1 and v2 are unequal.
assertThat(v2).isNotEqualTo(v1);
+ assertTraversalRootHashesAreEqual(v1, v2);
progressReceiver.clear();
// Edit a file in the directory and see that the value is rebuilt.
@@ -416,6 +443,9 @@
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v3);
assertThat(v3).isNotEqualTo(v2);
+ // Directories always have the same hash code, but that is fine because their contents are also
+ // part of the RecursiveFilesystemTraversalValue, so v2 and v3 are unequal.
+ assertTraversalRootHashesAreEqual(v2, v3);
progressReceiver.clear();
// Add a new file *outside* of the directory and see that the value is *not* rebuilt.
@@ -425,6 +455,7 @@
RecursiveFilesystemTraversalValue v4 =
traverseAndAssertFiles(traversalRoot, expected1, expected2, expected3);
assertThat(v4).isEqualTo(v3);
+ assertTraversalRootHashesAreEqual(v3, v4);
assertThat(progressReceiver.invalidations).doesNotContain(rftvSkyKey(traversalRoot));
}
@@ -512,6 +543,7 @@
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v2);
assertThat(v2).isNotEqualTo(v1);
+ assertTraversalRootHashesAreNotEqual(v1, v2);
progressReceiver.clear();
// Edit a file in the directory and see that the value is rebuilt.
@@ -521,6 +553,7 @@
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(traversalRoot));
assertThat(progressReceiver.evaluations).contains(v3);
assertThat(v3).isNotEqualTo(v2);
+ assertTraversalRootHashesAreNotEqual(v2, v3);
progressReceiver.clear();
// Add a new file *outside* of the directory and see that the value is *not* rebuilt.
@@ -530,6 +563,7 @@
RecursiveFilesystemTraversalValue v4 =
traverseAndAssertFiles(traversalRoot, expected1, expected2, expected3, expected4);
assertThat(v4).isEqualTo(v3);
+ assertTraversalRootHashesAreEqual(v3, v4);
assertThat(progressReceiver.invalidations).doesNotContain(rftvSkyKey(traversalRoot));
}
@@ -702,6 +736,7 @@
RecursiveFilesystemTraversalValue v2 = traverseAndAssertFiles(params, expected);
assertThat(progressReceiver.invalidations).contains(rftvSkyKey(params));
assertThat(v2).isNotEqualTo(v1);
+ assertTraversalRootHashesAreNotEqual(v1, v2);
}
@Test
@@ -723,6 +758,7 @@
path.asPath().setLastModifiedTime(mtime);
RecursiveFilesystemTraversalValue v2 = traverseAndAssertFiles(params, expected);
assertThat(v2).isEqualTo(v1);
+ assertTraversalRootHashesAreEqual(v1, v2);
}
@Test