summaryrefslogtreecommitdiff
path: root/synchronization.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'synchronization.cpp')
-rw-r--r--synchronization.cpp143
1 files changed, 60 insertions, 83 deletions
diff --git a/synchronization.cpp b/synchronization.cpp
index d641bafc..297dcf51 100644
--- a/synchronization.cpp
+++ b/synchronization.cpp
@@ -68,20 +68,20 @@ inline
void SyncStatistics::getNumbersRecursively(const HierarchyObject& hierObj)
{
//process directories
- std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(),
+ std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(),
boost::bind(&SyncStatistics::getDirNumbers, this, _1));
//process files
- std::for_each(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(),
+ std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(),
boost::bind(&SyncStatistics::getFileNumbers, this, _1));
//process symlinks
- std::for_each(hierObj.useSubLinks().begin(), hierObj.useSubLinks().end(),
+ std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(),
boost::bind(&SyncStatistics::getLinkNumbers, this, _1));
- rowsTotal += hierObj.useSubDirs(). size();
- rowsTotal += hierObj.useSubFiles().size();
- rowsTotal += hierObj.useSubLinks().size();
+ rowsTotal += hierObj.refSubDirs(). size();
+ rowsTotal += hierObj.refSubFiles().size();
+ rowsTotal += hierObj.refSubLinks().size();
}
@@ -364,10 +364,12 @@ SyncProcess::SyncProcess(xmlAccess::OptionalDialogs& warnings,
bool verifyCopiedFiles,
bool copyLockedFiles,
bool copyFilePermissions,
+ bool transactionalFileCopy,
ProcessCallback& handler) :
verifyCopiedFiles_(verifyCopiedFiles),
copyLockedFiles_(copyLockedFiles),
copyFilePermissions_(copyFilePermissions),
+ transactionalFileCopy_(transactionalFileCopy),
m_warnings(warnings),
procCallback(handler) {}
//--------------------------------------------------------------------------------------------------------------
@@ -569,7 +571,7 @@ void DeletionHandling::removeFolder(const Zstring& relativeName) const
break;
case MOVE_TO_RECYCLE_BIN:
- if (!dirExistsUpdating(fullName, *procCallback_))
+ if (dirExistsUpdating(fullName, *procCallback_))
{
const Zstring targetDir = sessionDelDir + relativeName;
const Zstring targetSuperDir = targetDir.BeforeLast(FILE_NAME_SEPARATOR);
@@ -593,7 +595,7 @@ void DeletionHandling::removeFolder(const Zstring& relativeName) const
break;
case MOVE_TO_CUSTOM_DIRECTORY:
- if (!dirExistsUpdating(fullName, *procCallback_))
+ if (dirExistsUpdating(fullName, *procCallback_))
{
const Zstring targetDir = sessionDelDir + relativeName;
const Zstring targetSuperDir = targetDir.BeforeLast(FILE_NAME_SEPARATOR);
@@ -657,7 +659,7 @@ private:
//don't process directories
//process files
- for (HierarchyObject::SubFileMapping::const_iterator i = hierObj.useSubFiles().begin(); i != hierObj.useSubFiles().end(); ++i)
+ for (HierarchyObject::SubFileMapping::const_iterator i = hierObj.refSubFiles().begin(); i != hierObj.refSubFiles().end(); ++i)
switch (i->getSyncOperation()) //evaluate comparison result and sync direction
{
case SO_CREATE_NEW_LEFT:
@@ -702,7 +704,7 @@ private:
//[...]
//recurse into sub-dirs
- std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), boost::bind(&DiskSpaceNeeded::processRecursively, this, _1));
+ std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), boost::bind(&DiskSpaceNeeded::processRecursively, this, _1));
}
const bool freeSpaceDelLeft_;
@@ -787,8 +789,9 @@ public:
#endif
delHandlingLeft_(delHandlingLeft),
delHandlingRight_(delHandlingRight),
- verifyCopiedFiles_(syncProc.verifyCopiedFiles_),
- copyFilePermissions_(syncProc.copyFilePermissions_),
+ verifyCopiedFiles(syncProc.verifyCopiedFiles_),
+ copyFilePermissions(syncProc.copyFilePermissions_),
+ transactionalFileCopy(syncProc.transactionalFileCopy_),
txtCopyingFile (toZ(_("Copying new file %x to %y")). Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)),
txtCopyingLink (toZ(_("Copying new Symbolic Link %x to %y")).Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)),
txtOverwritingFile(toZ(_("Overwriting file %x in %y")). Replace(Zstr("%x"), Zstr("\"%x\""), false).Replace(Zstr("%y"), Zstr("\n\"%y\""), false)),
@@ -834,8 +837,9 @@ private:
const DeletionHandling& delHandlingLeft_;
const DeletionHandling& delHandlingRight_;
- const bool verifyCopiedFiles_;
- const bool copyFilePermissions_;
+ const bool verifyCopiedFiles;
+ const bool copyFilePermissions;
+ const bool transactionalFileCopy;
//preload status texts
const Zstring txtCopyingFile;
@@ -852,7 +856,7 @@ template <SynchronizeFolderPair::PassId pass>
void SynchronizeFolderPair::execute(HierarchyObject& hierObj)
{
//synchronize files:
- std::for_each(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(),
+ std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(),
[&](FileMapping& fileObj)
{
const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(fileObj); //to be deleted files on first pass, rest on second!
@@ -862,11 +866,11 @@ void SynchronizeFolderPair::execute(HierarchyObject& hierObj)
//synchronize symbolic links: (process in second step only)
if (pass == SECOND_PASS)
- std::for_each(hierObj.useSubLinks().begin(), hierObj.useSubLinks().end(),
+ std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(),
[&](SymLinkMapping& linkObj) { tryReportingError(procCallback_, [&]() { synchronizeLink(linkObj); }); });
//synchronize folders:
- std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(),
+ std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(),
[&](DirMapping& dirObj)
{
const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(dirObj); //to be deleted files on first pass, rest on second!
@@ -879,34 +883,6 @@ void SynchronizeFolderPair::execute(HierarchyObject& hierObj)
}
-namespace
-{
-struct NullCommand
-{
- void operator()() const {}
-};
-
-
-template <SelectedSide side>
-class DelTargetCommand
-{
-public:
- DelTargetCommand(FileMapping& fileObj, const DeletionHandling& delHandling) : fileObj_(fileObj), delHandling_(delHandling) {}
-
- void operator()() const
- {
- //delete target and copy source
- delHandling_.removeFile(fileObj_.getObjRelativeName()); //throw (FileError)
- fileObj_.removeObject<side>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
- }
-
-private:
- FileMapping& fileObj_;
- const DeletionHandling& delHandling_;
-};
-}
-
-
void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
{
Zstring statusText;
@@ -923,8 +899,8 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText));
copyFileUpdating(fileObj.getFullName<RIGHT_SIDE>(), target,
- NullCommand(), //no target to delete
- fileObj.getFileSize<RIGHT_SIDE>());
+ []() {}, //no target to delete
+ fileObj.getFileSize<RIGHT_SIDE>());
break;
case SO_CREATE_NEW_RIGHT:
@@ -936,8 +912,8 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText));
copyFileUpdating(fileObj.getFullName<LEFT_SIDE>(), target,
- NullCommand(), //no target to delete
- fileObj.getFileSize<LEFT_SIDE>());
+ []() {}, //no target to delete
+ fileObj.getFileSize<LEFT_SIDE>());
break;
case SO_DELETE_LEFT:
@@ -965,8 +941,12 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText));
copyFileUpdating(fileObj.getFullName<RIGHT_SIDE>(), target,
- DelTargetCommand<LEFT_SIDE>(fileObj, delHandlingLeft_), //delete target at appropriate time
- fileObj.getFileSize<RIGHT_SIDE>());
+ [&]() //delete target at appropriate time
+ {
+ delHandlingLeft_.removeFile(fileObj.getObjRelativeName()); //throw (FileError)
+ fileObj.removeObject<LEFT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
+ },
+ fileObj.getFileSize<RIGHT_SIDE>());
break;
case SO_OVERWRITE_RIGHT:
@@ -978,8 +958,12 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const
procCallback_.reportInfo(utf8CvrtTo<wxString>(statusText));
copyFileUpdating(fileObj.getFullName<LEFT_SIDE>(), target,
- DelTargetCommand<RIGHT_SIDE>(fileObj, delHandlingRight_), //delete target at appropriate time
- fileObj.getFileSize<LEFT_SIDE>());
+ [&]() //delete target at appropriate time
+ {
+ delHandlingRight_.removeFile(fileObj.getObjRelativeName()); //throw (FileError)
+ fileObj.removeObject<RIGHT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!)
+ },
+ fileObj.getFileSize<LEFT_SIDE>());
break;
case SO_COPY_METADATA_TO_LEFT:
@@ -1157,7 +1141,7 @@ void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const
//some check to catch the error that directory on source has been deleted externally after "compare"...
if (!dirExistsUpdating(dirObj.getFullName<RIGHT_SIDE>(), procCallback_))
throw FileError(_("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<RIGHT_SIDE>() + "\"");
- createDirectory(target, dirObj.getFullName<RIGHT_SIDE>(), copyFilePermissions_); //no symlink copying!
+ createDirectory(target, dirObj.getFullName<RIGHT_SIDE>(), copyFilePermissions); //no symlink copying!
break;
case SO_CREATE_NEW_RIGHT:
@@ -1170,7 +1154,7 @@ void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const
//some check to catch the error that directory on source has been deleted externally after "compare"...
if (!dirExistsUpdating(dirObj.getFullName<LEFT_SIDE>(), procCallback_))
throw FileError(_("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<LEFT_SIDE>() + "\"");
- createDirectory(target, dirObj.getFullName<LEFT_SIDE>(), copyFilePermissions_); //no symlink copying!
+ createDirectory(target, dirObj.getFullName<LEFT_SIDE>(), copyFilePermissions); //no symlink copying!
break;
case SO_COPY_METADATA_TO_LEFT:
@@ -1206,9 +1190,9 @@ void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const
//progress indicator update: DON'T forget to notify about implicitly deleted objects!
const SyncStatistics subObjects(dirObj);
//...then remove everything
- dirObj.useSubFiles().clear();
- dirObj.useSubLinks().clear();
- dirObj.useSubDirs ().clear();
+ dirObj.refSubFiles().clear();
+ dirObj.refSubLinks().clear();
+ dirObj.refSubDirs ().clear();
procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess()));
}
break;
@@ -1224,9 +1208,9 @@ void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const
//progress indicator update: DON'T forget to notify about implicitly deleted objects!
const SyncStatistics subObjects(dirObj);
//...then remove everything
- dirObj.useSubFiles().clear();
- dirObj.useSubLinks().clear();
- dirObj.useSubDirs ().clear();
+ dirObj.refSubFiles().clear();
+ dirObj.refSubLinks().clear();
+ dirObj.refSubDirs ().clear();
procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess()));
}
break;
@@ -1650,34 +1634,26 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf
const Zstring dirnameLeft = j->getBaseDir<LEFT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR);
if (!dirnameLeft.empty() && !dirExistsUpdating(dirnameLeft, procCallback))
{
- if (!tryReportingError(procCallback, boost::bind(createDirectory, boost::cref(dirnameLeft)))) //may throw in error-callback!
- continue; //skip this folder pair
+ if (!tryReportingError(procCallback, [&]() { createDirectory(dirnameLeft); })) //may throw in error-callback!
+ continue; //skip this folder pair
}
const Zstring dirnameRight = j->getBaseDir<RIGHT_SIDE>().BeforeLast(FILE_NAME_SEPARATOR);
if (!dirnameRight.empty() && !dirExistsUpdating(dirnameRight, procCallback))
{
- if (!tryReportingError(procCallback, boost::bind(createDirectory, boost::cref(dirnameRight)))) //may throw in error-callback!
- continue; //skip this folder pair
+ if (!tryReportingError(procCallback, [&]() { createDirectory(dirnameRight); })) //may throw in error-callback!
+ continue; //skip this folder pair
}
//------------------------------------------------------------------------------------------
//execute synchronization recursively
//update synchronization database (automatic sync only)
- std::auto_ptr<EnforceUpdateDatabase> guardUpdateDb;
+ std::unique_ptr<EnforceUpdateDatabase> guardUpdateDb;
if (folderPairCfg.inAutomaticMode)
guardUpdateDb.reset(new EnforceUpdateDatabase(*j));
- //enforce removal of invalid entries (where element on both sides is empty)
- struct RemoveInvalid
- {
- RemoveInvalid(BaseDirMapping& baseDir) : baseDir_(baseDir) {}
- ~RemoveInvalid()
- {
- FileSystemObject::removeEmpty(baseDir_);
- }
- BaseDirMapping& baseDir_;
- } dummy1(*j);
-
+ //guarantee removal of invalid entries (where element on both sides is empty)
+ Loki::ScopeGuard guardInvalid = Loki::MakeGuard([&]() { BaseDirMapping::removeEmpty(*j); });
+ (void) guardInvalid;
SynchronizeFolderPair syncFP(*this,
#ifdef FFS_WIN
@@ -1757,7 +1733,8 @@ void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstrin
copyFile(source, //type File implicitly means symlinks need to be dereferenced!
target,
- copyFilePermissions_,
+ copyFilePermissions,
+ transactionalFileCopy,
&callback); //throw (FileError, ErrorFileLocked);
//inform about the (remaining) processed amount of data
@@ -1800,7 +1777,7 @@ void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstrin
if (!targetDir.empty())
{
- createDirectory(targetDir, templateDir, copyFilePermissions_); //throw (FileError)
+ createDirectory(targetDir, templateDir, copyFilePermissions); //throw (FileError)
/*symbolic link handling:
if "not traversing symlinks": fullName == c:\syncdir<symlinks>\some\dirs\leaf<symlink>
=> setting irrelevant
@@ -1815,7 +1792,7 @@ void SynchronizeFolderPair::copyFileUpdating(const Zstring& source, const Zstrin
//todo: transactional behavior: delete target if verification fails?
- if (verifyCopiedFiles_) //verify if data was copied correctly
+ if (verifyCopiedFiles) //verify if data was copied correctly
verifyFileCopy(source, target); //throw (FileError)
guardStatistics.Dismiss();
@@ -1829,11 +1806,11 @@ void SynchronizeFolderPair::copySymlink(const Zstring& source, const Zstring& ta
switch (type)
{
case LinkDescriptor::TYPE_DIR:
- zen::copySymlink(source, target, SYMLINK_TYPE_DIR, copyFilePermissions_); //throw (FileError)
+ zen::copySymlink(source, target, SYMLINK_TYPE_DIR, copyFilePermissions); //throw (FileError)
break;
case LinkDescriptor::TYPE_FILE: //Windows: true file symlink; Linux: file-link or broken link
- zen::copySymlink(source, target, SYMLINK_TYPE_FILE, copyFilePermissions_); //throw (FileError)
+ zen::copySymlink(source, target, SYMLINK_TYPE_FILE, copyFilePermissions); //throw (FileError)
break;
}
}
@@ -1848,7 +1825,7 @@ void SynchronizeFolderPair::copySymlink(const Zstring& source, const Zstring& ta
if (!targetDir.empty() && !dirExistsUpdating(targetDir, procCallback_))
{
- createDirectory(targetDir, templateDir, copyFilePermissions_); //throw (FileError)
+ createDirectory(targetDir, templateDir, copyFilePermissions); //throw (FileError)
/*symbolic link handling:
if "not traversing symlinks": fullName == c:\syncdir<symlinks>\some\dirs\leaf<symlink>
=> setting irrelevant
bgstack15