*
* @brief Implementation of DirScan (q.v.) and helper functions
*/
-// ID line follows -- this is updated by SVN
-// $Id: DirScan.cpp 6909 2009-07-11 13:03:42Z kimmov $
+#include "pch.h"
#include "DirScan.h"
#include <cassert>
+#include <memory>
#define POCO_NO_UNWINDOWS 1
#include <Poco/Semaphore.h>
#include <Poco/Notification.h>
#include <Poco/AutoPtr.h>
#include <Poco/Stopwatch.h>
#include <Poco/Format.h>
-#include <boost/shared_ptr.hpp>
#include "DiffThread.h"
#include "UnicodeString.h"
#include "DiffWrapper.h"
#include "CompareStats.h"
#include "FolderCmp.h"
#include "FileFilterHelper.h"
-#include "codepage.h"
#include "IAbortable.h"
-#include "FolderCmp.h"
#include "DirItem.h"
#include "DirTravel.h"
#include "paths.h"
#include "Plugins.h"
#include "MergeApp.h"
+#include "OptionsDef.h"
+#include "OptionsMgr.h"
+#include "PathContext.h"
+#include "DebugNew.h"
-using Poco::UIntPtr;
using Poco::NotificationQueue;
using Poco::Notification;
using Poco::AutoPtr;
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 TCHAR * sLeftDir, const TCHAR * sRightDir, const DirItem * lent, const DirItem * rent,
- unsigned code, DiffFuncStruct *myStruct, DIFFITEM *parent);
-static DIFFITEM *AddToList(const TCHAR * sLeftDir, const TCHAR * sMiddleDir, const TCHAR * sRightDir, const DirItem * lent, const DirItem * ment, 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 void UpdateDiffItem(DIFFITEM & di, bool & bExists, CDiffContext *pCtxt);
-static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, UIntPtr parentdiffpos);
+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, DIFFITEM *parentdiffpos);
class WorkNotification: public Poco::Notification
{
class WorkCompletedNotification: public Poco::Notification
{
public:
- WorkCompletedNotification(DIFFITEM& di): m_di(di) {}
+ explicit WorkCompletedNotification(DIFFITEM& di): m_di(di) {}
DIFFITEM& data() const { return m_di; }
private:
DIFFITEM& m_di;
class DiffWorker: public Runnable
{
public:
- DiffWorker(NotificationQueue& queue, CDiffContext *pCtxt):
- m_queue(queue), m_pCtxt(pCtxt) {}
+ DiffWorker(NotificationQueue& queue, CDiffContext *pCtxt, int id):
+ m_queue(queue), m_pCtxt(pCtxt), m_id(id) {}
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<Notification> pNf(m_queue.waitDequeueNotification());
- while (pNf)
+ while (pNf.get() != nullptr)
{
WorkNotification* pWorkNf = dynamic_cast<WorkNotification*>(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();
private:
NotificationQueue& m_queue;
CDiffContext *m_pCtxt;
+ int m_id;
};
-typedef boost::shared_ptr<DiffWorker> DiffWorkerPtr;
-
-/**
- * @brief Help minimize memory footprint by sharing CStringData if possible.
- *
- * Use OPTIMIZE_SHARE_CSTRINGDATA to conditionally include code that is merely
- * intended to minimize memory footprint by having two CStrings share one
- * CStringData if possible. The rule is that semantics must be identical
- * regardless of whether OPTIMIZE_SHARE_CSTRINGDATA(X) expands to X or to
- * nothing. If you suspect some bug to be related to this kind of optimization,
- * then you can simply change OPTIMIZE_SHARE_CSTRINGDATA to expand to nothing,
- * recompile, and see if bug disappears.
- */
-#define OPTIMIZE_SHARE_CSTRINGDATA(X) X
+typedef std::shared_ptr<DiffWorker> 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.
* @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.
* @return 1 normally, -1 if compare was aborted
*/
-int DirScan_GetItems(const PathContext &paths, const TCHAR * subdir[],
+int DirScan_GetItems(const PathContext &paths, const String subdir[],
DiffFuncStruct *myStruct,
bool casesensitive, int depth, DIFFITEM *parent,
bool bUniques)
String sDir[3];
String subprefix[3];
- int nIndex;
std::copy(paths.begin(), paths.end(), sDir);
- if (subdir[0][0])
+ if (!subdir[0].empty())
{
- for (nIndex = 0; nIndex < paths.GetSize(); nIndex++)
- sDir[nIndex] = paths_ConcatPath(sDir[nIndex], subdir[nIndex]);
- subprefix[0] = subdir[0];
- subprefix[0] += backslash;
- for (nIndex = 1; nIndex < paths.GetSize(); nIndex++)
+ for (int nIndex = 0; nIndex < paths.GetSize(); nIndex++)
{
- // minimize memory footprint by having left/rightsubprefix share CStringData if possible
- subprefix[nIndex] = OPTIMIZE_SHARE_CSTRINGDATA
- (
- _tcsicmp(subdir[0], subdir[nIndex]) == 0 ? subprefix[0] :
- ) String(subdir[nIndex]) + backslash;
+ sDir[nIndex] = paths::ConcatPath(sDir[nIndex], subdir[nIndex]);
+ subprefix[nIndex] = subdir[nIndex] + backslash;
}
}
- DirItemArray dirs[3], files[3];
- for (nIndex = 0; nIndex < nDirs; nIndex++)
- LoadAndSortFiles(sDir[nIndex], &dirs[nIndex], &files[nIndex], casesensitive);
+ DirItemArray dirs[3], aFiles[3];
+ for (int nIndex = 0; nIndex < nDirs; nIndex++)
+ LoadAndSortFiles(sDir[nIndex], &dirs[nIndex], &aFiles[nIndex], casesensitive);
// Allow user to abort scanning
if (pCtxt->ShouldAbort())
// 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 || files[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;
- unsigned nDiffCode;
- while (1)
+ while (true)
{
if (pCtxt->ShouldAbort())
return -1;
if (i >= dirs[0].size() && j >= dirs[1].size() && (nDirs < 3 || k >= dirs[2].size()))
break;
+ unsigned nDiffCode = DIFFCODE::DIR;
// Comparing directories leftDirs[i].name to rightDirs[j].name
-#ifdef _DEBUG
-TCHAR buf[1024];
-if (nDirs == 2)
- wsprintf(buf, _T("%s %s\n"), (i < dirs[0].size()) ? dirs[0][i].filename.c_str() : _T(""), (j < dirs[1].size()) ? dirs[1][j].filename.c_str() : _T(""));
-else
- wsprintf(buf, _T("%s %s %s\n"), (i < dirs[0].size()) ? dirs[0][i].filename.c_str() : _T(""), (j < dirs[1].size()) ? dirs[1][j].filename.c_str() : _T(""), (k < dirs[2].size()) ? dirs[2][k].filename.c_str() : _T(""));
-OutputDebugString(buf);
-#endif
-
if (i<dirs[0].size() && (j==dirs[1].size() || collstr(dirs[0][i].filename, dirs[1][j].filename, casesensitive)<0)
&& (nDirs < 3 || (k==dirs[2].size() || collstr(dirs[0][i].filename, dirs[2][k].filename, casesensitive)<0) ))
{
- nDiffCode = DIFFCODE::FIRST | DIFFCODE::DIR;
- if (!bUniques)
- {
- if (nDirs < 3)
- AddToList(subdir[0], subdir[1], &dirs[0][i], 0, nDiffCode, myStruct, parent);
- else
- AddToList(subdir[0], subdir[1], subdir[2], &dirs[0][i], 0, 0, nDiffCode, myStruct, parent);
- // Advance left pointer over left-only entry, and then retest with new pointers
- ++i;
- continue;
- }
+ nDiffCode |= DIFFCODE::FIRST;
}
else if (j<dirs[1].size() && (i==dirs[0].size() || collstr(dirs[1][j].filename, dirs[0][i].filename, casesensitive)<0)
&& (nDirs < 3 || (k==dirs[2].size() || collstr(dirs[1][j].filename, dirs[2][k].filename, casesensitive)<0) ))
{
- nDiffCode = DIFFCODE::SECOND | DIFFCODE::DIR;
- if (!bUniques)
- {
- if (nDirs < 3)
- AddToList(subdir[0], subdir[1], 0, &dirs[1][j], nDiffCode, myStruct, parent);
- else
- AddToList(subdir[0], subdir[1], subdir[2], 0, &dirs[1][j], 0, nDiffCode, myStruct, parent);
- // Advance right pointer over right-only entry, and then retest with new pointers
- ++j;
- continue;
- }
+ nDiffCode |= DIFFCODE::SECOND;
}
else if (nDirs < 3)
{
- nDiffCode = DIFFCODE::BOTH | DIFFCODE::DIR;
+ nDiffCode |= DIFFCODE::BOTH;
}
else
{
if (k<dirs[2].size() && (i==dirs[0].size() || collstr(dirs[2][k].filename, dirs[0][i].filename, casesensitive)<0)
&& (j==dirs[1].size() || collstr(dirs[2][k].filename, dirs[1][j].filename, casesensitive)<0) )
{
- nDiffCode = DIFFCODE::THIRD | DIFFCODE::DIR;
- if (!bUniques)
- {
- AddToList(subdir[0], subdir[1], subdir[2], 0, 0, &dirs[2][k], nDiffCode, myStruct, parent);
- ++k;
- // Advance right pointer over right-only entry, and then retest with new pointers
- continue;
-
- }
-
+ nDiffCode |= DIFFCODE::THIRD;
}
else if ((i<dirs[0].size() && j<dirs[1].size() && collstr(dirs[0][i].filename, dirs[1][j].filename, casesensitive) == 0)
&& (k==dirs[2].size() || collstr(dirs[2][k].filename, dirs[0][i].filename, casesensitive) != 0))
{
- nDiffCode = DIFFCODE::FIRST | DIFFCODE::SECOND | DIFFCODE::DIR;
- if (!bUniques)
- {
- AddToList(subdir[0], subdir[1], subdir[2], &dirs[0][i], &dirs[1][j], 0, nDiffCode, myStruct, parent);
- ++i;
- ++j;
- continue;
- }
+ nDiffCode |= DIFFCODE::FIRST | DIFFCODE::SECOND;
}
else if ((i<dirs[0].size() && k<dirs[2].size() && collstr(dirs[0][i].filename, dirs[2][k].filename, casesensitive) == 0)
&& (j==dirs[1].size() || collstr(dirs[1][j].filename, dirs[2][k].filename, casesensitive) != 0))
{
- nDiffCode = DIFFCODE::FIRST | DIFFCODE::THIRD | DIFFCODE::DIR;
- if (!bUniques)
- {
- AddToList(subdir[0], subdir[1], subdir[2], &dirs[0][i], 0, &dirs[2][k], nDiffCode, myStruct, parent);
- ++i;
- ++k;
- continue;
- }
+ nDiffCode |= DIFFCODE::FIRST | DIFFCODE::THIRD;
}
else if ((j<dirs[1].size() && k<dirs[2].size() && collstr(dirs[1][j].filename, dirs[2][k].filename, casesensitive) == 0)
&& (i==dirs[0].size() || collstr(dirs[0][i].filename, dirs[1][j].filename, casesensitive) != 0))
{
- nDiffCode = DIFFCODE::SECOND | DIFFCODE::THIRD | DIFFCODE::DIR;
- if (!bUniques)
- {
- AddToList(subdir[0], subdir[1], subdir[2], 0, &dirs[1][j], &dirs[2][k], nDiffCode, myStruct, parent);
- ++j;
- ++k;
- continue;
- }
+ nDiffCode |= DIFFCODE::SECOND | DIFFCODE::THIRD;
}
else
{
- nDiffCode = DIFFCODE::ALL | DIFFCODE::DIR;
+ nDiffCode |= DIFFCODE::ALL;
}
}
+ String leftnewsub;
+ String rightnewsub;
+ String middlenewsub;
+ if (nDirs < 3)
+ {
+ leftnewsub = (nDiffCode & DIFFCODE::FIRST) ? subprefix[0] + dirs[0][i].filename.get() : subprefix[0] + dirs[1][j].filename.get();
+ rightnewsub = (nDiffCode & DIFFCODE::SECOND) ? subprefix[1] + dirs[1][j].filename.get() : subprefix[1] + dirs[0][i].filename.get();
+
+ // 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!=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))
+ )
+ )
+ nDiffCode |= DIFFCODE::SKIPPED;
+ }
+ else
+ {
+ leftnewsub = subprefix[0];
+ if (nDiffCode & DIFFCODE::FIRST) leftnewsub += dirs[0][i].filename;
+ else if (nDiffCode & DIFFCODE::SECOND) leftnewsub += dirs[1][j].filename;
+ else if (nDiffCode & DIFFCODE::THIRD) leftnewsub += dirs[2][k].filename;
+ middlenewsub = subprefix[1];
+ if (nDiffCode & DIFFCODE::SECOND) middlenewsub += dirs[1][j].filename;
+ else if (nDiffCode & DIFFCODE::FIRST) middlenewsub += dirs[0][i].filename;
+ else if (nDiffCode & DIFFCODE::THIRD) middlenewsub += dirs[2][k].filename;
+ rightnewsub = subprefix[2];
+ if (nDiffCode & DIFFCODE::THIRD) rightnewsub += dirs[2][k].filename;
+ else if (nDiffCode & DIFFCODE::FIRST) rightnewsub += dirs[0][i].filename;
+ else if (nDiffCode & DIFFCODE::SECOND) rightnewsub += dirs[1][j].filename;
+
+ // 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!=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) ||
+ (nDiffCode & DIFFCODE::THIRD) && (dirs[2][k].flags.attributes & FILE_ATTRIBUTE_REPARSE_POINT))
+ )
+ )
+ nDiffCode |= DIFFCODE::SKIPPED;
+ }
+
// add to list
if (!depth)
{
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
{
// Recursive compare
- String leftnewsub;
- String rightnewsub;
- String middlenewsub;
if (nDirs < 3)
{
- leftnewsub = (nDiffCode & DIFFCODE::FIRST) ? subprefix[0] + dirs[0][i].filename : subprefix[0] + dirs[1][j].filename;
- rightnewsub = (nDiffCode & DIFFCODE::SECOND) ? subprefix[1] + dirs[1][j].filename : subprefix[1] + dirs[0][i].filename;
- }
- else
- {
- leftnewsub = subprefix[0];
- if (nDiffCode & DIFFCODE::FIRST) leftnewsub += dirs[0][i].filename;
- else if (nDiffCode & DIFFCODE::SECOND) leftnewsub += dirs[1][j].filename;
- else if (nDiffCode & DIFFCODE::THIRD) leftnewsub += dirs[2][k].filename;
- middlenewsub = subprefix[1];
- if (nDiffCode & DIFFCODE::SECOND) middlenewsub += dirs[1][j].filename;
- else if (nDiffCode & DIFFCODE::FIRST) middlenewsub += dirs[0][i].filename;
- else if (nDiffCode & DIFFCODE::THIRD) middlenewsub += dirs[2][k].filename;
- rightnewsub = subprefix[2];
- if (nDiffCode & DIFFCODE::THIRD) rightnewsub += dirs[2][k].filename;
- else if (nDiffCode & DIFFCODE::FIRST) rightnewsub += dirs[0][i].filename;
- else if (nDiffCode & DIFFCODE::SECOND) rightnewsub += dirs[1][j].filename;
- }
- if (nDirs < 3)
- {
- // 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)) ||
- (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))
- )
- )
- {
- nDiffCode |= DIFFCODE::SKIPPED;
- AddToList(subdir[0], subdir[1],
- nDiffCode & DIFFCODE::FIRST ? &dirs[0][i] : NULL,
- nDiffCode & DIFFCODE::SECOND ? &dirs[1][j] : NULL,
- nDiffCode, myStruct, parent);
- }
- else
+ DIFFITEM *me = AddToList(subdir[0], subdir[1],
+ (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))
{
- DIFFITEM *me = AddToList(subdir[0], subdir[1],
- nDiffCode & DIFFCODE::FIRST ? &dirs[0][i] : NULL,
- nDiffCode & DIFFCODE::SECOND ? &dirs[1][j] : NULL,
- nDiffCode, myStruct, parent);
// Scan recursively all subdirectories too, we are not adding folders
- const TCHAR * newsubdir[3];
- newsubdir[0] = leftnewsub.c_str();
- newsubdir[1] = rightnewsub.c_str();
+ String newsubdir[3] = {leftnewsub, rightnewsub};
int result = DirScan_GetItems(paths, newsubdir, myStruct, casesensitive,
depth - 1, me, bUniques);
if (result == -1)
return -1;
-/*
- if (result == 0)
- {
- if (!(nDiffCode & DIFFCODE::FIRST) || !(nDiffCode & DIFFCODE::SECOND))
- {
- AddToList(subdir[0], subdir[1],
- nDiffCode & DIFFCODE::FIRST ? &dirs[0][i] : NULL,
- nDiffCode & DIFFCODE::SECOND ? &dirs[1][j] : NULL,
- nDiffCode, myStruct, parent);
- }
- }
-*/
}
}
else
{
- // 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)) ||
- (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) ||
- (nDiffCode & DIFFCODE::THIRD) && (dirs[2][k].flags.attributes & FILE_ATTRIBUTE_REPARSE_POINT))
- )
- )
- {
- nDiffCode |= DIFFCODE::SKIPPED;
- 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, myStruct, parent);
- }
- else
+ DIFFITEM *me = AddToList(subdir[0], subdir[1], subdir[2],
+ (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))
{
- 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, myStruct, parent);
// Scan recursively all subdirectories too, we are not adding folders
- const TCHAR * newsubdir[3];
- newsubdir[0] = leftnewsub.c_str();
- newsubdir[1] = middlenewsub.c_str();
- newsubdir[2] = rightnewsub.c_str();
+ String newsubdir[3] = {leftnewsub, middlenewsub, rightnewsub};
int result = DirScan_GetItems(paths, newsubdir, myStruct, casesensitive,
depth - 1, me, bUniques);
if (result == -1)
return -1;
-/*
- if (result == 0)
- {
- if (!(nDiffCode & DIFFCODE::FIRST) || !(nDiffCode & DIFFCODE::SECOND) || !(nDiffCode & DIFFCODE::THIRD))
- {
- 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, myStruct, parent);
- }
- }
-*/
}
}
}
k++;
}
// Handle files
- // i points to current file in left list (files[0])
- // j points to current file in right list (files[1])
+ // 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;
- // Comparing file files[0][i].name to files[1][j].name
-#ifdef _DEBUG
-TCHAR buf[1024];
-if (nDirs == 2)
- wsprintf(buf, _T("%s %s\n"), (i < files[0].size()) ? files[0][i].filename.c_str() : _T(""), (j < files[1].size()) ? files[1][j].filename.c_str() : _T(""));
-else
- wsprintf(buf, _T("%s %s %s\n"), (i < files[0].size()) ? files[0][i].filename.c_str() : _T(""), (j < files[1].size()) ? files[1][j].filename.c_str() : _T(""),
-(k < files[2].size()) ? files[2][k].filename.c_str() : _T(""));
-OutputDebugString(buf);
-#endif
- if (i<files[0].size() && (j==files[1].size() ||
- collstr(files[0][i].filename, files[1][j].filename, casesensitive) < 0)
+ // Comparing file aFiles[0][i].name to aFiles[1][j].name
+ if (i<aFiles[0].size() && (j==aFiles[1].size() ||
+ collstr(aFiles[0][i].filename, aFiles[1][j].filename, casesensitive) < 0)
&& (nDirs < 3 ||
- (k==files[2].size() || collstr(files[0][i].filename, files[2][k].filename, casesensitive)<0) ))
+ (k==aFiles[2].size() || collstr(aFiles[0][i].filename, aFiles[2][k].filename, casesensitive)<0) ))
{
if (nDirs < 3)
{
const unsigned nDiffCode = DIFFCODE::FIRST | DIFFCODE::FILE;
- AddToList(subdir[0], subdir[1], &files[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], &files[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;
continue;
}
- if (j<files[1].size() && (i==files[0].size() ||
- collstr(files[0][i].filename, files[1][j].filename, casesensitive) > 0)
+ if (j<aFiles[1].size() && (i==aFiles[0].size() ||
+ collstr(aFiles[0][i].filename, aFiles[1][j].filename, casesensitive) > 0)
&& (nDirs < 3 ||
- (k==files[2].size() || collstr(files[1][j].filename, files[2][k].filename, casesensitive)<0) ))
+ (k==aFiles[2].size() || collstr(aFiles[1][j].filename, aFiles[2][k].filename, casesensitive)<0) ))
{
const unsigned nDiffCode = DIFFCODE::SECOND | DIFFCODE::FILE;
if (nDirs < 3)
- AddToList(subdir[0], subdir[1], 0, &files[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, &files[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;
}
if (nDirs == 3)
{
- if (k<files[2].size() && (i==files[0].size() ||
- collstr(files[2][k].filename, files[0][i].filename, casesensitive)<0)
- && (j==files[1].size() || collstr(files[2][k].filename, files[1][j].filename, casesensitive)<0) )
+ if (k<aFiles[2].size() && (i==aFiles[0].size() ||
+ collstr(aFiles[2][k].filename, aFiles[0][i].filename, casesensitive)<0)
+ && (j==aFiles[1].size() || collstr(aFiles[2][k].filename, aFiles[1][j].filename, casesensitive)<0) )
{
- int nDiffCode = DIFFCODE::THIRD | DIFFCODE::FILE;
- AddToList(subdir[0], subdir[1], subdir[2], 0, 0, &files[2][k], nDiffCode, myStruct, parent);
+ const unsigned nDiffCode = DIFFCODE::THIRD | DIFFCODE::FILE;
+ 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;
}
- if ((i<files[0].size() && j<files[1].size() && collstr(files[0][i].filename, files[1][j].filename, casesensitive) == 0)
- && (k==files[2].size() || collstr(files[0][i].filename, files[2][k].filename, casesensitive) != 0))
+ if ((i<aFiles[0].size() && j<aFiles[1].size() && collstr(aFiles[0][i].filename, aFiles[1][j].filename, casesensitive) == 0)
+ && (k==aFiles[2].size() || collstr(aFiles[0][i].filename, aFiles[2][k].filename, casesensitive) != 0))
{
- int nDiffCode = DIFFCODE::FIRST | DIFFCODE::SECOND | DIFFCODE::FILE;
- AddToList(subdir[0], subdir[1], subdir[2], &files[0][i], &files[1][j], 0, nDiffCode, myStruct, parent);
+ const unsigned nDiffCode = DIFFCODE::FIRST | DIFFCODE::SECOND | DIFFCODE::FILE;
+ AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], &aFiles[1][j], nullptr, nDiffCode, myStruct, parent);
++i;
++j;
continue;
}
- else if ((i<files[0].size() && k<files[2].size() && collstr(files[0][i].filename, files[2][k].filename, casesensitive) == 0)
- && (j==files[1].size() || collstr(files[1][j].filename, files[2][k].filename, casesensitive) != 0))
+ else if ((i<aFiles[0].size() && k<aFiles[2].size() && collstr(aFiles[0][i].filename, aFiles[2][k].filename, casesensitive) == 0)
+ && (j==aFiles[1].size() || collstr(aFiles[1][j].filename, aFiles[2][k].filename, casesensitive) != 0))
{
- int nDiffCode = DIFFCODE::FIRST | DIFFCODE::THIRD | DIFFCODE::FILE;
- AddToList(subdir[0], subdir[1], subdir[2], &files[0][i], 0, &files[2][k], nDiffCode, myStruct, parent);
+ const unsigned nDiffCode = DIFFCODE::FIRST | DIFFCODE::THIRD | DIFFCODE::FILE;
+ AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], nullptr, &aFiles[2][k], nDiffCode, myStruct, parent);
++i;
++k;
continue;
}
- else if ((j<files[1].size() && k<files[2].size() && collstr(files[1][j].filename, files[2][k].filename, casesensitive) == 0)
- && (i==files[0].size() || collstr(files[0][i].filename, files[1][j].filename, casesensitive) != 0))
+ else if ((j<aFiles[1].size() && k<aFiles[2].size() && collstr(aFiles[1][j].filename, aFiles[2][k].filename, casesensitive) == 0)
+ && (i==aFiles[0].size() || collstr(aFiles[0][i].filename, aFiles[1][j].filename, casesensitive) != 0))
{
- int nDiffCode = DIFFCODE::SECOND | DIFFCODE::THIRD | DIFFCODE::FILE;
- AddToList(subdir[0], subdir[1], subdir[2], 0, &files[1][j], &files[2][k], nDiffCode, myStruct, parent);
+ const unsigned nDiffCode = DIFFCODE::SECOND | DIFFCODE::THIRD | DIFFCODE::FILE;
+ AddToList(subdir[0], subdir[1], subdir[2], nullptr, &aFiles[1][j], &aFiles[2][k], nDiffCode, myStruct, parent);
++j;
++k;
continue;
}
}
- if (i<files[0].size())
+ if (i<aFiles[0].size())
{
if (nDirs < 3)
{
- assert(j<files[1].size());
- const int nDiffCode = DIFFCODE::BOTH | DIFFCODE::FILE;
- AddToList(subdir[0], subdir[1], &files[0][i], &files[1][j], nDiffCode, myStruct, parent);
+ assert(j<aFiles[1].size());
+ const unsigned nDiffCode = DIFFCODE::BOTH | DIFFCODE::FILE;
+ AddToList(subdir[0], subdir[1], &aFiles[0][i], &aFiles[1][j], nDiffCode, myStruct, parent);
++i;
++j;
continue;
}
else
{
- assert(j<files[1].size());
- assert(k<files[2].size());
- const int nDiffCode = DIFFCODE::ALL | DIFFCODE::FILE;
- AddToList(subdir[0], subdir[1], subdir[2], &files[0][i], &files[1][j], &files[2][k], nDiffCode, myStruct, parent);
+ assert(j<aFiles[1].size());
+ assert(k<aFiles[2].size());
+ const unsigned nDiffCode = DIFFCODE::ALL | DIFFCODE::FILE;
+ AddToList(subdir[0], subdir[1], subdir[2], &aFiles[0][i], &aFiles[1][j], &aFiles[2][k], nDiffCode, myStruct, parent);
++i;
++j;
++k;
}
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;
}
* @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 parentdiffpos)
+int DirScan_CompareItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos)
{
- ThreadPool threadPool;
+ const int compareMethod = myStruct->context->GetCompareMethod();
+ int nworkers = 1;
+
+ if (compareMethod == CMP_CONTENT || compareMethod == CMP_QUICK_CONTENT)
+ {
+ nworkers = GetOptionsMgr()->GetInt(OPT_CMP_COMPARE_THREADS);
+ if (nworkers <= 0)
+ {
+ nworkers += Environment::processorCount();
+ if (nworkers <= 0)
+ nworkers = 1;
+ }
+ }
+
+ ThreadPool threadPool(nworkers, nworkers);
std::vector<DiffWorkerPtr> workers;
- size_t nworkers = Environment::processorCount();
NotificationQueue queue;
-
- for (size_t i = 0; i < nworkers; ++i)
+ myStruct->context->m_pCompareStats->SetCompareThreadCount(nworkers);
+ for (int i = 0; i < nworkers; ++i)
{
- workers.push_back(DiffWorkerPtr(new DiffWorker(queue, myStruct->context)));
+ workers.push_back(DiffWorkerPtr(new DiffWorker(queue, myStruct->context, i)));
threadPool.start(*workers[i]);
}
return res;
}
-static int CompareItems(NotificationQueue& queue, DiffFuncStruct *myStruct, UIntPtr 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 pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos);
- while (pos)
+ DIFFITEM *pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos);
+ while (pos != nullptr)
{
if (pCtxt->ShouldAbort())
break;
stopwatch.restart();
}
myStruct->pSemaphore->wait();
- UIntPtr curpos = pos;
+ DIFFITEM *curpos = pos;
DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos);
- bool existsalldirs = ((pCtxt->GetCompareDirs() == 2 && di.diffcode.isSideBoth()) || (pCtxt->GetCompareDirs() == 3 && di.diffcode.isSideAll()));
+ 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;
+ }
}
- queue.enqueueNotification(new WorkNotification(di, queueResult));
+ if (existsalldirs)
+ queue.enqueueUrgentNotification(new WorkNotification(di, queueResult));
+ else
+ queue.enqueueNotification(new WorkNotification(di, queueResult));
++count;
pos = curpos;
pCtxt->GetNextSiblingDiffRefPosition(pos);
while (count > 0)
{
AutoPtr<Notification> pNf(queueResult.waitDequeueNotification());
- if (!pNf)
+ if (pNf.get() == nullptr)
break;
WorkCompletedNotification* pWorkCompletedNf = dynamic_cast<WorkCompletedNotification*>(pNf.get());
- if (pWorkCompletedNf) {
+ if (pWorkCompletedNf != nullptr) {
DIFFITEM &di = pWorkCompletedNf->data();
- bool existsalldirs = ((pCtxt->GetCompareDirs() == 2 && di.diffcode.isSideBoth()) || (pCtxt->GetCompareDirs() == 3 && di.diffcode.isSideAll()));
+ 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()))
+ (!di.diffcode.existAll() && !di.diffcode.isResultFiltered()))
res++;
}
--count;
}
- return pCtxt->ShouldAbort() ? -1 : res;
+ return bCompareFailure || pCtxt->ShouldAbort() ? -1 : res;
}
/**
* @param parentdiffpos [in] Position of parent diff item
* @return >= 0 number of diff items, -1 if compare was aborted
*/
-int DirScan_CompareRequestedItems(DiffFuncStruct *myStruct, UIntPtr parentdiffpos)
+static int CompareRequestedItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos)
{
CDiffContext *pCtxt = myStruct->context;
+ FolderCmp fc(pCtxt);
int res = 0;
- UIntPtr 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())
{
break;
}
- UIntPtr curpos = pos;
+ DIFFITEM *curpos = pos;
DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos);
- bool existsalldirs = ((pCtxt->GetCompareDirs() == 2 && di.diffcode.isSideBoth()) || (pCtxt->GetCompareDirs() == 3 && di.diffcode.isSideAll()));
- if (di.diffcode.isDirectory() && pCtxt->m_bRecursive)
+ bool existsalldirs = di.diffcode.existAll();
+ if (di.diffcode.isDirectory())
{
- di.diffcode.diffcode &= ~(DIFFCODE::DIFF | DIFFCODE::SAME);
- int ndiff = DirScan_CompareRequestedItems(myStruct, curpos);
- if (ndiff > 0)
+ if (pCtxt->m_bRecursive)
{
- if (existsalldirs)
- di.diffcode.diffcode |= DIFFCODE::DIFF;
- res += ndiff;
+ di.diffcode.diffcode &= ~(DIFFCODE::DIFF | DIFFCODE::SAME);
+ int ndiff = CompareRequestedItems(myStruct, curpos);
+ if (ndiff > 0)
+ {
+ if (existsalldirs)
+ di.diffcode.diffcode |= DIFFCODE::DIFF;
+ res += ndiff;
+ }
+ 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 (ndiff == 0)
- {
- if (existsalldirs)
- di.diffcode.diffcode |= DIFFCODE::SAME;
- }
}
else
{
if (di.diffcode.isScanNeeded())
{
- bool bItemsExist = true;
- UpdateDiffItem(di, bItemsExist, pCtxt);
- if (bItemsExist)
- {
- 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, DIFFITEM *parentdiffpos)
+{
+ return CompareRequestedItems(myStruct, parentdiffpos);
+}
+
+static int markChildrenForRescan(CDiffContext *pCtxt, DIFFITEM *parentdiffpos)
+{
+ int ncount = 0;
+ DIFFITEM *pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos);
+ while (pos != nullptr)
+ {
+ DIFFITEM *curpos = pos;
+ DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos);
+ if (di.diffcode.isDirectory())
+ ncount += markChildrenForRescan(pCtxt, curpos);
+ else
+ {
+ di.diffcode.diffcode |= DIFFCODE::NEEDSCAN;
+ ++ncount;
+ }
+ }
+ return ncount;
}
+int DirScan_UpdateMarkedItems(DiffFuncStruct *myStruct, DIFFITEM *parentdiffpos)
+{
+ CDiffContext *pCtxt = myStruct->context;
+ DIFFITEM *pos = pCtxt->GetFirstChildDiffPosition(parentdiffpos);
+ int ncount = 0;
+
+ while (pos != nullptr)
+ {
+ if (pCtxt->ShouldAbort())
+ break;
+ DIFFITEM *curpos = pos;
+ DIFFITEM &di = pCtxt->GetNextSiblingDiffRefPosition(pos);
+ if (di.diffcode.isScanNeeded())
+ {
+ bool bItemsExist = true;
+ UpdateDiffItem(di, bItemsExist, pCtxt);
+ if (!bItemsExist)
+ {
+ 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 (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();
+ di.diffcode.diffcode &= ~DIFFCODE::NEEDSCAN;
+
+ bool casesensitive = false;
+ int depth = myStruct->context->m_bRecursive ? -1 : 0;
+ String subdir[3];
+ PathContext paths = myStruct->context->GetNormalizedPaths();
+ for (int i = 0; i < pCtxt->GetCompareDirs(); ++i)
+ subdir[i] = di.diffFileInfo[i].GetFile();
+ DirScan_GetItems(paths, subdir, myStruct,
+ casesensitive, depth, &di, myStruct->context->m_bWalkUniques);
+ ncount += markChildrenForRescan(myStruct->context, curpos);
+ }
+ else
+ {
+ 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;
+}
/**
* @brief Update diffitem file/dir infos.
*
* - false if items were deleted, so diffitem is not valid
* @param [in] pCtxt Compare context
*/
-void UpdateDiffItem(DIFFITEM & di, bool & bExists, CDiffContext *pCtxt)
+static void UpdateDiffItem(DIFFITEM &di, bool & bExists, CDiffContext *pCtxt)
{
- // Clear side-info and file-infos
- di.diffFileInfo[0].ClearPartial();
- di.diffFileInfo[1].ClearPartial();
- di.diffcode.setSideBoth(); // FIXME: DIRTY HACK for UpdateInfoFromDiskHalf
- bool bLeftExists = pCtxt->UpdateInfoFromDiskHalf(di, 0);
- bool bRightExists = pCtxt->UpdateInfoFromDiskHalf(di, 1);
- bExists = bLeftExists || bRightExists;
- if (bLeftExists)
+ bExists = false;
+ di.diffcode.setSideNone();
+ for (int i = 0; i < pCtxt->GetCompareDirs(); ++i)
{
- if (bRightExists)
- di.diffcode.setSideBoth();
- else
- di.diffcode.setSideFirstOnly();
- }
- else
- {
- if (bRightExists)
- di.diffcode.setSideSecondOnly();
- else
- di.diffcode.setSideNone();
+ di.diffFileInfo[i].ClearPartial();
+ if (pCtxt->UpdateInfoFromDiskHalf(di, i))
+ {
+ di.diffcode.diffcode |= DIFFCODE::FIRST << i;
+ bExists = true;
+ }
}
}
*
* 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
* @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;
// Is it a directory?
if (di.diffcode.isDirectory())
{
- // 1. Test against filters
- if (!pCtxt->m_piFilterGlobal ||
- (nDirs == 2 && pCtxt->m_piFilterGlobal->includeDir(di.diffFileInfo[0].filename, di.diffFileInfo[1].filename)) ||
- (nDirs == 3 && pCtxt->m_piFilterGlobal->includeDir(di.diffFileInfo[0].filename, di.diffFileInfo[1].filename, di.diffFileInfo[2].filename))
- )
- di.diffcode.diffcode |= DIFFCODE::INCLUDED;
- else
- di.diffcode.diffcode |= DIFFCODE::SKIPPED;
// 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;
- // 2. Add unique files
- // We must compare unique files to itself to detect encoding
- if (di.diffcode.isSideFirstOnly() || di.diffcode.isSideSecondOnly() || (nDirs > 2 && di.diffcode.isSideThirdOnly()))
+ di.diffcode.diffcode |= fc.prepAndCompareFiles(di);
+ di.nsdiffs = fc.m_ndiffs;
+ di.nidiffs = fc.m_ntrivialdiffs;
+
+ for (int i = 0; i < nDirs; ++i)
{
- int nCurrentCompMethod = pCtxt->m_nCurrentCompMethod.get();
- if (nCurrentCompMethod != CMP_DATE &&
- nCurrentCompMethod != CMP_DATE_SIZE &&
- nCurrentCompMethod != CMP_SIZE)
+ // Set text statistics
+ if (di.diffcode.exists(i))
{
- FolderCmp folderCmp;
- unsigned diffCode = folderCmp.prepAndCompareFiles(pCtxt, di);
-
- // Add possible binary flag for unique items
- if (diffCode & DIFFCODE::BIN)
- di.diffcode.diffcode |= DIFFCODE::BIN;
- StoreDiffData(di, pCtxt, &folderCmp);
+ di.diffFileInfo[i].m_textStats = fc.m_diffFileData.m_textStats[i];
+ di.diffFileInfo[i].encoding = fc.m_diffFileData.m_FileLocation[i].encoding;
}
- else
- {
- StoreDiffData(di, pCtxt, NULL);
- }
- }
- // 3. Compare two files
- else
- {
- // Really compare
- FolderCmp folderCmp;
- di.diffcode.diffcode |= folderCmp.prepAndCompareFiles(pCtxt, di);
- StoreDiffData(di, pCtxt, &folderCmp);
}
}
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)
- {
- // Set text statistics
- if (di.diffcode.isSideLeftOnlyOrBoth())
- di.diffFileInfo[0].m_textStats = pCmpData->m_diffFileData.m_textStats[0];
- if (di.diffcode.isSideRightOnlyOrBoth())
- di.diffFileInfo[1].m_textStats = pCmpData->m_diffFileData.m_textStats[1];
-
- di.nsdiffs = pCmpData->m_ndiffs;
- di.nidiffs = pCmpData->m_ntrivialdiffs;
-
- if (!di.diffcode.isSideFirstOnly())
- {
- di.diffFileInfo[1].encoding = pCmpData->m_diffFileData.m_FileLocation[1].encoding;
- }
-
- if (!di.diffcode.isSideSecondOnly())
- {
- di.diffFileInfo[0].encoding = pCmpData->m_diffFileData.m_FileLocation[0].encoding;
- }
- }
-
pCtxt->m_pCompareStats->AddItem(di.diffcode.diffcode);
- //pCtxt->AddDiff(di);
}
/**
* @param [in] pCtxt Compare context.
* @param [in] parent Parent of item to be added
*/
-static DIFFITEM *AddToList(const TCHAR * sLeftDir, const TCHAR * sRightDir,
+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);
+ return AddToList(sLeftDir, sRightDir, sLeftDir, lent, rent, nullptr, code, myStruct, parent, 2);
}
/**
* @brief Add one compare item to list.
*/
-static DIFFITEM *AddToList(const TCHAR * sLeftDir, const TCHAR * sMiddleDir, const TCHAR * sRightDir,
- const DirItem * lent, const DirItem * ment, 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,
+ 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 = sLeftDir;
- di->diffFileInfo[1].path = sMiddleDir;
- di->diffFileInfo[2].path = sRightDir;
+ di->diffFileInfo[0].path = sDir1;
+ di->diffFileInfo[1].path = sDir2;
+ di->diffFileInfo[2].path = sDir3;
- if (lent)
+ if (ent1 != nullptr)
{
- di->diffFileInfo[0].filename = lent->filename;
- di->diffFileInfo[0].mtime = lent->mtime;
- di->diffFileInfo[0].ctime = lent->ctime;
- di->diffFileInfo[0].size = lent->size;
- di->diffFileInfo[0].flags.attributes = lent->flags.attributes;
+ di->diffFileInfo[0].filename = ent1->filename;
+ di->diffFileInfo[0].mtime = ent1->mtime;
+ di->diffFileInfo[0].ctime = ent1->ctime;
+ di->diffFileInfo[0].size = ent1->size;
+ di->diffFileInfo[0].flags.attributes = ent1->flags.attributes;
}
else
{
// Don't break CDirView::DoCopyRightToLeft()
- if (rent)
- di->diffFileInfo[0].filename = rent->filename;
- else
- di->diffFileInfo[0].filename = ment->filename;
+ if (ent3 != nullptr)
+ di->diffFileInfo[0].filename = ent3->filename;
+ else if (ent2 != nullptr)
+ di->diffFileInfo[0].filename = ent2->filename;
}
- if (ment)
+ if (ent2 != nullptr)
{
- di->diffFileInfo[1].filename = OPTIMIZE_SHARE_CSTRINGDATA
- (
- ment && di->diffFileInfo[0].filename == ment->filename ? di->diffFileInfo[0].filename :
- ) ment->filename;
- di->diffFileInfo[1].mtime = ment->mtime;
- di->diffFileInfo[1].ctime = ment->ctime;
- di->diffFileInfo[1].size = ment->size;
- di->diffFileInfo[1].flags.attributes = ment->flags.attributes;
+ di->diffFileInfo[1].filename = ent2->filename;
+ di->diffFileInfo[1].mtime = ent2->mtime;
+ di->diffFileInfo[1].ctime = ent2->ctime;
+ di->diffFileInfo[1].size = ent2->size;
+ di->diffFileInfo[1].flags.attributes = ent2->flags.attributes;
}
else
{
// Don't break CDirView::DoCopyLeftToRight()
- if (lent)
- di->diffFileInfo[1].filename = lent->filename;
- else
- di->diffFileInfo[1].filename = rent->filename;
+ if (ent1 != nullptr)
+ di->diffFileInfo[1].filename = ent1->filename;
+ else if (ent3 != nullptr)
+ di->diffFileInfo[1].filename = ent3->filename;
}
- if (rent)
+ if (ent3 != nullptr)
{
- di->diffFileInfo[2].filename = OPTIMIZE_SHARE_CSTRINGDATA
- (
- lent && di->diffFileInfo[0].filename == lent->filename ? di->diffFileInfo[0].filename :
- ) rent->filename;
- di->diffFileInfo[2].mtime = rent->mtime;
- di->diffFileInfo[2].ctime = rent->ctime;
- di->diffFileInfo[2].size = rent->size;
- di->diffFileInfo[2].flags.attributes = rent->flags.attributes;
+ di->diffFileInfo[2].filename = ent3->filename;
+ di->diffFileInfo[2].mtime = ent3->mtime;
+ di->diffFileInfo[2].ctime = ent3->ctime;
+ di->diffFileInfo[2].size = ent3->size;
+ di->diffFileInfo[2].flags.attributes = ent3->flags.attributes;
}
else
{
// Don't break CDirView::DoCopyLeftToRight()
- if (lent)
- di->diffFileInfo[2].filename = lent->filename;
- else
- di->diffFileInfo[2].filename = ment->filename;
+ if (ent1 != nullptr)
+ di->diffFileInfo[2].filename = ent1->filename;
+ else if (ent2 != nullptr)
+ di->diffFileInfo[2].filename = ent2->filename;
}
- di->diffcode = code;
+ if (nItems == 2)
+ di->diffcode.diffcode = code;
+ 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;
}