[VFS] Implement getRealPath for OverlayFileSystem.

Reviewers: bkramer

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D47060

llvm-svn: 332717
This commit is contained in:
Eric Liu 2018-05-18 13:22:49 +00:00
parent 215e4718ca
commit a840a46557
3 changed files with 59 additions and 1 deletions

View File

@ -304,15 +304,20 @@ public:
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
std::error_code getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) const override;
using iterator = FileSystemList::reverse_iterator;
using const_iterator = FileSystemList::const_reverse_iterator;
/// Get an iterator pointing to the most recently added file system.
iterator overlays_begin() { return FSList.rbegin(); }
const_iterator overlays_begin() const { return FSList.rbegin(); }
/// Get an iterator pointing one-past the least recently added file
/// system.
iterator overlays_end() { return FSList.rend(); }
const_iterator overlays_end() const { return FSList.rend(); }
};
namespace detail {

View File

@ -381,6 +381,15 @@ OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
return {};
}
std::error_code
OverlayFileSystem::getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) const {
for (auto &FS : FSList)
if (FS->exists(Path))
return FS->getRealPath(Path, Output);
return errc::no_such_file_or_directory;
}
clang::vfs::detail::DirIterImpl::~DirIterImpl() = default;
namespace {

View File

@ -67,6 +67,21 @@ public:
std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
return std::error_code();
}
// Map any symlink to "/symlink".
std::error_code getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) const override {
auto I = FilesAndDirs.find(Path.str());
if (I == FilesAndDirs.end())
return make_error_code(llvm::errc::no_such_file_or_directory);
if (I->second.isSymlink()) {
Output.clear();
Twine("/symlink").toVector(Output);
return std::error_code();
}
Output.clear();
Path.toVector(Output);
return std::error_code();
}
struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
std::map<std::string, vfs::Status> &FilesAndDirs;
@ -196,6 +211,35 @@ TEST(VirtualFileSystemTest, BaseOnlyOverlay) {
EXPECT_TRUE(Status->equivalent(*Status2));
}
TEST(VirtualFileSystemTest, GetRealPathInOverlay) {
IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
Lower->addRegularFile("/foo");
Lower->addSymlink("/lower_link");
IntrusiveRefCntPtr<DummyFileSystem> Upper(new DummyFileSystem());
IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
new vfs::OverlayFileSystem(Lower));
O->pushOverlay(Upper);
// Regular file.
SmallString<16> RealPath;
EXPECT_FALSE(O->getRealPath("/foo", RealPath));
EXPECT_EQ(RealPath.str(), "/foo");
// Expect no error getting real path for symlink in lower overlay.
EXPECT_FALSE(O->getRealPath("/lower_link", RealPath));
EXPECT_EQ(RealPath.str(), "/symlink");
// Try a non-existing link.
EXPECT_EQ(O->getRealPath("/upper_link", RealPath),
errc::no_such_file_or_directory);
// Add a new symlink in upper.
Upper->addSymlink("/upper_link");
EXPECT_FALSE(O->getRealPath("/upper_link", RealPath));
EXPECT_EQ(RealPath.str(), "/symlink");
}
TEST(VirtualFileSystemTest, OverlayFiles) {
IntrusiveRefCntPtr<DummyFileSystem> Base(new DummyFileSystem());
IntrusiveRefCntPtr<DummyFileSystem> Middle(new DummyFileSystem());