summaryrefslogtreecommitdiff
path: root/file_hierarchy.h
diff options
context:
space:
mode:
Diffstat (limited to 'file_hierarchy.h')
-rw-r--r--file_hierarchy.h1112
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
bgstack15