summaryrefslogtreecommitdiff
path: root/synchronization.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'synchronization.cpp')
-rw-r--r--synchronization.cpp662
1 files changed, 279 insertions, 383 deletions
diff --git a/synchronization.cpp b/synchronization.cpp
index 43bf22a6..0c49c3a1 100644
--- a/synchronization.cpp
+++ b/synchronization.cpp
@@ -9,10 +9,6 @@
#include "library/fileHandling.h"
#include <utility>
-#ifdef FFS_WIN
-#include <wx/msw/wrapwin.h> //includes "windows.h"
-#endif
-
using namespace FreeFileSync;
@@ -31,79 +27,43 @@ bool getBytesToTransfer(const FileCompareLine& fileCmpLine,
conflicts = 0;
dataToProcess = 0;
- //do not add filtered entries
- if (!fileCmpLine.selectedForSynchronization)
- return false;
+ switch (FreeFileSync::getSyncOperation(fileCmpLine.cmpResult, fileCmpLine.selectedForSynchronization, fileCmpLine.direction)) //evaluate comparison result and sync direction
+ {
+ case SO_CREATE_NEW_LEFT:
+ dataToProcess = fileCmpLine.fileDescrRight.fileSize;
+ objectsToCreate = 1;
+ return true;
+ case SO_CREATE_NEW_RIGHT:
+ dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
+ objectsToCreate = 1;
+ return true;
- switch (fileCmpLine.cmpResult)
- {
- case FILE_LEFT_SIDE_ONLY:
- //get data to process
- switch (fileCmpLine.direction)
- {
- case SYNC_DIR_LEFT: //delete file on left
- dataToProcess = 0;
- objectsToDelete = 1;
- return true;
- case SYNC_DIR_RIGHT: //copy from left to right
- dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
- objectsToCreate = 1;
- return true;
- case SYNC_UNRESOLVED_CONFLICT:
- assert(false); //conflicts have files on both sides
- conflicts = 1;
- return true;
- case SYNC_DIR_NONE:
- return false;
- }
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ dataToProcess = 0;
+ objectsToDelete = 1;
+ return true;
- case FILE_RIGHT_SIDE_ONLY:
- switch (fileCmpLine.direction)
- {
- case SYNC_DIR_LEFT: //copy from right to left
- dataToProcess = fileCmpLine.fileDescrRight.fileSize;
- objectsToCreate = 1;
- return true;
- case SYNC_DIR_RIGHT: //delete file on right
- dataToProcess = 0;
- objectsToDelete = 1;
- return true;
- case SYNC_UNRESOLVED_CONFLICT:
- assert(false); //conflicts have files on both sides
- conflicts = 1;
- return true;
- case SYNC_DIR_NONE:
- return false;
- }
+ case SO_OVERWRITE_RIGHT:
+ dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
+ objectsToOverwrite = 1;
+ return true;
- case FILE_LEFT_NEWER:
- case FILE_RIGHT_NEWER:
- case FILE_DIFFERENT:
- case FILE_CONFLICT:
- //get data to process
- switch (fileCmpLine.direction)
- {
- case SYNC_DIR_LEFT: //copy from right to left
- dataToProcess = fileCmpLine.fileDescrRight.fileSize;
- objectsToOverwrite = 1;
- return true;
- case SYNC_DIR_RIGHT: //copy from left to right
- dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
- objectsToOverwrite = 1;
- return true;
- case SYNC_UNRESOLVED_CONFLICT:
- conflicts = 1;
- return true;
- case SYNC_DIR_NONE:
- return false;
- }
+ case SO_OVERWRITE_LEFT:
+ dataToProcess = fileCmpLine.fileDescrRight.fileSize;
+ objectsToOverwrite = 1;
+ return true;
- case FILE_EQUAL:
+ case SO_DO_NOTHING:
return false;
- };
- return true; //dummy
+ case SO_UNRESOLVED_CONFLICT:
+ conflicts = 1;
+ return true;
+ }
+
+ return false; //dummy
}
@@ -253,50 +213,6 @@ bool FreeFileSync::synchronizationNeeded(const FolderComparison& folderCmp)
}
-void FreeFileSync::redetermineSyncDirection(const SyncConfiguration& config, FolderComparison& folderCmp)
-{
- //do not handle i->selectedForSynchronization in this method! handled in synchronizeFile(), synchronizeFolder()!
-
-
- for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j)
- {
- FileComparison& fileCmp = j->fileCmp;
- for (FileComparison::iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
- {
- switch (i->cmpResult)
- {
- case FILE_LEFT_SIDE_ONLY:
- i->direction = config.exLeftSideOnly;
- break;
-
- case FILE_RIGHT_SIDE_ONLY:
- i->direction = config.exRightSideOnly;
- break;
-
- case FILE_RIGHT_NEWER:
- i->direction = config.rightNewer;
- break;
-
- case FILE_LEFT_NEWER:
- i->direction = config.leftNewer;
- break;
-
- case FILE_DIFFERENT:
- i->direction = config.different;
- break;
-
- case FILE_CONFLICT:
- i->direction = SYNC_UNRESOLVED_CONFLICT;
- break;
-
- case FILE_EQUAL:
- i->direction = SYNC_DIR_NONE;
- }
- }
- }
-}
-
-
//test if more then 50% of files will be deleted/overwritten
bool significantDifferenceDetected(const FileComparison& fileCmp)
{
@@ -319,119 +235,188 @@ bool significantDifferenceDetected(const FileComparison& fileCmp)
}
-SyncProcess::SyncProcess(const bool useRecycler,
- const bool copyFileSymLinks,
- const bool traverseDirSymLinks,
- bool& warningSignificantDifference,
- bool& warningNotEnoughDiskSpace,
- bool& warningUnresolvedConflict,
- StatusHandler* handler) :
- m_useRecycleBin(useRecycler),
- m_copyFileSymLinks(copyFileSymLinks),
- m_traverseDirSymLinks(traverseDirSymLinks),
- m_warningSignificantDifference(warningSignificantDifference),
- m_warningNotEnoughDiskSpace(warningNotEnoughDiskSpace),
- m_warningUnresolvedConflict(warningUnresolvedConflict),
- statusUpdater(handler),
- txtCopyingFile(Zstring(_("Copying file %x to %y")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
- txtOverwritingFile(Zstring(_("Copying file %x to %y overwriting target")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
- txtCreatingFolder(Zstring(_("Creating folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)),
- txtDeletingFile(Zstring(_("Deleting file %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)),
- txtDeletingFolder(Zstring(_("Deleting folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)) {}
-
-
-inline
-bool SyncProcess::synchronizeFile(const FileCompareLine& cmpLine, const FolderPair& folderPair)
-{ //return false if nothing had to be done
-
- if (!cmpLine.selectedForSynchronization) return false;
-
- Zstring statusText;
- Zstring target;
+SyncOperation FreeFileSync::getSyncOperation( //evaluate comparison result and sync direction
+ const CompareFilesResult cmpResult,
+ const bool selectedForSynchronization,
+ const SyncDirection syncDir)
+{
+ if (!selectedForSynchronization) return SO_DO_NOTHING;
- //synchronize file:
- switch (cmpLine.cmpResult)
+ switch (cmpResult)
{
case FILE_LEFT_SIDE_ONLY:
- switch (cmpLine.direction)
+ switch (syncDir)
{
- case SYNC_DIR_LEFT: //delete files on left
- statusText = txtDeletingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
- return true;
- case SYNC_DIR_RIGHT: //copy files to right
- target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
-
- statusText = txtCopyingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- copyFileUpdating(cmpLine.fileDescrLeft.fullName, target, cmpLine.fileDescrLeft.fileSize);
- return true;
+ case SYNC_DIR_LEFT:
+ return SO_DELETE_LEFT; //delete files on left
+ case SYNC_DIR_RIGHT:
+ return SO_CREATE_NEW_RIGHT; //copy files to right
case SYNC_DIR_NONE:
+ return SO_DO_NOTHING;
case SYNC_UNRESOLVED_CONFLICT:
- return false;
+ assert(false);
}
+ break;
case FILE_RIGHT_SIDE_ONLY:
- switch (cmpLine.direction)
+ switch (syncDir)
{
- case SYNC_DIR_LEFT: //copy files to left
- target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
-
- statusText = txtCopyingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- copyFileUpdating(cmpLine.fileDescrRight.fullName, target, cmpLine.fileDescrRight.fileSize);
- return true;
- case SYNC_DIR_RIGHT: //delete files on right
- statusText = txtDeletingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
- return true;
+ case SYNC_DIR_LEFT:
+ return SO_CREATE_NEW_LEFT; //copy files to left
+ case SYNC_DIR_RIGHT:
+ return SO_DELETE_RIGHT; //delete files on right
case SYNC_DIR_NONE:
+ return SO_DO_NOTHING;
case SYNC_UNRESOLVED_CONFLICT:
- return false;
+ assert(false);
}
+ break;
case FILE_LEFT_NEWER:
case FILE_RIGHT_NEWER:
case FILE_DIFFERENT:
case FILE_CONFLICT:
- switch (cmpLine.direction)
+ switch (syncDir)
{
- case SYNC_DIR_LEFT: //copy from right to left
- statusText = txtOverwritingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), cmpLine.fileDescrLeft.fullName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
- copyFileUpdating(cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fileSize);
- return true;
- case SYNC_DIR_RIGHT: //copy from left to right
- statusText = txtOverwritingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), cmpLine.fileDescrRight.fullName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
- copyFileUpdating(cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fileSize);
- return true;
+ case SYNC_DIR_LEFT:
+ return SO_OVERWRITE_LEFT; //copy from right to left
+ case SYNC_DIR_RIGHT:
+ return SO_OVERWRITE_RIGHT; //copy from left to right
case SYNC_DIR_NONE:
+ return SO_DO_NOTHING;
case SYNC_UNRESOLVED_CONFLICT:
- return false;
+ return SO_UNRESOLVED_CONFLICT;
}
+ break;
case FILE_EQUAL:
+ assert(syncDir == SYNC_DIR_NONE);
+ return SO_DO_NOTHING;
+ }
+
+ return SO_DO_NOTHING; //dummy
+}
+
+
+const wxBitmap& FreeFileSync::getSyncOpImage(const CompareFilesResult cmpResult,
+ const bool selectedForSynchronization,
+ const SyncDirection syncDir)
+{
+ switch (getSyncOperation(cmpResult, selectedForSynchronization, syncDir)) //evaluate comparison result and sync direction
+ {
+ case SO_CREATE_NEW_LEFT:
+ return *GlobalResources::getInstance().bitmapCreateLeftSmall;
+ case SO_CREATE_NEW_RIGHT:
+ return *GlobalResources::getInstance().bitmapCreateRightSmall;
+ case SO_DELETE_LEFT:
+ return *GlobalResources::getInstance().bitmapDeleteLeftSmall;
+ case SO_DELETE_RIGHT:
+ return *GlobalResources::getInstance().bitmapDeleteRightSmall;
+ case SO_OVERWRITE_RIGHT:
+ return *GlobalResources::getInstance().bitmapSyncDirRightSmall;
+ case SO_OVERWRITE_LEFT:
+ return *GlobalResources::getInstance().bitmapSyncDirLeftSmall;
+ case SO_DO_NOTHING:
+ return *GlobalResources::getInstance().bitmapSyncDirNoneSmall;
+ case SO_UNRESOLVED_CONFLICT:
+ return *GlobalResources::getInstance().bitmapConflictSmall;
+ }
+
+ return wxNullBitmap; //dummy
+}
+
+
+SyncProcess::SyncProcess(const bool useRecycler,
+ const bool copyFileSymLinks,
+ const bool traverseDirSymLinks,
+ xmlAccess::WarningMessages& warnings,
+ StatusHandler* handler) :
+ m_useRecycleBin(useRecycler),
+ m_copyFileSymLinks(copyFileSymLinks),
+ m_traverseDirSymLinks(traverseDirSymLinks),
+ m_warnings(warnings),
+#ifdef FFS_WIN
+ shadowCopyHandler(new ShadowCopy),
+#endif
+ statusUpdater(handler),
+ txtCopyingFile(Zstring(_("Copying file %x to %y")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
+ txtOverwritingFile(Zstring(_("Copying file %x to %y overwriting target")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
+ txtCreatingFolder(Zstring(_("Creating folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)),
+ txtDeletingFile(useRecycler ? Zstring(_("Moving %x to Recycle Bin")).Replace(wxT("%x"), wxT("\"%x\""), false) :
+ Zstring(_("Deleting file %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)),
+ txtDeletingFolder(useRecycler ? Zstring(_("Moving %x to Recycle Bin")).Replace( wxT("%x"), wxT("\"%x\""), false) :
+ Zstring(_("Deleting folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)) {}
+
+
+inline
+bool SyncProcess::synchronizeFile(const FileCompareLine& cmpLine, const FolderPair& folderPair)
+{ //return false if nothing had to be done
+
+ Zstring statusText;
+ Zstring target;
+
+ switch (getSyncOperation(cmpLine.cmpResult, cmpLine.selectedForSynchronization, cmpLine.direction)) //evaluate comparison result and sync direction
+ {
+ case SO_CREATE_NEW_LEFT:
+ target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
+
+ statusText = txtCopyingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ copyFileUpdating(cmpLine.fileDescrRight.fullName, target, cmpLine.fileDescrRight.fileSize);
+ return true;
+
+ case SO_CREATE_NEW_RIGHT:
+ target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
+
+ statusText = txtCopyingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ copyFileUpdating(cmpLine.fileDescrLeft.fullName, target, cmpLine.fileDescrLeft.fileSize);
+ return true;
+
+ case SO_DELETE_LEFT:
+ statusText = txtDeletingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_DELETE_RIGHT:
+ statusText = txtDeletingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_OVERWRITE_RIGHT:
+ statusText = txtOverwritingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), cmpLine.fileDescrRight.fullName.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
+ copyFileUpdating(cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fileSize);
+ return true;
+
+ case SO_OVERWRITE_LEFT:
+ statusText = txtOverwritingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), cmpLine.fileDescrLeft.fullName.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
+ copyFileUpdating(cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fileSize);
+ return true;
+
+ case SO_DO_NOTHING:
+ case SO_UNRESOLVED_CONFLICT:
return false;
}
@@ -443,76 +428,59 @@ inline
bool SyncProcess::synchronizeFolder(const FileCompareLine& cmpLine, const FolderPair& folderPair)
{ //return false if nothing had to be done
- if (!cmpLine.selectedForSynchronization) return false;
-
Zstring statusText;
Zstring target;
//synchronize folders:
- switch (cmpLine.cmpResult)
+ switch (getSyncOperation(cmpLine.cmpResult, cmpLine.selectedForSynchronization, cmpLine.direction)) //evaluate comparison result and sync direction
{
- case FILE_LEFT_SIDE_ONLY:
- switch (cmpLine.direction)
- {
- case SYNC_DIR_LEFT: //delete folders on left
- statusText = txtDeletingFolder;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeDirectory(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
- return true;
- case SYNC_DIR_RIGHT: //create folders on right
- target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
-
- statusText = txtCreatingFolder;
- statusText.Replace(wxT("%x"), target, false);
- statusUpdater->updateStatusText(statusText);
-
- //some check to catch the error that directory on source has been deleted externally after "compare"...
- if (!wxDirExists(cmpLine.fileDescrLeft.fullName))
- throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrLeft.fullName + wxT("\""));
- createDirectory(target, cmpLine.fileDescrLeft.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
- return true;
- case SYNC_DIR_NONE:
- case SYNC_UNRESOLVED_CONFLICT:
- return false;
- }
+ case SO_CREATE_NEW_LEFT:
+ target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
- case FILE_RIGHT_SIDE_ONLY:
- switch (cmpLine.direction)
- {
- case SYNC_DIR_LEFT: //create folders on left
- target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
-
- statusText = txtCreatingFolder;
- statusText.Replace(wxT("%x"), target, false);
- statusUpdater->updateStatusText(statusText);
-
- //some check to catch the error that directory on source has been deleted externally after "compare"...
- if (!wxDirExists(cmpLine.fileDescrRight.fullName))
- throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrRight.fullName + wxT("\""));
- createDirectory(target, cmpLine.fileDescrRight.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
- return true;
- case SYNC_DIR_RIGHT: //delete folders on right
- statusText = txtDeletingFolder;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeDirectory(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
- return true;
- case SYNC_DIR_NONE:
- case SYNC_UNRESOLVED_CONFLICT:
- return false;
- }
+ statusText = txtCreatingFolder;
+ statusText.Replace(wxT("%x"), target, false);
+ statusUpdater->updateStatusText(statusText);
- case FILE_EQUAL:
- return false;
+ //some check to catch the error that directory on source has been deleted externally after "compare"...
+ if (!wxDirExists(cmpLine.fileDescrRight.fullName))
+ throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrRight.fullName + wxT("\""));
+ createDirectory(target, cmpLine.fileDescrRight.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
+ return true;
- case FILE_RIGHT_NEWER:
- case FILE_LEFT_NEWER:
- case FILE_DIFFERENT:
- case FILE_CONFLICT:
- assert (false);
+ case SO_CREATE_NEW_RIGHT:
+ target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
+
+ statusText = txtCreatingFolder;
+ statusText.Replace(wxT("%x"), target, false);
+ statusUpdater->updateStatusText(statusText);
+
+ //some check to catch the error that directory on source has been deleted externally after "compare"...
+ if (!wxDirExists(cmpLine.fileDescrLeft.fullName))
+ throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrLeft.fullName + wxT("\""));
+ createDirectory(target, cmpLine.fileDescrLeft.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
+ return true;
+
+ case SO_DELETE_LEFT:
+ statusText = txtDeletingFolder;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeDirectory(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_DELETE_RIGHT:
+ statusText = txtDeletingFolder;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeDirectory(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_OVERWRITE_RIGHT:
+ case SO_OVERWRITE_LEFT:
+ case SO_UNRESOLVED_CONFLICT:
+ assert(false);
+ case SO_DO_NOTHING:
return false;
}
@@ -539,7 +507,7 @@ public:
~RemoveAtExit()
{
- removeRowsFromVector(gridToWrite, rowsToDelete);
+ globalFunctions::removeRowsFromVector(rowsToDelete, gridToWrite);
}
void markRow(int nr)
@@ -592,7 +560,7 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
const FileComparison& fileCmp = j->fileCmp;
//check if more than 50% of total number of files/dirs are to be created/overwritten/deleted
- if (m_warningSignificantDifference) //test if check should be executed
+ if (m_warnings.warningSignificantDifference) //test if check should be executed
{
if (significantDifferenceDetected(fileCmp))
{
@@ -601,12 +569,12 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
j->syncPair.leftDirectory + wxT(" <-> ") + j->syncPair.rightDirectory + wxT("\n\n") +
_("More than 50% of the total number of files will be copied or deleted!"),
dontShowAgain);
- m_warningSignificantDifference = !dontShowAgain;
+ m_warnings.warningSignificantDifference = !dontShowAgain;
}
}
//check for sufficient free diskspace in left directory
- if (m_warningNotEnoughDiskSpace)
+ if (m_warnings.warningNotEnoughDiskSpace)
{
const std::pair<wxLongLong, wxLongLong> spaceNeeded = freeDiskSpaceNeeded(fileCmp, m_useRecycleBin);
@@ -620,12 +588,12 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
j->syncPair.leftDirectory + wxT("\n\n") +
_("Total required free disk space:") + wxT(" ") + formatFilesizeToShortString(spaceNeeded.first).c_str(),
dontShowAgain);
- m_warningNotEnoughDiskSpace = !dontShowAgain;
+ m_warnings.warningNotEnoughDiskSpace = !dontShowAgain;
}
}
//check for sufficient free diskspace in right directory
- if (m_warningNotEnoughDiskSpace)
+ if (m_warnings.warningNotEnoughDiskSpace)
{
wxLongLong freeDiskSpaceRight;
if (wxGetDiskSpace(j->syncPair.rightDirectory.c_str(), NULL, &freeDiskSpaceRight))
@@ -637,7 +605,7 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
j->syncPair.rightDirectory + wxT("\n\n") +
_("Total required free disk space:") + wxT(" ") + formatFilesizeToShortString(spaceNeeded.second).c_str(),
dontShowAgain);
- m_warningNotEnoughDiskSpace = !dontShowAgain;
+ m_warnings.warningNotEnoughDiskSpace = !dontShowAgain;
}
}
}
@@ -645,14 +613,14 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
}
//check if unresolved conflicts exist
- if (m_warningUnresolvedConflict) //test if check should be executed
+ if (m_warnings.warningUnresolvedConflicts) //test if check should be executed
{
if (conflicts > 0)
{
bool dontShowAgain = false;
statusUpdater->reportWarning(_("Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization."),
dontShowAgain);
- m_warningUnresolvedConflict = !dontShowAgain;
+ m_warnings.warningUnresolvedConflicts = !dontShowAgain;
}
}
@@ -787,144 +755,72 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
//###########################################################################################
//callback functionality for smooth progress indicators
-struct CallBackData
-{
- StatusHandler* handler;
- wxLongLong bytesTransferredLast;
-};
-
-#ifdef FFS_WIN
-const DWORD COPY_FILE_COPY_SYMLINK = 0x00000800;
-
-DWORD CALLBACK copyProcessCallback(
- LARGE_INTEGER totalFileSize,
- LARGE_INTEGER totalBytesTransferred,
- LARGE_INTEGER streamSize,
- LARGE_INTEGER streamBytesTransferred,
- DWORD dwStreamNumber,
- DWORD dwCallbackReason,
- HANDLE hSourceFile,
- HANDLE hDestinationFile,
- LPVOID lpData)
+class WhileCopying : public FreeFileSync::CopyFileCallback //callback functionality
{
- //small performance optimization: it seems this callback function is called for every 64 kB (depending on cluster size).
- static unsigned callNr = 0;
- if (++callNr % 50 == 0) //reduce by factor of 50 =^ 10-20 calls/sec
- {
- CallBackData* sharedData = static_cast<CallBackData*>(lpData);
+public:
- assert(totalBytesTransferred.HighPart >= 0);
+ WhileCopying(wxLongLong& bytesTransferredLast, StatusHandler* statusHandler) :
+ m_bytesTransferredLast(bytesTransferredLast),
+ m_statusHandler(statusHandler) {}
- if (totalBytesTransferred.HighPart < 0) //let's see if someone answers the call...
- wxMessageBox(wxT("You've just discovered a bug in WIN32 API function \"CopyFileEx\"! \n\n\
- Please write a mail to the author of FreeFileSync at zhnmju123@gmx.de and simply state that\n\
- \"totalBytesTransferred.HighPart can be below zero\"!\n\n\
- This will then be handled in future versions of FreeFileSync.\n\nThanks -ZenJu"), wxT("Warning"));
+ virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred)
+ {
+ //convert to signed
+ const wxLongLong totalBytes = globalFunctions::convertToSigned(totalBytesTransferred);
//inform about the (differential) processed amount of data
- const wxLongLong currentBytesTransferred(totalBytesTransferred.HighPart, totalBytesTransferred.LowPart);
- sharedData->handler->updateProcessedData(0, currentBytesTransferred - sharedData->bytesTransferredLast);
- sharedData->bytesTransferredLast = currentBytesTransferred;
-
- sharedData->handler->requestUiRefresh(false); //don't allow throwing exception within this call
-
- if (sharedData->handler->abortIsRequested())
- return PROGRESS_CANCEL;
- }
-
- return PROGRESS_CONTINUE;
-}
+ m_statusHandler->updateProcessedData(0, totalBytes - m_bytesTransferredLast);
+ m_bytesTransferredLast = totalBytes;
+#ifdef FFS_WIN
+ m_statusHandler->requestUiRefresh(false); //don't allow throwing exception within this call
+ if (m_statusHandler->abortIsRequested())
+ return CopyFileCallback::CANCEL;
#elif defined FFS_LINUX
-void copyProcessCallback(const wxULongLong& totalBytesTransferred, void* data)
-{ //called every 512 kB
-
- CallBackData* sharedData = static_cast<CallBackData*>(data);
-
- //convert to unsigned
- const wxLongLong totalBytes = globalFunctions::convertToSigned(totalBytesTransferred);
-
- //inform about the (differential) processed amount of data
- sharedData->handler->updateProcessedData(0, totalBytes - sharedData->bytesTransferredLast);
- sharedData->bytesTransferredLast = totalBytes;
-
- sharedData->handler->requestUiRefresh(); //exceptions may be thrown here!
-}
+ m_statusHandler->requestUiRefresh(); //exceptions may be thrown here!
#endif
+ return CopyFileCallback::CONTINUE;
+ }
+
+private:
+ wxLongLong& m_bytesTransferredLast;
+ StatusHandler* m_statusHandler;
+};
//copy file while executing statusUpdater->requestUiRefresh() calls
void SyncProcess::copyFileUpdating(const Zstring& source, const Zstring& target, const wxULongLong& totalBytesToCpy)
{
//create folders first (see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080)
- const Zstring targetDir = target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring targetDir = target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
if (!wxDirExists(targetDir.c_str()))
{
- const Zstring templateDir = source.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring templateDir = source.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
FreeFileSync::createDirectory(targetDir, templateDir, !m_traverseDirSymLinks); //might throw FileError() exception
}
//start of (possibly) long-running copy process: ensure status updates are performed regularly
-#ifdef FFS_WIN //update via call-back function
-
- CallBackData sharedData;
- sharedData.handler = statusUpdater;
-//data.bytesTransferredLast =
-
-
- DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS;
-
- if (m_copyFileSymLinks) //copy symbolic links instead of the files pointed at
- copyFlags |= COPY_FILE_COPY_SYMLINK;
-
- if (!CopyFileEx( //same performance as CopyFile()
- source.c_str(),
- target.c_str(),
- copyProcessCallback,
- &sharedData,
- NULL,
- copyFlags))
- {
- //error situation: undo communication of processed amount of data
- statusUpdater->updateProcessedData(0, sharedData.bytesTransferredLast * -1 );
-
- statusUpdater->requestUiRefresh(); //abort if requested, don't show error message if cancelled by user!
-
- Zstring errorMessage = Zstring(_("Error copying file:")) + wxT("\n\"") + source + wxT("\" -> \"") + target + wxT("\"");
- errorMessage += Zstring(wxT("\n\n"));
- errorMessage += FreeFileSync::getLastErrorFormatted(); //some additional windows error information
- throw FileError(errorMessage);
- }
-
- //inform about the (remaining) processed amount of data
- statusUpdater->updateProcessedData(0, globalFunctions::convertToSigned(totalBytesToCpy) - sharedData.bytesTransferredLast);
-
-
-#elif defined FFS_LINUX //update via call-back function
-
- CallBackData sharedData;
- sharedData.handler = statusUpdater;
-//data.bytesTransferredLast =
+ wxLongLong totalBytesTransferred;
+ WhileCopying callback(totalBytesTransferred, statusUpdater);
try
{
- FreeFileSync::copyFile(source,
- target,
- m_copyFileSymLinks,
- copyProcessCallback,
- &sharedData);
+#ifdef FFS_WIN
+ FreeFileSync::copyFile(source, target, m_copyFileSymLinks, shadowCopyHandler.get(), &callback);
+#elif defined FFS_LINUX
+ FreeFileSync::copyFile(source, target, m_copyFileSymLinks, &callback);
+#endif
}
catch (...)
{
//error situation: undo communication of processed amount of data
- statusUpdater->updateProcessedData(0, sharedData.bytesTransferredLast * -1 );
-
+ statusUpdater->updateProcessedData(0, totalBytesTransferred * -1 );
+ statusUpdater->requestUiRefresh(true); //windows build: abort if requested, don't show error message if cancelled by user!
throw;
}
//inform about the (remaining) processed amount of data
- statusUpdater->updateProcessedData(0, globalFunctions::convertToSigned(totalBytesToCpy) - sharedData.bytesTransferredLast);
-#endif
+ statusUpdater->updateProcessedData(0, globalFunctions::convertToSigned(totalBytesToCpy) - totalBytesTransferred);
}
/*
@@ -964,10 +860,10 @@ private:
void copyFileUpdating(const Zstring& source, const Zstring& target, const wxULongLong& totalBytesToCpy, StatusHandler* updateClass)
{
//create folders first (see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080)
- const Zstring targetDir = target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring targetDir = target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
if (!wxDirExists(targetDir.c_str()))
{
- const Zstring templateDir = source.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring templateDir = source.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
FreeFileSync::createDirectory(targetDir, templateDir); //might throw FileError() exception
}
bgstack15