From: Ben Hamilton Date: Thu, 16 Nov 2017 19:34:08 +0000 (+0000) Subject: [VirtualFileSystem] Support creating directories then adding files inside X-Git-Tag: llvmorg-6.0.0-rc1~3200 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=78381016785a3fc4b6304c8040198c9cdd0564d9;p=platform%2Fupstream%2Fllvm.git [VirtualFileSystem] Support creating directories then adding files inside Summary: In https://reviews.llvm.org/D39572 , I added support for specifying `Type` when invoking `InMemoryFileSystem::addFile()`. However, I didn't account for the fact that when `Type` is `directory_file`, we need to construct an `InMemoryDirectory`, not an `InMemoryFile`, or else clients cannot create files inside that directory. This diff fixes the bug and adds a test. Test Plan: New test added. Ran test with: % make -j12 check-clang-tools Reviewers: bkramer, hokein Reviewed By: bkramer Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D40140 llvm-svn: 318445 --- diff --git a/clang/include/clang/Basic/VirtualFileSystem.h b/clang/include/clang/Basic/VirtualFileSystem.h index a04166c..245452d 100644 --- a/clang/include/clang/Basic/VirtualFileSystem.h +++ b/clang/include/clang/Basic/VirtualFileSystem.h @@ -319,19 +319,23 @@ public: explicit InMemoryFileSystem(bool UseNormalizedPaths = true); ~InMemoryFileSystem() override; - /// Add a buffer to the VFS with a path. The VFS owns the buffer. - /// If present, User, Group, Type and Perms apply to the newly-created file. - /// \return true if the file was successfully added, false if the file already - /// exists in the file system with different contents. + /// Add a file containing a buffer or a directory to the VFS with a + /// path. The VFS owns the buffer. If present, User, Group, Type + /// and Perms apply to the newly-created file or directory. + /// \return true if the file or directory was successfully added, + /// false if the file or directory already exists in the file system with + /// different contents. bool addFile(const Twine &Path, time_t ModificationTime, std::unique_ptr Buffer, Optional User = None, Optional Group = None, Optional Type = None, Optional Perms = None); /// Add a buffer to the VFS with a path. The VFS does not own the buffer. - /// If present, User, Group, Type and Perms apply to the newly-created file. - /// \return true if the file was successfully added, false if the file already - /// exists in the file system with different contents. + /// If present, User, Group, Type and Perms apply to the newly-created file + /// or directory. + /// \return true if the file or directory was successfully added, + /// false if the file or directory already exists in the file system with + /// different contents. bool addFileNoOwn(const Twine &Path, time_t ModificationTime, llvm::MemoryBuffer *Buffer, Optional User = None, diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp index fd00019..9d44597 100644 --- a/clang/lib/Basic/VirtualFileSystem.cpp +++ b/clang/lib/Basic/VirtualFileSystem.cpp @@ -527,13 +527,19 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime, ++I; if (!Node) { if (I == E) { - // End of the path, create a new file. + // End of the path, create a new file or directory. Status Stat(P.str(), getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime), ResolvedUser, ResolvedGroup, Buffer->getBufferSize(), ResolvedType, ResolvedPerms); - Dir->addChild(Name, llvm::make_unique( - std::move(Stat), std::move(Buffer))); + std::unique_ptr Child; + if (ResolvedType == sys::fs::file_type::directory_file) { + Child.reset(new detail::InMemoryDirectory(std::move(Stat))); + } else { + Child.reset(new detail::InMemoryFile(std::move(Stat), + std::move(Buffer))); + } + Dir->addChild(Name, std::move(Child)); return true; } diff --git a/clang/unittests/Basic/VirtualFileSystemTest.cpp b/clang/unittests/Basic/VirtualFileSystemTest.cpp index 513e812..f9efbea 100644 --- a/clang/unittests/Basic/VirtualFileSystemTest.cpp +++ b/clang/unittests/Basic/VirtualFileSystemTest.cpp @@ -829,6 +829,19 @@ TEST_F(InMemoryFileSystemTest, AddFileWithPerms) { Stat->getPermissions()); } +TEST_F(InMemoryFileSystemTest, AddDirectoryThenAddChild) { + FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""), /*User=*/None, + /*Group=*/None, sys::fs::file_type::directory_file); + FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("abc"), /*User=*/None, + /*Group=*/None, sys::fs::file_type::regular_file); + auto Stat = FS.status("/a"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); + ASSERT_TRUE(Stat->isDirectory()); + Stat = FS.status("/a/b"); + ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); + ASSERT_TRUE(Stat->isRegularFile()); +} + // NOTE: in the tests below, we use '//root/' as our root directory, since it is // a legal *absolute* path on Windows as well as *nix. class VFSFromYAMLTest : public ::testing::Test {