From 32ebed17306375785ab861a36297cd892a93c9bc Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 24 May 2018 11:17:00 +0000 Subject: [PATCH] [VFS] Implement getRealPath in InMemoryFileSystem. Reviewers: bkramer Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D47262 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333172 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/VirtualFileSystem.h | 8 ++++++++ lib/Basic/VirtualFileSystem.cpp | 13 +++++++++++++ unittests/Basic/VirtualFileSystemTest.cpp | 22 ++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 21daeb2afc..2480b91123 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -374,6 +374,14 @@ public: llvm::ErrorOr getCurrentWorkingDirectory() const override { return WorkingDirectory; } + /// Canonicalizes \p Path by combining with the current working + /// directory and normalizing the path (e.g. remove dots). If the current + /// working directory is not set, this returns errc::operation_not_permitted. + /// + /// This doesn't resolve symlinks as they are not supported in in-memory file + /// system. + std::error_code getRealPath(const Twine &Path, + SmallVectorImpl &Output) const override; std::error_code setCurrentWorkingDirectory(const Twine &Path) override; }; diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp index b2eb5b9abf..234adcd9aa 100644 --- a/lib/Basic/VirtualFileSystem.cpp +++ b/lib/Basic/VirtualFileSystem.cpp @@ -788,6 +788,19 @@ std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) { return {}; } +std::error_code +InMemoryFileSystem::getRealPath(const Twine &Path, + SmallVectorImpl &Output) const { + auto CWD = getCurrentWorkingDirectory(); + if (!CWD || CWD->empty()) + return errc::operation_not_permitted; + Path.toVector(Output); + if (auto EC = makeAbsolute(Output)) + return EC; + llvm::sys::path::remove_dots(Output, /*remove_dot_dot=*/true); + return {}; +} + } // namespace vfs } // namespace clang diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp index 673eca88d6..e510c3e2e3 100644 --- a/unittests/Basic/VirtualFileSystemTest.cpp +++ b/unittests/Basic/VirtualFileSystemTest.cpp @@ -813,6 +813,28 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) { NormalizedFS.getCurrentWorkingDirectory().get())); } +TEST_F(InMemoryFileSystemTest, GetRealPath) { + SmallString<16> Path; + EXPECT_EQ(FS.getRealPath("b", Path), errc::operation_not_permitted); + + auto GetRealPath = [this](StringRef P) { + SmallString<16> Output; + auto EC = FS.getRealPath(P, Output); + EXPECT_FALSE(EC); + return Output.str().str(); + }; + + FS.setCurrentWorkingDirectory("a"); + EXPECT_EQ(GetRealPath("b"), "a/b"); + EXPECT_EQ(GetRealPath("../b"), "b"); + EXPECT_EQ(GetRealPath("b/./c"), "a/b/c"); + + FS.setCurrentWorkingDirectory("/a"); + EXPECT_EQ(GetRealPath("b"), "/a/b"); + EXPECT_EQ(GetRealPath("../b"), "/b"); + EXPECT_EQ(GetRealPath("b/./c"), "/a/b/c"); +} + TEST_F(InMemoryFileSystemTest, AddFileWithUser) { FS.addFile("/a/b/c", 0, MemoryBuffer::getMemBuffer("abc"), 0xFEEDFACE); auto Stat = FS.status("/a"); -- 2.40.0