summaryrefslogtreecommitdiff
path: root/comparison.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 16:58:10 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 16:58:10 +0200
commitfefe20351d0720683990b666584b6879c90bd37d (patch)
tree8ab90520ae2123ac84293b0f9cec006317e5fc01 /comparison.cpp
parent1.18 (diff)
downloadFreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.gz
FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.bz2
FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.zip
1.19
Diffstat (limited to 'comparison.cpp')
-rw-r--r--comparison.cpp137
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
bgstack15