OSDN Git Service

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