OSDN Git Service

Add Show "No Merge" and "First Parent Only" Option at Show ALL menu button
[tortoisegit/TortoiseGitJp.git] / src / TortoiseMerge / DiffData.cpp
1 // TortoiseMerge - a Diff/Patch program\r
2 \r
3 // Copyright (C) 2006-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "StdAfx.h"\r
20 #include "diff.h"\r
21 #include "TempFiles.h"\r
22 #include "registry.h"\r
23 #include "Resource.h"\r
24 #include "Diffdata.h"\r
25 #include "UnicodeUtils.h"\r
26 #include "GitAdminDir.h"\r
27 \r
28 \r
29 #pragma warning(push)\r
30 #pragma warning(disable: 4702) // unreachable code\r
31 int CDiffData::abort_on_pool_failure (int /*retcode*/)\r
32 {\r
33         abort ();\r
34         return -1;\r
35 }\r
36 #pragma warning(pop)\r
37 \r
38 CDiffData::CDiffData(void)\r
39 {\r
40 //      apr_initialize();\r
41 //      svn_dso_initialize();\r
42 //      g_SVNAdminDir.Init();\r
43 \r
44         m_bBlame = false;\r
45 \r
46         m_sPatchOriginal = _T(": original");\r
47         m_sPatchPatched = _T(": patched");\r
48 }\r
49 \r
50 CDiffData::~CDiffData(void)\r
51 {\r
52 ////    g_SVNAdminDir.Close();\r
53 //      apr_terminate();\r
54 }\r
55 \r
56 int CDiffData::GetLineCount()\r
57 {\r
58         int count = 0;\r
59         count = (int)m_arBaseFile.GetCount();\r
60         count = (int)(count > m_arTheirFile.GetCount() ? count : m_arTheirFile.GetCount());\r
61         count = (int)(count > m_arYourFile.GetCount() ? count : m_arYourFile.GetCount());\r
62         return count;\r
63 }\r
64 \r
65 int CDiffData::GetLineActualLength(int index)\r
66 {\r
67         int count = 0;\r
68         if (index < m_arBaseFile.GetCount())\r
69                 count = (count > m_arBaseFile.GetAt(index).GetLength() ? count : m_arBaseFile.GetAt(index).GetLength());\r
70         if (index < m_arTheirFile.GetCount())\r
71                 count = (count > m_arTheirFile.GetAt(index).GetLength() ? count : m_arTheirFile.GetAt(index).GetLength());\r
72         if (index < m_arYourFile.GetCount())\r
73                 count = (count > m_arYourFile.GetAt(index).GetLength() ? count : m_arYourFile.GetAt(index).GetLength());\r
74         return count;\r
75 }\r
76 \r
77 LPCTSTR CDiffData::GetLineChars(int index)\r
78 {\r
79         if (index < m_arBaseFile.GetCount())\r
80                 return m_arBaseFile.GetAt(index);\r
81         if (index < m_arTheirFile.GetCount())\r
82                 return m_arTheirFile.GetAt(index);\r
83         if (index < m_arYourFile.GetCount())\r
84                 return m_arYourFile.GetAt(index);\r
85         return NULL;\r
86 }\r
87 \r
88 BOOL CDiffData::Load()\r
89 {\r
90 \r
91         CString sConvertedBaseFilename, sConvertedTheirFilename, sConvertedYourFilename;\r
92         apr_pool_t * pool;\r
93 \r
94         apr_pool_create_ex (&pool, NULL, abort_on_pool_failure, NULL);\r
95 \r
96         m_arBaseFile.RemoveAll();\r
97         m_arYourFile.RemoveAll();\r
98         m_arTheirFile.RemoveAll();\r
99 \r
100         m_YourBaseBoth.Clear();\r
101         m_YourBaseLeft.Clear();\r
102         m_YourBaseRight.Clear();\r
103 \r
104         m_TheirBaseBoth.Clear();\r
105         m_TheirBaseLeft.Clear();\r
106         m_TheirBaseRight.Clear();\r
107 \r
108         m_Diff3.Clear();\r
109 \r
110         m_arDiff3LinesBase.RemoveAll();\r
111         m_arDiff3LinesYour.RemoveAll();\r
112         m_arDiff3LinesTheir.RemoveAll();\r
113 \r
114         CTempFiles tempfiles;\r
115         CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseMerge\\IgnoreWS"));\r
116         CRegDWORD regIgnoreEOL = CRegDWORD(_T("Software\\TortoiseMerge\\IgnoreEOL"), TRUE);\r
117         CRegDWORD regIgnoreCase = CRegDWORD(_T("Software\\TortoiseMerge\\CaseInsensitive"), FALSE);\r
118         DWORD dwIgnoreWS = regIgnoreWS;\r
119         bool bIgnoreEOL = ((DWORD)regIgnoreEOL)!=0;\r
120         BOOL bIgnoreCase = ((DWORD)regIgnoreCase)!=0;\r
121 \r
122         // The Subversion diff API only can ignore whitespaces and eol styles.\r
123         // It also can only handle one-byte charsets.\r
124         // To ignore case changes or to handle UTF-16 files, we have to\r
125         // save the original file in UTF-8 and/or the letters changed to lowercase\r
126         // so the Subversion diff can handle those.\r
127         sConvertedBaseFilename = m_baseFile.GetFilename();\r
128         sConvertedYourFilename = m_yourFile.GetFilename();\r
129         sConvertedTheirFilename = m_theirFile.GetFilename();\r
130         if (IsBaseFileInUse())\r
131         {\r
132                 if (!m_arBaseFile.Load(m_baseFile.GetFilename()))\r
133                 {\r
134                         m_sError = m_arBaseFile.GetErrorString();\r
135                         return FALSE;\r
136                 }\r
137                 if ((bIgnoreCase)||(m_arBaseFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))\r
138                 {\r
139                         CFileTextLines converted(m_arBaseFile);\r
140                         sConvertedBaseFilename = tempfiles.GetTempFilePath();\r
141                         converted.Save(sConvertedBaseFilename, m_arBaseFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);\r
142                 }\r
143         }\r
144 \r
145         if (IsTheirFileInUse())\r
146         {\r
147                 // m_arBaseFile.GetCount() is passed as a hint for the number of lines in this file\r
148                 // It's a fair guess that the files will be roughly the same size\r
149                 if (!m_arTheirFile.Load(m_theirFile.GetFilename(),m_arBaseFile.GetCount()))\r
150                 {\r
151                         m_sError = m_arTheirFile.GetErrorString();\r
152                         return FALSE;\r
153                 }\r
154                 if ((bIgnoreCase)||(m_arTheirFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))\r
155                 {\r
156                         CFileTextLines converted(m_arTheirFile);\r
157                         sConvertedTheirFilename = tempfiles.GetTempFilePath();\r
158                         converted.Save(sConvertedTheirFilename, m_arTheirFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);\r
159                 }\r
160         }\r
161 \r
162         if (IsYourFileInUse())\r
163         {\r
164                 // m_arBaseFile.GetCount() is passed as a hint for the number of lines in this file\r
165                 // It's a fair guess that the files will be roughly the same size\r
166                 if (!m_arYourFile.Load(m_yourFile.GetFilename(),m_arBaseFile.GetCount()))\r
167                 {\r
168                         m_sError = m_arYourFile.GetErrorString();\r
169                         return FALSE;\r
170                 }\r
171                 if ((bIgnoreCase)||(m_arYourFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))\r
172                 {\r
173                         CFileTextLines converted(m_arYourFile);\r
174                         sConvertedYourFilename = tempfiles.GetTempFilePath();\r
175                         converted.Save(sConvertedYourFilename, m_arYourFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);\r
176                 }\r
177         }\r
178 \r
179         // Calculate the number of lines in the largest of the three files\r
180         int lengthHint = max(m_arBaseFile.GetCount(), m_arTheirFile.GetCount());\r
181         lengthHint = max(lengthHint, m_arYourFile.GetCount());\r
182 \r
183         m_YourBaseBoth.Reserve(lengthHint);\r
184         m_YourBaseLeft.Reserve(lengthHint);\r
185         m_YourBaseRight.Reserve(lengthHint);\r
186 \r
187         m_TheirBaseBoth.Reserve(lengthHint);\r
188         m_TheirBaseLeft.Reserve(lengthHint);\r
189         m_TheirBaseRight.Reserve(lengthHint);\r
190 \r
191         m_arDiff3LinesBase.Reserve(lengthHint);\r
192         m_arDiff3LinesYour.Reserve(lengthHint);\r
193         m_arDiff3LinesTheir.Reserve(lengthHint);\r
194 \r
195         // Is this a two-way diff?\r
196         if (IsBaseFileInUse() && IsYourFileInUse() && !IsTheirFileInUse())\r
197         {\r
198                 if (!DoTwoWayDiff(sConvertedBaseFilename, sConvertedYourFilename, dwIgnoreWS, bIgnoreEOL, pool))\r
199                 {\r
200                         apr_pool_destroy (pool);                                        // free the allocated memory\r
201                         return FALSE;\r
202                 }\r
203         }\r
204 \r
205         if (IsBaseFileInUse() && IsTheirFileInUse() && !IsYourFileInUse())\r
206         {\r
207                 ASSERT(FALSE);\r
208         }\r
209 \r
210         if (IsBaseFileInUse() && IsTheirFileInUse() && IsYourFileInUse())\r
211         {\r
212                 m_Diff3.Reserve(lengthHint);\r
213 \r
214                 if (!DoThreeWayDiff(sConvertedBaseFilename, sConvertedYourFilename, sConvertedTheirFilename, dwIgnoreWS, bIgnoreEOL, !!bIgnoreCase, pool))\r
215                 {\r
216                         apr_pool_destroy (pool);                                        // free the allocated memory\r
217                         return FALSE;\r
218                 }\r
219         }\r
220 \r
221         apr_pool_destroy (pool);                                        // free the allocated memory\r
222 \r
223 \r
224         return TRUE;\r
225 }\r
226 \r
227 \r
228 bool\r
229 CDiffData::DoTwoWayDiff(const CString& sBaseFilename, const CString& sYourFilename, DWORD dwIgnoreWS, bool bIgnoreEOL,apr_pool_t *pool)\r
230 {\r
231         // convert CString filenames (UTF-16 or ANSI) to UTF-8\r
232         CStringA sBaseFilenameUtf8 = CUnicodeUtils::GetUTF8(sBaseFilename);\r
233         CStringA sYourFilenameUtf8 = CUnicodeUtils::GetUTF8(sYourFilename);\r
234 \r
235 \r
236         svn_diff_t * diffYourBase = NULL;\r
237         svn_error_t * svnerr = NULL;\r
238         svn_diff_file_options_t * options = svn_diff_file_options_create(pool);\r
239         options->ignore_eol_style = bIgnoreEOL;\r
240         options->ignore_space = svn_diff_file_ignore_space_none;\r
241         switch (dwIgnoreWS)\r
242         {\r
243         case 0:\r
244                 options->ignore_space = svn_diff_file_ignore_space_none;\r
245                 break;\r
246         case 1:\r
247                 options->ignore_space = svn_diff_file_ignore_space_all;\r
248                 break;\r
249         case 2:\r
250                 options->ignore_space = svn_diff_file_ignore_space_change;\r
251                 break;\r
252         }\r
253 \r
254         svnerr = svn_diff_file_diff_2(&diffYourBase, sBaseFilenameUtf8, sYourFilenameUtf8, options, pool);\r
255         if (svnerr)\r
256         {\r
257                 TRACE(_T("diff-error in CDiffData::Load()\n"));\r
258                 CString sMsg = CString(svnerr->message);\r
259                 while (svnerr->child)\r
260                 {\r
261                         svnerr = svnerr->child;\r
262                         sMsg += _T("\n");\r
263                         sMsg += CString(svnerr->message);\r
264                 }\r
265                 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);\r
266                 svn_error_clear(svnerr);\r
267                 return false;\r
268         }\r
269         svn_diff_t * tempdiff = diffYourBase;\r
270         LONG baseline = 0;\r
271         LONG yourline = 0;\r
272 \r
273         while (tempdiff)\r
274         {\r
275                 for (int i=0; i<tempdiff->original_length; i++)\r
276                 {\r
277                         if (baseline >= m_arBaseFile.GetCount())\r
278                         {\r
279                                 m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);\r
280                                 return false;\r
281                         }\r
282                         const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline);\r
283                         EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
284                         if (tempdiff->type == svn_diff__type_common)\r
285                         {\r
286                                 if (yourline >= m_arYourFile.GetCount())\r
287                                 {\r
288                                         m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);\r
289                                         return false;\r
290                                 }\r
291                                 const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline);\r
292                                 EOL endingYours = m_arYourFile.GetLineEnding(yourline);\r
293                                 if (sCurrentBaseLine != sCurrentYourLine)\r
294                                 {\r
295                                         if (dwIgnoreWS == 2 || dwIgnoreWS == 3)\r
296                                         {\r
297                                                 CString s1 = m_arBaseFile.GetAt(baseline);\r
298                                                 CString s2 = sCurrentYourLine;\r
299                                                 \r
300                                                 if ( dwIgnoreWS == 2 )\r
301                                                 {\r
302                                                         s1.TrimLeft(_T(" \t"));\r
303                                                         s2.TrimLeft(_T(" \t"));\r
304                                                 }\r
305                                                 else\r
306                                                 {\r
307                                                         s1.TrimRight(_T(" \t"));\r
308                                                         s2.TrimRight(_T(" \t"));\r
309                                                 }\r
310 \r
311                                                 if (s1 != s2)\r
312                                                 {\r
313                                                         // one-pane view: two lines, one 'removed' and one 'added'\r
314                                                         m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase);\r
315                                                         m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours);\r
316                                                 }\r
317                                                 else\r
318                                                 {\r
319                                                         m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);\r
320                                                 }\r
321                                         }\r
322                                         else if (dwIgnoreWS == 0)\r
323                                         {\r
324                                                 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase);\r
325                                                 m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours);\r
326                                         }\r
327                                         else\r
328                                         {\r
329                                                 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);\r
330                                         }\r
331                                 }\r
332                                 else\r
333                                 {\r
334                                         m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);\r
335                                 }\r
336                                 yourline++;             //in both files\r
337                         }\r
338                         else\r
339                         {\r
340                                 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVED, yourline, endingBase);\r
341                         }\r
342                         baseline++;\r
343                 }\r
344                 if (tempdiff->type == svn_diff__type_diff_modified)\r
345                 {\r
346                         for (int i=0; i<tempdiff->modified_length; i++)\r
347                         {\r
348                                 if (m_arYourFile.GetCount() > yourline)\r
349                                 {\r
350                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
351                                 }\r
352                                 yourline++;\r
353                         }\r
354                 }\r
355                 tempdiff = tempdiff->next;\r
356         }\r
357 \r
358         tempdiff = diffYourBase;\r
359         baseline = 0;\r
360         yourline = 0;\r
361         while (tempdiff)\r
362         {\r
363                 if (tempdiff->type == svn_diff__type_common)\r
364                 {\r
365                         for (int i=0; i<tempdiff->original_length; i++)\r
366                         {\r
367                                 const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline);\r
368                                 EOL endingYours = m_arYourFile.GetLineEnding(yourline);\r
369                                 const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline);\r
370                                 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
371                                 if (sCurrentBaseLine != sCurrentYourLine)\r
372                                 {\r
373                                         if (dwIgnoreWS == 2 || dwIgnoreWS == 3)\r
374                                         {\r
375                                                 CString s1 = sCurrentBaseLine;\r
376                                                 CString s2 = sCurrentYourLine;\r
377                                                 if ( dwIgnoreWS == 2 )\r
378                                                 {\r
379                                                         s1 = s1.TrimLeft(_T(" \t"));\r
380                                                         s2 = s2.TrimLeft(_T(" \t"));\r
381                                                 }\r
382                                                 else\r
383                                                 {\r
384                                                         s1 = s1.TrimRight(_T(" \t"));\r
385                                                         s2 = s2.TrimRight(_T(" \t"));\r
386                                                 }\r
387                                                 \r
388                                                 if (s1 != s2)\r
389                                                 {\r
390                                                         m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);\r
391                                                         m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);\r
392                                                 }\r
393                                                 else\r
394                                                 {\r
395                                                         m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);\r
396                                                         m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);\r
397                                                 }\r
398                                         }\r
399                                         else if (dwIgnoreWS == 0)\r
400                                         {\r
401                                                 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);\r
402                                                 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);\r
403                                         }\r
404                                         else\r
405                                         {\r
406                                                 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);\r
407                                                 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);\r
408                                         }\r
409                                 }\r
410                                 else\r
411                                 {\r
412                                         m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);\r
413                                         m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);\r
414                                 }\r
415                                 baseline++;\r
416                                 yourline++;\r
417                         }\r
418                 }\r
419                 if (tempdiff->type == svn_diff__type_diff_modified)\r
420                 {\r
421                         apr_off_t original_length = tempdiff->original_length;\r
422                         for (int i=0; i<tempdiff->modified_length; i++)\r
423                         {\r
424                                 if (m_arYourFile.GetCount() > yourline)\r
425                                 {\r
426                                         EOL endingYours = m_arYourFile.GetLineEnding(yourline);\r
427                                         if (original_length-- <= 0)\r
428                                         {\r
429                                                 m_YourBaseLeft.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
430                                                 m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, endingYours);\r
431                                         }\r
432                                         else\r
433                                         {\r
434                                                 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
435                                                 m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase);\r
436                                                 m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, endingYours);\r
437                                                 baseline++;\r
438                                         }\r
439                                         yourline++;\r
440                                 }\r
441                         }\r
442                         apr_off_t modified_length = tempdiff->modified_length;\r
443                         for (int i=0; i<tempdiff->original_length; i++)\r
444                         {\r
445                                 if (modified_length-- <= 0)\r
446                                 {\r
447                                         if (m_arBaseFile.GetCount() > baseline)\r
448                                         {\r
449                                                 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
450                                                 m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase);\r
451                                                 m_YourBaseRight.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
452                                                 baseline++;\r
453                                         }\r
454                                 }\r
455                         }\r
456                 }\r
457                 tempdiff = tempdiff->next;\r
458         }\r
459         TRACE(_T("done with 2-way diff\n"));\r
460 \r
461         return true;\r
462 }\r
463 \r
464 bool\r
465 CDiffData::DoThreeWayDiff(const CString& sBaseFilename, const CString& sYourFilename, const CString& sTheirFilename, DWORD dwIgnoreWS, bool bIgnoreEOL, bool bIgnoreCase,apr_pool_t *pool)\r
466 {\r
467         // convert CString filenames (UTF-16 or ANSI) to UTF-8\r
468         CStringA sBaseFilenameUtf8  = CUnicodeUtils::GetUTF8(sBaseFilename);\r
469         CStringA sYourFilenameUtf8  = CUnicodeUtils::GetUTF8(sYourFilename);\r
470         CStringA sTheirFilenameUtf8 = CUnicodeUtils::GetUTF8(sTheirFilename);\r
471 \r
472         svn_diff_t * diffTheirYourBase = NULL;\r
473         svn_diff_file_options_t * options = svn_diff_file_options_create(pool);\r
474         options->ignore_eol_style = bIgnoreEOL;\r
475         options->ignore_space = svn_diff_file_ignore_space_none;\r
476         switch (dwIgnoreWS)\r
477         {\r
478         case 0:\r
479                 options->ignore_space = svn_diff_file_ignore_space_none;\r
480                 break;\r
481         case 1:\r
482                 options->ignore_space = svn_diff_file_ignore_space_all;\r
483                 break;\r
484         case 2:\r
485                 options->ignore_space = svn_diff_file_ignore_space_change;\r
486                 break;\r
487         }\r
488         svn_error_t * svnerr = svn_diff_file_diff3_2(&diffTheirYourBase, sBaseFilenameUtf8, sTheirFilenameUtf8, sYourFilenameUtf8, options, pool);\r
489         if (svnerr)\r
490         {\r
491                 TRACE(_T("diff-error in CDiffData::Load()\n"));\r
492                 CString sMsg = CString(svnerr->message);\r
493                 while (svnerr->child)\r
494                 {\r
495                         svnerr = svnerr->child;\r
496                         sMsg += _T("\n");\r
497                         sMsg += CString(svnerr->message);\r
498                 }\r
499                 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);\r
500                 svn_error_clear(svnerr);\r
501                 return false;\r
502         }\r
503 \r
504         svn_diff_t * tempdiff = diffTheirYourBase;\r
505         LONG baseline = 0;\r
506         LONG yourline = 0;\r
507         LONG theirline = 0;\r
508         LONG resline = 0;\r
509         while (tempdiff)\r
510         {\r
511                 if (tempdiff->type == svn_diff__type_common)\r
512                 {\r
513                         ASSERT((tempdiff->latest_length == tempdiff->modified_length) && (tempdiff->modified_length == tempdiff->original_length));\r
514                         for (int i=0; i<tempdiff->original_length; i++)\r
515                         {\r
516                                 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))\r
517                                 {\r
518                                         m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, resline, m_arYourFile.GetLineEnding(yourline));\r
519 \r
520                                         m_arDiff3LinesBase.Add(baseline);\r
521                                         m_arDiff3LinesYour.Add(yourline);\r
522                                         m_arDiff3LinesTheir.Add(theirline);\r
523 \r
524                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, yourline, m_arYourFile.GetLineEnding(yourline));\r
525                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_NORMAL, theirline, m_arTheirFile.GetLineEnding(theirline));\r
526 \r
527                                         baseline++;\r
528                                         yourline++;\r
529                                         theirline++;\r
530                                         resline++;\r
531                                 }\r
532                         }\r
533                 }\r
534                 else if (tempdiff->type == svn_diff__type_diff_common)\r
535                 {\r
536                         ASSERT(tempdiff->latest_length == tempdiff->modified_length);\r
537                         //both theirs and yours have lines replaced\r
538                         for (int i=0; i<tempdiff->original_length; i++)\r
539                         {\r
540                                 if (m_arBaseFile.GetCount() > baseline)\r
541                                 {\r
542                                         m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
543 \r
544                                         m_arDiff3LinesBase.Add(baseline);\r
545                                         m_arDiff3LinesYour.Add(yourline);\r
546                                         m_arDiff3LinesTheir.Add(theirline);\r
547 \r
548                                         m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
549                                         m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
550 \r
551                                         baseline++;\r
552                                 }\r
553                         }\r
554                         for (int i=0; i<tempdiff->modified_length; i++)\r
555                         {\r
556                                 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))\r
557                                 {\r
558                                         m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, resline, m_arYourFile.GetLineEnding(yourline));\r
559 \r
560                                         m_arDiff3LinesBase.Add(baseline);\r
561                                         m_arDiff3LinesYour.Add(yourline);\r
562                                         m_arDiff3LinesTheir.Add(theirline);\r
563 \r
564                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
565                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_IDENTICALADDED, resline, m_arTheirFile.GetLineEnding(theirline));\r
566 \r
567                                         yourline++;\r
568                                         theirline++;\r
569                                         resline++;\r
570                                 }\r
571                         }\r
572                 }\r
573                 else if (tempdiff->type == svn_diff__type_conflict)\r
574                 {\r
575                         apr_off_t length = max(tempdiff->original_length, tempdiff->modified_length);\r
576                         length = max(tempdiff->latest_length, length);\r
577                         apr_off_t original = tempdiff->original_length;\r
578                         apr_off_t modified = tempdiff->modified_length;\r
579                         apr_off_t latest = tempdiff->latest_length;\r
580 \r
581                         apr_off_t originalresolved = 0;\r
582                         apr_off_t modifiedresolved = 0;\r
583                         apr_off_t latestresolved = 0;\r
584 \r
585                         LONG base = baseline;\r
586                         LONG your = yourline;\r
587                         LONG their = theirline;\r
588                         if (tempdiff->resolved_diff)\r
589                         {\r
590                                 originalresolved = tempdiff->resolved_diff->original_length;\r
591                                 modifiedresolved = tempdiff->resolved_diff->modified_length;\r
592                                 latestresolved = tempdiff->resolved_diff->latest_length;\r
593                         }\r
594                         for (int i=0; i<length; i++)\r
595                         {\r
596                                 if (original)\r
597                                 {\r
598                                         if (m_arBaseFile.GetCount() > baseline)\r
599                                         {\r
600                                                 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
601 \r
602                                                 m_arDiff3LinesBase.Add(baseline);\r
603                                                 m_arDiff3LinesYour.Add(yourline);\r
604                                                 m_arDiff3LinesTheir.Add(theirline);\r
605                                         }\r
606                                 }\r
607                                 else if ((originalresolved)||((modifiedresolved)&&(latestresolved)))\r
608                                 {\r
609                                         m_Diff3.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
610 \r
611                                         m_arDiff3LinesBase.Add(baseline);\r
612                                         m_arDiff3LinesYour.Add(yourline);\r
613                                         m_arDiff3LinesTheir.Add(theirline);\r
614 \r
615                                 }\r
616                                 if ((latest)&&(original))\r
617                                 {\r
618                                         if (m_arBaseFile.GetCount() > baseline)\r
619                                         {\r
620                                                 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
621                                         }\r
622                                 }\r
623                                 else\r
624                                 {\r
625                                         if (original)\r
626                                         {\r
627                                                 if (m_arBaseFile.GetCount() > baseline)\r
628                                                 {\r
629                                                         m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
630                                                 }\r
631                                         }\r
632                                         else if ((latestresolved)&&(modifiedresolved))\r
633                                         {\r
634                                                 m_YourBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
635                                         }\r
636                                 }\r
637                                 if ((modified)&&(original))\r
638                                 {\r
639                                         if (m_arBaseFile.GetCount() > baseline)\r
640                                         {\r
641                                                 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
642                                         }\r
643                                 }\r
644                                 else\r
645                                 {\r
646                                         if (original)\r
647                                         {\r
648                                                 if (m_arBaseFile.GetCount() > baseline)\r
649                                                 {\r
650                                                         m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
651                                                 }\r
652                                         }\r
653                                         else if ((modifiedresolved)&&(latestresolved))\r
654                                         {\r
655                                                 m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
656                                         }\r
657                                 }\r
658                                 if (original)\r
659                                 {\r
660                                         original--;\r
661                                         baseline++;\r
662                                 }\r
663                                 if (originalresolved)\r
664                                         originalresolved--;\r
665 \r
666                                 if (modified)\r
667                                 {\r
668                                         modified--;\r
669                                         theirline++;\r
670                                 }\r
671                                 if (modifiedresolved)\r
672                                         modifiedresolved--;\r
673                                 if (latest)\r
674                                 {\r
675                                         latest--;\r
676                                         yourline++;\r
677                                 }\r
678                                 if (latestresolved)\r
679                                         latestresolved--;\r
680                         }\r
681                         original = tempdiff->original_length;\r
682                         modified = tempdiff->modified_length;\r
683                         latest = tempdiff->latest_length;\r
684                         baseline = base;\r
685                         yourline = your;\r
686                         theirline = their;\r
687                         if (tempdiff->resolved_diff)\r
688                         {\r
689                                 originalresolved = tempdiff->resolved_diff->original_length;\r
690                                 modifiedresolved = tempdiff->resolved_diff->modified_length;\r
691                                 latestresolved = tempdiff->resolved_diff->latest_length;\r
692                         }\r
693                         for (int i=0; i<length; i++)\r
694                         {\r
695                                 if ((latest)||(modified))\r
696                                 {\r
697                                         m_Diff3.AddData(_T(""), DIFFSTATE_CONFLICTED, resline, EOL_NOENDING);\r
698 \r
699                                         m_arDiff3LinesBase.Add(baseline);\r
700                                         m_arDiff3LinesYour.Add(yourline);\r
701                                         m_arDiff3LinesTheir.Add(theirline);\r
702 \r
703                                         resline++;\r
704                                 }\r
705 \r
706                                 if (latest)\r
707                                 {\r
708                                         if (m_arYourFile.GetCount() > yourline)\r
709                                         {\r
710                                                 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_CONFLICTADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
711                                         }\r
712                                 }\r
713                                 else if ((latestresolved)||(modified)||(modifiedresolved))\r
714                                 {\r
715                                         m_YourBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
716                                 }\r
717                                 if (modified)\r
718                                 {\r
719                                         if (m_arTheirFile.GetCount() > theirline)\r
720                                         {\r
721                                                 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_CONFLICTADDED, theirline, m_arTheirFile.GetLineEnding(theirline));\r
722                                         }\r
723                                 }\r
724                                 else if ((modifiedresolved)||(latest)||(latestresolved))\r
725                                 {\r
726                                         m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
727                                 }\r
728                                 if (original)\r
729                                 {\r
730                                         original--;\r
731                                         baseline++;\r
732                                 }\r
733                                 if (originalresolved)\r
734                                         originalresolved--;\r
735                                 if (modified)\r
736                                 {\r
737                                         modified--;\r
738                                         theirline++;\r
739                                 }\r
740                                 if (modifiedresolved)\r
741                                         modifiedresolved--;\r
742                                 if (latest)\r
743                                 {\r
744                                         latest--;\r
745                                         yourline++;\r
746                                 }\r
747                                 if (latestresolved)\r
748                                         latestresolved--;\r
749                         }\r
750                 }\r
751                 else if (tempdiff->type == svn_diff__type_diff_modified)\r
752                 {\r
753                         //deleted!\r
754                         for (int i=0; i<tempdiff->original_length; i++)\r
755                         {\r
756                                 if ((m_arBaseFile.GetCount() > baseline)&&(m_arYourFile.GetCount() > yourline))\r
757                                 {\r
758                                         m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_THEIRSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
759 \r
760                                         m_arDiff3LinesBase.Add(baseline);\r
761                                         m_arDiff3LinesYour.Add(yourline);\r
762                                         m_arDiff3LinesTheir.Add(theirline);\r
763 \r
764                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, yourline, m_arYourFile.GetLineEnding(yourline));\r
765                                         m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_THEIRSREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
766                                         baseline++;\r
767                                         yourline++;\r
768                                 }\r
769                         }\r
770                         //added\r
771                         for (int i=0; i<tempdiff->modified_length; i++)\r
772                         {\r
773                                 if (m_arTheirFile.GetCount() > theirline)\r
774                                 {\r
775                                         m_Diff3.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_THEIRSADDED, resline, m_arTheirFile.GetLineEnding(theirline));\r
776 \r
777                                         m_arDiff3LinesBase.Add(baseline);\r
778                                         m_arDiff3LinesYour.Add(yourline);\r
779                                         m_arDiff3LinesTheir.Add(theirline);\r
780 \r
781                                         m_YourBaseBoth.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
782                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_THEIRSADDED, theirline, m_arTheirFile.GetLineEnding(theirline));\r
783 \r
784                                         theirline++;\r
785                                         resline++;\r
786                                 }\r
787                         }\r
788                 }\r
789                 else if (tempdiff->type == svn_diff__type_diff_latest)\r
790                 {\r
791                         //YOURS differs from base\r
792 \r
793                         for (int i=0; i<tempdiff->original_length; i++)\r
794                         {\r
795                                 if ((m_arBaseFile.GetCount() > baseline)&&(m_arTheirFile.GetCount() > theirline))\r
796                                 {\r
797                                         m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_YOURSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
798 \r
799                                         m_arDiff3LinesBase.Add(baseline);\r
800                                         m_arDiff3LinesYour.Add(yourline);\r
801                                         m_arDiff3LinesTheir.Add(theirline);\r
802 \r
803                                         m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_YOURSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
804                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_NORMAL, theirline, m_arTheirFile.GetLineEnding(theirline));\r
805 \r
806                                         baseline++;\r
807                                         theirline++;\r
808                                 }\r
809                         }\r
810                         for (int i=0; i<tempdiff->latest_length; i++)\r
811                         {\r
812                                 if (m_arYourFile.GetCount() > yourline)\r
813                                 {\r
814                                         m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_YOURSADDED, resline, m_arYourFile.GetLineEnding(yourline));\r
815 \r
816                                         m_arDiff3LinesBase.Add(baseline);\r
817                                         m_arDiff3LinesYour.Add(yourline);\r
818                                         m_arDiff3LinesTheir.Add(theirline);\r
819 \r
820                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
821                                         m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
822 \r
823                                         yourline++;\r
824                                         resline++;\r
825                                 }\r
826                         }\r
827                 }\r
828                 else\r
829                 {\r
830                         TRACE(_T("something bad happened during diff!\n"));\r
831                 }\r
832                 tempdiff = tempdiff->next;\r
833 \r
834         } // while (tempdiff)\r
835 \r
836         if ((options->ignore_space != svn_diff_file_ignore_space_none)||(bIgnoreCase)||(bIgnoreEOL))\r
837         {\r
838                 // If whitespaces are ignored, a conflict could have been missed\r
839                 // We now go through all lines again and check if they're identical.\r
840                 // If they're not, then that means it is a conflict, and we\r
841                 // mark the conflict with the proper colors.\r
842                 for (long i=0; i<m_Diff3.GetCount(); ++i)\r
843                 {\r
844                         DiffStates state1 = m_YourBaseBoth.GetState(i);\r
845                         DiffStates state2 = m_TheirBaseBoth.GetState(i);\r
846 \r
847                         if (((state1 == DIFFSTATE_IDENTICALADDED)||(state1 == DIFFSTATE_NORMAL))&&\r
848                                 ((state2 == DIFFSTATE_IDENTICALADDED)||(state2 == DIFFSTATE_NORMAL)))\r
849                         {\r
850                                 LONG lineyour = m_arDiff3LinesYour.GetAt(i);\r
851                                 LONG linetheir = m_arDiff3LinesTheir.GetAt(i);\r
852                                 LONG linebase = m_arDiff3LinesBase.GetAt(i);\r
853                                 if ((lineyour < m_arYourFile.GetCount()) &&\r
854                                         (linetheir < m_arTheirFile.GetCount()) &&\r
855                                         (linebase < m_arBaseFile.GetCount()))\r
856                                 {\r
857                                         if (((m_arYourFile.GetLineEnding(lineyour)!=m_arBaseFile.GetLineEnding(linebase))&&\r
858                                                 (m_arTheirFile.GetLineEnding(linetheir)!=m_arBaseFile.GetLineEnding(linebase))&&\r
859                                                 (m_arYourFile.GetLineEnding(lineyour)!=m_arTheirFile.GetLineEnding(linetheir))) ||\r
860                                                 ((m_arYourFile.GetAt(lineyour).Compare(m_arBaseFile.GetAt(linebase))!=0)&&\r
861                                                 (m_arTheirFile.GetAt(linetheir).Compare(m_arBaseFile.GetAt(linebase))!=0)&&\r
862                                                 (m_arYourFile.GetAt(lineyour).Compare(m_arTheirFile.GetAt(linetheir))!=0)))\r
863                                         {\r
864                                                 m_Diff3.SetState(i, DIFFSTATE_CONFLICTED_IGNORED);\r
865                                                 m_YourBaseBoth.SetState(i, DIFFSTATE_CONFLICTADDED);\r
866                                                 m_TheirBaseBoth.SetState(i, DIFFSTATE_CONFLICTADDED);\r
867                                         }\r
868                                 }\r
869                         }\r
870                 }\r
871         }\r
872         ASSERT(m_Diff3.GetCount() == m_YourBaseBoth.GetCount());\r
873         ASSERT(m_TheirBaseBoth.GetCount() == m_YourBaseBoth.GetCount());\r
874 \r
875         TRACE(_T("done with 3-way diff\n"));\r
876         return true;\r
877 }\r