Index: src/libchengine/TSubTaskScanDirectory.cpp =================================================================== diff -u -N -r85b07e753393f661f7d8f528e4238ebb6e9e1204 -re8897f4f07ba4523376c2d6599d87428424a4772 --- src/libchengine/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision 85b07e753393f661f7d8f528e4238ebb6e9e1204) +++ src/libchengine/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision e8897f4f07ba4523376c2d6599d87428424a4772) @@ -31,9 +31,9 @@ #include "TFileInfoArray.h" #include "TFileInfo.h" #include "TScopedRunningTimeTracker.h" -#include "TFeedbackHandlerWrapper.h" #include "TBufferSizes.h" #include "TFilesystemFeedbackWrapper.h" +#include using namespace chcore; using namespace string; @@ -78,11 +78,19 @@ m_tSubTaskStats.SetCurrentPath(TString()); } - TSubTaskScanDirectories::ESubOperationResult TSubTaskScanDirectories::Exec(const IFeedbackHandlerPtr& spFeedback) + TSubTaskScanDirectories::ESubOperationResult TSubTaskScanDirectories::Exec() { TScopedRunningTimeTracker guard(m_tSubTaskStats); - TFeedbackHandlerWrapperPtr spFeedbackHandler(std::make_shared(spFeedback, guard)); + FeedbackManagerPtr spFeedbackManager = GetContext().GetFeedbackManager(); + spFeedbackManager->SetSecondaryTimeTracker(&guard); +#pragma warning(push) +#pragma warning(disable: 4459) + BOOST_SCOPE_EXIT(&spFeedbackManager) { + spFeedbackManager->SetSecondaryTimeTracker(nullptr); + } BOOST_SCOPE_EXIT_END +#pragma warning(pop) + // log TFileInfoArray& rFilesCache = GetContext().GetFilesCache(); TWorkerThreadController& rThreadController = GetContext().GetThreadController(); @@ -91,7 +99,7 @@ const TFileFiltersArray& rafFilters = GetContext().GetFilters(); IFilesystemPtr spFilesystem = GetContext().GetLocalFilesystem(); - TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackHandler, spFilesystem, GetContext().GetLogFileData(), rThreadController); + TFilesystemFeedbackWrapper tFilesystemFBWrapper(spFeedbackManager, spFilesystem, GetContext().GetLogFileData(), rThreadController); LOG_INFO(m_spLog) << _T("Searching for files..."); @@ -111,6 +119,7 @@ bool bIgnoreDirs = GetTaskPropValue(rConfig); bool bForceDirectories = GetTaskPropValue(rConfig); + bool bExcludeEmptyDirectories = GetTaskPropValue(rConfig); // add everything TString strFormat; @@ -168,7 +177,7 @@ strFormat.Replace(_T("%path"), spFileInfo->GetFullFilePath().ToString()); LOG_INFO(m_spLog) << strFormat.c_str(); - ScanDirectory(spFileInfo->GetFullFilePath(), spBasePath, true, !bIgnoreDirs || bForceDirectories, rafFilters); + ScanDirectory(spFileInfo->GetFullFilePath(), spBasePath, !bIgnoreDirs || bForceDirectories, rafFilters, bExcludeEmptyDirectories); // check for kill need if (rThreadController.KillRequested()) @@ -210,48 +219,59 @@ m_tSubTaskStats.GetSnapshot(spStats); } - int TSubTaskScanDirectories::ScanDirectory(TSmartPath pathDirName, const TBasePathDataPtr& spBasePathData, - bool bRecurse, bool bIncludeDirs, const TFileFiltersArray& afFilters) + size_t TSubTaskScanDirectories::ScanDirectory(TSmartPath pathDirName, const TBasePathDataPtr& spBasePathData, + bool bIncludeDirs, const TFileFiltersArray& afFilters, bool bExcludeEmptyDirs) { TFileInfoArray& rFilesCache = GetContext().GetFilesCache(); TWorkerThreadController& rThreadController = GetContext().GetThreadController(); TBasePathDataContainerPtr spBasePaths = GetContext().GetBasePaths(); const IFilesystemPtr& spFilesystem = GetContext().GetLocalFilesystem(); + m_tSubTaskStats.SetCurrentPath(pathDirName.ToString()); + IFilesystemFindPtr spFinder = spFilesystem->CreateFinderObject(pathDirName, PathFromString(_T("*"))); TFileInfoPtr spFileInfo(std::make_shared()); + size_t stFilesCount = 0; while (spFinder->FindNext(spFileInfo)) { if (rThreadController.KillRequested()) break; - if (!spFileInfo->IsDirectory()) + if (spFileInfo->IsDirectory()) { - if (afFilters.Match(spFileInfo)) + TSmartPath pathCurrent = spFileInfo->GetFullFilePath(); + if(bIncludeDirs) { spFileInfo->SetParentObject(spBasePathData); rFilesCache.Add(spFileInfo); spFileInfo = std::make_shared(); } + + size_t stInnerFilesCount = ScanDirectory(pathCurrent, spBasePathData, bIncludeDirs, afFilters, bExcludeEmptyDirs); + if(bExcludeEmptyDirs && stInnerFilesCount == 0) + { + // if we want to exclude empty directories, now's a good time to get rid of freshly added directory + rFilesCache.RemoveLast(); + } + stFilesCount += stInnerFilesCount; } else { - TSmartPath pathCurrent = spFileInfo->GetFullFilePath(); - if (bIncludeDirs) + if (afFilters.Match(spFileInfo)) { spFileInfo->SetParentObject(spBasePathData); rFilesCache.Add(spFileInfo); spFileInfo = std::make_shared(); - } - if (bRecurse) - ScanDirectory(pathCurrent, spBasePathData, bRecurse, bIncludeDirs, afFilters); + ++stFilesCount; + } } } - return 0; + return stFilesCount; } + void TSubTaskScanDirectories::Store(const ISerializerPtr& spSerializer) const { ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtask_scan"));