From f5ce45fd55c7c77268e4d256d6a226e58d374ffd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 19 May 2018 23:40:07 -0700 Subject: [PATCH] filesystem.cc: deduplicate with UniqueID --- src/filesystem.cc | 53 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/filesystem.cc b/src/filesystem.cc index b3c31fe6..7ff90c85 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -3,6 +3,7 @@ using namespace llvm; #include "utils.h" +#include #include void GetFilesInFolder(std::string folder, @@ -10,23 +11,47 @@ void GetFilesInFolder(std::string folder, bool dir_prefix, const std::function& handler) { EnsureEndsInSlash(folder); - std::vector st{folder}; - while (st.size()) { - std::error_code ec; - folder = st.back(); - st.pop_back(); - for (sys::fs::directory_iterator I(folder, ec), E; I != E && !ec; - I.increment(ec)) { - auto Status = I->status(); - if (!Status) continue; - std::string path = I->path(), filename = sys::path::filename(path); - if (filename[0] != '.' || filename == ".ccls") { - if (sys::fs::is_regular_file(*Status)) { + sys::fs::file_status Status; + if (sys::fs::status(folder, Status, true)) + return; + sys::fs::UniqueID ID; + std::vector curr{folder}; + std::vector> succ; + std::set 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::string folder1 = curr.back(); + curr.pop_back(); + for (sys::fs::directory_iterator I(folder1, ec, false), E; I != E && !ec; + I.increment(ec)) { + std::string path = I->path(), filename = sys::path::filename(path); + if ((filename[0] == '.' && filename != ".ccls") || + 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) path = path.substr(folder.size()); handler(path); - } else if (recursive && sys::fs::is_directory(*Status)) - st.push_back(path); + } else if (recursive && sys::fs::is_directory(Status) && + !seen.count(ID = Status.getUniqueID())) { + curr.push_back(path); + seen.insert(ID); + } } } }