aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-06-13 19:31:46 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-06-13 19:37:19 +0000
commite8d8bef961a50d4dc22501cde4fb9fb0be1b2532 (patch)
tree94f04805f47bb7c59ae29690d8952b6074fff602 /contrib/llvm-project/llvm/lib/Support/FileCollector.cpp
parentbb130ff39747b94592cb26d71b7cb097b9a4ea6b (diff)
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/FileCollector.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/FileCollector.cpp128
1 files changed, 78 insertions, 50 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp b/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp
index 59755556a5a3..99482075f675 100644
--- a/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/FileCollector.cpp
@@ -15,6 +15,22 @@
using namespace llvm;
+FileCollectorBase::FileCollectorBase() = default;
+FileCollectorBase::~FileCollectorBase() = default;
+
+void FileCollectorBase::addFile(const Twine &File) {
+ std::lock_guard<std::mutex> lock(Mutex);
+ std::string FileStr = File.str();
+ if (markAsSeen(FileStr))
+ addFileImpl(FileStr);
+}
+
+void FileCollectorBase::addDirectory(const Twine &Dir) {
+ assert(sys::fs::is_directory(Dir));
+ std::error_code EC;
+ addDirectoryImpl(Dir, vfs::getRealFileSystem(), EC);
+}
+
static bool isCaseSensitivePath(StringRef Path) {
SmallString<256> TmpDest = Path, UpperDest, RealDest;
@@ -37,74 +53,82 @@ FileCollector::FileCollector(std::string Root, std::string OverlayRoot)
: Root(std::move(Root)), OverlayRoot(std::move(OverlayRoot)) {
}
-bool FileCollector::getRealPath(StringRef SrcPath,
- SmallVectorImpl<char> &Result) {
+void FileCollector::PathCanonicalizer::updateWithRealPath(
+ SmallVectorImpl<char> &Path) {
+ StringRef SrcPath(Path.begin(), Path.size());
+ StringRef Filename = sys::path::filename(SrcPath);
+ StringRef Directory = sys::path::parent_path(SrcPath);
+
+ // Use real_path to fix any symbolic link component present in the directory
+ // part of the path, caching the search because computing the real path is
+ // expensive.
SmallString<256> RealPath;
- StringRef FileName = sys::path::filename(SrcPath);
- std::string Directory = sys::path::parent_path(SrcPath).str();
- auto DirWithSymlink = SymlinkMap.find(Directory);
-
- // Use real_path to fix any symbolic link component present in a path.
- // Computing the real path is expensive, cache the search through the parent
- // path Directory.
- if (DirWithSymlink == SymlinkMap.end()) {
- auto EC = sys::fs::real_path(Directory, RealPath);
- if (EC)
- return false;
- SymlinkMap[Directory] = std::string(RealPath.str());
+ auto DirWithSymlink = CachedDirs.find(Directory);
+ if (DirWithSymlink == CachedDirs.end()) {
+ // FIXME: Should this be a call to FileSystem::getRealpath(), in some
+ // cases? What if there is nothing on disk?
+ if (sys::fs::real_path(Directory, RealPath))
+ return;
+ CachedDirs[Directory] = std::string(RealPath.str());
} else {
RealPath = DirWithSymlink->second;
}
- sys::path::append(RealPath, FileName);
- Result.swap(RealPath);
- return true;
-}
-
-void FileCollector::addFile(const Twine &File) {
- std::lock_guard<std::mutex> lock(Mutex);
- std::string FileStr = File.str();
- if (markAsSeen(FileStr))
- addFileImpl(FileStr);
-}
+ // Finish recreating the path by appending the original filename, since we
+ // don't need to resolve symlinks in the filename.
+ //
+ // FIXME: If we can cope with this, maybe we can cope without calling
+ // getRealPath() at all when there's no ".." component.
+ sys::path::append(RealPath, Filename);
-void FileCollector::addDirectory(const Twine &Dir) {
- assert(sys::fs::is_directory(Dir));
- std::error_code EC;
- addDirectoryImpl(Dir, vfs::getRealFileSystem(), EC);
+ // Swap to create the output.
+ Path.swap(RealPath);
}
-void FileCollector::addFileImpl(StringRef SrcPath) {
+/// Make Path absolute.
+static void makeAbsolute(SmallVectorImpl<char> &Path) {
// We need an absolute src path to append to the root.
- SmallString<256> AbsoluteSrc = SrcPath;
- sys::fs::make_absolute(AbsoluteSrc);
+ sys::fs::make_absolute(Path);
// Canonicalize src to a native path to avoid mixed separator styles.
- sys::path::native(AbsoluteSrc);
+ sys::path::native(Path);
// Remove redundant leading "./" pieces and consecutive separators.
- AbsoluteSrc = sys::path::remove_leading_dotslash(AbsoluteSrc);
+ Path.erase(Path.begin(), sys::path::remove_leading_dotslash(
+ StringRef(Path.begin(), Path.size()))
+ .begin());
+}
- // Canonicalize the source path by removing "..", "." components.
- SmallString<256> VirtualPath = AbsoluteSrc;
- sys::path::remove_dots(VirtualPath, /*remove_dot_dot=*/true);
+FileCollector::PathCanonicalizer::PathStorage
+FileCollector::PathCanonicalizer::canonicalize(StringRef SrcPath) {
+ PathStorage Paths;
+ Paths.VirtualPath = SrcPath;
+ makeAbsolute(Paths.VirtualPath);
// If a ".." component is present after a symlink component, remove_dots may
// lead to the wrong real destination path. Let the source be canonicalized
// like that but make sure we always use the real path for the destination.
- SmallString<256> CopyFrom;
- if (!getRealPath(AbsoluteSrc, CopyFrom))
- CopyFrom = VirtualPath;
+ Paths.CopyFrom = Paths.VirtualPath;
+ updateWithRealPath(Paths.CopyFrom);
+
+ // Canonicalize the virtual path by removing "..", "." components.
+ sys::path::remove_dots(Paths.VirtualPath, /*remove_dot_dot=*/true);
+
+ return Paths;
+}
+
+void FileCollector::addFileImpl(StringRef SrcPath) {
+ PathCanonicalizer::PathStorage Paths = Canonicalizer.canonicalize(SrcPath);
SmallString<256> DstPath = StringRef(Root);
- sys::path::append(DstPath, sys::path::relative_path(CopyFrom));
+ sys::path::append(DstPath, sys::path::relative_path(Paths.CopyFrom));
// Always map a canonical src path to its real path into the YAML, by doing
// this we map different virtual src paths to the same entry in the VFS
// overlay, which is a way to emulate symlink inside the VFS; this is also
// needed for correctness, not doing that can lead to module redefinition
// errors.
- addFileToMapping(VirtualPath, DstPath);
+ addFileToMapping(Paths.VirtualPath, DstPath);
}
llvm::vfs::directory_iterator
@@ -158,14 +182,6 @@ std::error_code FileCollector::copyFiles(bool StopOnError) {
std::lock_guard<std::mutex> lock(Mutex);
for (auto &entry : VFSWriter.getMappings()) {
- // Create directory tree.
- if (std::error_code EC =
- sys::fs::create_directories(sys::path::parent_path(entry.RPath),
- /*IgnoreExisting=*/true)) {
- if (StopOnError)
- return EC;
- }
-
// Get the status of the original file/directory.
sys::fs::file_status Stat;
if (std::error_code EC = sys::fs::status(entry.VPath, Stat)) {
@@ -174,6 +190,18 @@ std::error_code FileCollector::copyFiles(bool StopOnError) {
continue;
}
+ // Continue if the file doesn't exist.
+ if (Stat.type() == sys::fs::file_type::file_not_found)
+ continue;
+
+ // Create directory tree.
+ if (std::error_code EC =
+ sys::fs::create_directories(sys::path::parent_path(entry.RPath),
+ /*IgnoreExisting=*/true)) {
+ if (StopOnError)
+ return EC;
+ }
+
if (Stat.type() == sys::fs::file_type::directory_file) {
// Construct a directory when it's just a directory entry.
if (std::error_code EC =