diff options
Diffstat (limited to 'file_hierarchy.h')
-rw-r--r-- | file_hierarchy.h | 1112 |
1 files changed, 0 insertions, 1112 deletions
diff --git a/file_hierarchy.h b/file_hierarchy.h deleted file mode 100644 index ce3a96b0..00000000 --- a/file_hierarchy.h +++ /dev/null @@ -1,1112 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef FILEHIERARCHY_H_INCLUDED -#define FILEHIERARCHY_H_INCLUDED - -#include <map> -#include <string> -#include <memory> -#include <functional> -#include <zen/zstring.h> -#include <zen/fixed_list.h> -#include <zen/stl_tools.h> -#include "structures.h" -#include <zen/int64.h> -#include <zen/file_id_def.h> -#include "structures.h" -#include "lib/hard_filter.h" - -namespace zen -{ -struct FileDescriptor -{ - FileDescriptor() : fileIdx(), devId(), isFollowedSymlink() {} - FileDescriptor(const Int64& lastWriteTimeRawIn, - const UInt64& fileSizeIn, - const FileId& idIn, - bool isSymlink) : - lastWriteTimeRaw(lastWriteTimeRawIn), - fileSize(fileSizeIn), - fileIdx(idIn.second), - devId(idIn.first), - isFollowedSymlink(isSymlink) {} - - Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) - UInt64 fileSize; - FileIndex fileIdx; // == file id: optional! (however, always set on Linux, and *generally* available on Windows) - DeviceId devId; //split into file id into components to avoid padding overhead of a std::pair! - bool isFollowedSymlink; -}; - -inline -FileId getFileId(const FileDescriptor& fd) { return FileId(fd.devId, fd.fileIdx); } - -struct LinkDescriptor -{ - LinkDescriptor() {} - explicit LinkDescriptor(const Int64& lastWriteTimeRawIn) : lastWriteTimeRaw(lastWriteTimeRawIn) {} - - Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) -}; - - -enum SelectedSide -{ - LEFT_SIDE, - RIGHT_SIDE -}; - -template <SelectedSide side> -struct OtherSide; - -template <> -struct OtherSide<LEFT_SIDE> { static const SelectedSide result = RIGHT_SIDE; }; - -template <> -struct OtherSide<RIGHT_SIDE> { static const SelectedSide result = LEFT_SIDE; }; - - -template <SelectedSide side> -struct SelectParam; - -template <> -struct SelectParam<LEFT_SIDE> -{ - template <class T> - static T& get(T& left, T& right) { return left; } -}; - -template <> -struct SelectParam<RIGHT_SIDE> -{ - template <class T> - static T& get(T& left, T& right) { return right; } -}; - - -class BaseDirPair; -class DirPair; -class FilePair; -class SymlinkPair; -class FileSystemObject; - -//------------------------------------------------------------------ - -/* -ERD: - DirContainer 1 --> 0..n DirContainer - DirContainer 1 --> 0..n FileDescriptor - DirContainer 1 --> 0..n LinkDescriptor -*/ - -struct DirContainer -{ - //------------------------------------------------------------------ - typedef std::map<Zstring, DirContainer, LessFilename> DirList; // - typedef std::map<Zstring, FileDescriptor, LessFilename> FileList; //key: shortName - typedef std::map<Zstring, LinkDescriptor, LessFilename> LinkList; // - //------------------------------------------------------------------ - - DirList dirs; - FileList files; - LinkList links; //non-followed symlinks - - //convenience - DirContainer& addSubDir(const Zstring& shortName) - { - //use C++11 emplace when available - return dirs[shortName]; //value default-construction is okay here - //return dirs.insert(std::make_pair(shortName, DirContainer())).first->second; - } - - void addSubFile(const Zstring& shortName, const FileDescriptor& fileData) - { - files.insert(std::make_pair(shortName, fileData)); - } - - void addSubLink(const Zstring& shortName, const LinkDescriptor& linkData) - { - links.insert(std::make_pair(shortName, linkData)); - } -}; - -/*------------------------------------------------------------------ - inheritance diagram: - - ObjectMgr - /|\ - | - FileSystemObject HierarchyObject - /|\ /|\ - _______________|______________ ______|______ - | | | | | - SymlinkPair FilePair DirPair BaseDirPair - -------------------------------------------------------------------*/ - -class HierarchyObject -{ - friend class DirPair; - friend class FileSystemObject; - -public: - typedef zen::FixedList<FilePair> SubFileVec; //MergeSides::execute() requires a structure that doesn't invalidate pointers after push_back() - typedef zen::FixedList<SymlinkPair> SubLinkVec; //Note: deque<> has circular dependency in VCPP! - typedef zen::FixedList<DirPair> SubDirVec; - - DirPair& addSubDir(const Zstring& shortNameLeft, - const Zstring& shortNameRight, - CompareDirResult defaultCmpResult); - - template <SelectedSide side> - DirPair& addSubDir(const Zstring& shortName); //dir exists on one side only - - - FilePair& addSubFile(const Zstring& shortNameLeft, - const FileDescriptor& left, //file exists on both sides - CompareFilesResult defaultCmpResult, - const Zstring& shortNameRight, - const FileDescriptor& right); - - template <SelectedSide side> - FilePair& addSubFile(const Zstring& shortName, //file exists on one side only - const FileDescriptor& descr); - - SymlinkPair& addSubLink(const Zstring& shortNameLeft, - const LinkDescriptor& left, //link exists on both sides - CompareSymlinkResult defaultCmpResult, - const Zstring& shortNameRight, - const LinkDescriptor& right); - - template <SelectedSide side> - SymlinkPair& addSubLink(const Zstring& shortName, //link exists on one side only - const LinkDescriptor& descr); - - const SubFileVec& refSubFiles() const { return subFiles; } - /**/ SubFileVec& refSubFiles() { return subFiles; } - - const SubLinkVec& refSubLinks() const { return subLinks; } - /**/ SubLinkVec& refSubLinks() { return subLinks; } - - const SubDirVec& refSubDirs() const { return subDirs; } - /**/ SubDirVec& refSubDirs() { return subDirs; } - - BaseDirPair& getRoot() { return root_; } - - const Zstring& getObjRelativeNamePf() const { return objRelNamePf; } //postfixed or empty! - -protected: - HierarchyObject(const Zstring& relativeNamePf, - BaseDirPair& baseDirObj) : - objRelNamePf(relativeNamePf), - root_(baseDirObj) {} - - ~HierarchyObject() {} //don't need polymorphic deletion - - virtual void flip(); - - void removeEmptyRec(); - -private: - virtual void notifySyncCfgChanged() {} - - HierarchyObject(const HierarchyObject&); //this class is referenced by it's child elements => make it non-copyable/movable! - HierarchyObject& operator=(const HierarchyObject&); // - - SubFileVec subFiles; //contained file maps - SubLinkVec subLinks; //contained symbolic link maps - SubDirVec subDirs; //contained directory maps - - Zstring objRelNamePf; //postfixed or empty - BaseDirPair& root_; -}; - -//------------------------------------------------------------------ - -class BaseDirPair : public HierarchyObject //synchronization base directory -{ -public: - BaseDirPair(const Zstring& dirPostfixedLeft, - bool dirExistsLeft, - const Zstring& dirPostfixedRight, - bool dirExistsRight, - const HardFilter::FilterRef& filter, - CompareVariant cmpVar, - size_t fileTimeTolerance) : -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4355) //"The this pointer is valid only within nonstatic member functions. It cannot be used in the initializer list for a base class." -#endif - HierarchyObject(Zstring(), *this), -#ifdef _MSC_VER -#pragma warning(pop) -#endif - filter_(filter), cmpVar_(cmpVar), fileTimeTolerance_(fileTimeTolerance), - baseDirPfL (dirPostfixedLeft ), - baseDirPfR (dirPostfixedRight), - dirExistsLeft_ (dirExistsLeft ), - dirExistsRight_(dirExistsRight) {} - - template <SelectedSide side> const Zstring& getBaseDirPf() const; //base sync directory postfixed with FILE_NAME_SEPARATOR (or empty!) - static void removeEmpty(BaseDirPair& baseDir) { baseDir.removeEmptyRec(); }; //physically remove all invalid entries (where both sides are empty) recursively - - template <SelectedSide side> bool isExisting() const; //status of directory existence at the time of comparison! - template <SelectedSide side> void setExisting(bool value); //update after creating the directory in FFS - - //get settings which were used while creating BaseDirPair - const HardFilter& getFilter() const { return *filter_; } - CompareVariant getCompVariant() const { return cmpVar_; } - size_t getFileTimeTolerance() const { return fileTimeTolerance_; } - - virtual void flip(); - -private: - BaseDirPair(const BaseDirPair&); //this class is referenced by HierarchyObject => make it non-copyable/movable! - BaseDirPair& operator=(const BaseDirPair&); // - - HardFilter::FilterRef filter_; //filter used while scanning directory: represents sub-view of actual files! - CompareVariant cmpVar_; - size_t fileTimeTolerance_; - - Zstring baseDirPfL; //base sync dir postfixed - Zstring baseDirPfR; // - - bool dirExistsLeft_; - bool dirExistsRight_; -}; - - -template <> inline -const Zstring& BaseDirPair::getBaseDirPf<LEFT_SIDE>() const { return baseDirPfL; } - -template <> inline -const Zstring& BaseDirPair::getBaseDirPf<RIGHT_SIDE>() const { return baseDirPfR; } - - -//get rid of shared_ptr indirection -template <class IterTy, //underlying iterator type - class U> //target object type -class DerefIter : public std::iterator<std::bidirectional_iterator_tag, U> -{ -public: - DerefIter() {} - DerefIter(IterTy it) : iter(it) {} - DerefIter(const DerefIter& other) : iter(other.iter) {} - DerefIter& operator++() { ++iter; return *this; } - DerefIter& operator--() { --iter; return *this; } - DerefIter operator++(int) { DerefIter tmp(*this); operator++(); return tmp; } - DerefIter operator--(int) { DerefIter tmp(*this); operator--(); return tmp; } - inline friend ptrdiff_t operator-(const DerefIter& lhs, const DerefIter& rhs) { return lhs.iter - rhs.iter; } - inline friend bool operator==(const DerefIter& lhs, const DerefIter& rhs) { return lhs.iter == rhs.iter; } - inline friend bool operator!=(const DerefIter& lhs, const DerefIter& rhs) { return !(lhs == rhs); } - U& operator* () { return **iter; } - U* operator->() { return &** iter; } -private: - IterTy iter; -}; - -typedef std::vector<std::shared_ptr<BaseDirPair>> FolderComparison; //make sure pointers to sub-elements remain valid -//don't change this back to std::vector<BaseDirPair> too easily: comparison uses push_back to add entries which may result in a full copy! - -DerefIter<typename FolderComparison::iterator, BaseDirPair> inline begin(FolderComparison& vect) { return vect.begin(); } -DerefIter<typename FolderComparison::iterator, BaseDirPair> inline end (FolderComparison& vect) { return vect.end (); } -DerefIter<typename FolderComparison::const_iterator, const BaseDirPair> inline begin(const FolderComparison& vect) { return vect.begin(); } -DerefIter<typename FolderComparison::const_iterator, const BaseDirPair> inline end (const FolderComparison& vect) { return vect.end (); } - -//------------------------------------------------------------------ -class FSObjectVisitor -{ -public: - virtual ~FSObjectVisitor() {} - virtual void visit(const FilePair& fileObj) = 0; - virtual void visit(const SymlinkPair& linkObj) = 0; - virtual void visit(const DirPair& dirObj) = 0; -}; - -//inherit from this class to allow safe random access by id instead of unsafe raw pointer -//allow for similar semantics like std::weak_ptr without having to use std::shared_ptr -template <class T> -class ObjectMgr -{ -public: - typedef ObjectMgr* ObjectId; - typedef const ObjectMgr* ObjectIdConst; - - ObjectIdConst getId() const { return this; } - /**/ ObjectId getId() { return this; } - - static const T* retrieve(ObjectIdConst id) //returns nullptr if object is not valid anymore - { - auto iter = activeObjects().find(id); - return static_cast<const T*>(iter == activeObjects().end() ? nullptr : *iter); - } - static T* retrieve(ObjectId id) { return const_cast<T*>(retrieve(static_cast<ObjectIdConst>(id))); } - -protected: - ObjectMgr () { activeObjects().insert(this); } - ~ObjectMgr() { activeObjects().erase (this); } - -private: - ObjectMgr(const ObjectMgr& rhs); // - ObjectMgr& operator=(const ObjectMgr& rhs); //it's not well-defined what coping an objects means regarding object-identity in this context - - static zen::hash_set<const ObjectMgr*>& activeObjects() { static zen::hash_set<const ObjectMgr*> inst; return inst; } //external linkage (even in header file!) -}; - -//------------------------------------------------------------------ - -class FileSystemObject : public ObjectMgr<FileSystemObject> -{ -public: - virtual void accept(FSObjectVisitor& visitor) const = 0; - - Zstring getObjShortName () const; //same as getShortName() but also returns value if either side is empty - Zstring getObjRelativeName() const; //same as getRelativeName() but also returns value if either side is empty - template <SelectedSide side> bool isEmpty() const; - template <SelectedSide side> const Zstring& getShortName() const; //case sensitive! - template <SelectedSide side> Zstring getRelativeName() const; //get name relative to base sync dir without FILE_NAME_SEPARATOR prefix - template <SelectedSide side> const Zstring& getBaseDirPf() const; //base sync directory postfixed with FILE_NAME_SEPARATOR - template <SelectedSide side> Zstring getFullName() const; //getFullName() == getBaseDirPf() + getRelativeName() - - //comparison result - CompareFilesResult getCategory() const { return cmpResult; } - std::wstring getCatExtraDescription() const; //only filled if getCategory() == FILE_CONFLICT or FILE_DIFFERENT_METADATA - - //sync settings - SyncDirection getSyncDir() const; - void setSyncDir(SyncDirection newDir); - void setSyncDirConflict(const std::wstring& description); //set syncDir = SyncDirection::NONE + fill conflict description - - bool isActive() const; - void setActive(bool active); - - //sync operation - virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; //semantics: "what if"! assumes "active, no conflict, no recursion (directory)! - virtual SyncOperation getSyncOperation() const; - std::wstring getSyncOpConflict() const; //return conflict when determining sync direction or (still unresolved) conflict during categorization - - template <SelectedSide side> void removeObject(); //removes file or directory (recursively!) without physically removing the element: used by manual deletion - - bool isEmpty() const; //true, if both sides are empty - - const HierarchyObject& parent() const { return parent_; } - /**/ HierarchyObject& parent() { return parent_; } - const BaseDirPair& root() const { return parent_.getRoot(); } - /**/ BaseDirPair& root() { return parent_.getRoot(); } - - //for use during init in "CompareProcess" only: - template <CompareFilesResult res> void setCategory(); - void setCategoryConflict(const std::wstring& description); - void setCategoryDiffMetadata(const std::wstring& description); - -protected: - FileSystemObject(const Zstring& shortNameLeft, - const Zstring& shortNameRight, - HierarchyObject& parentObj, - CompareFilesResult defaultCmpResult) : - cmpResult(defaultCmpResult), - selectedForSynchronization(true), - syncDir_(SyncDirection::NONE), - shortNameLeft_(shortNameLeft), - shortNameRight_(shortNameRight), - //shortNameRight_(shortNameRight == shortNameLeft ? shortNameLeft : shortNameRight), -> strangely doesn't seem to shrink peak memory consumption at all! - parent_(parentObj) - { - parent_.notifySyncCfgChanged(); - } - - ~FileSystemObject() {} //don't need polymorphic deletion - //mustn't call parent here, it is already partially destroyed and nothing more than a pure HierarchyObject! - - virtual void flip(); - virtual void notifySyncCfgChanged() { parent().notifySyncCfgChanged(); /*propagate!*/ } - - void setSynced(const Zstring& shortName); - -private: - virtual void removeObjectL() = 0; - virtual void removeObjectR() = 0; - - //categorization - std::unique_ptr<std::wstring> cmpResultDescr; //only filled if getCategory() == FILE_CONFLICT or FILE_DIFFERENT_METADATA - CompareFilesResult cmpResult; //although this uses 4 bytes there is currently *no* space wasted in class layout! - - bool selectedForSynchronization; - - SyncDirection syncDir_; //1 byte: optimize memory layout! - std::unique_ptr<std::wstring> syncDirConflict; //non-empty if we have a conflict setting sync-direction - //get rid of std::wstring small string optimization (consumes 32/48 byte on VS2010 x86/x64!) - - //Note: we model *four* states with last two variables => "syncDirConflict is empty or syncDir == NONE" is a class invariant!!! - - Zstring shortNameLeft_; //slightly redundant under linux, but on windows the "same" filenames can differ in case - Zstring shortNameRight_; //use as indicator: an empty name means: not existing! - - HierarchyObject& parent_; -}; - -//------------------------------------------------------------------ - -class DirPair : public FileSystemObject, public HierarchyObject -{ - friend class HierarchyObject; - -public: - virtual void accept(FSObjectVisitor& visitor) const; - - CompareDirResult getDirCategory() const; //returns actually used subset of CompareFilesResult - - DirPair(const Zstring& shortNameLeft, //use empty shortname if "not existing" - const Zstring& shortNameRight, // - HierarchyObject& parentObj, - CompareDirResult defaultCmpResult) : - FileSystemObject(shortNameLeft, shortNameRight, parentObj, static_cast<CompareFilesResult>(defaultCmpResult)), - HierarchyObject(getObjRelativeName() + FILE_NAME_SEPARATOR, parentObj.getRoot()), - syncOpBuffered(SO_DO_NOTHING), - syncOpUpToDate(false) {} - - virtual SyncOperation getSyncOperation() const; - - void setSyncedTo(const Zstring& shortName); //call after sync, sets DIR_EQUAL - -private: - virtual void flip(); - virtual void removeObjectL(); - virtual void removeObjectR(); - virtual void notifySyncCfgChanged() { syncOpUpToDate = false; FileSystemObject::notifySyncCfgChanged(); HierarchyObject::notifySyncCfgChanged(); } - - mutable SyncOperation syncOpBuffered; //determining sync-op for directory may be expensive as it depends on child-objects -> buffer it - mutable bool syncOpUpToDate; // -}; - -//------------------------------------------------------------------ - -class FilePair : public FileSystemObject -{ - friend class HierarchyObject; //construction - -public: - virtual void accept(FSObjectVisitor& visitor) const; - - FilePair(const Zstring& shortNameLeft, //use empty string if "not existing" - const FileDescriptor& left, - CompareFilesResult defaultCmpResult, - const Zstring& shortNameRight, // - const FileDescriptor& right, - HierarchyObject& parentObj) : - FileSystemObject(shortNameLeft, shortNameRight, parentObj, defaultCmpResult), - dataLeft(left), - dataRight(right), - moveFileRef(nullptr) {} - - template <SelectedSide side> Int64 getLastWriteTime () const; - template <SelectedSide side> UInt64 getFileSize () const; - template <SelectedSide side> FileId getFileId () const; - template <SelectedSide side> bool isFollowedSymlink() const; - - void setMoveRef(ObjectId refId) { moveFileRef = refId; } //reference to corresponding renamed file - ObjectId getMoveRef() const { return moveFileRef; } //may be nullptr - - CompareFilesResult getFileCategory() const; - - virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; //semantics: "what if"! assumes "active, no conflict, no recursion (directory)! - virtual SyncOperation getSyncOperation() const; - - template <SelectedSide sideTrg> - void setSyncedTo(const Zstring& shortName, //call after sync, sets FILE_EQUAL - const UInt64& fileSize, - const Int64& lastWriteTimeTrg, - const Int64& lastWriteTimeSrc, - const FileId& fileIdTrg, - const FileId& fileIdSrc, - bool isSymlinkTrg, - bool isSymlinkSrc); - -private: - SyncOperation applyMoveOptimization(SyncOperation op) const; - - virtual void flip(); - virtual void removeObjectL(); - virtual void removeObjectR(); - - FileDescriptor dataLeft; - FileDescriptor dataRight; - - ObjectId moveFileRef; //optional, filled by redetermineSyncDirection() -}; - -//------------------------------------------------------------------ - -class SymlinkPair : public FileSystemObject //this class models a TRUE symbolic link, i.e. one that is NEVER dereferenced: deref-links should be directly placed in class File/DirPair -{ - friend class HierarchyObject; //construction - -public: - virtual void accept(FSObjectVisitor& visitor) const; - - template <SelectedSide side> zen::Int64 getLastWriteTime() const; //write time of the link, NOT target! - - CompareSymlinkResult getLinkCategory() const; //returns actually used subset of CompareFilesResult - - SymlinkPair(const Zstring& shortNameLeft, //use empty string if "not existing" - const LinkDescriptor& left, - CompareSymlinkResult defaultCmpResult, - const Zstring& shortNameRight, //use empty string if "not existing" - const LinkDescriptor& right, - HierarchyObject& parentObj) : - FileSystemObject(shortNameLeft, shortNameRight, parentObj, static_cast<CompareFilesResult>(defaultCmpResult)), - dataLeft(left), - dataRight(right) {} - - template <SelectedSide sideTrg> - void setSyncedTo(const Zstring& shortName, //call after sync, sets SYMLINK_EQUAL - const Int64& lastWriteTimeTrg, - const Int64& lastWriteTimeSrc); - -private: - virtual void flip(); - virtual void removeObjectL(); - virtual void removeObjectR(); - - LinkDescriptor dataLeft; - LinkDescriptor dataRight; -}; - -//------------------------------------------------------------------ - -//generic type descriptions (usecase CSV legend, sync config) -std::wstring getCategoryDescription(CompareFilesResult cmpRes); -std::wstring getSyncOpDescription (SyncOperation op); - -//item-specific type descriptions -std::wstring getCategoryDescription(const FileSystemObject& fsObj); -std::wstring getSyncOpDescription (const FileSystemObject& fsObj); - -//------------------------------------------------------------------ - - - - - - - - - - - - - - - - - - - - - - -//---------------Inline Implementation--------------------------------------------------- -//inline virtual... admittedly its use may be limited -inline void FilePair ::accept(FSObjectVisitor& visitor) const { visitor.visit(*this); } -inline void DirPair ::accept(FSObjectVisitor& visitor) const { visitor.visit(*this); } -inline void SymlinkPair::accept(FSObjectVisitor& visitor) const { visitor.visit(*this); } - - -inline -CompareFilesResult FilePair::getFileCategory() const -{ - return getCategory(); -} - - -inline -CompareDirResult DirPair::getDirCategory() const -{ - return static_cast<CompareDirResult>(getCategory()); -} - - -inline -std::wstring FileSystemObject::getCatExtraDescription() const -{ - assert(getCategory() == FILE_CONFLICT || getCategory() == FILE_DIFFERENT_METADATA); - return cmpResultDescr ? *cmpResultDescr : std::wstring(); -} - - -inline -SyncDirection FileSystemObject::getSyncDir() const -{ - return syncDir_; -} - - -inline -void FileSystemObject::setSyncDir(SyncDirection newDir) -{ - syncDir_ = newDir; - syncDirConflict.reset(); - - notifySyncCfgChanged(); -} - - -inline -void FileSystemObject::setSyncDirConflict(const std::wstring& description) -{ - syncDir_ = SyncDirection::NONE; - syncDirConflict.reset(new std::wstring(description)); - - notifySyncCfgChanged(); -} - - -inline -std::wstring FileSystemObject::getSyncOpConflict() const -{ - assert(getSyncOperation() == SO_UNRESOLVED_CONFLICT); - return syncDirConflict ? *syncDirConflict : std::wstring(); -} - - -inline -bool FileSystemObject::isActive() const -{ - return selectedForSynchronization; -} - - -inline -void FileSystemObject::setActive(bool active) -{ - selectedForSynchronization = active; - notifySyncCfgChanged(); -} - - -template <SelectedSide side> inline -bool FileSystemObject::isEmpty() const -{ - return SelectParam<side>::get(shortNameLeft_, shortNameRight_).empty(); -} - - -inline -bool FileSystemObject::isEmpty() const -{ - return isEmpty<LEFT_SIDE>() && isEmpty<RIGHT_SIDE>(); -} - - -template <SelectedSide side> inline -const Zstring& FileSystemObject::getShortName() const -{ - return SelectParam<side>::get(shortNameLeft_, shortNameRight_); //empty if not existing -} - - -template <SelectedSide side> inline -Zstring FileSystemObject::getRelativeName() const -{ - return isEmpty<side>() ? Zstring() : parent_.getObjRelativeNamePf() + getShortName<side>(); -} - - -inline -Zstring FileSystemObject::getObjRelativeName() const -{ - return parent_.getObjRelativeNamePf() + getObjShortName(); -} - - -inline -Zstring FileSystemObject::getObjShortName() const -{ - return isEmpty<LEFT_SIDE>() ? getShortName<RIGHT_SIDE>() : getShortName<LEFT_SIDE>(); -} - - -template <SelectedSide side> inline -Zstring FileSystemObject::getFullName() const -{ - return isEmpty<side>() ? Zstring() : getBaseDirPf<side>() + parent_.getObjRelativeNamePf() + getShortName<side>(); -} - - -template <SelectedSide side> inline -const Zstring& FileSystemObject::getBaseDirPf() const -{ - return root().getBaseDirPf<side>(); -} - - -template <> inline -void FileSystemObject::removeObject<LEFT_SIDE>() -{ - cmpResult = isEmpty<RIGHT_SIDE>() ? FILE_EQUAL : FILE_RIGHT_SIDE_ONLY; - shortNameLeft_.clear(); - removeObjectL(); - - setSyncDir(SyncDirection::NONE); //calls notifySyncCfgChanged() -} - - -template <> inline -void FileSystemObject::removeObject<RIGHT_SIDE>() -{ - cmpResult = isEmpty<LEFT_SIDE>() ? FILE_EQUAL : FILE_LEFT_SIDE_ONLY; - shortNameRight_.clear(); - removeObjectR(); - - setSyncDir(SyncDirection::NONE); //calls notifySyncCfgChanged() -} - - -inline -void FileSystemObject::setSynced(const Zstring& shortName) -{ - assert(!isEmpty()); - shortNameRight_ = shortNameLeft_ = shortName; - cmpResult = FILE_EQUAL; - setSyncDir(SyncDirection::NONE); -} - - -template <CompareFilesResult res> inline -void FileSystemObject::setCategory() -{ - cmpResult = res; -} -template <> void FileSystemObject::setCategory<FILE_CONFLICT>(); // -template <> void FileSystemObject::setCategory<FILE_DIFFERENT_METADATA>(); //not defined! -template <> void FileSystemObject::setCategory<FILE_LEFT_SIDE_ONLY>(); // -template <> void FileSystemObject::setCategory<FILE_RIGHT_SIDE_ONLY>(); // - -inline -void FileSystemObject::setCategoryConflict(const std::wstring& description) -{ - cmpResult = FILE_CONFLICT; - cmpResultDescr.reset(new std::wstring(description)); -} - -inline -void FileSystemObject::setCategoryDiffMetadata(const std::wstring& description) -{ - cmpResult = FILE_DIFFERENT_METADATA; - cmpResultDescr.reset(new std::wstring(description)); -} - -inline -void FileSystemObject::flip() -{ - std::swap(shortNameLeft_, shortNameRight_); - - switch (cmpResult) - { - case FILE_LEFT_SIDE_ONLY: - cmpResult = FILE_RIGHT_SIDE_ONLY; - break; - case FILE_RIGHT_SIDE_ONLY: - cmpResult = FILE_LEFT_SIDE_ONLY; - break; - case FILE_LEFT_NEWER: - cmpResult = FILE_RIGHT_NEWER; - break; - case FILE_RIGHT_NEWER: - cmpResult = FILE_LEFT_NEWER; - break; - case FILE_DIFFERENT: - case FILE_EQUAL: - case FILE_DIFFERENT_METADATA: - case FILE_CONFLICT: - break; - } - - notifySyncCfgChanged(); -} - - -inline -void HierarchyObject::flip() -{ - for (FilePair& fileObj : refSubFiles()) - fileObj.flip(); - for (SymlinkPair& linkObj : refSubLinks()) - linkObj.flip(); - for (DirPair& dirObj : refSubDirs()) - dirObj.flip(); -} - - -inline -DirPair& HierarchyObject::addSubDir(const Zstring& shortNameLeft, - const Zstring& shortNameRight, - CompareDirResult defaultCmpResult) -{ - subDirs.emplace_back(shortNameLeft, shortNameRight, *this, defaultCmpResult); - return subDirs.back(); -} - - -template <> inline -DirPair& HierarchyObject::addSubDir<LEFT_SIDE>(const Zstring& shortName) -{ - subDirs.emplace_back(shortName, Zstring(), *this, DIR_LEFT_SIDE_ONLY); - return subDirs.back(); -} - - -template <> inline -DirPair& HierarchyObject::addSubDir<RIGHT_SIDE>(const Zstring& shortName) -{ - subDirs.emplace_back(Zstring(), shortName, *this, DIR_RIGHT_SIDE_ONLY); - return subDirs.back(); -} - - -inline -FilePair& HierarchyObject::addSubFile(const Zstring& shortNameLeft, - const FileDescriptor& left, //file exists on both sides - CompareFilesResult defaultCmpResult, - const Zstring& shortNameRight, - const FileDescriptor& right) -{ - subFiles.emplace_back(shortNameLeft, left, defaultCmpResult, shortNameRight, right, *this); - return subFiles.back(); -} - - -template <> inline -FilePair& HierarchyObject::addSubFile<LEFT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) -{ - subFiles.emplace_back(shortName, descr, FILE_LEFT_SIDE_ONLY, Zstring(), FileDescriptor(), *this); - return subFiles.back(); -} - - -template <> inline -FilePair& HierarchyObject::addSubFile<RIGHT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) -{ - subFiles.emplace_back(Zstring(), FileDescriptor(), FILE_RIGHT_SIDE_ONLY, shortName, descr, *this); - return subFiles.back(); -} - - -inline -SymlinkPair& HierarchyObject::addSubLink( - const Zstring& shortNameLeft, - const LinkDescriptor& left, //link exists on both sides - CompareSymlinkResult defaultCmpResult, - const Zstring& shortNameRight, - const LinkDescriptor& right) -{ - subLinks.emplace_back(shortNameLeft, left, defaultCmpResult, shortNameRight, right, *this); - return subLinks.back(); -} - - -template <> inline -SymlinkPair& HierarchyObject::addSubLink<LEFT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) -{ - subLinks.emplace_back(shortName, descr, SYMLINK_LEFT_SIDE_ONLY, Zstring(), LinkDescriptor(), *this); - return subLinks.back(); -} - - -template <> inline -SymlinkPair& HierarchyObject::addSubLink<RIGHT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) -{ - subLinks.emplace_back(Zstring(), LinkDescriptor(), SYMLINK_RIGHT_SIDE_ONLY, shortName, descr, *this); - return subLinks.back(); -} - - -inline -void BaseDirPair::flip() -{ - HierarchyObject::flip(); - std::swap(baseDirPfL, baseDirPfR); - std::swap(dirExistsLeft_, dirExistsRight_); -} - - -inline -void DirPair::flip() -{ - HierarchyObject ::flip(); //call base class versions - FileSystemObject::flip(); // -} - - -inline -void DirPair::removeObjectL() -{ - for (FilePair& fileObj : refSubFiles()) - fileObj.removeObject<LEFT_SIDE>(); - for (SymlinkPair& linkObj : refSubLinks()) - linkObj.removeObject<LEFT_SIDE>(); - for (DirPair& dirObj : refSubDirs()) - dirObj.removeObject<LEFT_SIDE>(); -} - - -inline -void DirPair::removeObjectR() -{ - for (FilePair& fileObj : refSubFiles()) - fileObj.removeObject<RIGHT_SIDE>(); - for (SymlinkPair& linkObj : refSubLinks()) - linkObj.removeObject<RIGHT_SIDE>(); - for (DirPair& dirObj : refSubDirs()) - dirObj.removeObject<RIGHT_SIDE>(); -} - - -template <SelectedSide side> inline -bool BaseDirPair::isExisting() const -{ - return SelectParam<side>::get(dirExistsLeft_, dirExistsRight_); -} - - -template <SelectedSide side> inline -void BaseDirPair::setExisting(bool value) -{ - SelectParam<side>::get(dirExistsLeft_, dirExistsRight_) = value; -} - - -inline -void FilePair::flip() -{ - FileSystemObject::flip(); //call base class version - std::swap(dataLeft, dataRight); -} - - -inline -void FilePair::removeObjectL() -{ - dataLeft = FileDescriptor(); -} - - -inline -void FilePair::removeObjectR() -{ - dataRight = FileDescriptor(); -} - - -template <SelectedSide side> inline -zen::Int64 FilePair::getLastWriteTime() const -{ - return SelectParam<side>::get(dataLeft, dataRight).lastWriteTimeRaw; -} - - -template <SelectedSide side> inline -zen::UInt64 FilePair::getFileSize() const -{ - return SelectParam<side>::get(dataLeft, dataRight).fileSize; -} - - -template <SelectedSide side> inline -FileId FilePair::getFileId() const -{ - return FileId(SelectParam<side>::get(dataLeft, dataRight).devId, - SelectParam<side>::get(dataLeft, dataRight).fileIdx); -} - - -template <SelectedSide side> inline -bool FilePair::isFollowedSymlink() const -{ - return SelectParam<side>::get(dataLeft, dataRight).isFollowedSymlink; -} - - -template <SelectedSide sideTrg> inline -void FilePair::setSyncedTo(const Zstring& shortName, - const UInt64& fileSize, - const Int64& lastWriteTimeTrg, - const Int64& lastWriteTimeSrc, - const FileId& fileIdTrg, - const FileId& fileIdSrc, - bool isSymlinkTrg, - bool isSymlinkSrc) -{ - //FILE_EQUAL is only allowed for same short name and file size: enforced by this method! - static const SelectedSide sideSrc = OtherSide<sideTrg>::result; - - SelectParam<sideTrg>::get(dataLeft, dataRight) = FileDescriptor(lastWriteTimeTrg, fileSize, fileIdTrg, isSymlinkTrg); - SelectParam<sideSrc>::get(dataLeft, dataRight) = FileDescriptor(lastWriteTimeSrc, fileSize, fileIdSrc, isSymlinkSrc); - - moveFileRef = nullptr; - FileSystemObject::setSynced(shortName); //set FileSystemObject specific part -} - - -template <SelectedSide sideTrg> inline -void SymlinkPair::setSyncedTo(const Zstring& shortName, - const Int64& lastWriteTimeTrg, - const Int64& lastWriteTimeSrc) -{ - static const SelectedSide sideSrc = OtherSide<sideTrg>::result; - - SelectParam<sideTrg>::get(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeTrg); - SelectParam<sideSrc>::get(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeSrc); - - FileSystemObject::setSynced(shortName); //set FileSystemObject specific part -} - - -inline -void DirPair::setSyncedTo(const Zstring& shortName) -{ - FileSystemObject::setSynced(shortName); //set FileSystemObject specific part -} - - -template <SelectedSide side> inline -zen::Int64 SymlinkPair::getLastWriteTime() const -{ - return SelectParam<side>::get(dataLeft, dataRight).lastWriteTimeRaw; -} - - -inline -CompareSymlinkResult SymlinkPair::getLinkCategory() const -{ - return static_cast<CompareSymlinkResult>(getCategory()); -} - - -inline -void SymlinkPair::flip() -{ - FileSystemObject::flip(); //call base class versions - std::swap(dataLeft, dataRight); -} - - -inline -void SymlinkPair::removeObjectL() -{ - dataLeft = LinkDescriptor(); -} - - -inline -void SymlinkPair::removeObjectR() -{ - dataRight = LinkDescriptor(); -} -} - -#endif // FILEHIERARCHY_H_INCLUDED |