/* Add the blame for the diffs between LAST_FILE and CUR_FILE with the rev specified in FRB. LAST_FILE may be NULL in which case blame is added for every line of CUR_FILE. */ static svn_error_t * add_file_blame(const char *last_file, const char *cur_file, struct blame_chain *chain, struct rev *rev, const svn_diff_file_options_t *diff_options, apr_pool_t *pool) { if (!last_file) { SVN_ERR_ASSERT(chain->blame == NULL); chain->blame = blame_create(chain, rev, 0); } else { svn_diff_t *diff; struct diff_baton diff_baton; diff_baton.chain = chain; diff_baton.rev = rev; /* We have a previous file. Get the diff and adjust blame info. */ SVN_ERR(svn_diff_file_diff_2(&diff, last_file, cur_file, diff_options, pool)); SVN_ERR(svn_diff_output(diff, &diff_baton, &output_fns)); } return SVN_NO_ERROR; }
svn_error_t * svn_diff_file_diff(svn_diff_t **diff, const char *original, const char *modified, apr_pool_t *pool) { return svn_diff_file_diff_2(diff, original, modified, svn_diff_file_options_create(pool), pool); }
static svn_error_t * do_diff(svn_stream_t *ostream, const char *original, const char *modified, svn_boolean_t *has_changes, svn_diff_file_options_t *options, svn_boolean_t show_c_function, apr_pool_t *pool) { svn_diff_t *diff; SVN_ERR(svn_diff_file_diff_2(&diff, original, modified, options, pool)); *has_changes = svn_diff_contains_diffs(diff); return svn_diff_file_output_unified4(ostream, diff, original, modified, NULL, NULL, SVN_APR_LOCALE_CHARSET, NULL, show_c_function, options->context_size, NULL, NULL, pool); }
bool CAppUtils::CreateUnifiedDiff(const CString& orig, const CString& modified, const CString& output, bool bShowError) { apr_file_t * outfile = NULL; apr_pool_t * pool = svn_pool_create(NULL); svn_error_t * err = svn_io_file_open (&outfile, svn_path_internal_style(CUnicodeUtils::GetUTF8(output), pool), APR_WRITE | APR_CREATE | APR_BINARY | APR_TRUNCATE, APR_OS_DEFAULT, pool); if (err == NULL) { svn_stream_t * stream = svn_stream_from_aprfile2(outfile, false, pool); if (stream) { svn_diff_t * diff = NULL; svn_diff_file_options_t * opts = svn_diff_file_options_create(pool); opts->ignore_eol_style = false; opts->ignore_space = svn_diff_file_ignore_space_none; err = svn_diff_file_diff_2(&diff, svn_path_internal_style(CUnicodeUtils::GetUTF8(orig), pool), svn_path_internal_style(CUnicodeUtils::GetUTF8(modified), pool), opts, pool); if (err == NULL) { err = svn_diff_file_output_unified(stream, diff, svn_path_internal_style(CUnicodeUtils::GetUTF8(orig), pool), svn_path_internal_style(CUnicodeUtils::GetUTF8(modified), pool), NULL, NULL, pool); svn_stream_close(stream); } } apr_file_close(outfile); } if (err) { if (bShowError) AfxMessageBox(CAppUtils::GetErrorString(err), MB_ICONERROR); svn_error_clear(err); svn_pool_destroy(pool); return false; } svn_pool_destroy(pool); return true; }
bool CDiffData::DoTwoWayDiff(const CString& sBaseFilename, const CString& sYourFilename, DWORD dwIgnoreWS, bool bIgnoreEOL, apr_pool_t * pool) { svn_diff_file_options_t * options = CreateDiffFileOptions(dwIgnoreWS, bIgnoreEOL, pool); // convert CString filenames (UTF-16 or ANSI) to UTF-8 CStringA sBaseFilenameUtf8 = CUnicodeUtils::GetUTF8(sBaseFilename); CStringA sYourFilenameUtf8 = CUnicodeUtils::GetUTF8(sYourFilename); svn_diff_t * diffYourBase = NULL; svn_error_t * svnerr = svn_diff_file_diff_2(&diffYourBase, sBaseFilenameUtf8, sYourFilenameUtf8, options, pool); if (svnerr) return HandleSvnError(svnerr); tsvn_svn_diff_t_extension * movedBlocks = NULL; if(m_bViewMovedBlocks) movedBlocks = MovedBlocksDetect(diffYourBase, dwIgnoreWS, pool); // Side effect is that diffs are now splitted svn_diff_t * tempdiff = diffYourBase; LONG baseline = 0; LONG yourline = 0; while (tempdiff) { svn_diff__type_e diffType = tempdiff->type; // Side effect described above overcoming - sticking together apr_off_t original_length_sticked = tempdiff->original_length; apr_off_t modified_length_sticked = tempdiff->modified_length; StickAndSkip(tempdiff, original_length_sticked, modified_length_sticked); for (int i=0; i<original_length_sticked; i++) { if (baseline >= m_arBaseFile.GetCount()) { m_sError.LoadString(IDS_ERR_DIFF_NEWLINES); return false; } const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline); EOL endingBase = m_arBaseFile.GetLineEnding(baseline); if (diffType == svn_diff__type_common) { if (yourline >= m_arYourFile.GetCount()) { m_sError.LoadString(IDS_ERR_DIFF_NEWLINES); return false; } const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline); EOL endingYours = m_arYourFile.GetLineEnding(yourline); if (sCurrentBaseLine != sCurrentYourLine) { bool changedWS = false; if (dwIgnoreWS == 2 || dwIgnoreWS == 3) changedWS = CompareWithIgnoreWS(sCurrentBaseLine, sCurrentYourLine, dwIgnoreWS); if (changedWS || dwIgnoreWS == 0) { // one-pane view: two lines, one 'removed' and one 'added' m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase, HIDESTATE_SHOWN, -1); m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours, HIDESTATE_SHOWN, -1); } else { m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingBase, HIDESTATE_HIDDEN, -1); } } else { m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingBase, HIDESTATE_HIDDEN, -1); } yourline++; //in both files } else { // small trick - we need here a baseline, but we fix it back to yourline at the end of routine m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVED, -1, endingBase, HIDESTATE_SHOWN, -1); } baseline++; } if (diffType == svn_diff__type_diff_modified) { for (int i=0; i<modified_length_sticked; i++) { if (m_arYourFile.GetCount() > yourline) { m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, m_arYourFile.GetLineEnding(yourline), HIDESTATE_SHOWN, -1); } yourline++; } } tempdiff = tempdiff->next; } HideUnchangedSections(&m_YourBaseBoth, NULL, NULL); tempdiff = diffYourBase; baseline = 0; yourline = 0; while (tempdiff) { if (tempdiff->type == svn_diff__type_common) { for (int i=0; i<tempdiff->original_length; i++) { const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline); EOL endingYours = m_arYourFile.GetLineEnding(yourline); const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline); EOL endingBase = m_arBaseFile.GetLineEnding(baseline); if (sCurrentBaseLine != sCurrentYourLine) { bool changedWS = false; if (dwIgnoreWS == 2 || dwIgnoreWS == 3) changedWS = CompareWithIgnoreWS(sCurrentBaseLine, sCurrentYourLine, dwIgnoreWS); if (changedWS || dwIgnoreWS == 0) { m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase, HIDESTATE_SHOWN, -1); m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours, HIDESTATE_SHOWN, -1); } else { m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase, HIDESTATE_HIDDEN, -1); m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours, HIDESTATE_HIDDEN, -1); } } else { m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase, HIDESTATE_HIDDEN, -1); m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours, HIDESTATE_HIDDEN, -1); } baseline++; yourline++; } } if (tempdiff->type == svn_diff__type_diff_modified) { // now we trying to stick together parts, that were splitted by MovedBlocks apr_off_t original_length_sticked = tempdiff->original_length; apr_off_t modified_length_sticked = tempdiff->modified_length; StickAndSkip(tempdiff, original_length_sticked, modified_length_sticked); apr_off_t original_length = original_length_sticked; for (int i=0; i<modified_length_sticked; i++) { if (m_arYourFile.GetCount() > yourline) { EOL endingYours = m_arYourFile.GetLineEnding(yourline); m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, endingYours, HIDESTATE_SHOWN, -1); if (original_length-- <= 0) { m_YourBaseLeft.AddEmpty(); } else { EOL endingBase = m_arBaseFile.GetLineEnding(baseline); m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase, HIDESTATE_SHOWN, -1); baseline++; } yourline++; } } apr_off_t modified_length = modified_length_sticked; for (int i=0; i<original_length_sticked; i++) { if ((modified_length-- <= 0)&&(m_arBaseFile.GetCount() > baseline)) { EOL endingBase = m_arBaseFile.GetLineEnding(baseline); m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase, HIDESTATE_SHOWN, -1); m_YourBaseRight.AddEmpty(); baseline++; } } } tempdiff = tempdiff->next; } // add last (empty) lines if needed - diff don't report those if (m_arBaseFile.GetCount() > baseline) { if (m_arYourFile.GetCount() > yourline) { // last line is missing in both files add them to end and mark as no diff m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_NORMAL, baseline, m_arBaseFile.GetLineEnding(baseline), HIDESTATE_SHOWN, -1); m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, yourline, m_arYourFile.GetLineEnding(yourline), HIDESTATE_SHOWN, -1); yourline++; baseline++; } else { viewdata oViewData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, m_arBaseFile.GetLineEnding(baseline), HIDESTATE_SHOWN); baseline++; // find first EMPTY line in last blok int nPos = m_YourBaseLeft.GetCount(); while (--nPos>=0 && m_YourBaseLeft.GetState(nPos)==DIFFSTATE_EMPTY) ; if (++nPos<m_YourBaseLeft.GetCount()) { m_YourBaseLeft.SetData(nPos, oViewData); } else { m_YourBaseLeft.AddData(oViewData); m_YourBaseRight.AddEmpty(); } } } else if (m_arYourFile.GetCount() > yourline) { viewdata oViewData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, m_arYourFile.GetLineEnding(yourline), HIDESTATE_SHOWN); yourline++; // try to move last line higher int nPos = m_YourBaseRight.GetCount(); while (--nPos>=0 && m_YourBaseRight.GetState(nPos)==DIFFSTATE_EMPTY) ; if (++nPos<m_YourBaseRight.GetCount()) { m_YourBaseRight.SetData(nPos, oViewData); } else { m_YourBaseLeft.AddEmpty(); m_YourBaseRight.AddData(oViewData); } } // Fixing results for conforming moved blocks while(movedBlocks) { tempdiff = movedBlocks->base; if(movedBlocks->moved_to != -1) { // set states in a block original:length -> moved_to:length TieMovedBlocks((int)tempdiff->original_start, movedBlocks->moved_to, tempdiff->original_length); } if(movedBlocks->moved_from != -1) { // set states in a block modified:length -> moved_from:length TieMovedBlocks(movedBlocks->moved_from, (int)tempdiff->modified_start, tempdiff->modified_length); } movedBlocks = movedBlocks->next; } // replace baseline with the yourline in m_YourBaseBoth /* yourline = 0; for(int i=0; i<m_YourBaseBoth.GetCount(); i++) { DiffStates state = m_YourBaseBoth.GetState(i); if((state == DIFFSTATE_REMOVED)||(state == DIFFSTATE_MOVED_FROM)) { m_YourBaseBoth.SetLineNumber(i, -1); } else { yourline++; } }//*/ TRACE(_T("done with 2-way diff\n")); HideUnchangedSections(&m_YourBaseLeft, &m_YourBaseRight, NULL); return true; }