Skip to content

Commit 83dca65

Browse files
committed
Re-land "[FileCollector] Add a method to add a whole directory and it contents."
Extend the FileCollector's API with addDirectory which adds a directory and its contents to the VFS mapping. Differential revision: https://reviews.llvm.org/D76671 (cherry picked from commit 4151f2d)
1 parent 715aa78 commit 83dca65

File tree

3 files changed

+83
-26
lines changed

3 files changed

+83
-26
lines changed

llvm/include/llvm/Support/FileCollector.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@
1818
#include <mutex>
1919

2020
namespace llvm {
21-
21+
class FileCollectorFileSystem;
2222
/// Collects files into a directory and generates a mapping that can be used by
2323
/// the VFS.
2424
class FileCollector {
2525
public:
2626
FileCollector(std::string Root, std::string OverlayRoot);
2727

2828
void addFile(const Twine &file);
29+
void addDirectory(const Twine &Dir);
2930

3031
/// Write the yaml mapping (for the VFS) to the given file.
31-
std::error_code writeMapping(StringRef mapping_file);
32+
std::error_code writeMapping(StringRef MappingFile);
3233

3334
/// Copy the files into the root directory.
3435
///
@@ -44,7 +45,7 @@ class FileCollector {
4445
std::shared_ptr<FileCollector> Collector);
4546

4647
private:
47-
void addFileImpl(StringRef SrcPath);
48+
friend FileCollectorFileSystem;
4849

4950
bool markAsSeen(StringRef Path) {
5051
if (Path.empty())
@@ -55,10 +56,19 @@ class FileCollector {
5556
bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
5657

5758
void addFileToMapping(StringRef VirtualPath, StringRef RealPath) {
58-
VFSWriter.addFileMapping(VirtualPath, RealPath);
59+
if (sys::fs::is_directory(VirtualPath))
60+
VFSWriter.addDirectoryMapping(VirtualPath, RealPath);
61+
else
62+
VFSWriter.addFileMapping(VirtualPath, RealPath);
5963
}
6064

6165
protected:
66+
void addFileImpl(StringRef SrcPath);
67+
68+
llvm::vfs::directory_iterator
69+
addDirectoryImpl(const llvm::Twine &Dir,
70+
IntrusiveRefCntPtr<vfs::FileSystem> FS, std::error_code &EC);
71+
6272
/// Synchronizes adding files.
6373
std::mutex Mutex;
6474

llvm/lib/Support/FileCollector.cpp

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,19 @@ bool FileCollector::getRealPath(StringRef SrcPath,
6161
return true;
6262
}
6363

64-
void FileCollector::addFile(const Twine &file) {
64+
void FileCollector::addFile(const Twine &File) {
6565
std::lock_guard<std::mutex> lock(Mutex);
66-
std::string FileStr = file.str();
66+
std::string FileStr = File.str();
6767
if (markAsSeen(FileStr))
6868
addFileImpl(FileStr);
6969
}
7070

71+
void FileCollector::addDirectory(const Twine &Dir) {
72+
assert(sys::fs::is_directory(Dir));
73+
std::error_code EC;
74+
addDirectoryImpl(Dir, vfs::getRealFileSystem(), EC);
75+
}
76+
7177
void FileCollector::addFileImpl(StringRef SrcPath) {
7278
// We need an absolute src path to append to the root.
7379
SmallString<256> AbsoluteSrc = SrcPath;
@@ -101,6 +107,27 @@ void FileCollector::addFileImpl(StringRef SrcPath) {
101107
addFileToMapping(VirtualPath, DstPath);
102108
}
103109

110+
llvm::vfs::directory_iterator
111+
FileCollector::addDirectoryImpl(const llvm::Twine &Dir,
112+
IntrusiveRefCntPtr<vfs::FileSystem> FS,
113+
std::error_code &EC) {
114+
auto It = FS->dir_begin(Dir, EC);
115+
if (EC)
116+
return It;
117+
addFile(Dir);
118+
for (; !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
119+
if (It->type() == sys::fs::file_type::regular_file ||
120+
It->type() == sys::fs::file_type::directory_file ||
121+
It->type() == sys::fs::file_type::symlink_file) {
122+
addFile(It->path());
123+
}
124+
}
125+
if (EC)
126+
return It;
127+
// Return a new iterator.
128+
return FS->dir_begin(Dir, EC);
129+
}
130+
104131
/// Set the access and modification time for the given file from the given
105132
/// status object.
106133
static std::error_code
@@ -171,15 +198,15 @@ std::error_code FileCollector::copyFiles(bool StopOnError) {
171198
return {};
172199
}
173200

174-
std::error_code FileCollector::writeMapping(StringRef mapping_file) {
201+
std::error_code FileCollector::writeMapping(StringRef MappingFile) {
175202
std::lock_guard<std::mutex> lock(Mutex);
176203

177204
VFSWriter.setOverlayDir(OverlayRoot);
178205
VFSWriter.setCaseSensitivity(isCaseSensitivePath(OverlayRoot));
179206
VFSWriter.setUseExternalNames(false);
180207

181208
std::error_code EC;
182-
raw_fd_ostream os(mapping_file, EC, sys::fs::OF_Text);
209+
raw_fd_ostream os(MappingFile, EC, sys::fs::OF_Text);
183210
if (EC)
184211
return EC;
185212

@@ -188,7 +215,7 @@ std::error_code FileCollector::writeMapping(StringRef mapping_file) {
188215
return {};
189216
}
190217

191-
namespace {
218+
namespace llvm {
192219

193220
class FileCollectorFileSystem : public vfs::FileSystem {
194221
public:
@@ -213,22 +240,7 @@ class FileCollectorFileSystem : public vfs::FileSystem {
213240

214241
llvm::vfs::directory_iterator dir_begin(const llvm::Twine &Dir,
215242
std::error_code &EC) override {
216-
auto It = FS->dir_begin(Dir, EC);
217-
if (EC)
218-
return It;
219-
// Collect everything that's listed in case the user needs it.
220-
Collector->addFile(Dir);
221-
for (; !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
222-
if (It->type() == sys::fs::file_type::regular_file ||
223-
It->type() == sys::fs::file_type::directory_file ||
224-
It->type() == sys::fs::file_type::symlink_file) {
225-
Collector->addFile(It->path());
226-
}
227-
}
228-
if (EC)
229-
return It;
230-
// Return a new iterator.
231-
return FS->dir_begin(Dir, EC);
243+
return Collector->addDirectoryImpl(Dir, FS, EC);
232244
}
233245

234246
std::error_code getRealPath(const Twine &Path,
@@ -259,7 +271,7 @@ class FileCollectorFileSystem : public vfs::FileSystem {
259271
std::shared_ptr<FileCollector> Collector;
260272
};
261273

262-
} // end anonymous namespace
274+
} // namespace llvm
263275

264276
IntrusiveRefCntPtr<vfs::FileSystem>
265277
FileCollector::createCollectorVFS(IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,

llvm/unittests/Support/FileCollectorTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,41 @@ TEST(FileCollectorTest, addFile) {
120120
EXPECT_FALSE(FileCollector.hasSeen("/path/to/d"));
121121
}
122122

123+
TEST(FileCollectorTest, addDirectory) {
124+
ScopedDir file_root("file_root", true);
125+
126+
llvm::SmallString<128> aaa = file_root.Path;
127+
llvm::sys::path::append(aaa, "aaa");
128+
ScopedFile a(aaa.str());
129+
130+
llvm::SmallString<128> bbb = file_root.Path;
131+
llvm::sys::path::append(bbb, "bbb");
132+
ScopedFile b(bbb.str());
133+
134+
llvm::SmallString<128> ccc = file_root.Path;
135+
llvm::sys::path::append(ccc, "ccc");
136+
ScopedFile c(ccc.str());
137+
138+
std::string root_fs = std::string(file_root.Path.str());
139+
TestingFileCollector FileCollector(root_fs, root_fs);
140+
141+
FileCollector.addDirectory(file_root.Path);
142+
143+
// Make sure the root is correct.
144+
EXPECT_EQ(FileCollector.Root, root_fs);
145+
146+
// Make sure we've seen all the added files.
147+
EXPECT_TRUE(FileCollector.hasSeen(a.Path));
148+
EXPECT_TRUE(FileCollector.hasSeen(b.Path));
149+
EXPECT_TRUE(FileCollector.hasSeen(c.Path));
150+
151+
// Make sure we've only seen the added files.
152+
llvm::SmallString<128> ddd = file_root.Path;
153+
llvm::sys::path::append(ddd, "ddd");
154+
ScopedFile d(ddd.str());
155+
EXPECT_FALSE(FileCollector.hasSeen(d.Path));
156+
}
157+
123158
TEST(FileCollectorTest, copyFiles) {
124159
ScopedDir file_root("file_root", true);
125160
ScopedFile a(file_root + "/aaa");

0 commit comments

Comments
 (0)