diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:58:10 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:58:10 +0200 |
commit | fefe20351d0720683990b666584b6879c90bd37d (patch) | |
tree | 8ab90520ae2123ac84293b0f9cec006317e5fc01 /comparison.cpp | |
parent | 1.18 (diff) | |
download | FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.gz FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.bz2 FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.zip |
1.19
Diffstat (limited to 'comparison.cpp')
-rw-r--r-- | comparison.cpp | 137 |
1 files changed, 102 insertions, 35 deletions
diff --git a/comparison.cpp b/comparison.cpp index 8a092935..253b3d81 100644 --- a/comparison.cpp +++ b/comparison.cpp @@ -10,6 +10,8 @@ #include <memory> #include "library/statusHandler.h" #include "library/fileHandling.h" +#include "synchronization.h" +#include "library/filter.h" #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -21,10 +23,11 @@ using namespace FreeFileSync; class GetAllFilesFull : public FullDetailFileTraverser { public: - GetAllFilesFull(DirectoryDescrType& output, const Zstring& dirThatIsSearched, StatusHandler* handler) : + GetAllFilesFull(DirectoryDescrType& output, const Zstring& dirThatIsSearched, const FilterProcess* filter, StatusHandler* handler) : m_output(output), directory(dirThatIsSearched), textScanning(Zstring(_("Scanning:")) + wxT(" \n")), + filterInstance(filter), statusHandler(handler) { prefixLength = directory.length(); @@ -41,6 +44,10 @@ public: wxDirTraverseResult OnFile(const Zstring& fullFileName, const FileInfo& details) //virtual impl. { + //apply filter before processing (use relative name!) + if (filterInstance && !filterInstance->matchesFileFilter(fullFileName.c_str() + prefixLength)) + return wxDIR_CONTINUE; + FileDescrLine fileDescr; fileDescr.fullName = fullFileName; fileDescr.relativeName = fullFileName.zsubstr(prefixLength); @@ -75,6 +82,10 @@ public: wxDirTraverseResult OnDir(const Zstring& fullDirName) //virtual impl. { + //apply filter before processing (use relative name!) + if (filterInstance && !filterInstance->matchesDirFilter(fullDirName.c_str() + prefixLength)) + return wxDIR_IGNORE; + #ifdef FFS_WIN if ( fullDirName.EndsWith(wxT("\\RECYCLER")) || fullDirName.EndsWith(wxT("\\System Volume Information"))) @@ -137,6 +148,7 @@ private: Zstring directory; int prefixLength; const Zstring textScanning; + const FilterProcess* const filterInstance; //may be NULL! StatusHandler* statusHandler; }; @@ -160,8 +172,9 @@ struct DescrBufferLine class DirectoryDescrBuffer //buffer multiple scans of the same directories { public: - DirectoryDescrBuffer(const bool traverseDirectorySymlinks, StatusHandler* statusUpdater) : + DirectoryDescrBuffer(const bool traverseDirectorySymlinks, const FilterProcess* filter, StatusHandler* statusUpdater) : m_traverseDirectorySymlinks(traverseDirectorySymlinks), + filterInstance(filter), m_statusUpdater(statusUpdater) {} ~DirectoryDescrBuffer() @@ -189,7 +202,7 @@ public: buffer.insert(bufferEntry); //exception safety: insert into buffer right after creation! //get all files and folders from directoryFormatted (and subdirectories) - GetAllFilesFull traverser(*bufferEntry.directoryDesc, directoryFormatted, m_statusUpdater); //exceptions may be thrown! + GetAllFilesFull traverser(*bufferEntry.directoryDesc, directoryFormatted, filterInstance, m_statusUpdater); //exceptions may be thrown! traverseInDetail(directoryFormatted, m_traverseDirectorySymlinks, &traverser); return bufferEntry.directoryDesc; @@ -200,6 +213,7 @@ private: std::set<DescrBufferLine> buffer; const bool m_traverseDirectorySymlinks; + const FilterProcess* const filterInstance; //may be NULL! StatusHandler* m_statusUpdater; }; @@ -276,16 +290,18 @@ bool foldersHaveDependencies(const std::vector<FolderPair>& folderPairs, wxStrin CompareProcess::CompareProcess(const bool traverseSymLinks, - const unsigned fileTimeTol, + const unsigned int fileTimeTol, + const bool ignoreOneHourDiff, bool& warningDependentFolders, + const FilterProcess* filter, //may be NULL StatusHandler* handler) : - traverseDirectorySymlinks(traverseSymLinks), fileTimeTolerance(fileTimeTol), + ignoreOneHourDifference(ignoreOneHourDiff), m_warningDependentFolders(warningDependentFolders), statusUpdater(handler), txtComparingContentOfFiles(Zstring(_("Comparing content of files %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)) { - descriptionBuffer = new DirectoryDescrBuffer(traverseSymLinks, handler); + descriptionBuffer = new DirectoryDescrBuffer(traverseSymLinks, filter, handler); } @@ -457,18 +473,9 @@ bool filesHaveSameContentUpdating(const Zstring& filename1, const Zstring& filen }*/ -inline -bool sameFileTime(const wxLongLong& a, const wxLongLong& b, const unsigned tolerance) -{ - if (a < b) - return b - a <= tolerance; - else - return a - b <= tolerance; -} - - void CompareProcess::startCompareProcess(const std::vector<FolderPair>& directoryPairs, const CompareVariant cmpVar, + const SyncConfiguration& config, FolderComparison& output) { #ifndef __WXDEBUG__ @@ -477,6 +484,9 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director //PERF_START; + //init process: keep at beginning so that all gui elements are initialized properly + statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects + //format directory pairs: ensure they end with GlobalResources::FILE_NAME_SEPARATOR! std::vector<FolderPair> directoryPairsFormatted; for (std::vector<FolderPair>::const_iterator i = directoryPairs.begin(); i != directoryPairs.end(); ++i) @@ -484,7 +494,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director FolderPair(FreeFileSync::getFormattedDirectoryName(i->leftDirectory), FreeFileSync::getFormattedDirectoryName(i->rightDirectory))); - //some basic checks: + //-------------------some basic checks:------------------------------------------ //check if folders are valid wxString errorMessage; @@ -507,6 +517,9 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director } } + //-------------------end of basic checks------------------------------------------ + + try { FolderComparison output_tmp; //write to output not before END of process! @@ -520,7 +533,11 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director break; } - //only if everything was processed correctly output is written to! output mustn't change to be in sync with GUI grid view!!! + //actually this is the initial determination + FreeFileSync::redetermineSyncDirection(config, output_tmp); + + //only if everything was processed correctly output is written to! + //note: output mustn't change during this process to be in sync with GUI grid view!!! output_tmp.swap(output); } catch (const RuntimeException& theException) @@ -536,11 +553,21 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director } -void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryPairsFormatted, FolderComparison& output) +const CompareFilesResult FILE_UNDEFINED = CompareFilesResult(42); + + +inline +bool sameFileTime(const wxLongLong& a, const wxLongLong& b, const unsigned tolerance) { - //inform about the total amount of data that will be processed from now on - statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects + if (a < b) + return b - a <= tolerance; + else + return a - b <= tolerance; +} + +void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryPairsFormatted, FolderComparison& output) +{ //process one folder pair after each other for (std::vector<FolderPair>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair) { @@ -557,20 +584,63 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryP for (FileComparison::iterator i = fileCmp.begin(); i != fileCmp.end(); ++i) if (i->cmpResult == FILE_UNDEFINED) { - //last write time may differ by up to 2 seconds (NTFS vs FAT32) - if (sameFileTime(i->fileDescrLeft.lastWriteTimeRaw, i->fileDescrRight.lastWriteTimeRaw, fileTimeTolerance)) + if (i->fileDescrLeft.lastWriteTimeRaw != i->fileDescrRight.lastWriteTimeRaw) { - if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize) - i->cmpResult = FILE_EQUAL; - else - i->cmpResult = FILE_DIFFERENT; + //number of seconds since Jan 1st 1970 + 1 year (needn't be too precise) + static const long oneYearFromNow = wxGetUTCTime() + 365 * 24 * 3600; + + //check for erroneous dates (but only if dates are not (EXACTLY) the same) + if ( i->fileDescrLeft.lastWriteTimeRaw < 0 || //earlier than Jan 1st 1970 + i->fileDescrRight.lastWriteTimeRaw < 0 || //earlier than Jan 1st 1970 + i->fileDescrLeft.lastWriteTimeRaw > oneYearFromNow || //dated more than one year in future + i->fileDescrRight.lastWriteTimeRaw > oneYearFromNow) //dated more than one year in future + { + i->cmpResult = FILE_CONFLICT; + } + else //from this block on all dates are at least "valid" + { + //last write time may differ by up to 2 seconds (NTFS vs FAT32) + if (sameFileTime(i->fileDescrLeft.lastWriteTimeRaw, i->fileDescrRight.lastWriteTimeRaw, fileTimeTolerance)) + { + if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize) + i->cmpResult = FILE_EQUAL; + else + i->cmpResult = FILE_CONFLICT; //same date, different filesize + } + else + { + //finally: DST +/- 1-hour check: test if time diff is exactly +/- 1-hour (respecting 2 second FAT precision) + if (ignoreOneHourDifference && sameFileTime(i->fileDescrLeft.lastWriteTimeRaw, i->fileDescrRight.lastWriteTimeRaw, 3600 + 2)) + { + //date diff < 1 hour is a conflict: it's not safe to determine which file is newer + if (sameFileTime(i->fileDescrLeft.lastWriteTimeRaw, i->fileDescrRight.lastWriteTimeRaw, 3600 - 2 - 1)) + { + i->cmpResult = FILE_CONFLICT; + } + else //exact +/- 1-hour detected: treat as equal + { + if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize) + i->cmpResult = FILE_EQUAL; + else + i->cmpResult = FILE_CONFLICT; //same date, different filesize + } + } + else + { + if (i->fileDescrLeft.lastWriteTimeRaw < i->fileDescrRight.lastWriteTimeRaw) + i->cmpResult = FILE_RIGHT_NEWER; + else + i->cmpResult = FILE_LEFT_NEWER; + } + } + } } - else + else //same write time { - if (i->fileDescrLeft.lastWriteTimeRaw < i->fileDescrRight.lastWriteTimeRaw) - i->cmpResult = FILE_RIGHT_NEWER; + if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize) + i->cmpResult = FILE_EQUAL; else - i->cmpResult = FILE_LEFT_NEWER; + i->cmpResult = FILE_CONFLICT; //same date, different filesize } } } @@ -625,9 +695,6 @@ void CompareProcess::compareByContent(const std::vector<FolderPair>& directoryPa { //PERF_START; - //inform about the total amount of data that will be processed from now on - statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects - //process one folder pair after each other for (std::vector<FolderPair>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair) { @@ -800,7 +867,7 @@ void CompareProcess::performBaseComparison(const FolderPair& pair, FileCompariso output.reserve(output.size() + unsigned(std::max(directoryLeft->size(), directoryRight->size()) * 1.2)); //begin base comparison - FileCompareLine newline; + FileCompareLine newline(FILE_UNDEFINED, SYNC_DIR_NONE, true); DirectoryDescrType::iterator j; for (DirectoryDescrType::const_iterator i = directoryLeft->begin(); i != directoryLeft->end(); ++i) { //find files/folders that exist in left file tree but not in right one |