Skip to content

Commit

Permalink
Allow Diff algorithms (patience, histogram) other than default to be …
Browse files Browse the repository at this point in the history
…applied to folder comparisons (4)
  • Loading branch information
sdottaka committed Sep 5, 2023
1 parent 9856996 commit 9d0fa48
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 38 deletions.
2 changes: 1 addition & 1 deletion Src/CompareEngines/Wrap_DiffUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ bool DiffUtils::Diff2Files(struct change ** diffs, int depth,
if (m_pOptions->m_diffAlgorithm != DIFF_ALGORITHM_DEFAULT)
{
const unsigned xdl_flags = make_xdl_flags(*m_pOptions);
*diffs = diff_2_files_xdiff(m_inf, bin_status, 0, xdl_flags);
*diffs = diff_2_files_xdiff(m_inf, bin_status, bMovedBlocks, bin_file, xdl_flags);
files[0] = m_inf[0];
files[1] = m_inf[1];
}
Expand Down
2 changes: 1 addition & 1 deletion Src/DiffTextBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ int CDiffTextBuffer::SaveToFile (const String& pszFileName,
if (bTempFile)
{
file.SetUnicoding(ucr::UTF8);
file.SetBom(GetOptionsMgr()->GetInt(OPT_CMP_DIFF_ALGORITHM) == 0);
file.SetBom(true);
bOpenSuccess = !!file.OpenCreate(pszFileName);
}
else
Expand Down
3 changes: 2 additions & 1 deletion Src/DiffWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,8 @@ bool CDiffWrapper::Diff2Files(struct change ** diffs, DiffFileData *diffData,
if (m_options.m_diffAlgorithm != DIFF_ALGORITHM_DEFAULT)
{
const unsigned xdl_flags = make_xdl_flags(m_options);
*diffs = diff_2_files_xdiff(diffData->m_inf, bin_status, (m_pMovedLines[0] != nullptr), xdl_flags);
*diffs = diff_2_files_xdiff(diffData->m_inf, bin_status,
(m_pMovedLines[0] != nullptr), bin_file, xdl_flags);
files[0] = diffData->m_inf[0];
files[1] = diffData->m_inf[1];
}
Expand Down
140 changes: 106 additions & 34 deletions Src/xdiff_gnudiff_compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static int hunk_func(long start_a, long count_a, long start_b, long count_b, voi
return 0;
}

struct change * diff_2_files_xdiff (struct file_data filevec[], int* bin_status, int bMoved_blocks_flag, unsigned xdl_flags)
struct change * diff_2_files_xdiff (struct file_data filevec[], int* bin_status, int bMoved_blocks_flag, int* bin_file, unsigned xdl_flags)
{
mmfile_t mmfile1 = { 0 }, mmfile2 = { 0 };
change *script = nullptr;
Expand All @@ -79,46 +79,118 @@ struct change * diff_2_files_xdiff (struct file_data filevec[], int* bin_status,
xpparam_t xpp = { 0 };
xdemitconf_t xecfg = { 0 };
xdemitcb_t ecb = { 0 };
int bin_flag = 0;

read_files(filevec, no_details_flag & ~ignore_some_changes, &bin_flag);
if (read_files(filevec, no_details_flag & ~ignore_some_changes, bin_file))
{
int i;
int changes;
// copy from analyze.c
// We can now safely assume to have a pair of Binary files.

// Are both files Open and Regular (no Pipes, Directories, Devices (e.g. NUL))
if (filevec[0].desc < 0 || filevec[1].desc < 0 ||
!(S_ISREG (filevec[0].stat.st_mode)) || !(S_ISREG (filevec[1].stat.st_mode)) )
changes = 1;
else
// Files with different lengths must be different.
if (filevec[0].stat.st_size != filevec[1].stat.st_size)
changes = 1;
else
// Identical descriptor implies identical files
if (filevec[0].desc == filevec[1].desc)
changes = 0;
// Scan both files, a buffer at a time, looking for a difference.
else
{
// Same-sized buffers for both files were allocated in read_files().
size_t buffer_size = filevec[0].bufsize;

for (;;)
{
// Read a buffer's worth from both files.
for (i = 0; i < 2; i++)
while (filevec[i].buffered_chars < buffer_size)
{
int r = _read (filevec[i].desc,
filevec[i].buffer + filevec[i].buffered_chars,
(int)(buffer_size - filevec[i].buffered_chars));
if (r == 0)
break;
if (r < 0)
pfatal_with_name (filevec[i].name);
filevec[i].buffered_chars += r;
}

// If the buffers have different number of chars, the files differ.
if (filevec[0].buffered_chars != filevec[1].buffered_chars)
{
changes = 1;
break;
}

mmfile1.ptr = const_cast<char*>(filevec[0].prefix_end);
mmfile1.size = static_cast<long>(filevec[0].suffix_begin - filevec[0].prefix_end) - filevec[0].missing_newline;
mmfile2.ptr = const_cast<char*>(filevec[1].prefix_end);
mmfile2.size = static_cast<long>(filevec[1].suffix_begin - filevec[1].prefix_end) - filevec[1].missing_newline;
// If we reach end-of-file, the files are the same.
if (filevec[0].buffered_chars==0) // therefore: filevec[1].buffered_chars==0
{
changes = 0;
break;
}

xpp.flags = xdl_flags;
xecfg.hunk_func = hunk_func;
if (xdl_diff_modified(&mmfile1, &mmfile2, &xpp, &xecfg, &ecb, &xe, &xscr) == 0)
// If buffers have different contents, the files are different.
if (memcmp (filevec[0].buffer,
filevec[1].buffer,
filevec[0].buffered_chars) != 0)
{
changes = 1;
break;
}

// Files appear identical so far...
// Prepare to loop again for the next pair of buffers.
filevec[0].buffered_chars = filevec[1].buffered_chars = 0;
}
}
if (bin_status != NULL)
*bin_status = (changes != 0 ? -1 : 1);
}
else
{
change *prev = nullptr;
for (xdchange_t* xcur = xscr; xcur; xcur = xcur->next)
mmfile1.ptr = const_cast<char*>(filevec[0].prefix_end);
mmfile1.size = static_cast<long>(filevec[0].suffix_begin - filevec[0].prefix_end) - filevec[0].missing_newline;
mmfile2.ptr = const_cast<char*>(filevec[1].prefix_end);
mmfile2.size = static_cast<long>(filevec[1].suffix_begin - filevec[1].prefix_end) - filevec[1].missing_newline;

xpp.flags = xdl_flags;
xecfg.hunk_func = hunk_func;
if (xdl_diff_modified(&mmfile1, &mmfile2, &xpp, &xecfg, &ecb, &xe, &xscr) == 0)
{
change* e = static_cast<change*>(malloc(sizeof(change)));
if (!e)
goto abort;
if (!script)
script = e;
e->line0 = xcur->i1;
e->line1 = xcur->i2;
e->deleted = xcur->chg1;
e->inserted = xcur->chg2;
e->match0 = -1;
e->match1 = -1;
e->trivial = static_cast<char>(xcur->ignore);
e->link = nullptr;
e->ignore = 0;
if (prev)
prev->link = e;
prev = e;
}
change *prev = nullptr;
for (xdchange_t* xcur = xscr; xcur; xcur = xcur->next)
{
change* e = static_cast<change*>(malloc(sizeof(change)));
if (!e)
goto abort;
if (!script)
script = e;
e->line0 = xcur->i1;
e->line1 = xcur->i2;
e->deleted = xcur->chg1;
e->inserted = xcur->chg2;
e->match0 = -1;
e->match1 = -1;
e->trivial = static_cast<char>(xcur->ignore);
e->link = nullptr;
e->ignore = 0;
if (prev)
prev->link = e;
prev = e;
}

if (bMoved_blocks_flag)
moved_block_analysis(&script, filevec);
if (bMoved_blocks_flag)
moved_block_analysis(&script, filevec);

xdl_free_script(xscr);
xdl_free_env(&xe);
xdl_free_script(xscr);
xdl_free_env(&xe);
}
}

return script;
Expand Down
2 changes: 1 addition & 1 deletion Src/xdiff_gnudiff_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

class DiffutilsOptions;
unsigned long make_xdl_flags(const DiffutilsOptions& options);
struct change * diff_2_files_xdiff(struct file_data filevec[], int* bin_status, int bMoved_blocks_flag, unsigned xdl_flags);
struct change * diff_2_files_xdiff(struct file_data filevec[], int* bin_status, int bMoved_blocks_flag, int* bin_file, unsigned xdl_flags);

0 comments on commit 9d0fa48

Please sign in to comment.