summaryrefslogtreecommitdiff
path: root/file_hierarchy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'file_hierarchy.cpp')
-rw-r--r--file_hierarchy.cpp127
1 files changed, 74 insertions, 53 deletions
diff --git a/file_hierarchy.cpp b/file_hierarchy.cpp
index 769ad74f..f1bb7385 100644
--- a/file_hierarchy.cpp
+++ b/file_hierarchy.cpp
@@ -13,12 +13,12 @@ using namespace zen;
void HierarchyObject::removeEmptyRec()
{
- bool haveEmpty = false;
+ bool emptyExisting = false;
auto isEmpty = [&](const FileSystemObject& fsObj) -> bool
{
- bool objEmpty = fsObj.isEmpty();
+ const bool objEmpty = fsObj.isEmpty();
if (objEmpty)
- haveEmpty = true;
+ emptyExisting = true;
return objEmpty;
};
@@ -26,19 +26,20 @@ void HierarchyObject::removeEmptyRec()
refSubLinks().remove_if(isEmpty);
refSubDirs ().remove_if(isEmpty);
- if (haveEmpty) //notify if actual deletion happened
+ if (emptyExisting) //notify if actual deletion happened
notifySyncCfgChanged(); //mustn't call this in ~FileSystemObject(), since parent, usually a DirMapping, is already partially destroyed and existing as a pure HierarchyObject!
- //recurse
+ // for (auto& subDir : refSubDirs())
+ // subDir.removeEmptyRec(); //recurse
std::for_each(refSubDirs().begin(), refSubDirs().end(), std::mem_fun_ref(&HierarchyObject::removeEmptyRec));
}
namespace
{
-SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
- bool selectedForSynchronization,
- SyncDirection syncDir,
- bool haveDirConflict) //perf: std::wstring was wasteful here
+SyncOperation getIsolatedSyncOperation(CompareFilesResult cmpResult,
+ bool selectedForSynchronization,
+ SyncDirection syncDir,
+ bool hasDirConflict) //perf: std::wstring was wasteful here
{
if (!selectedForSynchronization)
return cmpResult == FILE_EQUAL ?
@@ -55,7 +56,7 @@ SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
case SYNC_DIR_RIGHT:
return SO_CREATE_NEW_RIGHT; //copy files to right
case SYNC_DIR_NONE:
- return haveDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
+ return hasDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
}
break;
@@ -67,7 +68,7 @@ SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
case SYNC_DIR_RIGHT:
return SO_DELETE_RIGHT; //delete files on right
case SYNC_DIR_NONE:
- return haveDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
+ return hasDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
}
break;
@@ -82,7 +83,7 @@ SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
case SYNC_DIR_RIGHT:
return SO_OVERWRITE_RIGHT; //copy from left to right
case SYNC_DIR_NONE:
- return haveDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
+ return hasDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
}
break;
@@ -94,7 +95,7 @@ SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
case SYNC_DIR_RIGHT:
return SO_COPY_METADATA_TO_RIGHT;
case SYNC_DIR_NONE:
- return haveDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
+ return hasDirConflict ? SO_UNRESOLVED_CONFLICT : SO_DO_NOTHING;
}
break;
@@ -103,6 +104,7 @@ SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
return SO_EQUAL;
}
+ assert(false);
return SO_DO_NOTHING; //dummy
}
@@ -110,27 +112,27 @@ SyncOperation proposedSyncOperation(CompareFilesResult cmpResult,
template <class Predicate> inline
bool hasDirectChild(const HierarchyObject& hierObj, Predicate p)
{
- return std::find_if(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), p) != hierObj.refSubFiles().end() ||
- std::find_if(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), p) != hierObj.refSubLinks().end() ||
- std::find_if(hierObj.refSubDirs(). begin(), hierObj.refSubDirs(). end(), p) != hierObj.refSubDirs ().end();
+ return std::any_of(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), p) ||
+ std::any_of(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), p) ||
+ std::any_of(hierObj.refSubDirs(). begin(), hierObj.refSubDirs(). end(), p);
}
}
-SyncOperation FileSystemObject::testSyncOperation(SyncDirection testSyncDir, bool active) const
+SyncOperation FileSystemObject::testSyncOperation(SyncDirection testSyncDir) const //semantics: "what if"! assumes "active, no conflict, no recursion (directory)!
{
- return proposedSyncOperation(getCategory(), active, testSyncDir, syncDirConflict.get() != NULL);
+ return getIsolatedSyncOperation(getCategory(), true, testSyncDir, false);
}
SyncOperation FileSystemObject::getSyncOperation() const
{
- return FileSystemObject::testSyncOperation(syncDir, selectedForSynchronization);
- //no *not* make a virtual call to testSyncOperation()! See FileMapping::testSyncOperation()!
+ return getIsolatedSyncOperation(getCategory(), selectedForSynchronization, syncDir, syncDirConflict.get() != nullptr);
+ //no *not* make a virtual call to testSyncOperation()! See FileMapping::testSyncOperation()! <- better not implement one in terms of the other!!!
}
-//SyncOperation DirMapping::testSyncOperation() const -> not required: we do NOT want to consider child elements when testing!
+//SyncOperation DirMapping::testSyncOperation() const -> no recursion: we do NOT want to consider child elements when testing!
SyncOperation DirMapping::getSyncOperation() const
@@ -163,80 +165,99 @@ SyncOperation DirMapping::getSyncOperation() const
case SO_DELETE_RIGHT:
case SO_DO_NOTHING:
case SO_UNRESOLVED_CONFLICT:
- {
if (isEmpty<LEFT_SIDE>())
{
//1. if at least one child-element is to be created, make sure parent folder is created also
//note: this automatically fulfills "create parent folders even if excluded";
//see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080
if (hasDirectChild(*this,
- [](const FileSystemObject& fsObj) -> bool { const SyncOperation op = fsObj.getSyncOperation(); return op == SO_CREATE_NEW_LEFT || op == SO_MOVE_LEFT_TARGET; }))
- syncOpBuffered = SO_CREATE_NEW_LEFT;
+ [](const FileSystemObject& fsObj) -> bool
+ {
+ const SyncOperation op = fsObj.getSyncOperation();
+ return op == SO_CREATE_NEW_LEFT ||
+ op == SO_MOVE_LEFT_TARGET;
+ }))
+ syncOpBuffered = SO_CREATE_NEW_LEFT;
//2. cancel parent deletion if only a single child is not also scheduled for deletion
else if (syncOpBuffered == SO_DELETE_RIGHT &&
hasDirectChild(*this,
[](const FileSystemObject& fsObj) -> bool
{
- if (fsObj.isEmpty()) return false; //fsObj may already be empty because it once contained a "move source"
- const SyncOperation op = fsObj.getSyncOperation(); return op != SO_DELETE_RIGHT && op != SO_MOVE_RIGHT_SOURCE;
+ if (fsObj.isEmpty())
+ return false; //fsObj may already be empty because it once contained a "move source"
+ const SyncOperation op = fsObj.getSyncOperation();
+ return op != SO_DELETE_RIGHT &&
+ op != SO_MOVE_RIGHT_SOURCE;
}))
syncOpBuffered = SO_DO_NOTHING;
}
else if (isEmpty<RIGHT_SIDE>())
{
if (hasDirectChild(*this,
- [](const FileSystemObject& fsObj) -> bool { const SyncOperation op = fsObj.getSyncOperation(); return op == SO_CREATE_NEW_RIGHT || op == SO_MOVE_RIGHT_TARGET; }))
- syncOpBuffered = SO_CREATE_NEW_RIGHT;
+ [](const FileSystemObject& fsObj) -> bool
+ {
+ const SyncOperation op = fsObj.getSyncOperation();
+ return op == SO_CREATE_NEW_RIGHT ||
+ op == SO_MOVE_RIGHT_TARGET;
+ }))
+ syncOpBuffered = SO_CREATE_NEW_RIGHT;
else if (syncOpBuffered == SO_DELETE_LEFT &&
hasDirectChild(*this,
[](const FileSystemObject& fsObj) -> bool
{
- if (fsObj.isEmpty()) return false;
+ if (fsObj.isEmpty())
+ return false;
const SyncOperation op = fsObj.getSyncOperation();
- return op != SO_DELETE_LEFT && op != SO_MOVE_LEFT_SOURCE;
+ return op != SO_DELETE_LEFT &&
+ op != SO_MOVE_LEFT_SOURCE;
}))
syncOpBuffered = SO_DO_NOTHING;
}
- }
- break;
+ break;
}
}
return syncOpBuffered;
}
-SyncOperation FileMapping::testSyncOperation(SyncDirection testSyncDir, bool active) const
+inline //it's private!
+SyncOperation FileMapping::applyMoveOptimization(SyncOperation op) const
{
- SyncOperation op = FileSystemObject::testSyncOperation(testSyncDir, active);
-
/*
check whether we can optimize "create + delete" via "move":
note: as long as we consider "create + delete" cases only, detection of renamed files, should be fine even for "binary" comparison variant!
*/
- if (const FileSystemObject* refFile = dynamic_cast<const FileMapping*>(FileSystemObject::retrieve(moveFileRef))) //we expect a "FileMapping", but only need a "FileSystemObject"
- {
- SyncOperation opRef = refFile->FileSystemObject::getSyncOperation(); //do *not* make a virtual call!
-
- if (op == SO_CREATE_NEW_LEFT &&
- opRef == SO_DELETE_LEFT)
- op = SO_MOVE_LEFT_TARGET;
- else if (op == SO_DELETE_LEFT &&
- opRef == SO_CREATE_NEW_LEFT)
- op = SO_MOVE_LEFT_SOURCE;
- else if (op == SO_CREATE_NEW_RIGHT &&
- opRef == SO_DELETE_RIGHT)
- op = SO_MOVE_RIGHT_TARGET;
- else if (op == SO_DELETE_RIGHT &&
- opRef == SO_CREATE_NEW_RIGHT)
- op = SO_MOVE_RIGHT_SOURCE;
- }
+ if (moveFileRef)
+ if (auto refFile = dynamic_cast<const FileMapping*>(FileSystemObject::retrieve(moveFileRef))) //we expect a "FileMapping", but only need a "FileSystemObject"
+ {
+ SyncOperation opRef = refFile->FileSystemObject::getSyncOperation(); //do *not* make a virtual call!
+
+ if (op == SO_CREATE_NEW_LEFT &&
+ opRef == SO_DELETE_LEFT)
+ op = SO_MOVE_LEFT_TARGET;
+ else if (op == SO_DELETE_LEFT &&
+ opRef == SO_CREATE_NEW_LEFT)
+ op = SO_MOVE_LEFT_SOURCE;
+ else if (op == SO_CREATE_NEW_RIGHT &&
+ opRef == SO_DELETE_RIGHT)
+ op = SO_MOVE_RIGHT_TARGET;
+ else if (op == SO_DELETE_RIGHT &&
+ opRef == SO_CREATE_NEW_RIGHT)
+ op = SO_MOVE_RIGHT_SOURCE;
+ }
return op;
}
+SyncOperation FileMapping::testSyncOperation(SyncDirection testSyncDir) const
+{
+ return applyMoveOptimization(FileSystemObject::testSyncOperation(testSyncDir));
+}
+
+
SyncOperation FileMapping::getSyncOperation() const
{
- return FileMapping::testSyncOperation(getSyncDir(), isActive());
+ return applyMoveOptimization(FileSystemObject::getSyncOperation());
}
bgstack15