Revision: 4075
http://svn.sourceforge.net/winmerge/?rev=4075&view=rev
Author: kimmov
Date: 2007-01-24 10:41:49 -0800 (Wed, 24 Jan 2007)
Log Message:
-----------
PATCH: [ 1642809 ] Move compare code out from DiffFileData
Modified Paths:
--------------
trunk/Src/Changes.txt
trunk/Src/DiffFileData.cpp
trunk/Src/DiffFileData.h
trunk/Src/DiffWrapper.cpp
trunk/Src/DirScan.cpp
trunk/Src/DirViewColItems.cpp
trunk/Src/Merge.dsp
Added Paths:
-----------
trunk/Src/FolderCmp.cpp
trunk/Src/FolderCmp.h
Modified: trunk/Src/Changes.txt
===================================================================
--- trunk/Src/Changes.txt 2007-01-22 17:34:50 UTC (rev 4074)
+++ trunk/Src/Changes.txt 2007-01-24 18:41:49 UTC (rev 4075)
@@ -2,6 +2,12 @@
Add new items to top.
(This summarizes all changes to all files under Src, including Src\Languages.)
+2007-01-24 Kimmo
+ PATCH: [ 1642809 ] Move compare code out from DiffFileData
+ Src: DiffFileData.cpp DiffFileData.h DiffWrapper.cpp DirScan.cpp
+ DirViewColItems.cpp Merge.dsp
+ Src new files: FolderCmp.cpp FolderCmp.h
+
2007-01-17 Kimmo
BUG: [ 1637433 ] Forget selected filter after close
Src: Merge.cpp OptionsInit.cpp
Modified: trunk/Src/DiffFileData.cpp
===================================================================
--- trunk/Src/DiffFileData.cpp 2007-01-22 17:34:50 UTC (rev 4074)
+++ trunk/Src/DiffFileData.cpp 2007-01-24 18:41:49 UTC (rev 4075)
@@ -13,40 +13,17 @@
#include "DiffItem.h"
#include "FileLocation.h"
#include "Diff.h"
-#include "IAbortable.h"
#include "Paths.h"
#include "DiffContext.h"
#include "FileTransform.h"
#include "common/unicoder.h"
-#include "DiffWrapper.h"
-#include "ByteComparator.h"
#include "codepage_detect.h"
#include <shlwapi.h>
#include "DiffFileData.h"
-static const int KILO = 1024; // Kilo(byte)
-/** @brief Quick contents compare's file buffer size. */
-static const int WMCMPBUFF = 32 * KILO;
-
-static void GetComparePaths(CDiffContext * pCtxt, const DIFFITEM &di, CString & left, CString & right);
-static bool Unpack(CString & filepathTransformed,
- const CString & filteredFilenames, PackingInfo * infoUnpacker);
-static void CopyTextStats(const file_data * inf, FileTextStats * myTextStats);
-static void CopyDiffutilTextStats(file_data *inf, DiffFileData * diffData);
-
static int f_defcp = 0; // default codepage
-
-struct FileHandle
-{
- FileHandle() : m_fp(0) { }
- void Assign(FILE * fp) { Close(); m_fp = fp; }
- void Close() { if (m_fp) { fclose(m_fp); m_fp = 0; } }
- ~FileHandle() { Close(); }
- FILE * m_fp;
-};
-
/**
* @brief Simple initialization of DiffFileData
* @note Diffcounts are initialized to invalid values, not zeros.
@@ -58,8 +35,6 @@
for (i=0; i<2; ++i)
memset(&m_inf[i], 0, sizeof(m_inf[i]));
m_used = false;
- m_ndiffs = DiffFileData::DIFFS_UNKNOWN;
- m_ntrivialdiffs = DiffFileData::DIFFS_UNKNOWN;
Reset();
// Set default codepages
for (i=0; i<sizeof(m_FileLocation)/sizeof(m_FileLocation[0]); ++i)
@@ -200,80 +175,8 @@
}
}
-/**
- * @brief Compare two specified files.
- *
- * @param [in] depth Current directory depth.
- * @return Compare result as DIFFCODE.
- */
-int DiffFileData::diffutils_compare_files(int depth)
-{
- int bin_flag = 0;
- int bin_file = 0; // bitmap for binary files
- // Do the actual comparison (generating a change script)
- struct change *script = NULL;
- BOOL success = Diff2Files(&script, depth, &bin_flag, FALSE, &bin_file);
- if (!success)
- {
- return DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::CMPERR;
- }
- int code = DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::SAME;
- // make sure to start counting diffs at 0
- // (usually it is -1 at this point, for unknown)
- m_ndiffs = 0;
- m_ntrivialdiffs = 0;
-
- // Free change script (which we don't want)
- if (script != NULL)
- {
- struct change *p,*e;
- for (e = script; e; e = p)
- {
- if (!e->trivial)
- ++m_ndiffs;
- else
- ++m_ntrivialdiffs;
- p = e->link;
- free (e);
- }
- if (m_ndiffs > 0)
- code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF;
- }
-
- // diff_2_files set bin_flag to -1 if different binary
- // diff_2_files set bin_flag to +1 if same binary
-
- if (bin_flag != 0)
- {
- // Clear text-flag, set binary flag
- // We don't know diff counts for binary files
- code = code & ~DIFFCODE::TEXT;
- switch (bin_file)
- {
- case BINFILE_SIDE1: code |= DIFFCODE::BINSIDE1;
- break;
- case BINFILE_SIDE2: code |= DIFFCODE::BINSIDE2;
- break;
- case BINFILE_SIDE1 | BINFILE_SIDE2: code |= DIFFCODE::BIN;
- break;
- default:
- _RPTF1(_CRT_ERROR, "Invalid bin_file value: %d", bin_file);
- break;
- }
- m_ndiffs = DiffFileData::DIFFS_UNKNOWN;
- }
-
- if (bin_flag < 0)
- {
- // Clear same-flag, set diff-flag
- code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF;
- }
-
- return code;
-}
-
/** @brief detect unicode file and quess encoding */
DiffFileData::UniFileBom::UniFileBom(int fd)
{
@@ -369,433 +272,6 @@
return true;
}
-/**
- * @brief Prepare files (run plugins) & compare them, and return diffcode.
- * This is function to compare two files in folder compare. It is not used in
- * file compare.
- * @param [in] pCtxt Pointer to compare context.
- * @param [in, out] di Compared files with associated data.
- * @return Compare result code.
- */
-int DiffFileData::prepAndCompareTwoFiles(CDiffContext * pCtxt, DIFFITEM &di)
-{
- int nCompMethod = pCtxt->m_nCompMethod;
- CString filepath1;
- CString filepath2;
- GetComparePaths(pCtxt, di, filepath1, filepath2);
- // Reset text stats
- m_textStats0.clear();
- m_textStats1.clear();
- int code = DIFFCODE::FILE | DIFFCODE::CMPERR;
- // For user chosen plugins, define bAutomaticUnpacker as false and use the chosen infoHandler
- // but how can we receive the infoHandler ? DirScan actually only
- // returns info, but can not use file dependent information.
- // Transformation happens here
- // text used for automatic mode : plugin filter must match it
- CString filteredFilenames = filepath1 + "|" + filepath2;
-
- PackingInfo * infoUnpacker=0;
- PrediffingInfo * infoPrediffer=0;
-
- // Get existing or new plugin infos
- pCtxt->FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer);
-
- // plugin may alter filepaths to temp copies (which we delete before returning in all cases)
- CString filepathUnpacked1 = filepath1;
- CString filepathUnpacked2 = filepath2;
-
- CString filepathTransformed1;
- CString filepathTransformed2;
-
- //DiffFileData diffdata; //(filepathTransformed1, filepathTransformed2);
- // Invoke unpacking plugins
- if (!Unpack(filepathUnpacked1, filteredFilenames, infoUnpacker))
- {
- di.errorDesc = _T("Unpack Error Side 1");
- goto exitPrepAndCompare;
- }
-
- // we use the same plugins for both files, so they must be defined before second file
- ASSERT(infoUnpacker->bToBeScanned == FALSE);
-
- if (!Unpack(filepathUnpacked2, filteredFilenames, infoUnpacker))
- {
- di.errorDesc = _T("Unpack Error Side 2");
- goto exitPrepAndCompare;
- }
-
- // As we keep handles open on unpacked files, Transform() may not delete them.
- // Unpacked files will be deleted at end of this function.
- filepathTransformed1 = filepathUnpacked1;
- filepathTransformed2 = filepathUnpacked2;
- SetDisplayFilepaths(filepath1, filepath2); // store true names for diff utils patch file
- if (!OpenFiles(filepathTransformed1, filepathTransformed2))
- {
- di.errorDesc = _T("OpenFiles Error (before tranform)");
- goto exitPrepAndCompare;
- }
-
- // Invoke prediff'ing plugins
- if (!Filepath_Transform(m_FileLocation[0], filepathUnpacked1, filepathTransformed1, filteredFilenames, infoPrediffer, m_inf[0].desc))
- {
- di.errorDesc = _T("Transform Error Side 1");
- goto exitPrepAndCompare;
- }
-
- // we use the same plugins for both files, so they must be defined before second file
- ASSERT(infoPrediffer->bToBeScanned == FALSE);
-
- if (!Filepath_Transform(m_FileLocation[1], filepathUnpacked2, filepathTransformed2, filteredFilenames, infoPrediffer, m_inf[1].desc))
- {
- di.errorDesc = _T("Transform Error Side 2");
- goto exitPrepAndCompare;
- }
-
- // If options are binary equivalent, we could check for filesize
- // difference here, and bail out if files are clearly different
- // But, then we don't know if file is ascii or binary, and this
- // affects behavior (also, we don't have an icon for unknown type)
-
- // Actually compare the files
- // diffutils_compare_files is a fairly thin front-end to diffutils
- if (filepathTransformed1 != filepathUnpacked1 || filepathTransformed2 != filepathUnpacked2)
- {
- //diffdata.m_sFilepath[0] = filepathTransformed1;
- //diffdata.m_sFilepath[1] = filepathTransformed2;
- if (!OpenFiles(filepathTransformed1, filepathTransformed2))
- {
- di.errorDesc = _T("OpenFiles Error (after tranform)");
- goto exitPrepAndCompare;
- }
- }
-
- // If either file is larger than limit compare files by quick contents
- // This allows us to (faster) compare big binary files
- if (pCtxt->m_nCompMethod == CMP_CONTENT &&
- (di.left.size > pCtxt->m_nQuickCompareLimit ||
- di.right.size > pCtxt->m_nQuickCompareLimit))
- {
- nCompMethod = CMP_QUICK_CONTENT;
- }
-
- if (nCompMethod == CMP_CONTENT)
- {
- // use diffutils
- code = diffutils_compare_files(0);
- // If unique item, it was being compared to itself to determine encoding
- // and the #diffs is invalid
- if (di.isSideRightOnly() || di.isSideLeftOnly())
- {
- m_ndiffs = DiffFileData::DIFFS_UNKNOWN;
- m_ntrivialdiffs = DiffFileData::DIFFS_UNKNOWN;
- }
- if (DIFFCODE::isResultError(code))
- di.errorDesc = _T("DiffUtils Error");
-
- if (!DIFFCODE::isResultError(code) && pCtxt->m_bGuessEncoding)
- {
- // entire file is in memory in the diffutils buffers
- // inside the diff context, so may as well use in-memory copy
- GuessEncoding_from_buffer_in_DiffContext(0, pCtxt);
- GuessEncoding_from_buffer_in_DiffContext(1, pCtxt);
- }
- }
- else if (nCompMethod == CMP_QUICK_CONTENT)
- {
- // use our own byte-by-byte compare
- code = byte_compare_files(pCtxt->m_bStopAfterFirstDiff, pCtxt->GetAbortable());
- // Quick contents doesn't know about diff counts
- // Set to special value to indicate invalid
- m_ndiffs = DIFFS_UNKNOWN_QUICKCOMPARE;
- m_ntrivialdiffs = DIFFS_UNKNOWN_QUICKCOMPARE;
- di.left.m_textStats = m_textStats0;
- di.right.m_textStats = m_textStats1;
-
- if (!DIFFCODE::isResultError(code) && pCtxt->m_bGuessEncoding)
- {
- GuessEncoding_from_FileLocation(m_FileLocation[0]);
- GuessEncoding_from_FileLocation(m_FileLocation[1]);
- }
- }
- else
- {
- // Print error since we should have handled by date compare earlier
- _RPTF0(_CRT_ERROR, "Invalid compare type, DiffFileData can't handle it");
- di.errorDesc = _T("Bad compare type");
- goto exitPrepAndCompare;
- }
-
-
-exitPrepAndCompare:
- Reset();
- // delete the temp files after comparison
- if (filepathTransformed1 != filepathUnpacked1)
- VERIFY(::DeleteFile(filepathTransformed1) || gLog::DeleteFileFailed(filepathTransformed1));
- if (filepathTransformed2 != filepathUnpacked2)
- VERIFY(::DeleteFile(filepathTransformed2) || gLog::DeleteFileFailed(filepathTransformed2));
- if (filepathUnpacked1 != filepath1)
- VERIFY(::DeleteFile(filepathUnpacked1) || gLog::DeleteFileFailed(filepathUnpacked1));
- if (filepathUnpacked2 != filepath2)
- VERIFY(::DeleteFile(filepathUnpacked2) || gLog::DeleteFileFailed(filepathUnpacked2));
- return code;
-}
-
-/**
- * @brief Compare two files using diffutils.
- *
- * Compare two files (in DiffFileData param) using diffutils. Run diffutils
- * inside SEH so we can trap possible error and exceptions. If error or
- * execption is trapped, return compare failure.
- * @param [out] diffs Pointer to list of change structs where diffdata is stored.
- * @param [in] depth Depth in folder compare (we use 0).
- * @param [out] bin_status used to return binary status from compare.
- * @param [in] bMovedBlocks If TRUE moved blocks are analyzed.
- * @param [out] bin_file Returns which file was binary file as bitmap.
- So if first file is binary, first bit is set etc. Can be NULL if binary file
- info is not needed (faster compare since diffutils don't bother checking
- second file if first is binary).
- * @return TRUE when compare succeeds, FALSE if error happened during compare.
- */
-BOOL DiffFileData::Diff2Files(struct change ** diffs, int depth,
- int * bin_status, BOOL bMovedBlocks, int * bin_file)
-{
- BOOL bRet = TRUE;
- __try
- {
- *diffs = diff_2_files (m_inf, depth, bin_status, bMovedBlocks, bin_file);
- CopyDiffutilTextStats(m_inf, this);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- *diffs = NULL;
- bRet = FALSE;
- }
- return bRet;
-}
-
-/**
- * @brief Compare two specified files, byte-by-byte
- * @param [in] bStopAfterFirstDiff Stop compare after we find first difference?
- * @param [in] piAbortable Interface allowing to abort compare
- * @return DIFFCODE
- */
-int DiffFileData::byte_compare_files(BOOL bStopAfterFirstDiff, const IAbortable * piAbortable)
-{
- // Close any descriptors open for diffutils
- Reset();
-
- // TODO
- // Right now, we assume files are in 8-bit encoding
- // because transform code converted any UCS-2 files to UTF-8
- // We could compare directly in UCS-2LE here, as an optimization, in that case
- char buff[2][WMCMPBUFF]; // buffered access to files
- FILE * fp[2]; // for files to compare
- FileHandle fhd[2]; // to ensure file handles fp get closed
- int i;
- int diffcode = 0;
-
- // Open both files
- for (i=0; i<2; ++i)
- {
- fp[i] = _tfopen(m_FileLocation[i].filepath, _T("rb"));
- if (!fp[i])
- return DIFFCODE::CMPERR;
- fhd[i].Assign(fp[i]);
- }
-
- // area of buffer currently holding data
- __int64 bfstart[2]; // offset into buff[i] where current data resides
- __int64 bfend[2]; // past-the-end pointer into buff[i], giving end of current data
- // buff[0] has bytes to process from buff[0][bfstart[0]] to buff[0][bfend[0]-1]
-
- bool eof[2]; // if we've finished file
-
- // initialize our buffer pointers and end of file flags
- for (i=0; i<2; ++i)
- {
- bfstart[i] = bfend[i] = 0;
- eof[i] = false;
- }
-
- ByteComparator comparator(ignore_case_flag, ignore_space_change_flag
- , ignore_all_space_flag, ignore_eol_diff, ignore_blank_lines_flag);
-
- // Begin loop
- // we handle the files in WMCMPBUFF sized buffers (variable buff[][])
- // That is, we do one buffer full at a time
- // or even less, as we process until one side buffer is empty, then reload that one
- // and continue
- while (!eof[0] || !eof[1])
- {
- if (piAbortable && piAbortable->ShouldAbort())
- return DIFFCODE::CMPABORT;
-
- // load or update buffers as appropriate
- for (i=0; i<2; ++i)
- {
- if (!eof[i] && bfstart[i]==countof(buff[i]))
- {
- bfstart[i]=bfend[i] = 0;
- }
- if (!eof[i] && bfend[i]<countof(buff[i])-1)
- {
- // Assume our blocks are in range of unsigned int
- unsigned int space = countof(buff[i]) - bfend[i];
- size_t rtn = fread(&buff[i][bfend[i]], 1, space, fp[i]);
- if (ferror(fp[i]))
- return DIFFCODE::CMPERR;
- if (feof(fp[i]))
- eof[i] = true;
- bfend[i] += rtn;
- }
- }
-
- // where to start comparing right now
- LPCSTR ptr0 = &buff[0][bfstart[0]];
- LPCSTR ptr1 = &buff[1][bfstart[1]];
-
- // remember where we started
- LPCSTR orig0 = ptr0, orig1 = ptr1;
-
- // how far can we go right now?
- LPCSTR end0 = &buff[0][bfend[0]];
- LPCSTR end1 = &buff[1][bfend[1]];
-
- __int64 offset0 = (ptr0 - &buff[0][0]);
- __int64 offset1 = (ptr1 - &buff[1][0]);
-
- // are these two buffers the same?
- if (!comparator.CompareBuffers(m_textStats0, m_textStats1,
- ptr0, ptr1, end0, end1, eof[0], eof[1], offset0, offset1))
- {
- if (bStopAfterFirstDiff)
- {
- // By bailing out here
- // we leave our text statistics incomplete
- return diffcode | DIFFCODE::DIFF;
- }
- else
- {
- diffcode |= DIFFCODE::DIFF;
- ptr0 = end0;
- ptr1 = end1;
- }
- }
- else
- {
- ptr0 = end0;
- ptr1 = end1;
- }
-
-
- // did we finish both files?
- if (eof[0] && eof[1])
- {
-
- BOOL bBin0 = (m_textStats0.nzeros>0);
- BOOL bBin1 = (m_textStats1.nzeros>0);
-
- if (bBin0 && bBin1)
- diffcode |= DIFFCODE::BIN;
- else if (bBin0)
- diffcode |= DIFFCODE::BINSIDE1;
- else if (bBin1)
- diffcode |= DIFFCODE::BINSIDE2;
-
- // If either unfinished, they differ
- if (ptr0 != end0 || ptr1 != end1)
- diffcode = (diffcode & DIFFCODE::DIFF);
-
- if (diffcode & DIFFCODE::DIFF)
- return diffcode | DIFFCODE::DIFF;
- else
- return diffcode | DIFFCODE::SAME;
- }
-
- // move our current pointers over what we just compared
- ASSERT(ptr0 >= orig0);
- ASSERT(ptr1 >= orig1);
- bfstart[0] += ptr0-orig0;
- bfstart[1] += ptr1-orig1;
- }
- return diffcode;
-}
-
-/**
- * @brief Get actual compared paths from DIFFITEM.
- * @note If item is unique, same path is returned for both.
- */
-void GetComparePaths(CDiffContext * pCtxt, const DIFFITEM &di, CString & left, CString & right)
-{
- static const TCHAR backslash[] = _T("\\");
-
- if (!di.isSideRightOnly())
- {
- // Compare file to itself to detect encoding
- left = pCtxt->GetNormalizedLeft();
- if (!paths_EndsWithSlash(left))
- left += backslash;
- if (!di.sLeftSubdir.IsEmpty())
- left += di.sLeftSubdir + backslash;
- left += di.sLeftFilename;
- if (di.isSideLeftOnly())
- right = left;
- }
- if (!di.isSideLeftOnly())
- {
- // Compare file to itself to detect encoding
- right = pCtxt->GetNormalizedRight();
- if (!paths_EndsWithSlash(right))
- right += backslash;
- if (!di.sRightSubdir.IsEmpty())
- right += di.sRightSubdir + backslash;
- right += di.sRightFilename;
- if (di.isSideRightOnly())
- left = right;
- }
-}
-
-/**
- * @brief Invoke appropriate plugins for unpacking
- * return false if anything fails
- * caller has to DeleteFile filepathTransformed, if it differs from filepath
- */
-static bool Unpack(CString & filepathTransformed,
- const CString & filteredFilenames, PackingInfo * infoUnpacker)
-{
- // first step : unpack (plugins)
- if (infoUnpacker->bToBeScanned)
- {
- if (!FileTransform_Unpacking(filepathTransformed, filteredFilenames, infoUnpacker, &infoUnpacker->subcode))
- return false;
- }
- else
- {
- if (!FileTransform_Unpacking(filepathTransformed, infoUnpacker, &infoUnpacker->subcode))
- return false;
- }
- return true;
-}
-
-/**
- * @brief Copy text stat results from diffutils back into the FileTextStats structure
- */
-static void CopyTextStats(const file_data * inf, FileTextStats * myTextStats)
-{
- myTextStats->ncrlfs = inf->count_crlfs;
- myTextStats->ncrs = inf->count_crs;
- myTextStats->nlfs = inf->count_lfs;
-}
-
-/**
- * @brief Copy both left & right text stats results back into the DiffFileData text stats
- */
-static void CopyDiffutilTextStats(file_data *inf, DiffFileData * diffData)
-{
- CopyTextStats(&inf[0], &diffData->m_textStats0);
- CopyTextStats(&inf[1], &diffData->m_textStats1);
-}
-
Modified: trunk/Src/DiffFileData.h
===================================================================
--- trunk/Src/DiffFileData.h 2007-01-22 17:34:50 UTC (rev 4074)
+++ trunk/Src/DiffFileData.h 2007-01-24 18:41:49 UTC (rev 4075)
@@ -14,10 +14,17 @@
// forward declarations needed by DiffFileData
struct file_data;
class PrediffingInfo;
-struct DIFFITEM;
-class IAbortable;
class CDiffContext;
+struct FileHandle
+{
+ FileHandle() : m_fp(0) { }
+ void Assign(FILE * fp) { Close(); m_fp = fp; }
+ void Close() { if (m_fp) { fclose(m_fp); m_fp = 0; } }
+ ~FileHandle() { Close(); }
+ FILE * m_fp;
+};
+
/**
* @brief C++ container for the structure (file_data) used by diffutils' diff_2_files(...)
*/
@@ -27,8 +34,6 @@
static void SetDefaultCodepage(int defcp); // set codepage to assume for all unknown files
-// enums
- enum { DIFFS_UNKNOWN=-1, DIFFS_UNKNOWN_QUICKCOMPARE=-9 };
// instance interface
@@ -40,11 +45,6 @@
void Close() { Reset(); }
void SetDisplayFilepaths(LPCTSTR szTrueFilepath1, LPCTSTR szTrueFilepath2);
- int diffutils_compare_files(int depth);
- int byte_compare_files(BOOL bStopAfterFirstDiff, const IAbortable * piAbortable);
- int prepAndCompareTwoFiles(CDiffContext * pCtxt, DIFFITEM &di);
- BOOL Diff2Files(struct change ** diffs, int depth,
- int * bin_status, BOOL bMovedBlocks, int * bin_file);
bool Filepath_Transform(FileLocation & fpenc, const CString & filepath, CString & filepathTransformed,
const CString & filteredFilenames, PrediffingInfo * infoPrediffer, int fd);
void GuessEncoding_from_buffer_in_DiffContext(int side, CDiffContext * pCtxt);
@@ -58,8 +58,6 @@
FileTextStats m_textStats0, m_textStats1;
CString m_sDisplayFilepath[2];
- int m_ndiffs;
- int m_ntrivialdiffs;
struct UniFileBom // detect unicode file and quess encoding
{
UniFileBom(int); // initialize from file descriptor
Modified: trunk/Src/DiffWrapper.cpp
===================================================================
--- trunk/Src/DiffWrapper.cpp 2007-01-22 17:34:50 UTC (rev 4074)
+++ trunk/Src/DiffWrapper.cpp 2007-01-24 18:41:49 UTC (rev 4075)
@@ -41,7 +41,8 @@
#include "paths.h"
#include "CompareOptions.h"
#include "FileTextStats.h"
-#include "DiffFileData.h"
+//#include "DiffFileData.h"
+#include "FolderCmp.h"
#include "FilterCommentsManager.h"
#ifdef _DEBUG
Modified: trunk/Src/DirScan.cpp
===================================================================
--- trunk/Src/DirScan.cpp 2007-01-22 17:34:50 UTC (rev 4074)
+++ trunk/Src/DirScan.cpp 2007-01-24 18:41:49 UTC (rev 4075)
@@ -15,6 +15,7 @@
#include "common/unicoder.h"
#include "DiffContext.h"
#include "DiffWrapper.h"
+#include "FolderCmp.h"
#include "FileFilterHelper.h"
#include "logfile.h"
#include "paths.h"
@@ -23,7 +24,8 @@
#include "DiffItemList.h"
#include "PathContext.h"
#include "IAbortable.h"
-#include "DiffFileData.h"
+#include "FolderCmp.h"
+//#include "DiffFileData.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -53,7 +55,7 @@
static void Sort(fentryArray * dirs, bool casesensitive);;
static int collstr(const CString & s1, const CString & s2, bool casesensitive);
static void StoreDiffData(DIFFITEM &di, CDiffContext * pCtxt,
- const DiffFileData * pDiffFileData);
+ const FolderCmp * pCmpData);
static void AddToList(const CString & sLeftDir, const CString & sRightDir, const fentry * lent, const fentry * rent,
int code, DiffItemList * pList, CDiffContext *pCtxt);
static void UpdateDiffItem(DIFFITEM & di, BOOL & bExists, CDiffContext *pCtxt);
@@ -391,13 +393,15 @@
pCtxt->m_nCompMethod != CMP_DATE_SIZE &&
pCtxt->m_nCompMethod != CMP_SIZE)
{
- DiffFileData diffdata;
- int diffCode = diffdata.prepAndCompareTwoFiles(pCtxt, di);
+ FolderCmp folderCmp;
+ //DiffFileData diffdata;
+ //int diffCode = diffdata.prepAndCompareTwoFiles(pCtxt, di);
+ int diffCode = folderCmp.prepAndCompareTwoFiles(pCtxt, di);
// Add possible binary flag for unique items
if (diffCode & DIFFCODE::BIN)
di.diffcode |= DIFFCODE::BIN;
- StoreDiffData(di, pCtxt, &diffdata);
+ StoreDiffData(di, pCtxt, &folderCmp);
}
else
{
@@ -465,10 +469,12 @@
else
{
// Really compare
- DiffFileData diffdata;
- di.diffcode |= diffdata.prepAndCompareTwoFiles(pCtxt, di);
+ //DiffFileData diffdata;
+ FolderCmp folderCmp;
+ //di.diffcode |= diffdata.prepAndCompareTwoFiles(pCtxt, di);
+ di.diffcode |= folderCmp.prepAndCompareTwoFiles(pCtxt, di);
// report result back to caller
- StoreDiffData(di, pCtxt, &diffdata);
+ StoreDiffData(di, pCtxt, &folderCmp);
}
}
else
@@ -607,27 +613,27 @@
* @brief Send one file or directory result back through the diff context
*/
static void StoreDiffData(DIFFITEM &di, CDiffContext * pCtxt,
- const DiffFileData * pDiffFileData)
+ const FolderCmp * pCmpData)
{
- if (pDiffFileData)
+ if (pCmpData)
{
// Set text statistics
if (di.isSideLeftOrBoth())
- di.left.m_textStats = pDiffFileData->m_textStats0;
+ di.left.m_textStats = pCmpData->m_diffFileData.m_textStats0;
if (di.isSideRightOrBoth())
- di.right.m_textStats = pDiffFileData->m_textStats1;
+ di.right.m_textStats = pCmpData->m_diffFileData.m_textStats1;
- di.nsdiffs = pDiffFileData->m_ndiffs;
- di.nidiffs = pDiffFileData->m_ntrivialdiffs;
+ di.nsdiffs = pCmpData->m_ndiffs;
+ di.nidiffs = pCmpData->m_ntrivialdiffs;
if (!di.isSideLeftOnly())
{
- di.right.encoding = pDiffFileData->m_FileLocation[1].encoding;
+ di.right.encoding = pCmpData->m_diffFileData.m_FileLocation[1].encoding;
}
if (!di.isSideRightOnly())
{
- di.left.encoding = pDiffFileData->m_FileLocation[0].encoding;
+ di.left.encoding = pCmpData->m_diffFileData.m_FileLocation[0].encoding;
}
}
Modified: trunk/Src/DirViewColItems.cpp
===================================================================
--- trunk/Src/DirViewColItems.cpp 2007-01-22 17:34:50 UTC (rev 4074)
+++ trunk/Src/DirViewColItems.cpp 2007-01-24 18:41:49 UTC (rev 4075)
@@ -20,7 +20,7 @@
#include "locality.h"
#include "unicoder.h"
#include "coretools.h"
-#include "DiffFileData.h"
+#include "FolderCmp.h"
// shlwapi.h prior to VC6SP6 might lack definition of StrIsIntlEqual
#ifdef UNICODE
@@ -296,11 +296,11 @@
{
const int &r = *static_cast<const int*>(p);
CString s;
- if (r == DiffFileData::DIFFS_UNKNOWN_QUICKCOMPARE)
+ if (r == FolderCmp::DIFFS_UNKNOWN_QUICKCOMPARE)
{ // QuickCompare, unknown
s = _T("*");
}
- else if (r == DiffFileData::DIFFS_UNKNOWN)
+ else if (r == FolderCmp::DIFFS_UNKNOWN)
{ // Unique item
s = _T("");
}
Added: trunk/Src/FolderCmp.cpp
===================================================================
--- trunk/Src/FolderCmp.cpp (rev 0)
+++ trunk/Src/FolderCmp.cpp 2007-01-24 18:41:49 UTC (rev 4075)
@@ -0,0 +1,542 @@
+/**
+ * @file FolderCmp.cpp
+ *
+ * @brief Implementation file for FolderCmp
+ */
+
+#include "stdafx.h"
+#include "paths.h"
+#include "DiffContext.h"
+#include "DiffWrapper.h"
+#include "FileTransform.h"
+#include "diff.h"
+#include "IAbortable.h"
+#include "FolderCmp.h"
+#include "ByteComparator.h"
+
+static const int KILO = 1024; // Kilo(byte)
+
+/** @brief Quick contents compare's file buffer size. */
+static const int WMCMPBUFF = 32 * KILO;
+
+static void CopyDiffutilTextStats(file_data *inf, DiffFileData * diffData);
+static void CopyTextStats(const file_data * inf, FileTextStats * myTextStats);
+static void GetComparePaths(CDiffContext * pCtxt, const DIFFITEM &di, CString & left, CString & right);
+static bool Unpack(CString & filepathTransformed,
+ const CString & filteredFilenames, PackingInfo * infoUnpacker);
+
+FolderCmp::FolderCmp()
+: m_ndiffs(DIFFS_UNKNOWN)
+, m_ntrivialdiffs(DIFFS_UNKNOWN)
+{
+
+}
+
+/**
+ * @brief Prepare files (run plugins) & compare them, and return diffcode.
+ * This is function to compare two files in folder compare. It is not used in
+ * file compare.
+ * @param [in] pCtxt Pointer to compare context.
+ * @param [in, out] di Compared files with associated data.
+ * @return Compare result code.
+ */
+int FolderCmp::prepAndCompareTwoFiles(CDiffContext * pCtxt, DIFFITEM &di)
+{
+ int nCompMethod = pCtxt->m_nCompMethod;
+ CString filepath1;
+ CString filepath2;
+ GetComparePaths(pCtxt, di, filepath1, filepath2);
+
+ // Reset text stats
+ m_diffFileData.m_textStats0.clear();
+ m_diffFileData.m_textStats1.clear();
+
+ int code = DIFFCODE::FILE | DIFFCODE::CMPERR;
+ // For user chosen plugins, define bAutomaticUnpacker as false and use the chosen infoHandler
+ // but how can we receive the infoHandler ? DirScan actually only
+ // returns info, but can not use file dependent information.
+
+ // Transformation happens here
+ // text used for automatic mode : plugin filter must match it
+ CString filteredFilenames = filepath1 + "|" + filepath2;
+
+ PackingInfo * infoUnpacker=0;
+ PrediffingInfo * infoPrediffer=0;
+
+ // Get existing or new plugin infos
+ pCtxt->FetchPluginInfos(filteredFilenames, &infoUnpacker, &infoPrediffer);
+
+ // plugin may alter filepaths to temp copies (which we delete before returning in all cases)
+ CString filepathUnpacked1 = filepath1;
+ CString filepathUnpacked2 = filepath2;
+
+ CString filepathTransformed1;
+ CString filepathTransformed2;
+
+ //DiffFileData diffdata; //(filepathTransformed1, filepathTransformed2);
+ // Invoke unpacking plugins
+ if (!Unpack(filepathUnpacked1, filteredFilenames, infoUnpacker))
+ {
+ di.errorDesc = _T("Unpack Error Side 1");
+ goto exitPrepAndCompare;
+ }
+
+ // we use the same plugins for both files, so they must be defined before second file
+ ASSERT(infoUnpacker->bToBeScanned == FALSE);
+
+ if (!Unpack(filepathUnpacked2, filteredFilenames, infoUnpacker))
+ {
+ di.errorDesc = _T("Unpack Error Side 2");
+ goto exitPrepAndCompare;
+ }
+
+ // As we keep handles open on unpacked files, Transform() may not delete them.
+ // Unpacked files will be deleted at end of this function.
+ filepathTransformed1 = filepathUnpacked1;
+ filepathTransformed2 = filepathUnpacked2;
+ m_diffFileData.SetDisplayFilepaths(filepath1, filepath2); // store true names for diff utils patch file
+ if (!m_diffFileData.OpenFiles(filepathTransformed1, filepathTransformed2))
+ {
+ di.errorDesc = _T("OpenFiles Error (before tranform)");
+ goto exitPrepAndCompare;
+ }
+
+ // Invoke prediff'ing plugins
+ if (!m_diffFileData.Filepath_Transform(m_diffFileData.m_FileLocation[0], filepathUnpacked1,
+ filepathTransformed1, filteredFilenames, infoPrediffer,
+ m_diffFileData.m_inf[0].desc))
+ {
+ di.errorDesc = _T("Transform Error Side 1");
+ goto exitPrepAndCompare;
+ }
+
+ // we use the same plugins for both files, so they must be defined before second file
+ ASSERT(infoPrediffer->bToBeScanned == FALSE);
+
+ if (!m_diffFileData.Filepath_Transform(m_diffFileData.m_FileLocation[1], filepathUnpacked2,
+ filepathTransformed2, filteredFilenames, infoPrediffer,
+ m_diffFileData.m_inf[1].desc))
+ {
+ di.errorDesc = _T("Transform Error Side 2");
+ goto exitPrepAndCompare;
+ }
+
+ // If options are binary equivalent, we could check for filesize
+ // difference here, and bail out if files are clearly different
+ // But, then we don't know if file is ascii or binary, and this
+ // affects behavior (also, we don't have an icon for unknown type)
+
+ // Actually compare the files
+ // diffutils_compare_files is a fairly thin front-end to diffutils
+ if (filepathTransformed1 != filepathUnpacked1 || filepathTransformed2 != filepathUnpacked2)
+ {
+ //diffdata.m_sFilepath[0] = filepathTransformed1;
+ //diffdata.m_sFilepath[1] = filepathTransformed2;
+ if (!m_diffFileData.OpenFiles(filepathTransformed1, filepathTransformed2))
+ {
+ di.errorDesc = _T("OpenFiles Error (after tranform)");
+ goto exitPrepAndCompare;
+ }
+ }
+
+ // If either file is larger than limit compare files by quick contents
+ // This allows us to (faster) compare big binary files
+ if (pCtxt->m_nCompMethod == CMP_CONTENT &&
+ (di.left.size > pCtxt->m_nQuickCompareLimit ||
+ di.right.size > pCtxt->m_nQuickCompareLimit))
+ {
+ nCompMethod = CMP_QUICK_CONTENT;
+ }
+
+ if (nCompMethod == CMP_CONTENT)
+ {
+ // use diffutils
+ code = diffutils_compare_files(0);
+ // If unique item, it was being compared to itself to determine encoding
+ // and the #diffs is invalid
+ if (di.isSideRightOnly() || di.isSideLeftOnly())
+ {
+ m_ndiffs = DIFFS_UNKNOWN;
+ m_ntrivialdiffs = DIFFS_UNKNOWN;
+ }
+ if (DIFFCODE::isResultError(code))
+ di.errorDesc = _T("DiffUtils Error");
+
+ if (!DIFFCODE::isResultError(code) && pCtxt->m_bGuessEncoding)
+ {
+ // entire file is in memory in the diffutils buffers
+ // inside the diff context, so may as well use in-memory copy
+ m_diffFileData.GuessEncoding_from_buffer_in_DiffContext(0, pCtxt);
+ m_diffFileData.GuessEncoding_from_buffer_in_DiffContext(1, pCtxt);
+ }
+ }
+ else if (nCompMethod == CMP_QUICK_CONTENT)
+ {
+ // use our own byte-by-byte compare
+ code = byte_compare_files(pCtxt->m_bStopAfterFirstDiff, pCtxt->GetAbortable());
+ // Quick contents doesn't know about diff counts
+ // Set to special value to indicate invalid
+ m_ndiffs = DIFFS_UNKNOWN_QUICKCOMPARE;
+ m_ntrivialdiffs = DIFFS_UNKNOWN_QUICKCOMPARE;
+ di.left.m_textStats = m_diffFileData.m_textStats0;
+ di.right.m_textStats = m_diffFileData.m_textStats1;
+
+ if (!DIFFCODE::isResultError(code) && pCtxt->m_bGuessEncoding)
+ {
+ m_diffFileData.GuessEncoding_from_FileLocation(m_diffFileData.m_FileLocation[0]);
+ m_diffFileData.GuessEncoding_from_FileLocation(m_diffFileData.m_FileLocation[1]);
+ }
+ }
+ else
+ {
+ // Print error since we should have handled by date compare earlier
+ _RPTF0(_CRT_ERROR, "Invalid compare type, DiffFileData can't handle it");
+ di.errorDesc = _T("Bad compare type");
+ goto exitPrepAndCompare;
+ }
+
+
+exitPrepAndCompare:
+ m_diffFileData.Reset();
+ // delete the temp files after comparison
+ if (filepathTransformed1 != filepathUnpacked1)
+ VERIFY(::DeleteFile(filepathTransformed1) || gLog::DeleteFileFailed(filepathTransformed1));
+ if (filepathTransformed2 != filepathUnpacked2)
+ VERIFY(::DeleteFile(filepathTransformed2) || gLog::DeleteFileFailed(filepathTransformed2));
+ if (filepathUnpacked1 != filepath1)
+ VERIFY(::DeleteFile(filepathUnpacked1) || gLog::DeleteFileFailed(filepathUnpacked1));
+ if (filepathUnpacked2 != filepath2)
+ VERIFY(::DeleteFile(filepathUnpacked2) || gLog::DeleteFileFailed(filepathUnpacked2));
+ return code;
+}
+
+
+/**
+ * @brief Compare two specified files.
+ *
+ * @param [in] depth Current directory depth.
+ * @return Compare result as DIFFCODE.
+ */
+int FolderCmp::diffutils_compare_files(int depth)
+{
+ int bin_flag = 0;
+ int bin_file = 0; // bitmap for binary files
+
+ // Do the actual comparison (generating a change script)
+ struct change *script = NULL;
+ BOOL success = Diff2Files(&script, depth, &bin_flag, FALSE, &bin_file);
+ if (!success)
+ {
+ return DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::CMPERR;
+ }
+ int code = DIFFCODE::FILE | DIFFCODE::TEXT | DIFFCODE::SAME;
+
+ // make sure to start counting diffs at 0
+ // (usually it is -1 at this point, for unknown)
+ m_ndiffs = 0;
+ m_ntrivialdiffs = 0;
+
+ // Free change script (which we don't want)
+ if (script != NULL)
+ {
+ struct change *p,*e;
+ for (e = script; e; e = p)
+ {
+ if (!e->trivial)
+ ++m_ndiffs;
+ else
+ ++m_ntrivialdiffs;
+ p = e->link;
+ free (e);
+ }
+ if (m_ndiffs > 0)
+ code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF;
+ }
+
+ // diff_2_files set bin_flag to -1 if different binary
+ // diff_2_files set bin_flag to +1 if same binary
+
+ if (bin_flag != 0)
+ {
+ // Clear text-flag, set binary flag
+ // We don't know diff counts for binary files
+ code = code & ~DIFFCODE::TEXT;
+ switch (bin_file)
+ {
+ case BINFILE_SIDE1: code |= DIFFCODE::BINSIDE1;
+ break;
+ case BINFILE_SIDE2: code |= DIFFCODE::BINSIDE2;
+ break;
+ case BINFILE_SIDE1 | BINFILE_SIDE2: code |= DIFFCODE::BIN;
+ break;
+ default:
+ _RPTF1(_CRT_ERROR, "Invalid bin_file value: %d", bin_file);
+ break;
+ }
+ m_ndiffs = DIFFS_UNKNOWN;
+ }
+
+ if (bin_flag < 0)
+ {
+ // Clear same-flag, set diff-flag
+ code = code & ~DIFFCODE::SAME | DIFFCODE::DIFF;
+ }
+
+ return code;
+}
+
+/**
+ * @brief Compare two specified files, byte-by-byte
+ * @param [in] bStopAfterFirstDiff Stop compare after we find first difference?
+ * @param [in] piAbortable Interface allowing to abort compare
+ * @return DIFFCODE
+ */
+int FolderCmp::byte_compare_files(BOOL bStopAfterFirstDiff, const IAbortable * piAbortable)
+{
+ // Close any descriptors open for diffutils
+ m_diffFileData.Reset();
+
+ // TODO
+ // Right now, we assume files are in 8-bit encoding
+ // because transform code converted any UCS-2 files to UTF-8
+ // We could compare directly in UCS-2LE here, as an optimization, in that case
+ char buff[2][WMCMPBUFF]; // buffered access to files
+ FILE * fp[2]; // for files to compare
+ FileHandle fhd[2]; // to ensure file handles fp get closed
+ int i;
+ int diffcode = 0;
+
+ // Open both files
+ for (i=0; i<2; ++i)
+ {
+ fp[i] = _tfopen(m_diffFileData.m_FileLocation[i].filepath, _T("rb"));
+ if (!fp[i])
+ return DIFFCODE::CMPERR;
+ fhd[i].Assign(fp[i]);
+ }
+
+ // area of buffer currently holding data
+ __int64 bfstart[2]; // offset into buff[i] where current data resides
+ __int64 bfend[2]; // past-the-end pointer into buff[i], giving end of current data
+ // buff[0] has bytes to process from buff[0][bfstart[0]] to buff[0][bfend[0]-1]
+
+ bool eof[2]; // if we've finished file
+
+ // initialize our buffer pointers and end of file flags
+ for (i=0; i<2; ++i)
+ {
+ bfstart[i] = bfend[i] = 0;
+ eof[i] = false;
+ }
+
+ ByteComparator comparator(ignore_case_flag, ignore_space_change_flag
+ , ignore_all_space_flag, ignore_eol_diff, ignore_blank_lines_flag);
+
+ // Begin loop
+ // we handle the files in WMCMPBUFF sized buffers (variable buff[][])
+ // That is, we do one buffer full at a time
+ // or even less, as we process until one side buffer is empty, then reload that one
+ // and continue
+ while (!eof[0] || !eof[1])
+ {
+ if (piAbortable && piAbortable->ShouldAbort())
+ return DIFFCODE::CMPABORT;
+
+ // load or update buffers as appropriate
+ for (i=0; i<2; ++i)
+ {
+ if (!eof[i] && bfstart[i]==countof(buff[i]))
+ {
+ bfstart[i]=bfend[i] = 0;
+ }
+ if (!eof[i] && bfend[i]<countof(buff[i])-1)
+ {
+ // Assume our blocks are in range of unsigned int
+ unsigned int space = countof(buff[i]) - bfend[i];
+ size_t rtn = fread(&buff[i][bfend[i]], 1, space, fp[i]);
+ if (ferror(fp[i]))
+ return DIFFCODE::CMPERR;
+ if (feof(fp[i]))
+ eof[i] = true;
+ bfend[i] += rtn;
+ }
+ }
+
+ // where to start comparing right now
+ LPCSTR ptr0 = &buff[0][bfstart[0]];
+ LPCSTR ptr1 = &buff[1][bfstart[1]];
+
+ // remember where we started
+ LPCSTR orig0 = ptr0, orig1 = ptr1;
+
+ // how far can we go right now?
+ LPCSTR end0 = &buff[0][bfend[0]];
+ LPCSTR end1 = &buff[1][bfend[1]];
+
+ __int64 offset0 = (ptr0 - &buff[0][0]);
+ __int64 offset1 = (ptr1 - &buff[1][0]);
+
+ // are these two buffers the same?
+ if (!comparator.CompareBuffers(m_diffFileData.m_textStats0, m_diffFileData.m_textStats1,
+ ptr0, ptr1, end0, end1, eof[0], eof[1], offset0, offset1))
+ {
+ if (bStopAfterFirstDiff)
+ {
+ // By bailing out here
+ // we leave our text statistics incomplete
+ return diffcode | DIFFCODE::DIFF;
+ }
+ else
+ {
+ diffcode |= DIFFCODE::DIFF;
+ ptr0 = end0;
+ ptr1 = end1;
+ }
+ }
+ else
+ {
+ ptr0 = end0;
+ ptr1 = end1;
+ }
+
+
+ // did we finish both files?
+ if (eof[0] && eof[1])
+ {
+
+ BOOL bBin0 = (m_diffFileData.m_textStats0.nzeros>0);
+ BOOL bBin1 = (m_diffFileData.m_textStats1.nzeros>0);
+
+ if (bBin0 && bBin1)
+ diffcode |= DIFFCODE::BIN;
+ else if (bBin0)
+ diffcode |= DIFFCODE::BINSIDE1;
+ else if (bBin1)
+ diffcode |= DIFFCODE::BINSIDE2;
+
+ // If either unfinished, they differ
+ if (ptr0 != end0 || ptr1 != end1)
+ diffcode = (diffcode & DIFFCODE::DIFF);
+
+ if (diffcode & DIFFCODE::DIFF)
+ return diffcode | DIFFCODE::DIFF;
+ else
+ return diffcode | DIFFCODE::SAME;
+ }
+
+ // move our current pointers over what we just compared
+ ASSERT(ptr0 >= orig0);
+ ASSERT(ptr1 >= orig1);
+ bfstart[0] += ptr0-orig0;
+ bfstart[1] += ptr1-orig1;
+ }
+ return diffcode;
+}
+
+/**
+ * @brief Compare two files using diffutils.
+ *
+ * Compare two files (in DiffFileData param) using diffutils. Run diffutils
+ * inside SEH so we can trap possible error and exceptions. If error or
+ * execption is trapped, return compare failure.
+ * @param [out] diffs Pointer to list of change structs where diffdata is stored.
+ * @param [in] depth Depth in folder compare (we use 0).
+ * @param [out] bin_status used to return binary status from compare.
+ * @param [in] bMovedBlocks If TRUE moved blocks are analyzed.
+ * @param [out] bin_file Returns which file was binary file as bitmap.
+ So if first file is binary, first bit is set etc. Can be NULL if binary file
+ info is not needed (faster compare since diffutils don't bother checking
+ second file if first is binary).
+ * @return TRUE when compare succeeds, FALSE if error happened during compare.
+ */
+BOOL FolderCmp::Diff2Files(struct change ** diffs, int depth,
+ int * bin_status, BOOL bMovedBlocks, int * bin_file)
+{
+ BOOL bRet = TRUE;
+ __try
+ {
+ *diffs = diff_2_files (m_diffFileData.m_inf, depth, bin_status, bMovedBlocks, bin_file);
+ CopyDiffutilTextStats(m_diffFileData.m_inf, &m_diffFileData);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ *diffs = NULL;
+ bRet = FALSE;
+ }
+ return bRet;
+}
+
+/**
+ * @brief Copy both left & right text stats results back into the DiffFileData text stats
+ */
+static void CopyDiffutilTextStats(file_data *inf, DiffFileData * diffData)
+{
+ CopyTextStats(&inf[0], &diffData->m_textStats0);
+ CopyTextStats(&inf[1], &diffData->m_textStats1);
+}
+
+/**
+ * @brief Copy text stat results from diffutils back into the FileTextStats structure
+ */
+static void CopyTextStats(const file_data * inf, FileTextStats * myTextStats)
+{
+ myTextStats->ncrlfs = inf->count_crlfs;
+ myTextStats->ncrs = inf->count_crs;
+ myTextStats->nlfs = inf->count_lfs;
+}
+
+/**
+ * @brief Get actual compared paths from DIFFITEM.
+ * @note If item is unique, same path is returned for both.
+ */
+void GetComparePaths(CDiffContext * pCtxt, const DIFFITEM &di, CString & left, CString & right)
+{
+ static const TCHAR backslash[] = _T("\\");
+
+ if (!di.isSideRightOnly())
+ {
+ // Compare file to itself to detect encoding
+ left = pCtxt->GetNormalizedLeft();
+ if (!paths_EndsWithSlash(left))
+ left += backslash;
+ if (!di.sLeftSubdir.IsEmpty())
+ left += di.sLeftSubdir + backslash;
+ left += di.sLeftFilename;
+ if (di.isSideLeftOnly())
+ right = left;
+ }
+ if (!di.isSideLeftOnly())
+ {
+ // Compare file to itself to detect encoding
+ right = pCtxt->GetNormalizedRight();
+ if (!paths_EndsWithSlash(right))
+ right += backslash;
+ if (!di.sRightSubdir.IsEmpty())
+ right += di.sRightSubdir + backslash;
+ right += di.sRightFilename;
+ if (di.isSideRightOnly())
+ left = right;
+ }
+}
+
+/**
+ * @brief Invoke appropriate plugins for unpacking
+ * return false if anything fails
+ * caller has to DeleteFile filepathTransformed, if it differs from filepath
+ */
+static bool Unpack(CString & filepathTransformed,
+ const CString & filteredFilenames, PackingInfo * infoUnpacker)
+{
+ // first step : unpack (plugins)
+ if (infoUnpacker->bToBeScanned)
+ {
+ if (!FileTransform_Unpacking(filepathTransformed, filteredFilenames, infoUnpacker, &infoUnpacker->subcode))
+ return false;
+ }
+ else
+ {
+ if (!FileTransform_Unpacking(filepathTransformed, infoUnpacker, &infoUnpacker->subcode))
+ return false;
+ }
+ return true;
+}
Added: trunk/Src/FolderCmp.h
===================================================================
--- trunk/Src/FolderCmp.h (rev 0)
+++ trunk/Src/FolderCmp.h 2007-01-24 18:41:49 UTC (rev 4075)
@@ -0,0 +1,41 @@
+/**
+ * @file FolderCmp.h
+ *
+ * @brief Declaration file for FolderCmp
+ */
+
+#ifndef _FOLDERCMP_H_
+#define _FOLDERCMP_H_
+
+#include "DiffFileData.h"
+
+class CDiffContext;
+class IAbortable;
+
+/**
+ * @brief Class implementing file compare for folder compare.
+ * This class implements (called from DirScan.cpp) compare of two files
+ * during folder compare. The class implements both diffutils compare and
+ * quick compare.
+ */
+class FolderCmp
+{
+public:
+
+ enum { DIFFS_UNKNOWN=-1, DIFFS_UNKNOWN_QUICKCOMPARE=-9 };
+
+ FolderCmp();
+ int prepAndCompareTwoFiles(CDiffContext * pCtxt, DIFFITEM &di);
+ int diffutils_compare_files(int depth);
+ int byte_compare_files(BOOL bStopAfterFirstDiff, const IAbortable * piAbortable);
+ BOOL Diff2Files(struct change ** diffs, int depth,
+ int * bin_status, BOOL bMovedBlocks, int * bin_file);
+
+ int m_ndiffs;
+ int m_ntrivialdiffs;
+
+ DiffFileData m_diffFileData;
+};
+
+
+#endif // _FOLDERCMP_H_
Modified: trunk/Src/Merge.dsp
===================================================================
--- trunk/Src/Merge.dsp 2007-01-22 17:34:50 UTC (rev 4074)
+++ trunk/Src/Merge.dsp 2007-01-24 18:41:49 UTC (rev 4075)
@@ -449,6 +449,10 @@
# End Source File
# Begin Source File
+SOURCE=.\FolderCmp.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\GhostTextBuffer.cpp
# End Source File
# Begin Source File
@@ -1193,6 +1197,10 @@
# End Source File
# Begin Source File
+SOURCE=.\FolderCmp.h
+# End Source File
+# Begin Source File
+
SOURCE=.\GhostTextBuffer.h
# End Source File
# Begin Source File
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|