diff --git a/bin/app/data/src/tictactoe/io.cpp b/bin/app/data/src/tictactoe/io.cpp deleted file mode 100644 index 0e7a98db..00000000 --- a/bin/app/data/src/tictactoe/io.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "io.h" - - #include - #include - #include - -int io::numberIn() { - std::string input; - getline( std::cin, input ); - std::stringstream stream( input ); - - int number; - stream >> number; - return number; -} - -void io::numberOut(int num) { - std::cout << num; -} - -void io::stringOut(const char* str) { - std::cout << str; -} diff --git a/bin/test/data/FileSystemTestSuite/Settings/src b/bin/test/data/FileSystemTestSuite/Settings/src new file mode 120000 index 00000000..e057607e --- /dev/null +++ b/bin/test/data/FileSystemTestSuite/Settings/src @@ -0,0 +1 @@ +../src/ \ No newline at end of file diff --git a/bin/test/data/FileSystemTestSuite/src/Settings b/bin/test/data/FileSystemTestSuite/src/Settings new file mode 120000 index 00000000..4c6b4d0f --- /dev/null +++ b/bin/test/data/FileSystemTestSuite/src/Settings @@ -0,0 +1 @@ +../Settings \ No newline at end of file diff --git a/bin/test/data/FileSystemTestSuite/src/main.cpp b/bin/test/data/FileSystemTestSuite/src/main.cpp new file mode 120000 index 00000000..cb9fa3f2 --- /dev/null +++ b/bin/test/data/FileSystemTestSuite/src/main.cpp @@ -0,0 +1 @@ +../main.cpp \ No newline at end of file diff --git a/bin/test/data/FileSystemTestSuite/src/self b/bin/test/data/FileSystemTestSuite/src/self new file mode 120000 index 00000000..0aca4de3 --- /dev/null +++ b/bin/test/data/FileSystemTestSuite/src/self @@ -0,0 +1 @@ +self \ No newline at end of file diff --git a/bin/test/data/FileSystemTestSuite/src/test.cpp b/bin/test/data/FileSystemTestSuite/src/test.cpp new file mode 100644 index 00000000..e375627c --- /dev/null +++ b/bin/test/data/FileSystemTestSuite/src/test.cpp @@ -0,0 +1,4 @@ +void test() +{ + +} diff --git a/bin/test/data/FileSystemTestSuite/src/test.h b/bin/test/data/FileSystemTestSuite/src/test.h new file mode 100644 index 00000000..5511b637 --- /dev/null +++ b/bin/test/data/FileSystemTestSuite/src/test.h @@ -0,0 +1,4 @@ +class Test +{ + +}; diff --git a/src/lib/utility/file/FileSystem.cpp b/src/lib/utility/file/FileSystem.cpp index ed8ca782..418582bc 100644 --- a/src/lib/utility/file/FileSystem.cpp +++ b/src/lib/utility/file/FileSystem.cpp @@ -1,11 +1,14 @@ #include "utility/file/FileSystem.h" +#include + #include "boost/date_time.hpp" #include "boost/filesystem.hpp" std::vector FileSystem::getFileNamesFromDirectory( const std::string& path, const std::vector& extensions ){ + std::set ext(extensions.begin(), extensions.end()); std::vector files; if (boost::filesystem::is_directory(path)) @@ -14,7 +17,18 @@ std::vector FileSystem::getFileNamesFromDirectory( boost::filesystem::recursive_directory_iterator endit; while (it != endit) { - if (boost::filesystem::is_regular_file(*it) && hasExtension(it->path().string(), extensions)) + if (boost::filesystem::is_symlink(*it)) + { + // check for self-referencing symlinks + boost::filesystem::path p = boost::filesystem::read_symlink(*it); + if (p.filename() == p.string() && p.filename() == it->path().filename()) + { + ++it; + continue; + } + } + + if (boost::filesystem::is_regular_file(*it) && ext.find(it->path().extension().string()) != ext.end()) { files.push_back(it->path().generic_string()); } @@ -24,34 +38,6 @@ std::vector FileSystem::getFileNamesFromDirectory( return files; } -std::vector FileSystem::getFileNamesFromDirectoryUpdatedAfter( - const std::string& path, const std::vector& extensions, const std::string& timeString -){ - std::vector files; - - const boost::posix_time::ptime time = boost::posix_time::from_iso_string(timeString); - - if (boost::filesystem::is_directory(path)) - { - boost::filesystem::recursive_directory_iterator it(path); - boost::filesystem::recursive_directory_iterator endit; - while (it != endit) - { - if (boost::filesystem::is_regular_file(*it) && hasExtension(it->path().string(), extensions)) - { - std::time_t t = boost::filesystem::last_write_time(*it); - boost::posix_time::ptime lastWriteTime = boost::posix_time::from_time_t(t); - if (lastWriteTime >= time) - { - files.push_back(it->path().generic_string()); - } - } - ++it; - } - } - return files; -} - FileInfo FileSystem::getFileInfoForPath(FilePath filePath) { if (filePath.exists()) @@ -64,39 +50,85 @@ FileInfo FileSystem::getFileInfoForPath(FilePath filePath) } std::vector FileSystem::getFileInfosFromPaths( - const std::vector& paths, const std::vector& fileExtensions + const std::vector& paths, const std::vector& fileExtensions, bool followSymLinks ){ + std::set ext(fileExtensions.begin(), fileExtensions.end()); + + std::set symlinkDirs; + std::set filePaths; + std::vector files; + for (const FilePath& path: paths) { if (path.isDirectory()) { - boost::filesystem::recursive_directory_iterator it(path.path()); + boost::filesystem::recursive_directory_iterator it(path.path(), boost::filesystem::symlink_option::recurse); boost::filesystem::recursive_directory_iterator endit; boost::system::error_code ec; for ( ; it != endit ; it.increment(ec) ) { - if (ec) + if (boost::filesystem::is_symlink(*it)) { - it.pop(); - continue; + if (!followSymLinks) + { + it.no_push(); + continue; + } + + // check for self-referencing symlinks + boost::filesystem::path p = boost::filesystem::read_symlink(*it); + if (p.filename() == p.string() && p.filename() == it->path().filename()) + { + continue; + } + + // check for duplicates when following directory symlinks + if (boost::filesystem::is_directory(*it)) + { + boost::filesystem::path absDir = boost::filesystem::canonical(p, it->path().parent_path()); + + if (symlinkDirs.find(absDir) != symlinkDirs.end()) + { + it.no_push(); + continue; + } + + symlinkDirs.insert(absDir); + } } + if (boost::filesystem::is_regular_file(*it) && - (!fileExtensions.size() || hasExtension(it->path().string(), fileExtensions))) + (!ext.size() || ext.find(it->path().extension().string()) != ext.end())) { + boost::filesystem::path p = boost::filesystem::canonical(it->path()); + if (filePaths.find(p) != filePaths.end()) + { + continue; + } + filePaths.insert(p); + std::time_t t = boost::filesystem::last_write_time(*it); boost::posix_time::ptime lastWriteTime = boost::posix_time::from_time_t(t); files.push_back(FileInfo(it->path(), lastWriteTime)); } } } - else if (path.exists() && (!fileExtensions.size() || path.hasExtension(fileExtensions))) + else if (path.exists() && (!ext.size() || ext.find(path.extension()) != ext.end())) { + boost::filesystem::path p = boost::filesystem::canonical(path.path()); + if (filePaths.find(p) != filePaths.end()) + { + continue; + } + filePaths.insert(p); + std::time_t t = boost::filesystem::last_write_time(path.path()); boost::posix_time::ptime lastWriteTime = boost::posix_time::from_time_t(t); files.push_back(FileInfo(path, lastWriteTime)); } } + return files; } @@ -204,20 +236,6 @@ std::string FileSystem::filePathWithoutExtension(const std::string& path) return boost::filesystem::path(path).replace_extension().generic_string(); } -bool FileSystem::hasExtension(const std::string& filepath, const std::vector& extensions) -{ - boost::filesystem::path path(filepath); - - for (std::string extension : extensions) - { - if (path.extension() == extension) - { - return true; - } - } - return false; -} - bool FileSystem::equivalent(const std::string& pathA, const std::string& pathB) { if (exists(pathA) && exists(pathB)) diff --git a/src/lib/utility/file/FileSystem.h b/src/lib/utility/file/FileSystem.h index 29bdf217..ecc6e78e 100644 --- a/src/lib/utility/file/FileSystem.h +++ b/src/lib/utility/file/FileSystem.h @@ -12,13 +12,11 @@ class FileSystem public: static std::vector getFileNamesFromDirectory( const std::string& path, const std::vector& extensions); - static std::vector getFileNamesFromDirectoryUpdatedAfter( - const std::string& path, const std::vector& extensions, const std::string& timeString); static FileInfo getFileInfoForPath(FilePath filePath); static std::vector getFileInfosFromPaths( - const std::vector& paths, const std::vector& fileExtensions); + const std::vector& paths, const std::vector& fileExtensions, bool followSymLinks = true); static TimePoint getLastWriteTime(const FilePath& filePath); static std::string getTimeStringNow(); @@ -38,7 +36,6 @@ public: static std::string extension(const std::string& path); static std::string filePathWithoutExtension(const std::string& path); - static bool hasExtension(const std::string& filepath, const std::vector& extensions); static bool equivalent(const std::string& pathA, const std::string& pathB); }; diff --git a/src/test/FileSystemTestSuite.h b/src/test/FileSystemTestSuite.h index d71bb023..85d16239 100644 --- a/src/test/FileSystemTestSuite.h +++ b/src/test/FileSystemTestSuite.h @@ -18,9 +18,11 @@ public: std::vector cppFiles = FileSystem::getFileNamesFromDirectory("data/FileSystemTestSuite", extensions); - TS_ASSERT_EQUALS(cppFiles.size(), 2); + TS_ASSERT_EQUALS(cppFiles.size(), 4); TS_ASSERT(isInVector(cppFiles, "data/FileSystemTestSuite/main.cpp")); TS_ASSERT(isInVector(cppFiles, "data/FileSystemTestSuite/Settings/sample.cpp")); + TS_ASSERT(isInVector(cppFiles, "data/FileSystemTestSuite/src/main.cpp")); + TS_ASSERT(isInVector(cppFiles, "data/FileSystemTestSuite/src/test.cpp")); } void test_find_h_files() @@ -31,9 +33,10 @@ public: std::vector headerFiles = FileSystem::getFileNamesFromDirectory("data/FileSystemTestSuite", extensions); - TS_ASSERT_EQUALS(headerFiles.size(), 2); + TS_ASSERT_EQUALS(headerFiles.size(), 3); TS_ASSERT(isInVector(headerFiles, "data/FileSystemTestSuite/tictactoe.h")); TS_ASSERT(isInVector(headerFiles, "data/FileSystemTestSuite/Settings/player.h")); + TS_ASSERT(isInVector(headerFiles, "data/FileSystemTestSuite/src/test.h")); } void test_find_all_source_files() @@ -46,29 +49,7 @@ public: std::vector sourceFiles = FileSystem::getFileNamesFromDirectory("data/FileSystemTestSuite", extensions); - TS_ASSERT_EQUALS(sourceFiles.size(), 5); - } - - void test_find_updated_source_files() - { - std::string timeString = FileSystem::getTimeStringNow(); - - std::fstream fileStream; - fileStream.open("./data/FileSystemTestSuite/update.c"); - fileStream << "update"; - fileStream.close(); - - std::vector extensions; - extensions.push_back(".h"); - extensions.push_back(".c"); - extensions.push_back(".hpp"); - extensions.push_back(".cpp"); - - std::vector sourceFiles = - FileSystem::getFileNamesFromDirectoryUpdatedAfter("data/FileSystemTestSuite", extensions, timeString); - - TS_ASSERT_EQUALS(sourceFiles.size(), 1); - TS_ASSERT_EQUALS(sourceFiles[0], "data/FileSystemTestSuite/update.c"); + TS_ASSERT_EQUALS(sourceFiles.size(), 8); } void test_find_file_infos() @@ -79,11 +60,33 @@ public: extensions.push_back(".cpp"); std::vector directoryPaths; - directoryPaths.push_back("./data/FileSystemTestSuite"); + directoryPaths.push_back("./data/FileSystemTestSuite/src"); - std::vector files = FileSystem::getFileInfosFromPaths(directoryPaths, extensions); + std::vector files = FileSystem::getFileInfosFromPaths(directoryPaths, extensions, false); + + TS_ASSERT_EQUALS(files.size(), 2); + TS_ASSERT(isInFileInfos(files, "./data/FileSystemTestSuite/src/test.cpp")); + TS_ASSERT(isInFileInfos(files, "./data/FileSystemTestSuite/src/test.h")); + } + + void test_find_file_infos_with_symlinks() + { + std::vector extensions; + extensions.push_back(".h"); + extensions.push_back(".hpp"); + extensions.push_back(".cpp"); + + std::vector directoryPaths; + directoryPaths.push_back("./data/FileSystemTestSuite/src"); + + std::vector files = FileSystem::getFileInfosFromPaths(directoryPaths, extensions, true); TS_ASSERT_EQUALS(files.size(), 5); + TS_ASSERT(isInFileInfos(files, "./data/FileSystemTestSuite/src/Settings/player.h")); + TS_ASSERT(isInFileInfos(files, "./data/FileSystemTestSuite/src/Settings/sample.cpp")); + TS_ASSERT(isInFileInfos(files, "./data/FileSystemTestSuite/src/main.cpp")); + TS_ASSERT(isInFileInfos(files, "./data/FileSystemTestSuite/src/Settings/src/test.cpp")); + TS_ASSERT(isInFileInfos(files, "./data/FileSystemTestSuite/src/Settings/src/test.h")); } void test_filesystem_finds_existing_files() @@ -121,4 +124,17 @@ private: { return std::end(files) != std::find(std::begin(files), std::end(files), filename); } + + bool isInFileInfos(const std::vector& infos, const std::string filename) + { + for (const FileInfo& info : infos) + { + if (info.path.str() == filename) + { + return true; + } + } + + return false; + } };