X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=Src%2FDirScan.cpp;h=4f456230c42851be4b36bf86f8b3d26f506a968e;hb=5a478c4115f3ffeb35fb51df893912409c793bb0;hp=c3e046af480a6007cc4a1eab2193b263b5a5f5c4;hpb=56731d4646df290074fa201a1ccc15c6ee8d4a8b;p=winmerge-jp%2Fwinmerge-jp.git diff --git a/Src/DirScan.cpp b/Src/DirScan.cpp index c3e046af4..4f456230c 100644 --- a/Src/DirScan.cpp +++ b/Src/DirScan.cpp @@ -4,6 +4,7 @@ * @brief Implementation of DirScan (q.v.) and helper functions */ +#include "pch.h" #include "DirScan.h" #include #include @@ -26,7 +27,6 @@ #include "FolderCmp.h" #include "FileFilterHelper.h" #include "IAbortable.h" -#include "FolderCmp.h" #include "DirItem.h" #include "DirTravel.h" #include "paths.h" @@ -34,6 +34,8 @@ #include "MergeApp.h" #include "OptionsDef.h" #include "OptionsMgr.h" +#include "PathContext.h" +#include "DebugNew.h" using Poco::NotificationQueue; using Poco::Notification; @@ -45,15 +47,13 @@ using Poco::Environment; using Poco::Stopwatch; // Static functions (ie, functions only used locally) -void CompareDiffItem(DIFFITEM &di, CDiffContext * pCtxt); -static void StoreDiffData(DIFFITEM &di, CDiffContext * pCtxt, - const FolderCmp * pCmpData); -static DIFFITEM *AddToList(const String& sLeftDir, const String& sRightDir, const DirItem * lent, const DirItem * rent, +static void CompareDiffItem(FolderCmp &fc, DIFFITEM &di); +static DIFFITEM *AddToList(const String &sLeftDir, const String &sRightDir, const DirItem *lent, const DirItem *rent, unsigned code, DiffFuncStruct *myStruct, DIFFITEM *parent); -static DIFFITEM *AddToList(const String& sDir1, const String& sDir2, const String& sDir3, const DirItem * ent1, const DirItem * ent2, const DirItem * ent3, +static DIFFITEM *AddToList(const String &sDir1, const String &sDir2, const String &sDir3, const DirItem *ent1, const DirItem *ent2, const DirItem *ent3, unsigned code, DiffFuncStruct *myStruct, DIFFITEM *parent, int nItems = 3); -static void UpdateDiffItem(DIFFITEM & di, bool & bExists, CDiffContext *pCtxt); -static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, uintptr_t parentdiffpos); +static void UpdateDiffItem(DIFFITEM &di, bool &bExists, CDiffContext *pCtxt); +static int CompareItems(NotificationQueue &queue, DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos); class WorkNotification: public Poco::Notification { @@ -83,18 +83,19 @@ public: void run() { + FolderCmp fc(m_pCtxt); // keep the scripts alive during the Rescan // when we exit the thread, we delete this and release the scripts CAssureScriptsForThread scriptsForRescan; AutoPtr pNf(m_queue.waitDequeueNotification()); - while (pNf) + while (pNf.get() != nullptr) { WorkNotification* pWorkNf = dynamic_cast(pNf.get()); - if (pWorkNf) { + if (pWorkNf != nullptr) { m_pCtxt->m_pCompareStats->BeginCompare(&pWorkNf->data(), m_id); if (!m_pCtxt->ShouldAbort()) - CompareDiffItem(pWorkNf->data(), m_pCtxt); + CompareDiffItem(fc, pWorkNf->data()); pWorkNf->queueResult().enqueueNotification(new WorkCompletedNotification(pWorkNf->data())); } pNf = m_queue.waitDequeueNotification(); @@ -113,7 +114,7 @@ typedef std::shared_ptr DiffWorkerPtr; * @brief Collect file- and folder-names to list. * This function walks given folders and adds found subfolders and files into * lists. There are two modes, determined by the @p depth: - * - in non-recursive mode we walk only given folders, and add files. + * - in non-recursive mode we walk only given folders, and add files * contained. Subfolders are added as folder items, not walked into. * - in recursive mode we walk all subfolders and add the files they * contain into list. @@ -126,7 +127,7 @@ typedef std::shared_ptr DiffWorkerPtr; * @param [in] rightsubdir Right side subdirectory under root path * @param [in] bRightUniq Is right-side folder unique folder? * @param [in] myStruct Compare-related data, like context etc. - * @param [in] casesensitive Is filename compare casesensitive? + * @param [in] casesensitive Is filename compare case sensitive? * @param [in] depth Levels of subdirectories to scan, -1 scans all * @param [in] parent Folder diff item to be scanned * @param [in] bUniques If true, walk into unique folders. @@ -143,12 +144,11 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], String sDir[3]; String subprefix[3]; - int nIndex; std::copy(paths.begin(), paths.end(), sDir); if (!subdir[0].empty()) { - for (nIndex = 0; nIndex < paths.GetSize(); nIndex++) + for (int nIndex = 0; nIndex < paths.GetSize(); nIndex++) { sDir[nIndex] = paths::ConcatPath(sDir[nIndex], subdir[nIndex]); subprefix[nIndex] = subdir[nIndex] + backslash; @@ -156,7 +156,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], } DirItemArray dirs[3], aFiles[3]; - for (nIndex = 0; nIndex < nDirs; nIndex++) + for (int nIndex = 0; nIndex < nDirs; nIndex++) LoadAndSortFiles(sDir[nIndex], &dirs[nIndex], &aFiles[nIndex], casesensitive); // Allow user to abort scanning @@ -167,13 +167,16 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], // i points to current directory in left list (leftDirs) // j points to current directory in right list (rightDirs) - for (nIndex = 0; nIndex < nDirs; nIndex++) - if (dirs[nIndex].size() != 0 || aFiles[nIndex].size() != 0) break; - if (nIndex == nDirs) - return 0; + { + int nIndex; + for (nIndex = 0; nIndex < nDirs; nIndex++) + if (dirs[nIndex].size() != 0 || aFiles[nIndex].size() != 0) break; + if (nIndex == nDirs) + return 0; + } DirItemArray::size_type i=0, j=0, k=0; - while (1) + while (true) { if (pCtxt->ShouldAbort()) return -1; @@ -235,7 +238,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], // Test against filter so we don't include contents of filtered out directories // Also this is only place we can test for both-sides directories in recursive compare - if ((pCtxt->m_piFilterGlobal && !pCtxt->m_piFilterGlobal->includeDir(leftnewsub, rightnewsub)) || + if ((pCtxt->m_piFilterGlobal!=nullptr && !pCtxt->m_piFilterGlobal->includeDir(leftnewsub, rightnewsub)) || (pCtxt->m_bIgnoreReparsePoints && ( (nDiffCode & DIFFCODE::FIRST) && (dirs[0][i].flags.attributes & FILE_ATTRIBUTE_REPARSE_POINT) || (nDiffCode & DIFFCODE::SECOND) && (dirs[1][j].flags.attributes & FILE_ATTRIBUTE_REPARSE_POINT)) @@ -260,7 +263,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], // Test against filter so we don't include contents of filtered out directories // Also this is only place we can test for both-sides directories in recursive compare - if ((pCtxt->m_piFilterGlobal && !pCtxt->m_piFilterGlobal->includeDir(leftnewsub, middlenewsub, rightnewsub)) || + if ((pCtxt->m_piFilterGlobal!=nullptr && !pCtxt->m_piFilterGlobal->includeDir(leftnewsub, middlenewsub, rightnewsub)) || (pCtxt->m_bIgnoreReparsePoints && ( (nDiffCode & DIFFCODE::FIRST) && (dirs[0][i].flags.attributes & FILE_ATTRIBUTE_REPARSE_POINT) || (nDiffCode & DIFFCODE::SECOND) && (dirs[1][j].flags.attributes & FILE_ATTRIBUTE_REPARSE_POINT) || @@ -275,14 +278,14 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], { if (nDirs < 3) AddToList(subdir[0], subdir[1], - (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : NULL, - (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : NULL, + (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : nullptr, + (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : nullptr, nDiffCode, myStruct, parent); else AddToList(subdir[0], subdir[1], subdir[2], - (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : NULL, - (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : NULL, - (nDiffCode & DIFFCODE::THIRD ) ? &dirs[2][k] : NULL, + (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : nullptr, + (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : nullptr, + (nDiffCode & DIFFCODE::THIRD ) ? &dirs[2][k] : nullptr, nDiffCode, myStruct, parent); } else @@ -291,8 +294,8 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], if (nDirs < 3) { DIFFITEM *me = AddToList(subdir[0], subdir[1], - (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : NULL, - (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : NULL, + (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : nullptr, + (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : nullptr, nDiffCode, myStruct, parent); if ((nDiffCode & DIFFCODE::SKIPPED) == 0 && ((nDiffCode & DIFFCODE::SIDEFLAGS) == DIFFCODE::BOTH || bUniques)) { @@ -307,9 +310,9 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], else { DIFFITEM *me = AddToList(subdir[0], subdir[1], subdir[2], - (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : NULL, - (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : NULL, - (nDiffCode & DIFFCODE::THIRD ) ? &dirs[2][k] : NULL, + (nDiffCode & DIFFCODE::FIRST ) ? &dirs[0][i] : nullptr, + (nDiffCode & DIFFCODE::SECOND) ? &dirs[1][j] : nullptr, + (nDiffCode & DIFFCODE::THIRD ) ? &dirs[2][k] : nullptr, nDiffCode, myStruct, parent); if ((nDiffCode & DIFFCODE::SKIPPED) == 0 && ((nDiffCode & DIFFCODE::SIDEFLAGS) == DIFFCODE::ALL || bUniques)) { @@ -333,7 +336,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], // i points to current file in left list (aFiles[0]) // j points to current file in right list (aFiles[1]) i=0, j=0, k=0; - while (1) + while (true) { if (pCtxt->ShouldAbort()) return -1; @@ -348,12 +351,12 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], if (nDirs < 3) { const unsigned nDiffCode = DIFFCODE::FIRST | DIFFCODE::FILE; - AddToList(subdir[0], subdir[1], &aFiles[0][i], 0, nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], &aFiles[0][i], nullptr, nDiffCode, myStruct, parent); } else { const unsigned nDiffCode = DIFFCODE::FIRST | DIFFCODE::FILE; - AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], 0, 0, nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], nullptr, nullptr, nDiffCode, myStruct, parent); } // Advance left pointer over left-only entry, and then retest with new pointers ++i; @@ -366,9 +369,9 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], { const unsigned nDiffCode = DIFFCODE::SECOND | DIFFCODE::FILE; if (nDirs < 3) - AddToList(subdir[0], subdir[1], 0, &aFiles[1][j], nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], nullptr, &aFiles[1][j], nDiffCode, myStruct, parent); else - AddToList(subdir[0], subdir[1], subdir[2], 0, &aFiles[1][j], 0, nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], subdir[2], nullptr, &aFiles[1][j], nullptr, nDiffCode, myStruct, parent); // Advance right pointer over right-only entry, and then retest with new pointers ++j; continue; @@ -380,7 +383,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], && (j==aFiles[1].size() || collstr(aFiles[2][k].filename, aFiles[1][j].filename, casesensitive)<0) ) { const unsigned nDiffCode = DIFFCODE::THIRD | DIFFCODE::FILE; - AddToList(subdir[0], subdir[1], subdir[2], 0, 0, &aFiles[2][k], nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], subdir[2], nullptr, nullptr, &aFiles[2][k], nDiffCode, myStruct, parent); ++k; // Advance right pointer over right-only entry, and then retest with new pointers continue; @@ -390,7 +393,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], && (k==aFiles[2].size() || collstr(aFiles[0][i].filename, aFiles[2][k].filename, casesensitive) != 0)) { const unsigned nDiffCode = DIFFCODE::FIRST | DIFFCODE::SECOND | DIFFCODE::FILE; - AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], &aFiles[1][j], 0, nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], &aFiles[1][j], nullptr, nDiffCode, myStruct, parent); ++i; ++j; continue; @@ -399,7 +402,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], && (j==aFiles[1].size() || collstr(aFiles[1][j].filename, aFiles[2][k].filename, casesensitive) != 0)) { const unsigned nDiffCode = DIFFCODE::FIRST | DIFFCODE::THIRD | DIFFCODE::FILE; - AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], 0, &aFiles[2][k], nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], nullptr, &aFiles[2][k], nDiffCode, myStruct, parent); ++i; ++k; continue; @@ -408,7 +411,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], && (i==aFiles[0].size() || collstr(aFiles[0][i].filename, aFiles[1][j].filename, casesensitive) != 0)) { const unsigned nDiffCode = DIFFCODE::SECOND | DIFFCODE::THIRD | DIFFCODE::FILE; - AddToList(subdir[0], subdir[1], subdir[2], 0, &aFiles[1][j], &aFiles[2][k], nDiffCode, myStruct, parent); + AddToList(subdir[0], subdir[1], subdir[2], nullptr, &aFiles[1][j], &aFiles[2][k], nDiffCode, myStruct, parent); ++j; ++k; continue; @@ -439,6 +442,25 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], } break; } + + if (parent != nullptr) + { + for (int nIndex = 0; nIndex < nDirs; ++nIndex) + if (parent->diffcode.exists(nIndex) && parent->diffFileInfo[nIndex].size == DirItem::FILE_SIZE_NONE) + parent->diffFileInfo[nIndex].size = 0; + + DIFFITEM *dic = parent->GetFirstChild(); + while (dic) + { + for (int nIndex = 0; nIndex < nDirs; ++nIndex) + { + if (dic->diffFileInfo[nIndex].size != DirItem::FILE_SIZE_NONE) + parent->diffFileInfo[nIndex].size += dic->diffFileInfo[nIndex].size; + } + dic = dic->GetFwdSiblingLink(); + } + } + return 1; } @@ -449,7 +471,7 @@ int DirScan_GetItems(const PathContext &paths, const String subdir[], * @param parentdiffpos [in] Position of parent diff item * @return >= 0 number of diff items, -1 if compare was aborted */ -int DirScan_CompareItems(DiffFuncStruct *myStruct, uintptr_t parentdiffpos) +int DirScan_CompareItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos) { const int compareMethod = myStruct->context->GetCompareMethod(); int nworkers = 1; @@ -484,18 +506,19 @@ int DirScan_CompareItems(DiffFuncStruct *myStruct, uintptr_t parentdiffpos) return res; } -static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, uintptr_t parentdiffpos) +static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos) { NotificationQueue queueResult; Stopwatch stopwatch; CDiffContext *pCtxt = myStruct->context; int res = 0; int count = 0; - if (!parentdiffpos) + bool bCompareFailure = false; + if (parentdiffpos == nullptr) myStruct->pSemaphore->wait(); stopwatch.start(); - uintptr_t pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); - while (pos) + DIFFITEM *pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); + while (pos != nullptr) { if (pCtxt->ShouldAbort()) break; @@ -507,24 +530,35 @@ static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, uint stopwatch.restart(); } myStruct->pSemaphore->wait(); - uintptr_t curpos = pos; + DIFFITEM *curpos = pos; DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos); bool existsalldirs = di.diffcode.existAll(); if (di.diffcode.isDirectory() && pCtxt->m_bRecursive) { - di.diffcode.diffcode &= ~(DIFFCODE::DIFF | DIFFCODE::SAME); + if ((di.diffcode.diffcode & DIFFCODE::CMPERR) != DIFFCODE::CMPERR) + { // Only clear DIFF|SAME flags if not CMPERR (eg. both flags together) + di.diffcode.diffcode &= ~(DIFFCODE::DIFF | DIFFCODE::SAME); + } int ndiff = CompareItems(queue, myStruct, curpos); + // Propogate sub-directory status to this directory if (ndiff > 0) - { + { // There were differences in the sub-directories if (existsalldirs) di.diffcode.diffcode |= DIFFCODE::DIFF; res += ndiff; } - else if (ndiff == 0) - { + else + if (ndiff == 0) + { // Sub-directories were identical if (existsalldirs) di.diffcode.diffcode |= DIFFCODE::SAME; } + else + if (ndiff == -1) + { // There were file IO-errors during sub-directory comparison. + di.diffcode.diffcode |= DIFFCODE::CMPERR; + bCompareFailure = true; + } } if (existsalldirs) queue.enqueueUrgentNotification(new WorkNotification(di, queueResult)); @@ -538,11 +572,21 @@ static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, uint while (count > 0) { AutoPtr pNf(queueResult.waitDequeueNotification()); - if (!pNf) + if (pNf.get() == nullptr) break; WorkCompletedNotification* pWorkCompletedNf = dynamic_cast(pNf.get()); - if (pWorkCompletedNf) { + if (pWorkCompletedNf != nullptr) { DIFFITEM &di = pWorkCompletedNf->data(); + if (di.diffcode.isResultError()) { + DIFFITEM *diParent = di.GetParentLink(); + assert(diParent != nullptr); + if (diParent != nullptr) + { + diParent->diffcode.diffcode |= DIFFCODE::CMPERR; + bCompareFailure = true; + } + } + if (di.diffcode.isResultDiff() || (!di.diffcode.existAll() && !di.diffcode.isResultFiltered())) res++; @@ -550,7 +594,7 @@ static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, uint --count; } - return pCtxt->ShouldAbort() ? -1 : res; + return bCompareFailure || pCtxt->ShouldAbort() ? -1 : res; } /** @@ -560,13 +604,16 @@ static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, uint * @param parentdiffpos [in] Position of parent diff item * @return >= 0 number of diff items, -1 if compare was aborted */ -static int CompareRequestedItems(DiffFuncStruct *myStruct, uintptr_t parentdiffpos) +static int CompareRequestedItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos) { CDiffContext *pCtxt = myStruct->context; + FolderCmp fc(pCtxt); int res = 0; - uintptr_t pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); - - while (pos != NULL) + bool bCompareFailure = false; + if (parentdiffpos == nullptr) + myStruct->pSemaphore->wait(); + DIFFITEM *pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); + while (pos != nullptr) { if (pCtxt->ShouldAbort()) { @@ -574,7 +621,7 @@ static int CompareRequestedItems(DiffFuncStruct *myStruct, uintptr_t parentdiffp break; } - uintptr_t curpos = pos; + DIFFITEM *curpos = pos; DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos); bool existsalldirs = di.diffcode.existAll(); if (di.diffcode.isDirectory()) @@ -589,38 +636,56 @@ static int CompareRequestedItems(DiffFuncStruct *myStruct, uintptr_t parentdiffp di.diffcode.diffcode |= DIFFCODE::DIFF; res += ndiff; } - else if (ndiff == 0) + else + if (ndiff == 0) { if (existsalldirs) di.diffcode.diffcode |= DIFFCODE::SAME; + } + else + if (ndiff == -1) + { // There were file IO-errors during sub-directory comparison. + di.diffcode.diffcode |= DIFFCODE::CMPERR; + bCompareFailure = true; } } } else { if (di.diffcode.isScanNeeded()) - CompareDiffItem(di, pCtxt); + { + CompareDiffItem(fc, di); + if (di.diffcode.isResultError()) { + DIFFITEM *diParent = di.GetParentLink(); + assert(diParent != nullptr); + if (diParent != nullptr) + { + diParent->diffcode.diffcode |= DIFFCODE::CMPERR; + bCompareFailure = true; + } + } + + } } if (di.diffcode.isResultDiff() || (!existsalldirs && !di.diffcode.isResultFiltered())) res++; } - return res; + return bCompareFailure ? -1 : res;; } -int DirScan_CompareRequestedItems(DiffFuncStruct *myStruct, uintptr_t parentdiffpos) +int DirScan_CompareRequestedItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos) { - CAssureScriptsForThread scriptsForRescan; return CompareRequestedItems(myStruct, parentdiffpos); } -static int markChildrenForRescan(CDiffContext *pCtxt, uintptr_t parentdiffpos) +static int markChildrenForRescan(CDiffContext *pCtxt, DIFFITEM *parentdiffpos) { int ncount = 0; - uintptr_t pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); - while (pos != NULL) + DIFFITEM *pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); + while (pos != nullptr) { - uintptr_t curpos = pos; + DIFFITEM *curpos = pos; DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos); if (di.diffcode.isDirectory()) ncount += markChildrenForRescan(pCtxt, curpos); @@ -633,29 +698,36 @@ static int markChildrenForRescan(CDiffContext *pCtxt, uintptr_t parentdiffpos) return ncount; } -int DirScan_UpdateMarkedItems(DiffFuncStruct *myStruct, uintptr_t parentdiffpos) +int DirScan_UpdateMarkedItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos) { CDiffContext *pCtxt = myStruct->context; - uintptr_t pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); + DIFFITEM *pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos); int ncount = 0; - - while (pos != NULL) + + while (pos != nullptr) { if (pCtxt->ShouldAbort()) break; - uintptr_t curpos = pos; + DIFFITEM *curpos = pos; DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos); - bool bItemsExist = true; if (di.diffcode.isScanNeeded()) { + bool bItemsExist = true; UpdateDiffItem(di, bItemsExist, pCtxt); if (!bItemsExist) - di.RemoveSelf(); - else if (!di.diffcode.isDirectory()) + { + di.DelinkFromSiblings(); // delink from list of Siblings + delete &di; // Also delete all Children items + continue; // (... because `di` is now invalid) + } + if (!di.diffcode.isDirectory()) ++ncount; } - if (bItemsExist && di.diffcode.isDirectory() && pCtxt->m_bRecursive) + if (di.diffcode.isDirectory() && pCtxt->m_bRecursive) { + for (int i = 0; i < pCtxt->GetCompareDirs(); ++i) + if (di.diffcode.exists(i)) + di.diffFileInfo[i].size = 0; if (di.diffcode.isScanNeeded() && !di.diffcode.isResultFiltered()) { di.RemoveChildren(); @@ -676,6 +748,12 @@ int DirScan_UpdateMarkedItems(DiffFuncStruct *myStruct, uintptr_t parentdiffpos) ncount += DirScan_UpdateMarkedItems(myStruct, curpos); } } + if (parentdiffpos != nullptr && pCtxt->m_bRecursive) + { + for (int nIndex = 0; nIndex < pCtxt->GetCompareDirs(); ++nIndex) + if (curpos->diffFileInfo[nIndex].size != DirItem::FILE_SIZE_NONE) + parentdiffpos->diffFileInfo[nIndex].size += curpos->diffFileInfo[nIndex].size; + } } return ncount; } @@ -693,7 +771,7 @@ int DirScan_UpdateMarkedItems(DiffFuncStruct *myStruct, uintptr_t parentdiffpos) * - false if items were deleted, so diffitem is not valid * @param [in] pCtxt Compare context */ -static void UpdateDiffItem(DIFFITEM & di, bool & bExists, CDiffContext *pCtxt) +static void UpdateDiffItem(DIFFITEM &di, bool & bExists, CDiffContext *pCtxt) { bExists = false; di.diffcode.setSideNone(); @@ -713,9 +791,9 @@ static void UpdateDiffItem(DIFFITEM & di, bool & bExists, CDiffContext *pCtxt) * * This function does the actual compare for previously gathered list of * items. Basically we: - * - ignore items matching filefilters + * - ignore items matching file filters * - add non-ignored directories (no compare for directory items) - * - add unique files + * - add unique files * - compare files * * @param [in] di DiffItem to compare @@ -723,8 +801,9 @@ static void UpdateDiffItem(DIFFITEM & di, bool & bExists, CDiffContext *pCtxt) * @todo For date compare, maybe we should use creation date if modification * date is missing? */ -void CompareDiffItem(DIFFITEM &di, CDiffContext * pCtxt) +static void CompareDiffItem(FolderCmp &fc, DIFFITEM &di) { + CDiffContext *const pCtxt = fc.m_pCtxt; int nDirs = pCtxt->GetCompareDirs(); // Clear rescan-request flag (not set by all codepaths) di.diffcode.diffcode &= ~DIFFCODE::NEEDSCAN; @@ -733,56 +812,36 @@ void CompareDiffItem(DIFFITEM &di, CDiffContext * pCtxt) { // We don't actually 'compare' directories, just add non-ignored // directories to list. - StoreDiffData(di, pCtxt, NULL); } else { // 1. Test against filters - if (!pCtxt->m_piFilterGlobal || + if (pCtxt->m_piFilterGlobal==nullptr || (nDirs == 2 && pCtxt->m_piFilterGlobal->includeFile(di.diffFileInfo[0].filename, di.diffFileInfo[1].filename)) || (nDirs == 3 && pCtxt->m_piFilterGlobal->includeFile(di.diffFileInfo[0].filename, di.diffFileInfo[1].filename, di.diffFileInfo[2].filename)) ) { di.diffcode.diffcode |= DIFFCODE::INCLUDED; - FolderCmp folderCmp; - di.diffcode.diffcode |= folderCmp.prepAndCompareFiles(pCtxt, di); - StoreDiffData(di, pCtxt, &folderCmp); + di.diffcode.diffcode |= fc.prepAndCompareFiles(di); + di.nsdiffs = fc.m_ndiffs; + di.nidiffs = fc.m_ntrivialdiffs; + + for (int i = 0; i < nDirs; ++i) + { + // Set text statistics + if (di.diffcode.exists(i)) + { + di.diffFileInfo[i].m_textStats = fc.m_diffFileData.m_textStats[i]; + di.diffFileInfo[i].encoding = fc.m_diffFileData.m_FileLocation[i].encoding; + } + } } else { di.diffcode.diffcode |= DIFFCODE::SKIPPED; - StoreDiffData(di, pCtxt, NULL); } } -} - -/** - * @brief Send one file or directory result back through the diff context. - * @param [in] di Data to store. - * @param [in] pCtxt Compare context. - * @param [in] pCmpData Folder compare data. - */ -static void StoreDiffData(DIFFITEM &di, CDiffContext * pCtxt, - const FolderCmp * pCmpData) -{ - if (pCmpData) - { - di.nsdiffs = pCmpData->m_ndiffs; - di.nidiffs = pCmpData->m_ntrivialdiffs; - - for (int i = 0; i < pCtxt->GetCompareDirs(); ++i) - { - // Set text statistics - if (di.diffcode.exists(i)) - { - di.diffFileInfo[i].m_textStats = pCmpData->m_diffFileData.m_textStats[i]; - di.diffFileInfo[i].encoding = pCmpData->m_diffFileData.m_FileLocation[i].encoding; - } - } - } - pCtxt->m_pCompareStats->AddItem(di.diffcode.diffcode); - //pCtxt->AddDiff(di); } /** @@ -798,27 +857,26 @@ static DIFFITEM *AddToList(const String& sLeftDir, const String& sRightDir, const DirItem * lent, const DirItem * rent, unsigned code, DiffFuncStruct *myStruct, DIFFITEM *parent) { - return AddToList(sLeftDir, sRightDir, sLeftDir, lent, rent, 0, code, myStruct, parent, 2); + return AddToList(sLeftDir, sRightDir, sLeftDir, lent, rent, nullptr, code, myStruct, parent, 2); } /** * @brief Add one compare item to list. */ static DIFFITEM *AddToList(const String& sDir1, const String& sDir2, const String& sDir3, - const DirItem * ent1, const DirItem * ent2, const DirItem * ent3, - unsigned code, DiffFuncStruct *myStruct, DIFFITEM *parent, int nItems) + const DirItem *ent1, const DirItem *ent2, const DirItem *ent3, + unsigned code, DiffFuncStruct *myStruct, DIFFITEM *parent, int nItems /*= 3*/) { // We must store both paths - we cannot get paths later // and we need unique item paths for example when items // change to identical - DIFFITEM *di = myStruct->context->AddDiff(parent); + DIFFITEM *di = myStruct->context->AddNewDiff(parent); - di->parent = parent; di->diffFileInfo[0].path = sDir1; di->diffFileInfo[1].path = sDir2; di->diffFileInfo[2].path = sDir3; - if (ent1) + if (ent1 != nullptr) { di->diffFileInfo[0].filename = ent1->filename; di->diffFileInfo[0].mtime = ent1->mtime; @@ -829,13 +887,13 @@ static DIFFITEM *AddToList(const String& sDir1, const String& sDir2, const Strin else { // Don't break CDirView::DoCopyRightToLeft() - if (ent3) + if (ent3 != nullptr) di->diffFileInfo[0].filename = ent3->filename; - else if (ent2) + else if (ent2 != nullptr) di->diffFileInfo[0].filename = ent2->filename; } - if (ent2) + if (ent2 != nullptr) { di->diffFileInfo[1].filename = ent2->filename; di->diffFileInfo[1].mtime = ent2->mtime; @@ -846,13 +904,13 @@ static DIFFITEM *AddToList(const String& sDir1, const String& sDir2, const Strin else { // Don't break CDirView::DoCopyLeftToRight() - if (ent1) + if (ent1 != nullptr) di->diffFileInfo[1].filename = ent1->filename; - else if (ent3) + else if (ent3 != nullptr) di->diffFileInfo[1].filename = ent3->filename; } - if (ent3) + if (ent3 != nullptr) { di->diffFileInfo[2].filename = ent3->filename; di->diffFileInfo[2].mtime = ent3->mtime; @@ -863,9 +921,9 @@ static DIFFITEM *AddToList(const String& sDir1, const String& sDir2, const Strin else { // Don't break CDirView::DoCopyLeftToRight() - if (ent1) + if (ent1 != nullptr) di->diffFileInfo[2].filename = ent1->filename; - else if (ent2) + else if (ent2 != nullptr) di->diffFileInfo[2].filename = ent2->filename; } @@ -874,7 +932,10 @@ static DIFFITEM *AddToList(const String& sDir1, const String& sDir2, const Strin else di->diffcode.diffcode = code | DIFFCODE::THREEWAY; - myStruct->context->m_pCompareStats->IncreaseTotalItems(); - myStruct->pSemaphore->set(); + if (myStruct->m_fncCollect) + { + myStruct->context->m_pCompareStats->IncreaseTotalItems(); + myStruct->pSemaphore->set(); + } return di; }