[VFS] Let the user decide if they want path normalization.
This is a more principled version of what I did earlier. Path normalization is generally a good thing, but may break users in strange environments, e. g. using lots of symlinks. Let the user choose and default it to on. This also changes adding a duplicated file into returning an error if the file contents are different instead of an assertion failure. Differential Revision: http://reviews.llvm.org/D13658 llvm-svn: 250060
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Basic/VirtualFileSystem.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
@@ -474,11 +475,12 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
InMemoryFileSystem::InMemoryFileSystem()
|
||||
InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
|
||||
: Root(new detail::InMemoryDirectory(
|
||||
Status("", getNextVirtualUniqueID(), llvm::sys::TimeValue::MinTime(),
|
||||
0, 0, 0, llvm::sys::fs::file_type::directory_file,
|
||||
llvm::sys::fs::perms::all_all))) {}
|
||||
llvm::sys::fs::perms::all_all))),
|
||||
UseNormalizedPaths(UseNormalizedPaths) {}
|
||||
|
||||
InMemoryFileSystem::~InMemoryFileSystem() {}
|
||||
|
||||
@@ -486,7 +488,7 @@ std::string InMemoryFileSystem::toString() const {
|
||||
return Root->toString(/*Indent=*/0);
|
||||
}
|
||||
|
||||
void InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
|
||||
bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
|
||||
SmallString<128> Path;
|
||||
P.toVector(Path);
|
||||
@@ -496,14 +498,14 @@ void InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
|
||||
assert(!EC);
|
||||
(void)EC;
|
||||
|
||||
if (useNormalizedPaths())
|
||||
FileManager::removeDotPaths(Path, /*RemoveDotDot=*/true);
|
||||
|
||||
if (Path.empty())
|
||||
return false;
|
||||
|
||||
detail::InMemoryDirectory *Dir = Root.get();
|
||||
auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
|
||||
if (*I == ".")
|
||||
++I;
|
||||
|
||||
if (I == E)
|
||||
return;
|
||||
|
||||
while (true) {
|
||||
StringRef Name = *I;
|
||||
detail::InMemoryNode *Node = Dir->getChild(Name);
|
||||
@@ -519,7 +521,7 @@ void InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
|
||||
llvm::sys::fs::all_all);
|
||||
Dir->addChild(Name, llvm::make_unique<detail::InMemoryFile>(
|
||||
std::move(Stat), std::move(Buffer)));
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create a new directory. Use the path up to here.
|
||||
@@ -534,12 +536,24 @@ void InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node))
|
||||
if (auto *NewDir = dyn_cast<detail::InMemoryDirectory>(Node)) {
|
||||
Dir = NewDir;
|
||||
} else {
|
||||
assert(isa<detail::InMemoryFile>(Node) &&
|
||||
"Must be either file or directory!");
|
||||
|
||||
// Trying to insert a directory in place of a file.
|
||||
if (I != E)
|
||||
return false;
|
||||
|
||||
// Return false only if the new file is different from the existing one.
|
||||
return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
|
||||
Buffer->getBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
|
||||
bool InMemoryFileSystem::addFileNoOwn(const Twine &P, time_t ModificationTime,
|
||||
llvm::MemoryBuffer *Buffer) {
|
||||
return addFile(P, ModificationTime,
|
||||
llvm::MemoryBuffer::getMemBuffer(
|
||||
@@ -557,13 +571,13 @@ lookupInMemoryNode(const InMemoryFileSystem &FS, detail::InMemoryDirectory *Dir,
|
||||
assert(!EC);
|
||||
(void)EC;
|
||||
|
||||
auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
|
||||
if (*I == ".")
|
||||
++I;
|
||||
if (FS.useNormalizedPaths())
|
||||
FileManager::removeDotPaths(Path, /*RemoveDotDot=*/true);
|
||||
|
||||
if (I == E)
|
||||
if (Path.empty())
|
||||
return Dir;
|
||||
|
||||
auto I = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path);
|
||||
while (true) {
|
||||
detail::InMemoryNode *Node = Dir->getChild(*I);
|
||||
++I;
|
||||
|
||||
Reference in New Issue
Block a user