Tolerate the situation of injecting nodes that already exist into an edgeless graph. This can happen if the previous Bazel command ends after an injection is planned, but before it happens, and the next build is edgeless (the first build could be edgeless too, doesn't matter).
Also make InMemoryNodeEntry#toString tolerant to not having deps.
PiperOrigin-RevId: 233152512
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
index e174c36..4c05231 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryMemoizingEvaluator.java
@@ -225,26 +225,32 @@
SkyValue newValue = entry.getValue();
NodeEntry prevEntry = graph.get(null, Reason.OTHER, key);
if (prevEntry != null && prevEntry.isDone()) {
- try {
- Iterable<SkyKey> directDeps = prevEntry.getDirectDeps();
- if (Iterables.isEmpty(directDeps)) {
- if (newValue.equals(prevEntry.getValue())
- && !valuesToDirty.contains(key)
- && !valuesToDelete.contains(key)) {
+ if (keepEdges) {
+ try {
+ Iterable<SkyKey> directDeps = prevEntry.getDirectDeps();
+ if (Iterables.isEmpty(directDeps)) {
+ if (newValue.equals(prevEntry.getValue())
+ && !valuesToDirty.contains(key)
+ && !valuesToDelete.contains(key)) {
+ it.remove();
+ }
+ } else {
+ // Rare situation of an injected dep that depends on another node. Usually the dep is
+ // the error transience node. When working with external repositories, it can also be
+ // an external workspace file. Don't bother injecting it, just invalidate it.
+ // We'll wastefully evaluate the node freshly during evaluation, but this happens very
+ // rarely.
+ valuesToDirty.add(key);
it.remove();
}
- } else {
- // Rare situation of an injected dep that depends on another node. Usually the dep is
- // the error transience node. When working with external repositories, it can also be an
- // external workspace file. Don't bother injecting it, just invalidate it.
- // We'll wastefully evaluate the node freshly during evaluation, but this happens very
- // rarely.
- valuesToDirty.add(key);
- it.remove();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException(
+ "InMemoryGraph does not throw: " + entry + ", " + prevEntry, e);
}
- } catch (InterruptedException e) {
- throw new IllegalStateException(
- "InMemoryGraph does not throw: " + entry + ", " + prevEntry, e);
+ } else {
+ // No incrementality. Just delete the old value from the graph. The new value is about to
+ // be injected.
+ graph.remove(key);
}
}
}
diff --git a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
index f72d069..bf76f6d 100644
--- a/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
+++ b/src/main/java/com/google/devtools/build/skyframe/InMemoryNodeEntry.java
@@ -751,7 +751,11 @@
.add("value", value)
.add("lastChangedVersion", lastChangedVersion)
.add("lastEvaluatedVersion", lastEvaluatedVersion)
- .add("directDeps", isDone() ? GroupedList.create(directDeps) : directDeps)
+ .add(
+ "directDeps",
+ isDone() && keepEdges() != KeepEdgesPolicy.NONE
+ ? GroupedList.create(directDeps)
+ : directDeps)
.add("signaledDeps", signaledDeps)
.add("reverseDeps", ReverseDepsUtility.toString(this))
.add("dirtyBuildingState", dirtyBuildingState);