Skip to content

Commit 2d7f22a

Browse files
MichaelCuevasfacebook-github-bot
authored andcommitted
fix scm-aware Watchman queries when filters are active
Summary: # Context We received several reports of scm-aware Watchman queries returning incorrect results when FilteredFS was being used and filters were actively enabled[1]. In these reports, users would expect that modified files between commits would be reported as changed, however Watchman (err, EdenFS in this case) reported these files as unmodified between commits. This was causing build tools to use stale file content. After further investigation, I found that disabling filters (running `hg filteredfs disable`) caused Watchman to report correct results. Therefore, the bug only occurred when a non-null filter was enabled on FilteredFS. This significantly narrowed down the possible causes. # Root Cause The root cause was a bug in the ObjectID comparison logic for FilteredBackingStores. FilteredBackingStores use FilteredObjectIDs. When determining differences between these IDs, we must take into account three things: 1) Do the FilteredObjectIDs have the same type (Blob, Tree, or Unfiltered Tree)? 2) Do the Filters associated w/ each FilteredObjectID resolve to the exact same coverage (i.e. do they filter the same descendents)? 3) Do the underlying ObjectIDs associated w/ each FilteredObjectID refer to the same object(s). We were successfully determining #1 and #2, but we failed to determine #3 correctly in one specific edge case. This was causing us to incorrectly calculate two FilteredObjectIDs as identical when they were actually different. # This diff This diff ensures that object equality (aka #3 from above) is checked in all cases. Therefore we don't hit a scenario where #1 and #2 are equal and #3 is ignored altogether. Reviewed By: kmancini Differential Revision: D55350885 fbshipit-source-id: bdafab99e56ddfa98446b4ba26dc0bde96121dad
1 parent a896507 commit 2d7f22a

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

eden/fs/store/FilteredBackingStore.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,19 @@ ObjectComparison FilteredBackingStore::compareObjectsById(
136136
filteredOne.filter(),
137137
filteredTwo.filter());
138138
if (pathAffected.isReady()) {
139-
return std::move(pathAffected).get();
139+
auto filterComparison = std::move(pathAffected).get();
140+
141+
// If the filters are identical, we need to check whether the underlying
142+
// Objects are identical. In other words, the filters being identical is
143+
// not enough to confirm that the objects are identical.
144+
if (filterComparison == ObjectComparison::Identical) {
145+
return backingStore_->compareObjectsById(
146+
filteredOne.object(), filteredTwo.object());
147+
} else {
148+
// If the filter coverage is different, the objects must be filtered
149+
// differently (or we can't confirm they're filtered the same way).
150+
return filterComparison;
151+
}
140152
} else {
141153
// We can't immediately tell if the path is affected by the filter
142154
// change. Instead of chaining the future and queueing up a bunch of

eden/fs/store/test/FilteredBackingStoreTest.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,12 @@ TEST_F(FakePrefixFilteredBackingStoreTest, testCompareSimilarTreeObjectsById) {
797797
return;
798798
}
799799

800+
// These two trees have different filters, but the filters evaluate to the
801+
// same filtering results. These two trees are also different objects
802+
// altogether (i.e. they have different underlying ObjectIDs).
803+
//
804+
// These two trees should resolve to different objects, but a previous bug in
805+
// comparison logic caused them to evaluate as identical.
800806
auto substringFilter = std::make_unique<FakePrefixFilter>();
801807
auto treeFOID =
802808
FilteredObjectId{RelativePath{"bar"}, "foooo", makeTestHash("0000")};
@@ -820,8 +826,8 @@ TEST_F(FakePrefixFilteredBackingStoreTest, testCompareSimilarTreeObjectsById) {
820826
};
821827

822828
// We expect a tree with the same filter coverage but different underlying
823-
// objects to be identical (due to a bug).
824-
EXPECT_EQ(
829+
// objects to not be identical.
830+
EXPECT_NE(
825831
filteredStore_->compareObjectsById(
826832
ObjectId{treeFOID.getValue()}, ObjectId{similarFOID.getValue()}),
827833
ObjectComparison::Identical);

0 commit comments

Comments
 (0)