Index: src/ch/TSubTaskScanDirectory.cpp =================================================================== diff -u -N -rb7709acbab26fdb108b77d3e08d3872f54248af2 -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4 --- src/ch/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision b7709acbab26fdb108b77d3e08d3872f54248af2) +++ src/ch/TSubTaskScanDirectory.cpp (.../TSubTaskScanDirectory.cpp) (revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4) @@ -22,4 +22,249 @@ // ============================================================================ #include "stdafx.h" #include "TSubTaskScanDirectory.h" +#include "TSubTaskContext.h" +#include "TTaskConfiguration.h" +#include "TTaskDefinition.h" +#include "FeedbackHandler.h" +#include "TLocalFilesystem.h" +#include "..\libchcore\FeedbackHandlerBase.h" +#include "TBasePathData.h" +#include "TWorkerThreadController.h" +#include "TTaskLocalStats.h" +TSubTaskScanDirectories::TSubTaskScanDirectories(TSubTaskContext& rContext) : + TSubTaskBase(rContext) +{ +} + +TSubTaskScanDirectories::~TSubTaskScanDirectories() +{ +} + +TSubTaskScanDirectories::ESubOperationResult TSubTaskScanDirectories::Exec() +{ + // log + icpf::log_file& rLog = GetContext().GetLog(); + CFileInfoArray& rFilesCache = GetContext().GetFilesCache(); + TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); + chcore::IFeedbackHandler* piFeedbackHandler = GetContext().GetFeedbackHandler(); + const TBasePathDataContainer& rarrSourcePathsInfo = GetContext().GetTaskDefinition().GetSourcePaths(); + TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + + rLog.logi(_T("Searching for files...")); + + // delete the content of rFilesCache + rFilesCache.Clear(); + + // read filtering options + CFiltersArray afFilters; + GetTaskPropValue(rTaskDefinition.GetConfiguration(), afFilters); + + // enter some data to rFilesCache + int iDestDrvNumber = 0; + TLocalFilesystem::GetDriveData(rTaskDefinition.GetDestinationPath(), &iDestDrvNumber, NULL); + + bool bIgnoreDirs = GetTaskPropValue(rTaskDefinition.GetConfiguration()); + bool bForceDirectories = GetTaskPropValue(rTaskDefinition.GetConfiguration()); + bool bMove = rTaskDefinition.GetOperationType() == eOperation_Move; + + // add everything + ictranslate::CFormat fmt; + bool bRetry = true; + bool bSkipInputPath = false; + + size_t stSize = rTaskDefinition.GetSourcePathCount(); + for(size_t stIndex = 0; stIndex < stSize ; stIndex++) + { + CFileInfoPtr spFileInfo; + + bSkipInputPath = false; + + spFileInfo.reset(new CFileInfo()); + spFileInfo->SetClipboard(&rTaskDefinition.GetSourcePaths()); + + // try to get some info about the input path; let user know if the path does not exist. + do + { + bRetry = false; + + // read attributes of src file/folder + bool bExists = spFileInfo->Create(rTaskDefinition.GetSourcePathAt(stIndex), stIndex); + if(!bExists) + { + FEEDBACK_FILEERROR ferr = { rTaskDefinition.GetSourcePathAt(stIndex).ToString(), NULL, eFastMoveError, ERROR_FILE_NOT_FOUND }; + CFeedbackHandler::EFeedbackResult frResult = (CFeedbackHandler::EFeedbackResult)piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_FileError, &ferr); + switch(frResult) + { + case CFeedbackHandler::eResult_Cancel: + rFilesCache.Clear(); + return eSubResult_CancelRequest; + + case CFeedbackHandler::eResult_Retry: + bRetry = true; + break; + + case CFeedbackHandler::eResult_Pause: + rFilesCache.Clear(); + return eSubResult_PauseRequest; + + case CFeedbackHandler::eResult_Skip: + bSkipInputPath = true; + break; // just do nothing + + default: + BOOST_ASSERT(FALSE); // unknown result + THROW(_T("Unhandled case"), 0, 0, 0); + } + } + } + while(bRetry); + + // if we have chosen to skip the input path then there's nothing to do + if(bSkipInputPath) + continue; + + // log + fmt.SetFormat(_T("Adding file/folder (clipboard) : %path ...")); + fmt.SetParam(_t("%path"), rTaskDefinition.GetSourcePathAt(stIndex).ToString()); + rLog.logi(fmt); + + // found file/folder - check if the dest name has been generated + if(!rarrSourcePathsInfo.GetAt(stIndex)->IsDestinationPathSet()) + { + // generate something - if dest folder == src folder - search for copy + if(rTaskDefinition.GetDestinationPath() == spFileInfo->GetFullFilePath().GetFileRoot()) + { + chcore::TSmartPath pathSubst = FindFreeSubstituteName(spFileInfo->GetFullFilePath(), rTaskDefinition.GetDestinationPath()); + rarrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(pathSubst); + } + else + rarrSourcePathsInfo.GetAt(stIndex)->SetDestinationPath(spFileInfo->GetFullFilePath().GetFileName()); + } + + // add if needed + if(spFileInfo->IsDirectory()) + { + // add if folder's aren't ignored + if(!bIgnoreDirs && !bForceDirectories) + { + // add directory info; it is not to be filtered with afFilters + rFilesCache.AddFileInfo(spFileInfo); + + // log + fmt.SetFormat(_T("Added folder %path")); + fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString()); + rLog.logi(fmt); + } + + // don't add folder contents when moving inside one disk boundary + if(bIgnoreDirs || !bMove || iDestDrvNumber == -1 || iDestDrvNumber != GetDriveNumber(spFileInfo) || + TLocalFilesystem::PathExist(CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) ) + { + // log + fmt.SetFormat(_T("Recursing folder %path")); + fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString()); + rLog.logi(fmt); + + // no movefile possibility - use CustomCopyFileFB + rarrSourcePathsInfo.GetAt(stIndex)->SetMove(false); + + ScanDirectory(spFileInfo->GetFullFilePath(), stIndex, true, !bIgnoreDirs || bForceDirectories, afFilters); + } + + // check for kill need + if(rThreadController.KillRequested()) + { + // log + rLog.logi(_T("Kill request while adding data to files array (RecurseDirectories)")); + rFilesCache.Clear(); + return eSubResult_KillRequest; + } + } + else + { + if(bMove && iDestDrvNumber != -1 && iDestDrvNumber == GetDriveNumber(spFileInfo) && + !TLocalFilesystem::PathExist(CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1)) ) + { + // if moving within one partition boundary set the file size to 0 so the overall size will + // be ok + spFileInfo->SetLength64(0); + } + else + rarrSourcePathsInfo.GetAt(stIndex)->SetMove(false); // no MoveFile + + // add file info if passes filters + if(afFilters.Match(spFileInfo)) + rFilesCache.AddFileInfo(spFileInfo); + + // log + fmt.SetFormat(_T("Added file %path")); + fmt.SetParam(_t("%path"), spFileInfo->GetFullFilePath().ToString()); + rLog.logi(fmt); + } + } + + // calc size of all files + GetContext().GetTaskLocalStats().SetTotalSize(rFilesCache.CalculateTotalSize()); + + // log + rLog.logi(_T("Searching for files finished")); + + return eSubResult_Continue; +} + +int TSubTaskScanDirectories::ScanDirectory(chcore::TSmartPath pathDirName, size_t stSrcIndex, bool bRecurse, bool bIncludeDirs, CFiltersArray& afFilters) +{ + CFileInfoArray& rFilesCache = GetContext().GetFilesCache(); + TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); + TWorkerThreadController& rThreadController = GetContext().GetThreadController(); + + WIN32_FIND_DATA wfd; + chcore::TSmartPath pathCurrent; + + pathCurrent = pathDirName + chcore::PathFromString(_T("*")); + + // Iterate through dirs & files + HANDLE hFind = FindFirstFile(pathCurrent.ToString(), &wfd); + if(hFind != INVALID_HANDLE_VALUE) + { + do + { + if(!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + CFileInfoPtr spFileInfo(boost::make_shared()); + spFileInfo->SetClipboard(&rTaskDefinition.GetSourcePaths()); // this is the link table (CClipboardArray) + + spFileInfo->Create(&wfd, pathDirName, stSrcIndex); + if(afFilters.Match(spFileInfo)) + rFilesCache.AddFileInfo(spFileInfo); + } + else if(wfd.cFileName[0] != _T('.') || (wfd.cFileName[1] != _T('\0') && (wfd.cFileName[1] != _T('.') || wfd.cFileName[2] != _T('\0')))) + { + if(bIncludeDirs) + { + CFileInfoPtr spFileInfo(boost::make_shared()); + spFileInfo->SetClipboard(&rTaskDefinition.GetSourcePaths()); // this is the link table (CClipboardArray) + + // Add directory itself + spFileInfo->Create(&wfd, pathDirName, stSrcIndex); + rFilesCache.AddFileInfo(spFileInfo); + } + if(bRecurse) + { + pathCurrent = pathDirName + chcore::PathFromString(wfd.cFileName) + chcore::PathFromString(_T("\\")); + // Recurse Dirs + ScanDirectory(pathCurrent, stSrcIndex, bRecurse, bIncludeDirs, afFilters); + } + } + + if(rThreadController.KillRequested()) + break; + } + while(FindNextFile(hFind, &wfd)); + + FindClose(hFind); + } + + return 0; +}