From: Eric Liu Date: Fri, 18 May 2018 13:22:49 +0000 (+0000) Subject: [VFS] Implement getRealPath for OverlayFileSystem. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f10aa0146bf7206a84ff0244f0e665d29f5547d6;p=clang [VFS] Implement getRealPath for OverlayFileSystem. Reviewers: bkramer Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47060 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@332717 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 59e33791f2..21daeb2afc 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -304,15 +304,20 @@ public: directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; llvm::ErrorOr getCurrentWorkingDirectory() const override; std::error_code setCurrentWorkingDirectory(const Twine &Path) override; + std::error_code getRealPath(const Twine &Path, + SmallVectorImpl &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 { diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index 1727b7d0e7..b2eb5b9abf 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -381,6 +381,15 @@ OverlayFileSystem::setCurrentWorkingDirectory(const Twine &Path) { return {}; } +std::error_code +OverlayFileSystem::getRealPath(const Twine &Path, + SmallVectorImpl &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 { diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp index 383c1ffeb3..673eca88d6 100644 --- a/unittests/Basic/VirtualFileSystemTest.cpp +++ b/unittests/Basic/VirtualFileSystemTest.cpp @@ -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 &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 &FilesAndDirs; @@ -196,6 +211,35 @@ TEST(VirtualFileSystemTest, BaseOnlyOverlay) { EXPECT_TRUE(Status->equivalent(*Status2)); } +TEST(VirtualFileSystemTest, GetRealPathInOverlay) { + IntrusiveRefCntPtr Lower(new DummyFileSystem()); + Lower->addRegularFile("/foo"); + Lower->addSymlink("/lower_link"); + IntrusiveRefCntPtr Upper(new DummyFileSystem()); + + IntrusiveRefCntPtr 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 Base(new DummyFileSystem()); IntrusiveRefCntPtr Middle(new DummyFileSystem());