diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:58:10 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 16:58:10 +0200 |
commit | fefe20351d0720683990b666584b6879c90bd37d (patch) | |
tree | 8ab90520ae2123ac84293b0f9cec006317e5fc01 /algorithm.cpp | |
parent | 1.18 (diff) | |
download | FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.gz FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.tar.bz2 FreeFileSync-fefe20351d0720683990b666584b6879c90bd37d.zip |
1.19
Diffstat (limited to 'algorithm.cpp')
-rw-r--r-- | algorithm.cpp | 200 |
1 files changed, 75 insertions, 125 deletions
diff --git a/algorithm.cpp b/algorithm.cpp index c595bdd3..00c1e81f 100644 --- a/algorithm.cpp +++ b/algorithm.cpp @@ -148,78 +148,18 @@ void FreeFileSync::swapGrids(FolderComparison& folderCmp) else if (i->cmpResult == FILE_LEFT_NEWER) i->cmpResult = FILE_RIGHT_NEWER; + //swap sync direction + if (i->direction == SYNC_DIR_LEFT) + i->direction = SYNC_DIR_RIGHT; + else if (i->direction == SYNC_DIR_RIGHT) + i->direction = SYNC_DIR_LEFT; + //swap file descriptors std::swap(i->fileDescrLeft, i->fileDescrRight); } } } -/* -void FreeFileSync::adjustModificationTimes(const Zstring& parentDirectory, const int timeInSeconds, ErrorHandler* errorHandler) throw(AbortThisProcess) -{ -#ifndef __WXDEBUG__ - wxLogNull noWxLogs; //prevent wxWidgets logging -#endif - - if (timeInSeconds == 0) - return; - - std::vector<Zstring> fileList; - std::vector<Zstring> dirList; - - while (true) //should be executed in own scope so that directory access does not disturb deletion - { - try - { //get all files and folders from directory (and subdirectories) - FreeFileSync::getAllFilesAndDirs(parentDirectory, fileList, dirList); - break; - } - catch (const FileError& e) - { - ErrorHandler::Response rv = errorHandler->reportError(e.show()); - if (rv == ErrorHandler::IGNORE_ERROR) - break; - else if (rv == ErrorHandler::RETRY) - ; //continue with loop - else - assert (false); - } - } - - //this part is only a bit slower than direct Windows API-access! - wxDateTime modTime; - for (unsigned int j = 0; j < fileList.size(); ++j) - { - while (true) //own scope for directory access to not disturb file access! - { - try - { - wxFileName file(fileList[j].c_str()); - if (!file.GetTimes(NULL, &modTime, NULL)) //get modification time - throw FileError(Zstring(_("Error changing modification time:")) + wxT(" \"") + fileList[j] + wxT("\"")); - - modTime.Add(wxTimeSpan(0, 0, timeInSeconds, 0)); - - if (!file.SetTimes(NULL, &modTime, NULL)) //get modification time - throw FileError(Zstring(_("Error changing modification time:")) + wxT(" \"") + fileList[j] + wxT("\"")); - - break; - } - catch (const FileError& error) - { - ErrorHandler::Response rv = errorHandler->reportError(error.show()); - if (rv == ErrorHandler::IGNORE_ERROR) - break; - else if (rv == ErrorHandler::RETRY) - ; //continue with loop - else - assert (false); - } - } - } -} -*/ - //add(!) all files and subfolder gridlines that are dependent from the directory void FreeFileSync::addSubElements(const FileComparison& fileCmp, const FileCompareLine& relevantRow, std::set<int>& subElements) @@ -358,35 +298,44 @@ private: template <bool leftSide> //update compareGrid row information after deletion from leftSide (or !leftSide) inline -void updateCmpLineAfterDeletion(FileCompareLine& relevantRow, const int rowNr, RemoveAtExit& markForRemoval) +void updateCmpLineAfterDeletion(const int rowNr, const SyncConfiguration& syncConfig, FileComparison& fileCmp, RemoveAtExit& markForRemoval) { - FileDescrLine* fileDescr; //get descriptor for file to be deleted; evaluated at compile time - FileDescrLine* fileDescrPartner; //file descriptor for "other side" - if (leftSide) - { - fileDescr = &relevantRow.fileDescrLeft; - fileDescrPartner = &relevantRow.fileDescrRight; - } - else - { - fileDescr = &relevantRow.fileDescrRight; - fileDescrPartner = &relevantRow.fileDescrLeft; - } + //retrieve all files and subfolder gridlines that are dependent from this deleted entry + std::set<int> rowsToDelete; + rowsToDelete.insert(rowNr); + FreeFileSync::addSubElements(fileCmp, fileCmp[rowNr], rowsToDelete); - - //remove deleted entries from grid - if (fileDescrPartner->objType == FileDescrLine::TYPE_NOTHING) - markForRemoval.removeRow(rowNr); - else + //remove deleted entries from fileCmp (or adapt it if deleted from one side only) + for (std::set<int>::iterator j = rowsToDelete.begin(); j != rowsToDelete.end(); ++j) { - //initialize fileDescr for deleted file/folder - *fileDescr = FileDescrLine(); + FileCompareLine& currentLine = fileCmp[*j]; - //adapt the compare result - if (leftSide) //again evaluated at compile time - relevantRow.cmpResult = FILE_RIGHT_SIDE_ONLY; + //file descriptor for "other side" + const FileDescrLine* const fileDescrPartner = leftSide ? ¤tLine.fileDescrRight : ¤tLine.fileDescrLeft; + + //remove deleted entries from grid + if (fileDescrPartner->objType == FileDescrLine::TYPE_NOTHING) + markForRemoval.removeRow(*j); else - relevantRow.cmpResult = FILE_LEFT_SIDE_ONLY; + { + //get descriptor for file to be deleted; evaluated at compile time + FileDescrLine* const fileDescr = leftSide ? ¤tLine.fileDescrLeft : ¤tLine.fileDescrRight; + + //initialize fileDescr for deleted file/folder + *fileDescr = FileDescrLine(); + + //adapt the compare result and sync direction + if (leftSide) //again evaluated at compile time + { + currentLine.cmpResult = FILE_RIGHT_SIDE_ONLY; + currentLine.direction = syncConfig.exRightSideOnly; + } + else + { + currentLine.cmpResult = FILE_LEFT_SIDE_ONLY; + currentLine.direction = syncConfig.exLeftSideOnly; + } + } } } @@ -396,43 +345,32 @@ void deleteFromGridAndHDOneSide(FileComparison& fileCmp, const std::set<int>& rowsToDeleteOneSide, const bool useRecycleBin, RemoveAtExit& markForRemoval, + const SyncConfiguration& syncConfig, ErrorHandler* errorHandler) { for (std::set<int>::iterator i = rowsToDeleteOneSide.begin(); i != rowsToDeleteOneSide.end(); ++i) { - FileCompareLine& currentCmpLine = fileCmp[*i]; - - FileDescrLine* fileDescr = NULL; //get descriptor for file to be deleted; evaluated at compile time - if (leftSide) - fileDescr = ¤tCmpLine.fileDescrLeft; - else - fileDescr = ¤tCmpLine.fileDescrRight; + //get descriptor for file to be deleted; evaluated at compile time + const FileDescrLine* const fileDescr = leftSide ? &fileCmp[*i].fileDescrLeft : &fileCmp[*i].fileDescrRight; while (true) { try { - if (fileDescr->objType == FileDescrLine::TYPE_FILE) + switch (fileDescr->objType) + { + case FileDescrLine::TYPE_FILE: FreeFileSync::removeFile(fileDescr->fullName, useRecycleBin); - else if (fileDescr->objType == FileDescrLine::TYPE_DIRECTORY) + updateCmpLineAfterDeletion<leftSide>(*i, syncConfig, fileCmp, markForRemoval); //remove entries from fileCmp + break; + case FileDescrLine::TYPE_DIRECTORY: FreeFileSync::removeDirectory(fileDescr->fullName, useRecycleBin); - else if (fileDescr->objType == FileDescrLine::TYPE_NOTHING) - break; //nothing to do - else - { - assert(false); + updateCmpLineAfterDeletion<leftSide>(*i, syncConfig, fileCmp, markForRemoval); //remove entries from fileCmp + break; + case FileDescrLine::TYPE_NOTHING: break; } - //retrieve all files and subfolder gridlines that are dependent from this deleted entry - std::set<int> rowsToDelete; - rowsToDelete.insert(*i); - FreeFileSync::addSubElements(fileCmp, currentCmpLine, rowsToDelete); - - //remove deleted entries from fileCmp (or adapt it if deleted from one side only) - for (std::set<int>::iterator j = rowsToDelete.begin(); j != rowsToDelete.end(); ++j) - updateCmpLineAfterDeletion<leftSide>(fileCmp[*j], *j, markForRemoval); - break; } catch (const FileError& error) @@ -457,6 +395,7 @@ void FreeFileSync::deleteFromGridAndHD(FileComparison& fileCmp, const std::set<int>& rowsToDeleteOnRight, const bool deleteOnBothSides, const bool useRecycleBin, + const SyncConfiguration& syncConfig, ErrorHandler* errorHandler) { //remove deleted rows from fileCmp (AFTER all rows to be deleted are known: consider row references! @@ -473,12 +412,14 @@ void FreeFileSync::deleteFromGridAndHD(FileComparison& fileCmp, rowsToDeleteBothSides, useRecycleBin, markForRemoval, + syncConfig, errorHandler); deleteFromGridAndHDOneSide<false>(fileCmp, rowsToDeleteBothSides, useRecycleBin, markForRemoval, + syncConfig, errorHandler); } else @@ -487,12 +428,14 @@ void FreeFileSync::deleteFromGridAndHD(FileComparison& fileCmp, rowsToDeleteOnLeft, useRecycleBin, markForRemoval, + syncConfig, errorHandler); deleteFromGridAndHDOneSide<false>(fileCmp, rowsToDeleteOnRight, useRecycleBin, markForRemoval, + syncConfig, errorHandler); } } @@ -528,11 +471,12 @@ void writeFourDigitNumber(unsigned int number, wxChar*& position) } -wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime) +wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zstring& filename) { #ifdef FFS_WIN //convert ansi C time to FILETIME wxLongLong fileTimeLong(utcTime); + fileTimeLong += wxLongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s fileTimeLong *= 10000000; @@ -540,19 +484,29 @@ wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime) lastWriteTimeUtc.dwLowDateTime = fileTimeLong.GetLo(); //GetLo() returns unsigned lastWriteTimeUtc.dwHighDateTime = unsigned(fileTimeLong.GetHi()); //GetHi() returns signed + FILETIME localFileTime; - if (FileTimeToLocalFileTime( //convert to local time + if (::FileTimeToLocalFileTime( //convert to local time &lastWriteTimeUtc, //pointer to UTC file time to convert &localFileTime //pointer to converted file time ) == 0) - throw RuntimeException(wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME")); + throw RuntimeException(wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME: ") + + wxT("(") + wxULongLong(lastWriteTimeUtc.dwHighDateTime, lastWriteTimeUtc.dwLowDateTime).ToString() + wxT(") ") + + filename.c_str() + wxT("\n\n") + getLastErrorFormatted().c_str()); + + if (localFileTime.dwHighDateTime > 2147483647) //== 256^4 / 2 - 1 == 0x7fffffff + return _("Error"); //this actually CAN happen if UTC time is just below this border and ::FileTimeToLocalFileTime() adds 2 hours due to DST or whatever! + //Testcase (UTC): dateHigh = 2147483647 -> year 30000 + // dateLow = 4294967295 SYSTEMTIME time; - if (FileTimeToSystemTime( + if (::FileTimeToSystemTime( &localFileTime, //pointer to file time to convert &time //pointer to structure to receive system time ) == 0) - throw RuntimeException(wxString(_("Conversion error:")) + wxT(" FILETIME -> SYSTEMTIME")); + throw RuntimeException(wxString(_("Conversion error:")) + wxT(" local FILETIME -> SYSTEMTIME: ") + + wxT("(") + wxULongLong(localFileTime.dwHighDateTime, localFileTime.dwLowDateTime).ToString() + wxT(") ") + + filename.c_str() + wxT("\n\n") + getLastErrorFormatted().c_str()); //assemble time string (performance optimized) wxChar formattedTime[21]; @@ -589,10 +543,8 @@ wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime) #ifdef FFS_WIN Zstring FreeFileSync::getLastErrorFormatted(const unsigned long lastError) //try to get additional Windows error information { - unsigned long lastErrorCode = lastError; - //determine error code if none was specified - if (lastErrorCode == 0) - lastErrorCode = GetLastError(); + //determine error code if none was specified + const unsigned long lastErrorCode = lastError == 0 ? GetLastError() : lastError; Zstring output = Zstring(wxT("Windows Error Code ")) + wxString::Format(wxT("%u"), lastErrorCode).c_str(); @@ -605,10 +557,8 @@ Zstring FreeFileSync::getLastErrorFormatted(const unsigned long lastError) //try #elif defined FFS_LINUX Zstring FreeFileSync::getLastErrorFormatted(const int lastError) //try to get additional Linux error information { - int lastErrorCode = lastError; //determine error code if none was specified - if (lastErrorCode == 0) - lastErrorCode = errno; + const int lastErrorCode = lastError == 0 ? errno : lastError; Zstring output = Zstring(wxT("Linux Error Code ")) + wxString::Format(wxT("%i"), lastErrorCode).c_str(); output += Zstring(wxT(": ")) + strerror(lastErrorCode); |