Skip to content

Commit a0443be

Browse files
Chris Dinhfacebook-github-bot
Chris Dinh
authored andcommitted
Implement usage of root inside changesSinceV2
Summary: # Context We are introducing EdenFS notifications to support scalable and ergonomic file system notifications for EdenFS mounts. Watchman has a concept known as a relative root https://www.internalfb.com/intern/staticdocs/watchman/docs/file-query#relative-roots This diff introduces the concept of a root to changesSinceV2. A root is a path starting from the existing mount, from which all paths are computed against and acts as an overall include root, eg. all returned paths will start with the root, after which include/exclude roots will be computed, and paths outside the root will not be returned. # This Diff Implements root checking. Use the following flowchart for computing included/excluded roots. ```lang=mermaid flowchart TD A[Has Root?] -->|No| B(No Change) A -->|Yes| C(Has included roots?) C-->|Yes| D(Root is prepended to included roots and excluded roots) C-->|No| E(Root becomes included root, and prependended to excluded roots, if any) ``` Use the following flowchart for determining how to handle outputs ```lang=mermaid flowchart TD A[Has Root?] -->|No| B(No Change) A -->|Yes| C(Does change contain only one path) C-->|Yes| D(Root is stripped from output) C-->|No| E(Are both paths inside the root?) E-->|Yes| F(Strip root from both paths, return replace/rename) E-->|No| G(Is the change from outside the root into the root) G-->|Yes| H(Does the path already exist inside the root) G-->|No| I(Convert the change into Removed) H-->|Yes| J(Convert the change into Modified, from Replaced) H-->|No| K(Convert the change into Added, From Renamed) ``` Note that a directory rename is converted from a Large Change(DirectoryRenamed) into a Small Change(Directory Added/removed/modified) # Technical Details This diff adds some additional allocation overhead. This is to make the code more readable. If it becomes a performance issue, this can be optimized down the line. The root matching is implemented by augmenting the includedRoots entries, as demonstrated in the flowchart above. The input included/excluded roots are appended to the root value. # Discussion Points Reviewed By: jdelliot Differential Revision: D72603242 fbshipit-source-id: 60d3b54ffd0ad5472856b13bf3c8920f1801ac01
1 parent 1e597f8 commit a0443be

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

eden/common/utils/PathFuncs.h

+24
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,30 @@ class RelativePathBase : public ComposedPathBase<
15041504
bool isParentDirOf(const RelativePathPiece& other) const {
15051505
return other.findParent(*this) != other.allPaths().end();
15061506
}
1507+
1508+
/** Returns the substring of this path.
1509+
* If the new substring ends on a dir separator, remove that as well
1510+
* to satisfy RelativePathSanityCheck
1511+
*
1512+
* It is up to the caller to verify the position passed in, this function does
1513+
* not check if the path exists or not
1514+
*
1515+
* For example,
1516+
* calling substr() on "foo/bar/baz" will yield the following results:
1517+
* substr(0) => foo/bar/baz
1518+
* substr(20) => throws std::out_of_range exception
1519+
* substr(3) => bar/baz
1520+
* substr(4) => bar/baz
1521+
* substr(1) => oo/bar/baz
1522+
*/
1523+
RelativePathPiece substr(size_t pos) const {
1524+
string_view substr_result = this->path_.substr(pos);
1525+
if (substr_result.size() > 0 && isDirSeparator(substr_result[0])) {
1526+
return RelativePathPiece{substr_result.substr(1)};
1527+
}
1528+
return RelativePathPiece{substr_result};
1529+
}
1530+
15071531
}; // namespace detail
15081532

15091533
/// Asserts that val is well formed absolute path

eden/common/utils/test/PathFuncsTest.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -1382,4 +1382,25 @@ TEST(PathFuncs, move_or_copy) {
13821382
}
13831383
}
13841384

1385+
TEST(PathFuncs, substr) {
1386+
RelativePathPiece base{"root/bar/baz"};
1387+
RelativePathPiece root{"root"};
1388+
RelativePathPiece sub{"bar/baz"};
1389+
RelativePathPiece empty{""};
1390+
1391+
EXPECT_EQ(base.substr(0), base);
1392+
EXPECT_THROW(base.substr(20), std::out_of_range);
1393+
EXPECT_EQ(base.substr(root.view().size()), sub);
1394+
EXPECT_EQ(base.substr(root.view().size() + 1), sub);
1395+
EXPECT_EQ(base.substr(1), RelativePathPiece{"oot/bar/baz"});
1396+
EXPECT_EQ(base.substr(12), empty);
1397+
EXPECT_EQ(empty.substr(0), empty);
1398+
1399+
if (folly::kIsWindows) {
1400+
RelativePathPiece winBase{"root\\bar/baz"};
1401+
EXPECT_EQ(winBase.substr(root.view().size()), sub);
1402+
EXPECT_EQ(winBase.substr(root.view().size() + 1), sub);
1403+
}
1404+
}
1405+
13851406
} // namespace facebook::eden

0 commit comments

Comments
 (0)