OSDN Git Service

20596cc8e07e2dc764bd171309e695fba03d5f1d
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / GitLogListAction.cpp
1 // GitLogList.cpp : implementation file\r
2 //\r
3 /*\r
4         Description: qgit revision list view\r
5 \r
6         Author: Marco Costalba (C) 2005-2007\r
7 \r
8         Copyright: See COPYING file that comes with this distribution\r
9 \r
10 */\r
11 #include "stdafx.h"\r
12 #include "TortoiseProc.h"\r
13 #include "GitLogList.h"\r
14 #include "GitRev.h"\r
15 //#include "VssStyle.h"\r
16 #include "IconMenu.h"\r
17 // CGitLogList\r
18 #include "cursor.h"\r
19 #include "InputDlg.h"\r
20 #include "PropDlg.h"\r
21 #include "SVNProgressDlg.h"\r
22 #include "ProgressDlg.h"\r
23 #include "SysProgressDlg.h"\r
24 //#include "RepositoryBrowser.h"\r
25 //#include "CopyDlg.h"\r
26 //#include "StatGraphDlg.h"\r
27 #include "Logdlg.h"\r
28 #include "MessageBox.h"\r
29 #include "Registry.h"\r
30 #include "AppUtils.h"\r
31 #include "PathUtils.h"\r
32 #include "StringUtils.h"\r
33 #include "UnicodeUtils.h"\r
34 #include "TempFile.h"\r
35 //#include "GitInfo.h"\r
36 //#include "GitDiff.h"\r
37 #include "IconMenu.h"\r
38 //#include "RevisionRangeDlg.h"\r
39 //#include "BrowseFolder.h"\r
40 //#include "BlameDlg.h"\r
41 //#include "Blame.h"\r
42 //#include "GitHelpers.h"\r
43 #include "GitStatus.h"\r
44 //#include "LogDlgHelper.h"\r
45 //#include "CachedLogInfo.h"\r
46 //#include "RepositoryInfo.h"\r
47 //#include "EditPropertiesDlg.h"\r
48 #include "FileDiffDlg.h"\r
49 #include "CommitDlg.h"\r
50 #include "RebaseDlg.h"\r
51 \r
52 IMPLEMENT_DYNAMIC(CGitLogList, CHintListCtrl)\r
53 \r
54 int CGitLogList::CherryPickFrom(CString from, CString to)\r
55 {\r
56         CLogDataVector logs;\r
57         if(logs.ParserFromLog(NULL,-1,0,&from,&to))\r
58                 return -1;\r
59 \r
60         if(logs.size() == 0)\r
61                 return 0;\r
62 \r
63         CSysProgressDlg progress;\r
64         if (progress.IsValid())\r
65         {\r
66                 progress.SetTitle(_T("Cherry Pick"));\r
67                 progress.SetAnimation(IDR_MOVEANI);\r
68                 progress.SetTime(true);\r
69                 progress.ShowModeless(this);\r
70         }\r
71 \r
72         for(int i=logs.size()-1;i>=0;i--)\r
73         {\r
74                 if (progress.IsValid())\r
75                 {\r
76                         progress.FormatPathLine(1, _T("Pick up %s"), logs[i].m_CommitHash);\r
77                         progress.FormatPathLine(2, _T("%s"), logs[i].m_Subject);\r
78                         progress.SetProgress(logs.size()-i, logs.size());\r
79                 }\r
80                 if ((progress.IsValid())&&(progress.HasUserCancelled()))\r
81                 {\r
82                         //CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);\r
83                         throw std::exception(CUnicodeUtils::GetUTF8(_T("User canceled\r\n\r\n")));\r
84                         return -1;\r
85                 }\r
86                 CString cmd,out;\r
87                 cmd.Format(_T("git.exe cherry-pick %s"),logs[i].m_CommitHash);\r
88                 out.Empty();\r
89                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
90                 {\r
91                         throw std::exception(CUnicodeUtils::GetUTF8(CString(_T("Cherry Pick Failure\r\n\r\n"))+out));\r
92                         return -1;\r
93                 }\r
94         }\r
95         \r
96         return 0;\r
97 }\r
98 \r
99 void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)\r
100 {       \r
101         POSITION pos = GetFirstSelectedItemPosition();\r
102         int indexNext = GetNextSelectedItem(pos);\r
103         if (indexNext < 0)\r
104                 return;\r
105 \r
106         GitRev* pSelLogEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(indexNext));\r
107 \r
108         theApp.DoWaitCursor(1);\r
109         bool bOpenWith = false;\r
110         switch (cmd&0xFFFF)\r
111                 {\r
112                         case ID_GNUDIFF1:\r
113                         {\r
114                                 CString tempfile=GetTempFile();\r
115                                 CString cmd;\r
116                                 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
117                                 cmd.Format(_T("git.exe diff-tree -r -p --stat %s"),r1->m_CommitHash);\r
118                                 g_Git.RunLogFile(cmd,tempfile);\r
119                                 CAppUtils::StartUnifiedDiffViewer(tempfile,r1->m_CommitHash.Left(6)+_T(":")+r1->m_Subject);\r
120                         }\r
121                         break;\r
122 \r
123                         case ID_GNUDIFF2:\r
124                         {\r
125                                 CString tempfile=GetTempFile();\r
126                                 CString cmd;\r
127                                 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
128                                 GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
129                                 cmd.Format(_T("git.exe diff-tree -r -p --stat %s %s"),r1->m_CommitHash,r2->m_CommitHash);\r
130                                 g_Git.RunLogFile(cmd,tempfile);\r
131                                 CAppUtils::StartUnifiedDiffViewer(tempfile,r1->m_CommitHash.Left(6)+_T(":")+r2->m_CommitHash.Left(6));\r
132 \r
133                         }\r
134                         break;\r
135 \r
136                 case ID_COMPARETWO:\r
137                         {\r
138                                 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
139                                 GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
140                                 CFileDiffDlg dlg;\r
141                                 dlg.SetDiff(NULL,*r1,*r2);\r
142                                 dlg.DoModal();\r
143                                 \r
144                         }\r
145                         break;\r
146                 \r
147 \r
148                 case ID_COMPARE:\r
149                         {\r
150                                 GitRev * r1 = &m_wcRev;\r
151                                 GitRev * r2 = pSelLogEntry;\r
152                                 CFileDiffDlg dlg;\r
153                                 dlg.SetDiff(NULL,*r1,*r2);\r
154                                 dlg.DoModal();\r
155 \r
156                                 //user clicked on the menu item "compare with working copy"\r
157                                 //if (PromptShown())\r
158                                 //{\r
159                                 //      GitDiff diff(this, m_hWnd, true);\r
160                                 //      diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));\r
161                                 //      diff.SetHEADPeg(m_LogRevision);\r
162                                 //      diff.ShowCompare(m_path, GitRev::REV_WC, m_path, revSelected);\r
163                                 //}\r
164                                 //else\r
165                                 //      CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_WC, m_path, revSelected, GitRev(), m_LogRevision, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));\r
166                         }\r
167                         break;\r
168 \r
169                 case ID_COMPAREWITHPREVIOUS:\r
170                         {\r
171 \r
172                                 CFileDiffDlg dlg;\r
173                                 \r
174                                 if(pSelLogEntry->m_ParentHash.size()>0)\r
175                                 //if(m_logEntries.m_HashMap[pSelLogEntry->m_ParentHash[0]]>=0)\r
176                                 {\r
177                                         dlg.SetDiff(NULL,pSelLogEntry->m_CommitHash,pSelLogEntry->m_ParentHash[0]);\r
178                                         dlg.DoModal();\r
179                                 }else\r
180                                 {\r
181                                         CMessageBox::Show(NULL,_T("No previous version"),_T("TortoiseGit"),MB_OK);      \r
182                                 }\r
183                                 //if (PromptShown())\r
184                                 //{\r
185                                 //      GitDiff diff(this, m_hWnd, true);\r
186                                 //      diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));\r
187                                 //      diff.SetHEADPeg(m_LogRevision);\r
188                                 //      diff.ShowCompare(CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected);\r
189                                 //}\r
190                                 //else\r
191                                 //      CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));\r
192                         }\r
193                         break;\r
194                 case ID_COPYCLIPBOARD:\r
195                         {\r
196                                 CopySelectionToClipBoard();\r
197                         }\r
198                         break;\r
199                 case ID_COPYHASH:\r
200                         {\r
201                                 CopySelectionToClipBoard(TRUE);\r
202                         }\r
203                         break;\r
204                 case ID_EXPORT:\r
205                         CAppUtils::Export(&pSelLogEntry->m_CommitHash);\r
206                         break;\r
207                 case ID_CREATE_BRANCH:\r
208                         CAppUtils::CreateBranchTag(FALSE,&pSelLogEntry->m_CommitHash);\r
209                         ReloadHashMap();\r
210                         Invalidate();                   \r
211                         break;\r
212                 case ID_CREATE_TAG:\r
213                         CAppUtils::CreateBranchTag(TRUE,&pSelLogEntry->m_CommitHash);\r
214                         ReloadHashMap();\r
215                         Invalidate();\r
216                         break;\r
217                 case ID_SWITCHTOREV:\r
218                         CAppUtils::Switch(&pSelLogEntry->m_CommitHash);\r
219                         ReloadHashMap();\r
220                         Invalidate();\r
221                         break;\r
222                 case ID_RESET:\r
223                         CAppUtils::GitReset(&pSelLogEntry->m_CommitHash);\r
224                         ReloadHashMap();\r
225                         Invalidate();\r
226                         break;\r
227                 case ID_REBASE_PICK:\r
228                         SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_PICK);\r
229                         break;\r
230                 case ID_REBASE_EDIT:\r
231                         SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_EDIT);\r
232                         break;\r
233                 case ID_REBASE_SQUASH:\r
234                         SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_SQUASH);\r
235                         break;\r
236                 case ID_REBASE_SKIP:\r
237                         SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_SKIP);\r
238                         break;\r
239                 case ID_COMBINE_COMMIT:\r
240                 {\r
241                         CString head;\r
242                         CString headhash;\r
243                         CString hashFirst,hashLast;\r
244 \r
245                         int headindex=GetHeadIndex();\r
246                         if(headindex>=0) //incase show all branch, head is not the first commits. \r
247                         {\r
248                                 head.Format(_T("HEAD~%d"),FirstSelect-headindex);\r
249                                 hashFirst=g_Git.GetHash(head);\r
250 \r
251                                 head.Format(_T("HEAD~%d"),LastSelect-headindex);\r
252                                 hashLast=g_Git.GetHash(head);\r
253                         }\r
254                                                 \r
255                         GitRev* pFirstEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
256                         GitRev* pLastEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
257                         if(pFirstEntry->m_CommitHash != hashFirst || pLastEntry->m_CommitHash != hashLast)\r
258                         {\r
259                                 CMessageBox::Show(NULL,_T(\r
260                                         "Cannot combine commits now.\r\n\\r
261                                         Make sure you are viewing the log of your current branch and \\r
262                                         no filters are applied."),_T("TortoiseGit"),MB_OK);\r
263                                 break;\r
264                         }\r
265                         \r
266                         headhash=g_Git.GetHash(CString(_T("HEAD")));\r
267                         \r
268                         if(!g_Git.CheckCleanWorkTree())\r
269                         {\r
270                                 CMessageBox::Show(NULL,_T("Combine needs a clean work tree"),_T("TortoiseGit"),MB_OK);\r
271                                 break;\r
272                         }\r
273                         CString cmd,out;\r
274 \r
275                         //Use throw to abort this process (reset back to original HEAD)\r
276                         try\r
277                         {\r
278                                 cmd.Format(_T("git.exe reset --hard  %s"),pFirstEntry->m_CommitHash);\r
279                                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
280                                 {\r
281                                         CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
282                                         throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to first commit (first step) aborting...\r\n\r\n")+out));\r
283                                 }\r
284                                 cmd.Format(_T("git.exe reset --mixed  %s"),hashLast);\r
285                                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
286                                 {\r
287                                         CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
288                                         throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to last commit (second step) aborting...\r\n\r\n")+out));\r
289                                 }\r
290                                 CCommitDlg dlg;\r
291                                 for(int i=FirstSelect;i<=LastSelect;i++)\r
292                                 {\r
293                                         GitRev* pRev = reinterpret_cast<GitRev*>(m_arShownList.GetAt(i));\r
294                                         dlg.m_sLogMessage+=pRev->m_Subject+_T("\n")+pRev->m_Body;\r
295                                         dlg.m_sLogMessage+=_T("\n");\r
296                                 }\r
297                                 dlg.m_bWholeProject=true;\r
298                                 dlg.m_bSelectFilesForCommit = true;\r
299                                 dlg.m_bCommitAmend=true;\r
300                                 dlg.m_AmendStr=dlg.m_sLogMessage;\r
301 \r
302                                 bool abort=false;\r
303                                 if (dlg.DoModal() == IDOK)\r
304                                 {\r
305                                         if(pFirstEntry->m_CommitHash!=headhash)\r
306                                         {\r
307                                                 //Commitrange firstEntry..headhash (from top of combine to original head) needs to be 'cherry-picked'\r
308                                                 //on top of new commit.\r
309                                                 //Use the rebase --onto command for it.\r
310                                                 //\r
311                                                 //All this can be done in one step using the following command:\r
312                                                 //cmd.Format(_T("git.exe format-patch --stdout --binary --full-index -k %s..%s | git am -k -3"),\r
313                                                 //      pFirstEntry->m_CommitHash,\r
314                                                 //      headhash);\r
315                                                 //But I am not sure if a '|' is going to work in a CreateProcess() call.\r
316                                                 //\r
317                                                 //Later the progress dialog could be used to execute these steps.\r
318 \r
319                                                 if(CherryPickFrom(pFirstEntry->m_CommitHash,headhash))\r
320                                                 {\r
321                                                         CString msg;\r
322                                                         msg.Format(_T("Error while cherry pick commits on top of combined commits. Aborting.\r\n\r\n"));\r
323                                                         throw std::exception(CUnicodeUtils::GetUTF8(msg));\r
324                                                 }\r
325 #if 0\r
326                                                 CString currentBranch=g_Git.GetCurrentBranch();\r
327                                                 cmd.Format(_T("git.exe rebase --onto \"%s\" %s %s"),\r
328                                                         currentBranch,\r
329                                                         pFirstEntry->m_CommitHash,\r
330                                                         headhash);\r
331                                                 if(g_Git.Run(cmd,&out,CP_UTF8)!=0)\r
332                                                 {\r
333                                                         CString msg;\r
334                                                         msg.Format(_T("Error while rebasing commits on top of combined commits. Aborting.\r\n\r\n%s"),out);\r
335 //                                                      CMessageBox::Show(NULL,msg,_T("TortoiseGit"),MB_OK);\r
336                                                         g_Git.Run(_T("git.exe rebase --abort"),&out,CP_UTF8);\r
337                                                         throw std::exception(CUnicodeUtils::GetUTF8(msg));\r
338                                                 }\r
339 \r
340                                                 //HEAD is now on <no branch>. \r
341                                                 //The following steps are to get HEAD back on the original branch and reset the branch to the new HEAD\r
342                                                 //To avoid 2 working copy changes, we could use git branch -f <original branch> <hash new head> \r
343                                                 //And then git checkout <original branch>\r
344                                                 //But I don't know if 'git branch -f' removes tracking options. So for now, do a checkout and a reset.\r
345                                                 \r
346                                                 //Store new HEAD\r
347                                                 CString newHead=g_Git.GetHash(CString(_T("HEAD")));\r
348 \r
349                                                 //Checkout working branch\r
350                                                 cmd.Format(_T("git.exe checkout -f \"%s\""),currentBranch);\r
351                                                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
352                                                         throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not checkout original branch. Aborting...\r\n\r\n")+out));\r
353 \r
354                                                 //Reset to new HEAD\r
355                                                 cmd.Format(_T("git.exe reset --hard  %s"),newHead);\r
356                                                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
357                                                         throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to new head. Aborting...\r\n\r\n")+out));\r
358 #endif\r
359                                         }\r
360                                 }\r
361                                 else\r
362                                         throw std::exception("User aborted the combine process");\r
363                         }\r
364                         catch(std::exception& e)\r
365                         {\r
366                                 CMessageBox::Show(NULL,CUnicodeUtils::GetUnicode(CStringA(e.what())),_T("TortoiseGit: Combine error"),MB_OK|MB_ICONERROR);\r
367                                 cmd.Format(_T("git.exe reset --hard  %s"),headhash);\r
368                                 out.Empty();\r
369                                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
370                                 {\r
371                                         CMessageBox::Show(NULL,_T("Could not reset to original HEAD\r\n\r\n")+out,_T("TortoiseGit"),MB_OK);\r
372                                 }\r
373                         }\r
374                         Refresh();\r
375                 }\r
376                         break;\r
377 \r
378                 case ID_CHERRY_PICK:\r
379                         if(!g_Git.CheckCleanWorkTree())\r
380                         {\r
381                                 CMessageBox::Show(NULL,_T("Cherry Pick requires a clean working tree"),_T("TortoiseGit"),MB_OK);\r
382                         \r
383                         }else\r
384                         {\r
385                                 CRebaseDlg dlg;\r
386                                 dlg.m_IsCherryPick = TRUE;\r
387                                 dlg.m_Upstream = this->m_CurrentBranch;\r
388                                 POSITION pos = GetFirstSelectedItemPosition();\r
389                                 while(pos)\r
390                                 {\r
391                                         int indexNext = GetNextSelectedItem(pos);\r
392                                         dlg.m_CommitList.m_logEntries.push_back(*(GitRev*)m_arShownList[indexNext]);\r
393                                         dlg.m_CommitList.m_logEntries.at(dlg.m_CommitList.m_logEntries.size()-1).m_Action |= CTGitPath::LOGACTIONS_REBASE_PICK;\r
394                                 }\r
395         \r
396                                 if(dlg.DoModal() == IDOK)\r
397                                 {\r
398                                         Refresh();\r
399                                 }\r
400                         }\r
401                         break;\r
402                 case ID_REBASE_TO_VERSION:\r
403                         if(!g_Git.CheckCleanWorkTree())\r
404                         {\r
405                                 CMessageBox::Show(NULL,_T("Rebase requires a clean working tree"),_T("TortoiseGit"),MB_OK);\r
406                         \r
407                         }else\r
408                         {\r
409                                 CRebaseDlg dlg;\r
410                                 dlg.m_Upstream = pSelLogEntry->m_CommitHash;\r
411 \r
412                                 if(dlg.DoModal() == IDOK)\r
413                                 {\r
414                                         Refresh();\r
415                                 }\r
416                         }\r
417 \r
418                         break;\r
419 \r
420                 case ID_STASH_APPLY:\r
421                         CAppUtils::StashApply(pSelLogEntry->m_Ref);\r
422                         break;\r
423                 \r
424                 case ID_REFLOG_DEL:\r
425                         {       \r
426                                 CString str;\r
427                                 str.Format(_T("Warning: %s will be permanently deleted. It can <ct=0x0000FF><b>NOT</b></ct> be recovered!\r\n \r\n Are you sure you want to continue?"),pSelLogEntry->m_Ref);\r
428                                 if(CMessageBox::Show(NULL,str,_T("TortoiseGit"),MB_YESNO|MB_ICONWARNING) == IDYES)\r
429                                 {\r
430                                         CString cmd,out;\r
431                                         cmd.Format(_T("git.exe reflog delete %s"),pSelLogEntry->m_Ref);\r
432                                         if(g_Git.Run(cmd,&out,CP_ACP))\r
433                                         {\r
434                                                 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
435                                         }                                               \r
436                                         ::PostMessage(this->GetParent()->m_hWnd,MSG_REFLOG_CHANGED,0,0);\r
437                                 }\r
438                         }\r
439                         break;\r
440                 case ID_CREATE_PATCH:\r
441                         {\r
442                                 int select=this->GetSelectedCount();\r
443                                 CString cmd;\r
444                                 cmd = CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe");\r
445                                 cmd += _T(" /command:formatpatch");\r
446 \r
447                                 cmd += _T(" /path:")+g_Git.m_CurrentDir+_T(" ");\r
448 \r
449                                 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
450                                 GitRev * r2 = NULL;\r
451                                 if(select == 1)\r
452                                 {\r
453                                         cmd += _T(" /startrev:")+r1->m_CommitHash;\r
454                                 }\r
455                                 else \r
456                                 {\r
457                                         r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
458                                         if( this->m_IsOldFirst )\r
459                                         {       \r
460                                                 cmd += _T(" /startrev:")+r1->m_CommitHash;\r
461                                                 cmd += _T(" /endrev:")+r2->m_CommitHash;\r
462         \r
463                                         }else\r
464                                         {       \r
465                                                 cmd += _T(" /startrev:")+r2->m_CommitHash;\r
466                                                 cmd += _T(" /endrev:")+r1->m_CommitHash;        \r
467                                         }                               \r
468                                         \r
469                                 }\r
470 \r
471                                 CAppUtils::LaunchApplication(cmd,IDS_ERR_PROC,false);\r
472                         }\r
473                         break;\r
474                 case ID_DELETE:\r
475                         {\r
476                                 int index = cmd>>16;\r
477                                 if( this->m_HashMap.find(pSelLogEntry->m_CommitHash) == m_HashMap.end() )\r
478                                 {\r
479                                         CMessageBox::Show(NULL,IDS_ERROR_NOREF,IDS_APPNAME,MB_OK|MB_ICONERROR);\r
480                                         return;\r
481                                 }\r
482                                 if( index >= m_HashMap[pSelLogEntry->m_CommitHash].size())\r
483                                 {\r
484                                         CMessageBox::Show(NULL,IDS_ERROR_INDEX,IDS_APPNAME,MB_OK|MB_ICONERROR);\r
485                                         return;                         \r
486                                 }\r
487                                 CString ref,msg;\r
488                                 ref=m_HashMap[pSelLogEntry->m_CommitHash][index];\r
489                                 \r
490                                 msg=CString(_T("<ct=0x0000FF>Delete</ct> <b>"))+ref;\r
491                                 msg+=_T("</b>\n\n Are you sure?");\r
492                                 if( CMessageBox::Show(NULL,msg,_T("TortoiseGit"),MB_YESNO) == IDYES )\r
493                                 {\r
494                                         CString shortname;\r
495                                         CString cmd;\r
496                                         if(this->GetShortName(ref,shortname,_T("refs/heads/")))\r
497                                         {\r
498                                                 cmd.Format(_T("git.exe branch -D %s"),shortname);\r
499                                         }\r
500 \r
501                                         if(this->GetShortName(ref,shortname,_T("refs/remotes/")))\r
502                                         {\r
503                                                 cmd.Format(_T("git.exe branch -r -D %s"),shortname);\r
504                                         }\r
505 \r
506                                         if(this->GetShortName(ref,shortname,_T("refs/tags/")))\r
507                                         {\r
508                                                 cmd.Format(_T("git.exe tag -d %s"),shortname);\r
509                                         }\r
510 \r
511                                         CString out;\r
512                                         if(g_Git.Run(cmd,&out,CP_UTF8))\r
513                                         {\r
514                                                 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
515                                         }\r
516                                         this->ReloadHashMap();\r
517                                         CRect rect;\r
518                                         this->GetItemRect(FirstSelect,&rect,LVIR_BOUNDS);\r
519                                         this->InvalidateRect(rect);\r
520                                 }\r
521                         }\r
522                         break;\r
523                 default:\r
524                         //CMessageBox::Show(NULL,_T("Have not implemented"),_T("TortoiseGit"),MB_OK);\r
525                         break;\r
526 #if 0\r
527         \r
528                 case ID_REVERTREV:\r
529                         {\r
530                                 // we need an URL to complete this command, so error out if we can't get an URL\r
531                                 if (pathURL.IsEmpty())\r
532                                 {\r
533                                         CString strMessage;\r
534                                         strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));\r
535                                         CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);\r
536                                         TRACE(_T("could not retrieve the URL of the folder!\n"));\r
537                                         break;          //exit\r
538                                 }\r
539                                 CString msg;\r
540                                 msg.Format(IDS_LOG_REVERT_CONFIRM, m_path.GetWinPath());\r
541                                 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)\r
542                                 {\r
543                                         CGitProgressDlg dlg;\r
544                                         dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);\r
545                                         dlg.SetPathList(CTGitPathList(m_path));\r
546                                         dlg.SetUrl(pathURL);\r
547                                         dlg.SetSecondUrl(pathURL);\r
548                                         revisionRanges.AdjustForMerge(true);\r
549                                         dlg.SetRevisionRanges(revisionRanges);\r
550                                         dlg.SetPegRevision(m_LogRevision);\r
551                                         dlg.DoModal();\r
552                                 }\r
553                         }\r
554                         break;\r
555                 case ID_MERGEREV:\r
556                         {\r
557                                 // we need an URL to complete this command, so error out if we can't get an URL\r
558                                 if (pathURL.IsEmpty())\r
559                                 {\r
560                                         CString strMessage;\r
561                                         strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));\r
562                                         CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);\r
563                                         TRACE(_T("could not retrieve the URL of the folder!\n"));\r
564                                         break;          //exit\r
565                                 }\r
566 \r
567                                 CString path = m_path.GetWinPathString();\r
568                                 bool bGotSavePath = false;\r
569                                 if ((GetSelectedCount() == 1)&&(!m_path.IsDirectory()))\r
570                                 {\r
571                                         bGotSavePath = CAppUtils::FileOpenSave(path, NULL, IDS_LOG_MERGETO, IDS_COMMONFILEFILTER, true, GetSafeHwnd());\r
572                                 }\r
573                                 else\r
574                                 {\r
575                                         CBrowseFolder folderBrowser;\r
576                                         folderBrowser.SetInfo(CString(MAKEINTRESOURCE(IDS_LOG_MERGETO)));\r
577                                         bGotSavePath = (folderBrowser.Show(GetSafeHwnd(), path, path) == CBrowseFolder::OK);\r
578                                 }\r
579                                 if (bGotSavePath)\r
580                                 {\r
581                                         CGitProgressDlg dlg;\r
582                                         dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);\r
583                                         dlg.SetPathList(CTGitPathList(CTGitPath(path)));\r
584                                         dlg.SetUrl(pathURL);\r
585                                         dlg.SetSecondUrl(pathURL);\r
586                                         revisionRanges.AdjustForMerge(false);\r
587                                         dlg.SetRevisionRanges(revisionRanges);\r
588                                         dlg.SetPegRevision(m_LogRevision);\r
589                                         dlg.DoModal();\r
590                                 }\r
591                         }\r
592                         break;\r
593                 case ID_REVERTTOREV:\r
594                         {\r
595                                 // we need an URL to complete this command, so error out if we can't get an URL\r
596                                 if (pathURL.IsEmpty())\r
597                                 {\r
598                                         CString strMessage;\r
599                                         strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));\r
600                                         CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);\r
601                                         TRACE(_T("could not retrieve the URL of the folder!\n"));\r
602                                         break;          //exit\r
603                                 }\r
604 \r
605                                 CString msg;\r
606                                 msg.Format(IDS_LOG_REVERTTOREV_CONFIRM, m_path.GetWinPath());\r
607                                 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)\r
608                                 {\r
609                                         CGitProgressDlg dlg;\r
610                                         dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);\r
611                                         dlg.SetPathList(CTGitPathList(m_path));\r
612                                         dlg.SetUrl(pathURL);\r
613                                         dlg.SetSecondUrl(pathURL);\r
614                                         GitRevRangeArray revarray;\r
615                                         revarray.AddRevRange(GitRev::REV_HEAD, revSelected);\r
616                                         dlg.SetRevisionRanges(revarray);\r
617                                         dlg.SetPegRevision(m_LogRevision);\r
618                                         dlg.DoModal();\r
619                                 }\r
620                         }\r
621                         break;\r
622         \r
623 \r
624         \r
625                 case ID_BLAMECOMPARE:\r
626                         {\r
627                                 //user clicked on the menu item "compare with working copy"\r
628                                 //now first get the revision which is selected\r
629                                 if (PromptShown())\r
630                                 {\r
631                                         GitDiff diff(this, this->m_hWnd, true);\r
632                                         diff.SetHEADPeg(m_LogRevision);\r
633                                         diff.ShowCompare(m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), false, true);\r
634                                 }\r
635                                 else\r
636                                         CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), m_LogRevision, false, false, true);\r
637                         }\r
638                         break;\r
639                 case ID_BLAMETWO:\r
640                         {\r
641                                 //user clicked on the menu item "compare and blame revisions"\r
642                                 if (PromptShown())\r
643                                 {\r
644                                         GitDiff diff(this, this->m_hWnd, true);\r
645                                         diff.SetHEADPeg(m_LogRevision);\r
646                                         diff.ShowCompare(CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), false, true);\r
647                                 }\r
648                                 else\r
649                                         CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);\r
650                         }\r
651                         break;\r
652                 case ID_BLAMEWITHPREVIOUS:\r
653                         {\r
654                                 //user clicked on the menu item "Compare and Blame with previous revision"\r
655                                 if (PromptShown())\r
656                                 {\r
657                                         GitDiff diff(this, this->m_hWnd, true);\r
658                                         diff.SetHEADPeg(m_LogRevision);\r
659                                         diff.ShowCompare(CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), false, true);\r
660                                 }\r
661                                 else\r
662                                         CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);\r
663                         }\r
664                         break;\r
665                 \r
666                 case ID_OPENWITH:\r
667                         bOpenWith = true;\r
668                 case ID_OPEN:\r
669                         {\r
670                                 CProgressDlg progDlg;\r
671                                 progDlg.SetTitle(IDS_APPNAME);\r
672                                 progDlg.SetAnimation(IDR_DOWNLOAD);\r
673                                 CString sInfoLine;\r
674                                 sInfoLine.Format(IDS_PROGRESSGETFILEREVISION, m_path.GetWinPath(), (LPCTSTR)revSelected.ToString());\r
675                                 progDlg.SetLine(1, sInfoLine, true);\r
676                                 SetAndClearProgressInfo(&progDlg);\r
677                                 progDlg.ShowModeless(m_hWnd);\r
678                                 CTGitPath tempfile = CTempFiles::Instance().GetTempFilePath(false, m_path, revSelected);\r
679                                 bool bSuccess = true;\r
680                                 if (!Cat(m_path, GitRev(GitRev::REV_HEAD), revSelected, tempfile))\r
681                                 {\r
682                                         bSuccess = false;\r
683                                         // try again, but with the selected revision as the peg revision\r
684                                         if (!Cat(m_path, revSelected, revSelected, tempfile))\r
685                                         {\r
686                                                 progDlg.Stop();\r
687                                                 SetAndClearProgressInfo((HWND)NULL);\r
688                                                 CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);\r
689                                                 EnableOKButton();\r
690                                                 break;\r
691                                         }\r
692                                         bSuccess = true;\r
693                                 }\r
694                                 if (bSuccess)\r
695                                 {\r
696                                         progDlg.Stop();\r
697                                         SetAndClearProgressInfo((HWND)NULL);\r
698                                         SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);\r
699                                         int ret = 0;\r
700                                         if (!bOpenWith)\r
701                                                 ret = (int)ShellExecute(this->m_hWnd, NULL, tempfile.GetWinPath(), NULL, NULL, SW_SHOWNORMAL);\r
702                                         if ((ret <= HINSTANCE_ERROR)||bOpenWith)\r
703                                         {\r
704                                                 CString cmd = _T("RUNDLL32 Shell32,OpenAs_RunDLL ");\r
705                                                 cmd += tempfile.GetWinPathString() + _T(" ");\r
706                                                 CAppUtils::LaunchApplication(cmd, NULL, false);\r
707                                         }\r
708                                 }\r
709                         }\r
710                         break;\r
711                 case ID_BLAME:\r
712                         {\r
713                                 CBlameDlg dlg;\r
714                                 dlg.EndRev = revSelected;\r
715                                 if (dlg.DoModal() == IDOK)\r
716                                 {\r
717                                         CBlame blame;\r
718                                         CString tempfile;\r
719                                         CString logfile;\r
720                                         tempfile = blame.BlameToTempFile(m_path, dlg.StartRev, dlg.EndRev, dlg.EndRev, logfile, _T(""), dlg.m_bIncludeMerge, TRUE, TRUE);\r
721                                         if (!tempfile.IsEmpty())\r
722                                         {\r
723                                                 if (dlg.m_bTextView)\r
724                                                 {\r
725                                                         //open the default text editor for the result file\r
726                                                         CAppUtils::StartTextViewer(tempfile);\r
727                                                 }\r
728                                                 else\r
729                                                 {\r
730                                                         CString sParams = _T("/path:\"") + m_path.GetGitPathString() + _T("\" ");\r
731                                                         if(!CAppUtils::LaunchTortoiseBlame(tempfile, logfile, CPathUtils::GetFileNameFromPath(m_path.GetFileOrDirectoryName()),sParams))\r
732                                                         {\r
733                                                                 break;\r
734                                                         }\r
735                                                 }\r
736                                         }\r
737                                         else\r
738                                         {\r
739                                                 CMessageBox::Show(this->m_hWnd, blame.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);\r
740                                         }\r
741                                 }\r
742                         }\r
743                         break;\r
744                 case ID_UPDATE:\r
745                         {\r
746                                 CString sCmd;\r
747                                 CString url = _T("tgit:")+pathURL;\r
748                                 sCmd.Format(_T("%s /command:update /path:\"%s\" /rev:%ld"),\r
749                                         (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),\r
750                                         (LPCTSTR)m_path.GetWinPath(), (LONG)revSelected);\r
751                                 CAppUtils::LaunchApplication(sCmd, NULL, false);\r
752                         }\r
753                         break;\r
754                 case ID_FINDENTRY:\r
755                         {\r
756                                 m_nSearchIndex = GetSelectionMark();\r
757                                 if (m_nSearchIndex < 0)\r
758                                         m_nSearchIndex = 0;\r
759                                 if (m_pFindDialog)\r
760                                 {\r
761                                         break;\r
762                                 }\r
763                                 else\r
764                                 {\r
765                                         m_pFindDialog = new CFindReplaceDialog();\r
766                                         m_pFindDialog->Create(TRUE, NULL, NULL, FR_HIDEUPDOWN | FR_HIDEWHOLEWORD, this);                                                                        \r
767                                 }\r
768                         }\r
769                         break;\r
770                 case ID_REPOBROWSE:\r
771                         {\r
772                                 CString sCmd;\r
773                                 sCmd.Format(_T("%s /command:repobrowser /path:\"%s\" /rev:%s"),\r
774                                         (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),\r
775                                         (LPCTSTR)pathURL, (LPCTSTR)revSelected.ToString());\r
776 \r
777                                 CAppUtils::LaunchApplication(sCmd, NULL, false);\r
778                         }\r
779                         break;\r
780                 case ID_EDITLOG:\r
781                         {\r
782                                 EditLogMessage(selIndex);\r
783                         }\r
784                         break;\r
785                 case ID_EDITAUTHOR:\r
786                         {\r
787                                 EditAuthor(selEntries);\r
788                         }\r
789                         break;\r
790                 case ID_REVPROPS:\r
791                         {\r
792                                 CEditPropertiesDlg dlg;\r
793                                 dlg.SetProjectProperties(&m_ProjectProperties);\r
794                                 CTGitPathList escapedlist;\r
795                                 dlg.SetPathList(CTGitPathList(CTGitPath(pathURL)));\r
796                                 dlg.SetRevision(revSelected);\r
797                                 dlg.RevProps(true);\r
798                                 dlg.DoModal();\r
799                         }\r
800                         break;\r
801                 \r
802                 case ID_EXPORT:\r
803                         {\r
804                                 CString sCmd;\r
805                                 sCmd.Format(_T("%s /command:export /path:\"%s\" /revision:%ld"),\r
806                                         (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),\r
807                                         (LPCTSTR)pathURL, (LONG)revSelected);\r
808                                 CAppUtils::LaunchApplication(sCmd, NULL, false);\r
809                         }\r
810                         break;\r
811                 case ID_CHECKOUT:\r
812                         {\r
813                                 CString sCmd;\r
814                                 CString url = _T("tgit:")+pathURL;\r
815                                 sCmd.Format(_T("%s /command:checkout /url:\"%s\" /revision:%ld"),\r
816                                         (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),\r
817                                         (LPCTSTR)url, (LONG)revSelected);\r
818                                 CAppUtils::LaunchApplication(sCmd, NULL, false);\r
819                         }\r
820                         break;\r
821                 case ID_VIEWREV:\r
822                         {\r
823                                 CString url = m_ProjectProperties.sWebViewerRev;\r
824                                 url = GetAbsoluteUrlFromRelativeUrl(url);\r
825                                 url.Replace(_T("%REVISION%"), revSelected.ToString());\r
826                                 if (!url.IsEmpty())\r
827                                         ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);                                        \r
828                         }\r
829                         break;\r
830                 case ID_VIEWPATHREV:\r
831                         {\r
832                                 CString relurl = pathURL;\r
833                                 CString sRoot = GetRepositoryRoot(CTGitPath(relurl));\r
834                                 relurl = relurl.Mid(sRoot.GetLength());\r
835                                 CString url = m_ProjectProperties.sWebViewerPathRev;\r
836                                 url = GetAbsoluteUrlFromRelativeUrl(url);\r
837                                 url.Replace(_T("%REVISION%"), revSelected.ToString());\r
838                                 url.Replace(_T("%PATH%"), relurl);\r
839                                 if (!url.IsEmpty())\r
840                                         ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);                                        \r
841                         }\r
842                         break;\r
843 #endif\r
844                 \r
845                 } // switch (cmd)\r
846 \r
847                 theApp.DoWaitCursor(-1);\r
848 }\r
849 \r
850 void CGitLogList::SetSelectedAction(int action)\r
851 {\r
852         POSITION pos = GetFirstSelectedItemPosition();\r
853         int index;\r
854         while(pos)\r
855         {\r
856                 index = GetNextSelectedItem(pos);\r
857                 ((GitRev*)m_arShownList[index])->m_Action = action;\r
858                 CRect rect;\r
859                 this->GetItemRect(index,&rect,LVIR_BOUNDS);\r
860                 this->InvalidateRect(rect);\r
861 \r
862         }\r
863 \r
864 }