mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 06:18:07 +03:00
add a splitFirst() function to PathFuncs
Summary: Add a splitFirst() function that, if you think about a path as a linked list, splits the head and the tail. Normally you could use the components iterator, but split() is easier when the iteration is asynchronous and requires lambda capture. Reviewed By: pkaush Differential Revision: D10154746 fbshipit-source-id: 6372a0bbde27f6596659ad1244cc96fa1f9eb6ff
This commit is contained in:
parent
bf85e7ea15
commit
d99eef5354
@ -245,6 +245,20 @@ AbsolutePath normalizeBestEffort(folly::StringPiece path) {
|
||||
return normalizeBestEffort(path.str().c_str());
|
||||
}
|
||||
|
||||
std::pair<PathComponentPiece, RelativePathPiece> splitFirst(
|
||||
RelativePathPiece path) {
|
||||
auto piece = path.stringPiece();
|
||||
auto p = piece.find(kDirSeparator);
|
||||
if (p != std::string::npos) {
|
||||
return {PathComponentPiece{
|
||||
folly::StringPiece{piece.begin(), piece.begin() + p}},
|
||||
RelativePathPiece{
|
||||
folly::StringPiece{piece.begin() + p + 1, piece.end()}}};
|
||||
} else {
|
||||
return {PathComponentPiece{piece}, RelativePathPiece{}};
|
||||
}
|
||||
}
|
||||
|
||||
void validatePathComponentLength(PathComponentPiece name) {
|
||||
if (name.value().size() > kMaxPathComponentLength) {
|
||||
folly::throwSystemErrorExplicit(
|
||||
|
@ -1051,7 +1051,7 @@ class RelativePathBase : public ComposedPathBase<
|
||||
bool isParentDirOf(const RelativePathPiece& other) const {
|
||||
return other.findParent(*this) != other.allPaths().end();
|
||||
}
|
||||
};
|
||||
}; // namespace detail
|
||||
|
||||
/// Asserts that val is well formed absolute path
|
||||
struct AbsolutePathSanityCheck {
|
||||
@ -1179,8 +1179,9 @@ class AbsolutePathBase : public ComposedPathBase<
|
||||
if (myIter != myPaths.end()) {
|
||||
childIter++;
|
||||
} else {
|
||||
// We do not want to increment childIter here or else we will be missing
|
||||
// a path component when we call remainder() after the while loop.
|
||||
// We do not want to increment childIter here or else we will be
|
||||
// missing a path component when we call remainder() after the while
|
||||
// loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1233,8 +1234,8 @@ class AbsolutePathBase : public ComposedPathBase<
|
||||
* An iterator over suffixes in a composed path.
|
||||
*
|
||||
* PathSuffixIterator always returns RelativePathPiece objects, even when
|
||||
* iterating over an AbsolutePath. This is intentional, since the suffixes are
|
||||
* relative to some other location inside the path.
|
||||
* iterating over an AbsolutePath. This is intentional, since the suffixes
|
||||
* are relative to some other location inside the path.
|
||||
*
|
||||
* For example, when iterating forwards over the path "foo/bar/baz", the
|
||||
* iterator yields:
|
||||
@ -1652,6 +1653,14 @@ normalizeBestEffort(const T& path) {
|
||||
return normalizeBestEffort(path.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a path into the first component and the remainder of the path.
|
||||
* If the path has only one component, the remainder will be empty. If the
|
||||
* path is empty, an exception is thrown.
|
||||
*/
|
||||
std::pair<PathComponentPiece, RelativePathPiece> splitFirst(
|
||||
RelativePathPiece path);
|
||||
|
||||
/**
|
||||
* Throws std::system_error with ENAMETOOLONG if the given PathComponent is
|
||||
* longer than kMaxPathComponentLength.
|
||||
|
@ -515,6 +515,22 @@ TEST(PathFuncs, format) {
|
||||
EXPECT_EQ("x(src/abc.def)", folly::sformat("x({})", relPiece));
|
||||
}
|
||||
|
||||
TEST(PathFuncs, splitFirst) {
|
||||
using SplitResult = decltype(splitFirst(std::declval<RelativePath>()));
|
||||
|
||||
RelativePath rp1{""};
|
||||
EXPECT_THROW(splitFirst(rp1), std::domain_error);
|
||||
|
||||
RelativePath rp2{"foo"};
|
||||
EXPECT_EQ((SplitResult{"foo", ""}), splitFirst(rp2));
|
||||
|
||||
RelativePath rp3{"foo/bar"};
|
||||
EXPECT_EQ((SplitResult{"foo", "bar"}), splitFirst(rp3));
|
||||
|
||||
RelativePath rp4{"foo/bar/baz"};
|
||||
EXPECT_EQ((SplitResult{"foo", "bar/baz"}), splitFirst(rp4));
|
||||
}
|
||||
|
||||
namespace {
|
||||
/*
|
||||
* Helper class to create a temporary directory and cd into it while this
|
||||
|
Loading…
Reference in New Issue
Block a user