OSDN Git Service

Add conflict handle
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / Commands / ConflictEditorCommand.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2008-2009 - 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 #pragma once\r
20 #include "stdafx.h"\r
21 #include "ConflictEditorCommand.h"\r
22 #include "GitStatus.h"\r
23 #include "GitDiff.h"\r
24 //#include "SVNInfo.h"\r
25 #include "UnicodeUtils.h"\r
26 #include "PathUtils.h"\r
27 #include "AppUtils.h"\r
28 //#include "EditPropConflictDlg.h"\r
29 //#include "TreeConflictEditorDlg.h"\r
30 \r
31 bool ConflictEditorCommand::Execute()\r
32 {\r
33         bool bRet = false;\r
34 \r
35         CTGitPath merge = cmdLinePath;\r
36         CTGitPath directory = merge.GetDirectory();\r
37         \r
38         bool bAlternativeTool = !!parser.HasKey(_T("alternative"));\r
39 \r
40         // we have the conflicted file (%merged)\r
41         // now look for the other required files\r
42         //GitStatus stat;\r
43         //stat.GetStatus(merge);\r
44         //if (stat.status == NULL)\r
45         //      return false;\r
46 \r
47         BYTE_VECTOR vector;\r
48 \r
49         CString cmd;\r
50         cmd.Format(_T("git.exe ls-files -u -t -z -- \"%s\""),merge.GetGitPathString());\r
51 \r
52         if(g_Git.Run(cmd,&vector))\r
53         {\r
54                 return FALSE;\r
55         }\r
56 \r
57         CTGitPathList list;\r
58         list.ParserFromLsFile(vector);\r
59 \r
60         if(list.GetCount() == 0)\r
61                 return FALSE;\r
62 \r
63         TCHAR szTempName[512];  \r
64         GetTempFileName(_T(""),_T(""),0,szTempName);\r
65         CString temp(szTempName);\r
66         temp=temp.Mid(1,temp.GetLength()-5);\r
67 \r
68         CTGitPath theirs;\r
69         CTGitPath mine;\r
70         CTGitPath base;\r
71 \r
72         CString format;\r
73         format=g_Git.m_CurrentDir+_T("\\")+directory.GetWinPathString()+merge.GetFilename()+CString(_T(".%s."))+temp+merge.GetFileExtension();\r
74 \r
75         CString file;\r
76         file.Format(format,_T("LOCAL"));\r
77         mine.SetFromGit(file);\r
78         file.Format(format,_T("REMOTE"));\r
79         theirs.SetFromGit(file);\r
80         file.Format(format,_T("BASE"));\r
81         base.SetFromGit(file);\r
82 \r
83         \r
84         format=_T("git.exe cat-file blob \":%d:%s\"");\r
85         for(int i=0;i<list.GetCount();i++)\r
86         {\r
87                 CString cmd;\r
88                 CString outfile;\r
89                 cmd.Format(format,list[i].m_Stage,list[i].GetGitPathString());\r
90 \r
91                 if( list[i].m_Stage == 1)\r
92                 {\r
93                         outfile=base.GetWinPathString();\r
94                 }\r
95                 if( list[i].m_Stage == 2 )\r
96                 {\r
97                         outfile=mine.GetWinPathString();\r
98                 }\r
99                 if( list[i].m_Stage == 3 )\r
100                 {\r
101                         outfile=theirs.GetWinPathString();\r
102                 }\r
103                 g_Git.RunLogFile(cmd,outfile);\r
104         }\r
105 \r
106         merge.SetFromWin(g_Git.m_CurrentDir+_T("\\")+merge.GetWinPathString());\r
107         bRet = !!CAppUtils::StartExtMerge(base, theirs, mine, merge,_T("BASE"),_T("REMOTE"),_T("LOCAL"));\r
108 \r
109 #if 0\r
110 \r
111         CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), \r
112                         base, theirs, mine, merge);\r
113 #endif\r
114 #if 0\r
115         if (stat.status->text_status == svn_wc_status_conflicted)\r
116         {\r
117                 // we have a text conflict, use our merge tool to resolve the conflict\r
118 \r
119                 CTSVNPath theirs(directory);\r
120                 CTSVNPath mine(directory);\r
121                 CTSVNPath base(directory);\r
122                 bool bConflictData = false;\r
123 \r
124                 if ((stat.status->entry)&&(stat.status->entry->conflict_new))\r
125                 {\r
126                         theirs.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_new));\r
127                         bConflictData = true;\r
128                 }\r
129                 if ((stat.status->entry)&&(stat.status->entry->conflict_old))\r
130                 {\r
131                         base.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_old));\r
132                         bConflictData = true;\r
133                 }\r
134                 if ((stat.status->entry)&&(stat.status->entry->conflict_wrk))\r
135                 {\r
136                         mine.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->conflict_wrk));\r
137                         bConflictData = true;\r
138                 }\r
139                 else\r
140                 {\r
141                         mine = merge;\r
142                 }\r
143                 if (bConflictData)\r
144                         bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool), \r
145                                                                                                 base, theirs, mine, merge);\r
146         }\r
147 \r
148         if (stat.status->prop_status == svn_wc_status_conflicted)\r
149         {\r
150                 // we have a property conflict\r
151                 CTSVNPath prej(directory);\r
152                 if ((stat.status->entry)&&(stat.status->entry->prejfile))\r
153                 {\r
154                         prej.AppendPathString(CUnicodeUtils::GetUnicode(stat.status->entry->prejfile));\r
155                         // there's a problem: the prej file contains a _description_ of the conflict, and\r
156                         // that description string might be translated. That means we have no way of parsing\r
157                         // the file to find out the conflicting values.\r
158                         // The only thing we can do: show a dialog with the conflict description, then\r
159                         // let the user either accept the existing property or open the property edit dialog\r
160                         // to manually change the properties and values. And a button to mark the conflict as\r
161                         // resolved.\r
162                         CEditPropConflictDlg dlg;\r
163                         dlg.SetPrejFile(prej);\r
164                         dlg.SetConflictedItem(merge);\r
165                         bRet = (dlg.DoModal() != IDCANCEL);\r
166                 }\r
167         }\r
168 \r
169         if (stat.status->tree_conflict)\r
170         {\r
171                 // we have a tree conflict\r
172                 SVNInfo info;\r
173                 const SVNInfoData * pInfoData = info.GetFirstFileInfo(merge, SVNRev(), SVNRev());\r
174                 if (pInfoData)\r
175                 {\r
176                         if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_text)\r
177                         {\r
178                                 CTSVNPath theirs(directory);\r
179                                 CTSVNPath mine(directory);\r
180                                 CTSVNPath base(directory);\r
181                                 bool bConflictData = false;\r
182 \r
183                                 if (pInfoData->treeconflict_theirfile)\r
184                                 {\r
185                                         theirs.AppendPathString(pInfoData->treeconflict_theirfile);\r
186                                         bConflictData = true;\r
187                                 }\r
188                                 if (pInfoData->treeconflict_basefile)\r
189                                 {\r
190                                         base.AppendPathString(pInfoData->treeconflict_basefile);\r
191                                         bConflictData = true;\r
192                                 }\r
193                                 if (pInfoData->treeconflict_myfile)\r
194                                 {\r
195                                         mine.AppendPathString(pInfoData->treeconflict_myfile);\r
196                                         bConflictData = true;\r
197                                 }\r
198                                 else\r
199                                 {\r
200                                         mine = merge;\r
201                                 }\r
202                                 if (bConflictData)\r
203                                         bRet = !!CAppUtils::StartExtMerge(CAppUtils::MergeFlags().AlternativeTool(bAlternativeTool),\r
204                                                                                                                 base, theirs, mine, merge);\r
205                         }\r
206                         else if (pInfoData->treeconflict_kind == svn_wc_conflict_kind_tree)\r
207                         {\r
208                                 CString sConflictAction;\r
209                                 CString sConflictReason;\r
210                                 CString sResolveTheirs;\r
211                                 CString sResolveMine;\r
212                                 CTSVNPath treeConflictPath = CTSVNPath(pInfoData->treeconflict_path);\r
213                                 CString sItemName = treeConflictPath.GetUIFileOrDirectoryName();\r
214                                 \r
215                                 if (pInfoData->treeconflict_nodekind == svn_node_file)\r
216                                 {\r
217                                         switch (pInfoData->treeconflict_operation)\r
218                                         {\r
219                                         case svn_wc_operation_update:\r
220                                                 switch (pInfoData->treeconflict_action)\r
221                                                 {\r
222                                                 case svn_wc_conflict_action_edit:\r
223                                                         sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEEDIT, (LPCTSTR)sItemName);\r
224                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
225                                                         break;\r
226                                                 case svn_wc_conflict_action_add:\r
227                                                         sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEADD, (LPCTSTR)sItemName);\r
228                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
229                                                         break;\r
230                                                 case svn_wc_conflict_action_delete:\r
231                                                         sConflictAction.Format(IDS_TREECONFLICT_FILEUPDATEDELETE, (LPCTSTR)sItemName);\r
232                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
233                                                         break;\r
234                                                 }\r
235                                                 break;\r
236                                         case svn_wc_operation_switch:\r
237                                                 switch (pInfoData->treeconflict_action)\r
238                                                 {\r
239                                                 case svn_wc_conflict_action_edit:\r
240                                                         sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHEDIT, (LPCTSTR)sItemName);\r
241                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
242                                                         break;\r
243                                                 case svn_wc_conflict_action_add:\r
244                                                         sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHADD, (LPCTSTR)sItemName);\r
245                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
246                                                         break;\r
247                                                 case svn_wc_conflict_action_delete:\r
248                                                         sConflictAction.Format(IDS_TREECONFLICT_FILESWITCHDELETE, (LPCTSTR)sItemName);\r
249                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
250                                                         break;\r
251                                                 }\r
252                                                 break;\r
253                                         case svn_wc_operation_merge:\r
254                                                 switch (pInfoData->treeconflict_action)\r
255                                                 {\r
256                                                 case svn_wc_conflict_action_edit:\r
257                                                         sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEEDIT, (LPCTSTR)sItemName);\r
258                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
259                                                         break;\r
260                                                 case svn_wc_conflict_action_add:\r
261                                                         sResolveTheirs.Format(IDS_TREECONFLICT_FILEMERGEADD, (LPCTSTR)sItemName);\r
262                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYFILE);\r
263                                                         break;\r
264                                                 case svn_wc_conflict_action_delete:\r
265                                                         sConflictAction.Format(IDS_TREECONFLICT_FILEMERGEDELETE, (LPCTSTR)sItemName);\r
266                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
267                                                         break;\r
268                                                 }\r
269                                                 break;\r
270                                         }\r
271                                 }\r
272                                 else if (pInfoData->treeconflict_nodekind == svn_node_dir)\r
273                                 {\r
274                                         switch (pInfoData->treeconflict_operation)\r
275                                         {\r
276                                         case svn_wc_operation_update:\r
277                                                 switch (pInfoData->treeconflict_action)\r
278                                                 {\r
279                                                 case svn_wc_conflict_action_edit:\r
280                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEEDIT, (LPCTSTR)sItemName);\r
281                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
282                                                         break;\r
283                                                 case svn_wc_conflict_action_add:\r
284                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEADD, (LPCTSTR)sItemName);\r
285                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
286                                                         break;\r
287                                                 case svn_wc_conflict_action_delete:\r
288                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRUPDATEDELETE, (LPCTSTR)sItemName);\r
289                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);\r
290                                                         break;\r
291                                                 }\r
292                                                 break;\r
293                                         case svn_wc_operation_switch:\r
294                                                 switch (pInfoData->treeconflict_action)\r
295                                                 {\r
296                                                 case svn_wc_conflict_action_edit:\r
297                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHEDIT, (LPCTSTR)sItemName);\r
298                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
299                                                         break;\r
300                                                 case svn_wc_conflict_action_add:\r
301                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHADD, (LPCTSTR)sItemName);\r
302                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
303                                                         break;\r
304                                                 case svn_wc_conflict_action_delete:\r
305                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRSWITCHDELETE, (LPCTSTR)sItemName);\r
306                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);\r
307                                                         break;\r
308                                                 }\r
309                                                 break;\r
310                                         case svn_wc_operation_merge:\r
311                                                 switch (pInfoData->treeconflict_action)\r
312                                                 {\r
313                                                 case svn_wc_conflict_action_edit:\r
314                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEEDIT, (LPCTSTR)sItemName);\r
315                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
316                                                         break;\r
317                                                 case svn_wc_conflict_action_add:\r
318                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEADD, (LPCTSTR)sItemName);\r
319                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_KEEPREPOSITORYDIR);\r
320                                                         break;\r
321                                                 case svn_wc_conflict_action_delete:\r
322                                                         sConflictAction.Format(IDS_TREECONFLICT_DIRMERGEDELETE, (LPCTSTR)sItemName);\r
323                                                         sResolveTheirs.LoadString(IDS_TREECONFLICT_RESOLVE_REMOVEDIR);\r
324                                                         break;\r
325                                                 }\r
326                                                 break;\r
327                                         }\r
328                                 }\r
329 \r
330                                 UINT uReasonID = 0;\r
331                                 switch (pInfoData->treeconflict_reason)\r
332                                 { \r
333                                 case svn_wc_conflict_reason_edited:\r
334                                         uReasonID = IDS_TREECONFLICT_REASON_EDITED;\r
335                                         sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
336                                         break;\r
337                                 case svn_wc_conflict_reason_obstructed:\r
338                                         uReasonID = IDS_TREECONFLICT_REASON_OBSTRUCTED;\r
339                                         sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
340                                         break;\r
341                                 case svn_wc_conflict_reason_deleted:\r
342                                         uReasonID = IDS_TREECONFLICT_REASON_DELETED;\r
343                                         sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_REMOVEDIR : IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
344                                         break;\r
345                                 case svn_wc_conflict_reason_added:\r
346                                         uReasonID = IDS_TREECONFLICT_REASON_ADDED;\r
347                                         sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
348                                         break;\r
349                                 case svn_wc_conflict_reason_missing:\r
350                                         uReasonID = IDS_TREECONFLICT_REASON_MISSING;\r
351                                         sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_REMOVEDIR : IDS_TREECONFLICT_RESOLVE_REMOVEFILE);\r
352                                         break;\r
353                                 case svn_wc_conflict_reason_unversioned:\r
354                                         uReasonID = IDS_TREECONFLICT_REASON_UNVERSIONED;\r
355                                         sResolveMine.LoadString(pInfoData->treeconflict_nodekind == svn_node_dir ? IDS_TREECONFLICT_RESOLVE_KEEPLOCALDIR : IDS_TREECONFLICT_RESOLVE_KEEPLOCALFILE);\r
356                                         break;\r
357                                 }\r
358                                 sConflictReason.Format(uReasonID, (LPCTSTR)sConflictAction);\r
359 \r
360                                 CTreeConflictEditorDlg dlg;\r
361                                 dlg.SetConflictInfoText(sConflictReason);\r
362                                 dlg.SetResolveTexts(sResolveTheirs, sResolveMine);\r
363                                 dlg.SetPath(treeConflictPath);\r
364                                 INT_PTR dlgRet = dlg.DoModal();\r
365                                 bRet = (dlgRet != IDCANCEL);\r
366                         }\r
367                 }\r
368         }\r
369 #endif\r
370         return bRet;\r
371 }\r