44 static std::string
addFiles2(std::list<FileWithDetails>&files,
const std::string &path,
const std::set<std::string> &extra,
bool recursive,
const PathMatch& ignored)
53 std::string searchPattern = cleanedPath;
58 if (checkAllFilesInDir) {
59 const char c = cleanedPath.back();
63 basedir = cleanedPath;
66 basedir = cleanedPath.substr(0, cleanedPath.length() - 1);
69 searchPattern +=
"\\*";
70 if (cleanedPath !=
".")
71 basedir = cleanedPath +
'\\';
74 const std::string::size_type pos = cleanedPath.find_last_of(
'\\');
75 if (std::string::npos != pos) {
76 basedir = cleanedPath.substr(0, pos + 1);
81 HANDLE hFind = FindFirstFileA(searchPattern.c_str(), &ffd);
82 if (INVALID_HANDLE_VALUE == hFind) {
83 const DWORD err = GetLastError();
84 if (err == ERROR_FILE_NOT_FOUND) {
88 return "finding files failed. Search pattern: '" + searchPattern +
"'. (error: " + std::to_string(err) +
")";
90 std::unique_ptr<void, decltype(&FindClose)> hFind_deleter(hFind, FindClose);
93 if (ffd.cFileName[0] !=
'.' && ffd.cFileName[0] !=
'\0')
95 const char* ansiFfd = ffd.cFileName;
96 if (std::strchr(ansiFfd,
'?')) {
97 ansiFfd = ffd.cAlternateFileName;
100 const std::string fname(basedir + ansiFfd);
102 if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
109 const std::size_t filesize = (
static_cast<std::size_t
>(ffd.nFileSizeHigh) << 32) | ffd.nFileSizeLow;
111 const std::size_t filesize = ffd.nFileSizeLow;
114 files.emplace_back(std::move(nativename), filesize);
119 if (!ignored.
match(fname)) {
120 std::list<FileWithDetails> filesSorted;
122 std::string err =
addFiles2(filesSorted, fname, extra, recursive, ignored);
131 files.insert(files.end(), std::make_move_iterator(filesSorted.begin()), std::make_move_iterator(filesSorted.end()));
137 if (!FindNextFileA(hFind, &ffd)) {
138 const DWORD err = GetLastError();
140 if (err != ERROR_NO_MORE_FILES)
141 return "failed to get next file (error: " + std::to_string(err) +
")";
149 std::string
FileLister::addFiles(std::list<FileWithDetails> &files,
const std::string &path,
const std::set<std::string> &extra,
bool recursive,
const PathMatch& ignored)
152 return "no path specified";
154 std::list<FileWithDetails> filesSorted;
156 std::string err =
addFiles2(filesSorted, path, extra, recursive, ignored);
162 files.insert(files.end(), std::make_move_iterator(filesSorted.begin()), std::make_move_iterator(filesSorted.end()));
173 #if defined(__CYGWIN__)
174 #undef __STRICT_ANSI__
178 #include <sys/stat.h>
181 static std::string
addFiles2(std::list<FileWithDetails> &files,
182 const std::string &path,
183 const std::set<std::string> &extra,
188 if (ignored.
match(path))
191 struct stat file_stat;
192 if (stat(path.c_str(), &file_stat) == -1)
194 if ((file_stat.st_mode & S_IFMT) != S_IFDIR)
196 files.emplace_back(path, file_stat.st_size);
202 DIR * dir = opendir(path.c_str());
204 const int err = errno;
205 return "could not open directory '" + path +
"' (errno: " + std::to_string(err) +
")";
207 std::unique_ptr<DIR, decltype(&closedir)> dir_deleter(dir, closedir);
209 std::string new_path = path;
212 while (
const dirent* dir_result = readdir(dir)) {
213 if ((std::strcmp(dir_result->d_name,
".") == 0) ||
214 (std::strcmp(dir_result->d_name,
"..") == 0))
217 new_path.erase(path.length() + 1);
218 new_path += dir_result->d_name;
220 #if defined(_DIRENT_HAVE_D_TYPE) || defined(_BSD_SOURCE)
221 const bool path_is_directory = (dir_result->d_type == DT_DIR || (dir_result->d_type == DT_UNKNOWN &&
Path::isDirectory(new_path)));
225 if (path_is_directory) {
226 if (recursive && !ignored.
match(new_path)) {
227 std::string err =
addFiles2(files, new_path, extra, recursive, ignored);
234 if (stat(new_path.c_str(), &file_stat) == -1) {
235 const int err = errno;
236 return "could not stat file '" + new_path +
"' (errno: " + std::to_string(err) +
")";
238 files.emplace_back(new_path, file_stat.st_size);
246 std::string
FileLister::addFiles(std::list<FileWithDetails> &files,
const std::string &path,
const std::set<std::string> &extra,
bool recursive,
const PathMatch& ignored)
249 return "no path specified";
251 std::string corrected_path = path;
253 corrected_path.erase(corrected_path.end() - 1);
255 std::list<FileWithDetails> filesSorted;
257 std::string err =
addFiles2(filesSorted, corrected_path, extra, recursive, ignored);
263 files.insert(files.end(), std::make_move_iterator(filesSorted.begin()), std::make_move_iterator(filesSorted.end()));
272 return addFiles(files, path, extra,
true, ignored);
static std::string recursiveAddFiles(std::list< FileWithDetails > &files, const std::string &path, const PathMatch &ignored)
Recursively add source files to a map.
static std::string addFiles(std::list< FileWithDetails > &files, const std::string &path, const std::set< std::string > &extra, bool recursive, const PathMatch &ignored)
(Recursively) add source files to a map.
const std::string & path() const
Simple path matching for ignoring paths in CLI.
bool match(const std::string &path) const
Match path against list of masks.
static std::string fromNativeSeparators(std::string path)
Convert path to use internal path separators.
static std::string toNativeSeparators(std::string path)
Convert path to use native separators.
static bool acceptFile(const std::string &filename)
Check if the file extension indicates that it's a C/C++ source file.
static bool isDirectory(const std::string &path)
Checks if a given path is a directory.
static std::string addFiles2(std::list< FileWithDetails > &files, const std::string &path, const std::set< std::string > &extra, bool recursive, const PathMatch &ignored)
bool endsWith(const std::string &str, char c)