1 // TortoiseSVN - a Windows shell extension for easy version control
\r
3 // Copyright (C) 2007-2008 - TortoiseSVN
\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
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
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
20 #include "TortoiseProc.h"
\r
21 #include "ConflictResolveDlg.h"
\r
22 #include "TSVNPath.h"
\r
23 #include "UnicodeUtils.h"
\r
24 #include "PathUtils.h"
\r
25 #include "AppUtils.h"
\r
26 #include "TempFile.h"
\r
28 IMPLEMENT_DYNAMIC(CConflictResolveDlg, CResizableStandAloneDialog)
\r
30 CConflictResolveDlg::CConflictResolveDlg(CWnd* pParent /*=NULL*/)
\r
31 : CResizableStandAloneDialog(CConflictResolveDlg::IDD, pParent)
\r
32 , m_pConflictDescription(NULL)
\r
33 , m_choice(svn_wc_conflict_choose_postpone)
\r
34 , m_bCancelled(false)
\r
39 CConflictResolveDlg::~CConflictResolveDlg()
\r
43 void CConflictResolveDlg::DoDataExchange(CDataExchange* pDX)
\r
45 CResizableStandAloneDialog::DoDataExchange(pDX);
\r
49 BEGIN_MESSAGE_MAP(CConflictResolveDlg, CResizableStandAloneDialog)
\r
50 ON_BN_CLICKED(IDC_USELOCAL, &CConflictResolveDlg::OnBnClickedUselocal)
\r
51 ON_BN_CLICKED(IDC_USEREPO, &CConflictResolveDlg::OnBnClickedUserepo)
\r
52 ON_BN_CLICKED(IDC_EDITCONFLICT, &CConflictResolveDlg::OnBnClickedEditconflict)
\r
53 ON_BN_CLICKED(IDC_RESOLVED, &CConflictResolveDlg::OnBnClickedResolved)
\r
54 ON_BN_CLICKED(IDC_RESOLVEALLLATER, &CConflictResolveDlg::OnBnClickedResolvealllater)
\r
55 ON_BN_CLICKED(IDHELP, &CConflictResolveDlg::OnBnClickedHelp)
\r
56 ON_BN_CLICKED(IDC_ABORT, &CConflictResolveDlg::OnBnClickedAbort)
\r
60 // CConflictResolveDlg message handlers
\r
62 BOOL CConflictResolveDlg::OnInitDialog()
\r
64 CResizableStandAloneDialog::OnInitDialog();
\r
66 // without a conflict description, this dialog is useless.
\r
67 ASSERT(m_pConflictDescription);
\r
69 CString filename = CUnicodeUtils::GetUnicode(m_pConflictDescription->path);
\r
70 filename = CPathUtils::GetFileNameFromPath(filename);
\r
73 CString sActionText;
\r
74 CString sReasonText;
\r
75 switch (m_pConflictDescription->action)
\r
77 case svn_wc_conflict_action_edit:
\r
78 if (m_pConflictDescription->property_name)
\r
79 sActionText.Format(IDS_EDITCONFLICT_PROP_ACTIONINFO_MODIFY,
\r
80 (LPCTSTR)CUnicodeUtils::GetUnicode(m_pConflictDescription->property_name),
\r
83 sActionText.Format(IDS_EDITCONFLICT_ACTIONINFO_MODIFY, (LPCTSTR)filename);
\r
85 case svn_wc_conflict_action_add:
\r
86 if (m_pConflictDescription->property_name)
\r
87 sActionText.Format(IDS_EDITCONFLICT_PROP_ACTIONINFO_ADD,
\r
88 (LPCTSTR)CUnicodeUtils::GetUnicode(m_pConflictDescription->property_name),
\r
91 sActionText.Format(IDS_EDITCONFLICT_ACTIONINFO_ADD, (LPCTSTR)filename);
\r
93 case svn_wc_conflict_action_delete:
\r
94 if (m_pConflictDescription->property_name)
\r
95 sActionText.Format(IDS_EDITCONFLICT_PROP_ACTIONINFO_DELETE,
\r
96 (LPCTSTR)CUnicodeUtils::GetUnicode(m_pConflictDescription->property_name),
\r
99 sActionText.Format(IDS_EDITCONFLICT_ACTIONINFO_DELETE, (LPCTSTR)filename);
\r
105 switch (m_pConflictDescription->reason)
\r
107 case svn_wc_conflict_reason_edited:
\r
108 sReasonText.LoadString(IDS_EDITCONFLICT_REASONINFO_EDITED);
\r
110 case svn_wc_conflict_reason_obstructed:
\r
111 sReasonText.LoadString(IDS_EDITCONFLICT_REASONINFO_OBSTRUCTED);
\r
113 case svn_wc_conflict_reason_deleted:
\r
114 sReasonText.LoadString(IDS_EDITCONFLICT_REASONINFO_DELETED);
\r
116 case svn_wc_conflict_reason_missing:
\r
117 sReasonText.LoadString(IDS_EDITCONFLICT_REASONINFO_MISSING);
\r
119 case svn_wc_conflict_reason_unversioned:
\r
120 sReasonText.LoadString(IDS_EDITCONFLICT_REASONINFO_UNVERSIONED);
\r
126 sInfoText = sActionText + _T(" ") + sReasonText;
\r
127 SetDlgItemText(IDC_INFOLABEL, sInfoText);
\r
129 // if we deal with a binary file, editing the conflict isn't possible
\r
130 // because the 'merged_file' is not used and Subversion therefore can't
\r
131 // use it as the result of the edit.
\r
132 if (m_pConflictDescription->is_binary)
\r
134 GetDlgItem(IDC_RESOLVELABEL)->EnableWindow(FALSE);
\r
135 GetDlgItem(IDC_EDITCONFLICT)->EnableWindow(FALSE);
\r
136 GetDlgItem(IDC_RESOLVED)->EnableWindow(FALSE);
\r
139 // the "resolved" button must not be enabled as long as the user hasn't used
\r
140 // the "edit" button.
\r
141 GetDlgItem(IDC_RESOLVED)->EnableWindow(FALSE);
\r
143 m_bCancelled = false;
\r
145 AddAnchor(IDC_INFOLABEL, TOP_LEFT, BOTTOM_RIGHT);
\r
146 AddAnchor(IDC_GROUP, BOTTOM_LEFT, BOTTOM_RIGHT);
\r
147 AddAnchor(IDC_CHOOSELABEL, BOTTOM_LEFT);
\r
148 AddAnchor(IDC_USELOCAL, BOTTOM_LEFT);
\r
149 AddAnchor(IDC_USEREPO, BOTTOM_RIGHT);
\r
150 AddAnchor(IDC_ORLABEL, BOTTOM_LEFT);
\r
151 AddAnchor(IDC_RESOLVELABEL, BOTTOM_LEFT);
\r
152 AddAnchor(IDC_EDITCONFLICT, BOTTOM_LEFT);
\r
153 AddAnchor(IDC_RESOLVED, BOTTOM_RIGHT);
\r
154 AddAnchor(IDC_ORLABEL2, BOTTOM_LEFT);
\r
155 AddAnchor(IDC_LEAVELABEL, BOTTOM_LEFT);
\r
156 AddAnchor(IDCANCEL, BOTTOM_LEFT);
\r
157 AddAnchor(IDC_RESOLVEALLLATER, BOTTOM_RIGHT);
\r
158 AddAnchor(IDC_ABORT, BOTTOM_RIGHT);
\r
159 AddAnchor(IDHELP, BOTTOM_RIGHT);
\r
165 void CConflictResolveDlg::OnBnClickedUselocal()
\r
167 m_choice = svn_wc_conflict_choose_mine_full;
\r
171 void CConflictResolveDlg::OnBnClickedUserepo()
\r
173 m_choice = svn_wc_conflict_choose_theirs_full;
\r
177 void CConflictResolveDlg::OnBnClickedEditconflict()
\r
179 CString filename, n1, n2, n3;
\r
180 if (m_pConflictDescription->property_name)
\r
182 filename = CUnicodeUtils::GetUnicode(m_pConflictDescription->property_name);
\r
183 n1.Format(IDS_DIFF_PROP_WCNAME, (LPCTSTR)filename);
\r
184 n2.Format(IDS_DIFF_PROP_BASENAME, (LPCTSTR)filename);
\r
185 n3.Format(IDS_DIFF_PROP_REMOTENAME, (LPCTSTR)filename);
\r
189 filename = CUnicodeUtils::GetUnicode(m_pConflictDescription->path);
\r
190 filename = CPathUtils::GetFileNameFromPath(filename);
\r
191 n1.Format(IDS_DIFF_WCNAME, (LPCTSTR)filename);
\r
192 n2.Format(IDS_DIFF_BASENAME, (LPCTSTR)filename);
\r
193 n3.Format(IDS_DIFF_REMOTENAME, (LPCTSTR)filename);
\r
196 if (m_pConflictDescription->base_file == NULL)
\r
198 CAppUtils::DiffFlags flags;
\r
199 // no base file, start TortoiseMerge in Two-way diff mode
\r
200 CAppUtils::StartExtDiff(CTSVNPath(CUnicodeUtils::GetUnicode(m_pConflictDescription->their_file)),
\r
201 CTSVNPath(CUnicodeUtils::GetUnicode(m_pConflictDescription->my_file)),
\r
206 // Subversion segfaults (1.5.1) if the path of the merged file is not a child of the
\r
207 // folder where the conflict occurs. That's why we try to use the provided file path first...
\r
208 if (m_pConflictDescription->merged_file)
\r
209 m_mergedfile = CUnicodeUtils::GetUnicode(m_pConflictDescription->merged_file);
\r
211 m_mergedfile = CTempFiles::Instance().GetTempFilePath(false, CTSVNPath(CUnicodeUtils::GetUnicode(m_pConflictDescription->path))).GetWinPath();
\r
212 CAppUtils::StartExtMerge(CTSVNPath(CUnicodeUtils::GetUnicode(m_pConflictDescription->base_file)),
\r
213 CTSVNPath(CUnicodeUtils::GetUnicode(m_pConflictDescription->their_file)),
\r
214 CTSVNPath(CUnicodeUtils::GetUnicode(m_pConflictDescription->my_file)),
\r
215 CTSVNPath(m_mergedfile),
\r
216 n2, n3, n1, CString(), false);
\r
219 GetDlgItem(IDC_RESOLVED)->EnableWindow(TRUE);
\r
222 void CConflictResolveDlg::OnBnClickedResolved()
\r
224 m_choice = svn_wc_conflict_choose_merged;
\r
225 if (m_mergedfile.IsEmpty())
\r
226 m_mergedfile = CUnicodeUtils::GetUnicode(m_pConflictDescription->my_file);
\r
230 void CConflictResolveDlg::OnBnClickedResolvealllater()
\r
232 m_choice = svn_wc_conflict_choose_postpone;
\r
236 void CConflictResolveDlg::OnCancel()
\r
238 m_choice = svn_wc_conflict_choose_postpone;
\r
240 CResizableStandAloneDialog::OnCancel();
\r
243 void CConflictResolveDlg::OnBnClickedHelp()
\r
248 void CConflictResolveDlg::OnBnClickedAbort()
\r
250 m_bCancelled = true;
\r
251 m_choice = svn_wc_conflict_choose_postpone;
\r
252 CResizableStandAloneDialog::OnCancel();
\r