filesystem.cc: deduplicate with UniqueID

This commit is contained in:
Fangrui Song 2018-05-19 23:40:07 -07:00
parent 4e2f64893c
commit 32bde07df6

View File

@ -3,6 +3,7 @@ using namespace llvm;
#include "utils.h" #include "utils.h"
#include <set>
#include <vector> #include <vector>
void GetFilesInFolder(std::string folder, void GetFilesInFolder(std::string folder,
@ -10,23 +11,47 @@ void GetFilesInFolder(std::string folder,
bool dir_prefix, bool dir_prefix,
const std::function<void(const std::string&)>& handler) { const std::function<void(const std::string&)>& handler) {
EnsureEndsInSlash(folder); EnsureEndsInSlash(folder);
std::vector<std::string> st{folder}; sys::fs::file_status Status;
while (st.size()) { if (sys::fs::status(folder, Status, true))
return;
sys::fs::UniqueID ID;
std::vector<std::string> curr{folder};
std::vector<std::pair<std::string, sys::fs::file_status>> succ;
std::set<sys::fs::UniqueID> seen{Status.getUniqueID()};
while (curr.size() || succ.size()) {
if (curr.empty()) {
for (auto& it : succ)
if (!seen.count(it.second.getUniqueID()))
curr.push_back(std::move(it.first));
succ.clear();
} else {
std::error_code ec; std::error_code ec;
folder = st.back(); std::string folder1 = curr.back();
st.pop_back(); curr.pop_back();
for (sys::fs::directory_iterator I(folder, ec), E; I != E && !ec; for (sys::fs::directory_iterator I(folder1, ec, false), E; I != E && !ec;
I.increment(ec)) { I.increment(ec)) {
auto Status = I->status();
if (!Status) continue;
std::string path = I->path(), filename = sys::path::filename(path); std::string path = I->path(), filename = sys::path::filename(path);
if (filename[0] != '.' || filename == ".ccls") { if ((filename[0] == '.' && filename != ".ccls") ||
if (sys::fs::is_regular_file(*Status)) { sys::fs::status(path, Status, false))
continue;
if (sys::fs::is_symlink_file(Status)) {
if (sys::fs::status(path, Status, true))
continue;
if (sys::fs::is_directory(Status)) {
if (recursive)
succ.emplace_back(path, Status);
continue;
}
}
if (sys::fs::is_regular_file(Status)) {
if (!dir_prefix) if (!dir_prefix)
path = path.substr(folder.size()); path = path.substr(folder.size());
handler(path); handler(path);
} else if (recursive && sys::fs::is_directory(*Status)) } else if (recursive && sys::fs::is_directory(Status) &&
st.push_back(path); !seen.count(ID = Status.getUniqueID())) {
curr.push_back(path);
seen.insert(ID);
}
} }
} }
} }