better fix for 9e39b918b0057be0e215fd59788f145b77a67ff5
[TortoiseGit.git] / src / TortoiseGitBlame / LogListBlameAction.cpp
blob96306918ef41299dabf4df174473f68e09cd915e
1 #include "stdafx.h"
2 #include "GitBlameLogList.h"
3 #include "GitRev.h"
4 #include "TortoiseGitBlameDoc.h"
5 #include "TortoiseGitBlameView.h"
6 #include "MainFrm.h"
7 #include "PathUtils.h"
9 IMPLEMENT_DYNAMIC(CGitBlameLogList, CHintListCtrl)
11 void CGitBlameLogList::hideUnimplementedCommands()
13 hideFromContextMenu(
14 GetContextMenuBit(ID_COPYCLIPBOARD) |
15 GetContextMenuBit(ID_COPYHASH) |
16 GetContextMenuBit(ID_EXPORT) |
17 GetContextMenuBit(ID_CREATE_BRANCH) |
18 GetContextMenuBit(ID_CREATE_TAG) |
19 GetContextMenuBit(ID_SWITCHTOREV)
20 , true);
21 m_ContextMenuMask |= GetContextMenuBit(ID_BLAME);
24 void CGitBlameLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect,CMenu * menu)
26 POSITION pos = GetFirstSelectedItemPosition();
27 int indexNext = GetNextSelectedItem(pos);
28 if (indexNext < 0)
29 return;
31 CString procCmd;
33 GitRev* pSelLogEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(indexNext));
35 bool bOpenWith = false;
37 procCmd+=_T(" /path:\"");
38 procCmd+=((CMainFrame*)::AfxGetApp()->GetMainWnd())->GetActiveView()->GetDocument()->GetPathName();
39 procCmd+=_T("\" ");
40 procCmd+=_T(" /rev:")+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
42 procCmd+=_T(" /command:");
44 switch (cmd)
46 case ID_GNUDIFF1:
47 procCmd+=_T("diff /udiff");
48 break;
50 #if 0
51 case ID_GNUDIFF2:
53 CString tempfile=GetTempFile();
54 CString cmd;
55 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
56 GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));
57 cmd.Format(_T("git.exe diff-tree -r -p --stat %s %s"),r1->m_CommitHash,r2->m_CommitHash);
58 g_Git.RunLogFile(cmd,tempfile);
59 CAppUtils::StartUnifiedDiffViewer(tempfile,r1->m_CommitHash.Left(6)+_T(":")+r2->m_CommitHash.Left(6));
62 break;
63 #endif
64 #if 0
65 case ID_COMPARETWO:
67 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
68 GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));
69 CFileDiffDlg dlg;
70 dlg.SetDiff(NULL,*r1,*r2);
71 dlg.DoModal();
74 break;
75 #endif
76 #if 0
77 case ID_COMPARE:
79 GitRev * r1 = &m_wcRev;
80 GitRev * r2 = pSelLogEntry;
81 CFileDiffDlg dlg;
82 dlg.SetDiff(NULL,*r1,*r2);
83 dlg.DoModal();
85 //user clicked on the menu item "compare with working copy"
86 //if (PromptShown())
87 //{
88 // GitDiff diff(this, m_hWnd, true);
89 // diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
90 // diff.SetHEADPeg(m_LogRevision);
91 // diff.ShowCompare(m_path, GitRev::REV_WC, m_path, revSelected);
92 //}
93 //else
94 // CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_WC, m_path, revSelected, GitRev(), m_LogRevision, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
96 break;
97 #endif
98 case ID_COMPARE:
99 procCmd+=CString(_T("diff \rev1:"))+CString(GIT_REV_ZERO)+CString(_T(" \rev2:"))+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
100 break;
101 case ID_COMPAREWITHPREVIOUS:
102 procCmd+=_T("prevdiff");
103 break;
104 case ID_COPYCLIPBOARD:
106 CopySelectionToClipBoard();
108 return;
109 case ID_COPYHASH:
111 CopySelectionToClipBoard(TRUE);
113 return;
114 case ID_EXPORT:
115 procCmd+=_T("export");
116 break;
117 case ID_CREATE_BRANCH:
118 procCmd+=_T("branch");
119 break;
120 case ID_CREATE_TAG:
121 procCmd+=_T("tag");
122 break;
123 case ID_SWITCHTOREV:
124 procCmd+=_T("switch");
125 break;
126 case ID_BLAME:
127 procCmd+=_T("blame");
128 procCmd+=_T(" /endrev:") + this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
129 break;
130 default:
131 //CMessageBox::Show(NULL,_T("Have not implemented"),_T("TortoiseGit"),MB_OK);
132 return;
134 #if 0
136 case ID_REVERTREV:
138 // we need an URL to complete this command, so error out if we can't get an URL
139 if (pathURL.IsEmpty())
141 CString strMessage;
142 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
143 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
144 TRACE(_T("could not retrieve the URL of the folder!\n"));
145 break; //exit
147 CString msg;
148 msg.Format(IDS_LOG_REVERT_CONFIRM, m_path.GetWinPath());
149 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
151 CGitProgressDlg dlg;
152 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
153 dlg.SetPathList(CTGitPathList(m_path));
154 dlg.SetUrl(pathURL);
155 dlg.SetSecondUrl(pathURL);
156 revisionRanges.AdjustForMerge(true);
157 dlg.SetRevisionRanges(revisionRanges);
158 dlg.SetPegRevision(m_LogRevision);
159 dlg.DoModal();
162 break;
163 case ID_MERGEREV:
165 // we need an URL to complete this command, so error out if we can't get an URL
166 if (pathURL.IsEmpty())
168 CString strMessage;
169 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
170 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
171 TRACE(_T("could not retrieve the URL of the folder!\n"));
172 break; //exit
175 CString path = m_path.GetWinPathString();
176 bool bGotSavePath = false;
177 if ((GetSelectedCount() == 1)&&(!m_path.IsDirectory()))
179 bGotSavePath = CAppUtils::FileOpenSave(path, NULL, IDS_LOG_MERGETO, IDS_COMMONFILEFILTER, true, GetSafeHwnd());
181 else
183 CBrowseFolder folderBrowser;
184 folderBrowser.SetInfo(CString(MAKEINTRESOURCE(IDS_LOG_MERGETO)));
185 bGotSavePath = (folderBrowser.Show(GetSafeHwnd(), path, path) == CBrowseFolder::OK);
187 if (bGotSavePath)
189 CGitProgressDlg dlg;
190 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
191 dlg.SetPathList(CTGitPathList(CTGitPath(path)));
192 dlg.SetUrl(pathURL);
193 dlg.SetSecondUrl(pathURL);
194 revisionRanges.AdjustForMerge(false);
195 dlg.SetRevisionRanges(revisionRanges);
196 dlg.SetPegRevision(m_LogRevision);
197 dlg.DoModal();
200 break;
201 case ID_REVERTTOREV:
203 // we need an URL to complete this command, so error out if we can't get an URL
204 if (pathURL.IsEmpty())
206 CString strMessage;
207 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
208 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
209 TRACE(_T("could not retrieve the URL of the folder!\n"));
210 break; //exit
213 CString msg;
214 msg.Format(IDS_LOG_REVERTTOREV_CONFIRM, m_path.GetWinPath());
215 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
217 CGitProgressDlg dlg;
218 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
219 dlg.SetPathList(CTGitPathList(m_path));
220 dlg.SetUrl(pathURL);
221 dlg.SetSecondUrl(pathURL);
222 GitRevRangeArray revarray;
223 revarray.AddRevRange(GitRev::REV_HEAD, revSelected);
224 dlg.SetRevisionRanges(revarray);
225 dlg.SetPegRevision(m_LogRevision);
226 dlg.DoModal();
229 break;
233 case ID_BLAMECOMPARE:
235 //user clicked on the menu item "compare with working copy"
236 //now first get the revision which is selected
237 if (PromptShown())
239 GitDiff diff(this, this->m_hWnd, true);
240 diff.SetHEADPeg(m_LogRevision);
241 diff.ShowCompare(m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), false, true);
243 else
244 CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), m_LogRevision, false, false, true);
246 break;
247 case ID_BLAMETWO:
249 //user clicked on the menu item "compare and blame revisions"
250 if (PromptShown())
252 GitDiff diff(this, this->m_hWnd, true);
253 diff.SetHEADPeg(m_LogRevision);
254 diff.ShowCompare(CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), false, true);
256 else
257 CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);
259 break;
260 case ID_BLAMEWITHPREVIOUS:
262 //user clicked on the menu item "Compare and Blame with previous revision"
263 if (PromptShown())
265 GitDiff diff(this, this->m_hWnd, true);
266 diff.SetHEADPeg(m_LogRevision);
267 diff.ShowCompare(CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), false, true);
269 else
270 CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);
272 break;
274 case ID_OPENWITH:
275 bOpenWith = true;
276 case ID_OPEN:
278 CProgressDlg progDlg;
279 progDlg.SetTitle(IDS_APPNAME);
280 progDlg.SetAnimation(IDR_DOWNLOAD);
281 CString sInfoLine;
282 sInfoLine.Format(IDS_PROGRESSGETFILEREVISION, m_path.GetWinPath(), (LPCTSTR)revSelected.ToString());
283 progDlg.SetLine(1, sInfoLine, true);
284 SetAndClearProgressInfo(&progDlg);
285 progDlg.ShowModeless(m_hWnd);
286 CTGitPath tempfile = CTempFiles::Instance().GetTempFilePath(false, m_path, revSelected);
287 bool bSuccess = true;
288 if (!Cat(m_path, GitRev(GitRev::REV_HEAD), revSelected, tempfile))
290 bSuccess = false;
291 // try again, but with the selected revision as the peg revision
292 if (!Cat(m_path, revSelected, revSelected, tempfile))
294 progDlg.Stop();
295 SetAndClearProgressInfo((HWND)NULL);
296 CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
297 EnableOKButton();
298 break;
300 bSuccess = true;
302 if (bSuccess)
304 progDlg.Stop();
305 SetAndClearProgressInfo((HWND)NULL);
306 SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
307 int ret = 0;
308 if (!bOpenWith)
309 ret = (int)ShellExecute(this->m_hWnd, NULL, tempfile.GetWinPath(), NULL, NULL, SW_SHOWNORMAL);
310 if ((ret <= HINSTANCE_ERROR)||bOpenWith)
312 CString cmd = _T("RUNDLL32 Shell32,OpenAs_RunDLL ");
313 cmd += tempfile.GetWinPathString() + _T(" ");
314 CAppUtils::LaunchApplication(cmd, NULL, false);
318 break;
319 case ID_BLAME:
321 CBlameDlg dlg;
322 dlg.EndRev = revSelected;
323 if (dlg.DoModal() == IDOK)
325 CBlame blame;
326 CString tempfile;
327 CString logfile;
328 tempfile = blame.BlameToTempFile(m_path, dlg.StartRev, dlg.EndRev, dlg.EndRev, logfile, _T(""), dlg.m_bIncludeMerge, TRUE, TRUE);
329 if (!tempfile.IsEmpty())
331 if (dlg.m_bTextView)
333 //open the default text editor for the result file
334 CAppUtils::StartTextViewer(tempfile);
336 else
338 CString sParams = _T("/path:\"") + m_path.GetGitPathString() + _T("\" ");
339 if(!CAppUtils::LaunchTortoiseBlame(tempfile, logfile, CPathUtils::GetFileNameFromPath(m_path.GetFileOrDirectoryName()),sParams))
341 break;
345 else
347 CMessageBox::Show(this->m_hWnd, blame.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
351 break;
352 case ID_UPDATE:
354 CString sCmd;
355 CString url = _T("tgit:")+pathURL;
356 sCmd.Format(_T("%s /command:update /path:\"%s\" /rev:%ld"),
357 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
358 (LPCTSTR)m_path.GetWinPath(), (LONG)revSelected);
359 CAppUtils::LaunchApplication(sCmd, NULL, false);
361 break;
362 case ID_FINDENTRY:
364 m_nSearchIndex = GetSelectionMark();
365 if (m_nSearchIndex < 0)
366 m_nSearchIndex = 0;
367 if (m_pFindDialog)
369 break;
371 else
373 m_pFindDialog = new CFindReplaceDialog();
374 m_pFindDialog->Create(TRUE, NULL, NULL, FR_HIDEUPDOWN | FR_HIDEWHOLEWORD, this);
377 break;
378 case ID_REPOBROWSE:
380 CString sCmd;
381 sCmd.Format(_T("%s /command:repobrowser /path:\"%s\" /rev:%s"),
382 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
383 (LPCTSTR)pathURL, (LPCTSTR)revSelected.ToString());
385 CAppUtils::LaunchApplication(sCmd, NULL, false);
387 break;
388 case ID_EDITLOG:
390 EditLogMessage(selIndex);
392 break;
393 case ID_EDITAUTHOR:
395 EditAuthor(selEntries);
397 break;
398 case ID_REVPROPS:
400 CEditPropertiesDlg dlg;
401 dlg.SetProjectProperties(&m_ProjectProperties);
402 CTGitPathList escapedlist;
403 dlg.SetPathList(CTGitPathList(CTGitPath(pathURL)));
404 dlg.SetRevision(revSelected);
405 dlg.RevProps(true);
406 dlg.DoModal();
408 break;
410 case ID_EXPORT:
412 CString sCmd;
413 sCmd.Format(_T("%s /command:export /path:\"%s\" /revision:%ld"),
414 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
415 (LPCTSTR)pathURL, (LONG)revSelected);
416 CAppUtils::LaunchApplication(sCmd, NULL, false);
418 break;
419 case ID_CHECKOUT:
421 CString sCmd;
422 CString url = _T("tgit:")+pathURL;
423 sCmd.Format(_T("%s /command:checkout /url:\"%s\" /revision:%ld"),
424 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
425 (LPCTSTR)url, (LONG)revSelected);
426 CAppUtils::LaunchApplication(sCmd, NULL, false);
428 break;
429 case ID_VIEWREV:
431 CString url = m_ProjectProperties.sWebViewerRev;
432 url = GetAbsoluteUrlFromRelativeUrl(url);
433 url.Replace(_T("%REVISION%"), revSelected.ToString());
434 if (!url.IsEmpty())
435 ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);
437 break;
438 case ID_VIEWPATHREV:
440 CString relurl = pathURL;
441 CString sRoot = GetRepositoryRoot(CTGitPath(relurl));
442 relurl = relurl.Mid(sRoot.GetLength());
443 CString url = m_ProjectProperties.sWebViewerPathRev;
444 url = GetAbsoluteUrlFromRelativeUrl(url);
445 url.Replace(_T("%REVISION%"), revSelected.ToString());
446 url.Replace(_T("%PATH%"), relurl);
447 if (!url.IsEmpty())
448 ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);
450 break;
451 #endif
453 } // switch (cmd)
456 STARTUPINFO startup;
457 PROCESS_INFORMATION process;
458 memset(&startup, 0, sizeof(startup));
459 startup.cb = sizeof(startup);
460 memset(&process, 0, sizeof(process));
461 CString tortoiseProcPath = CPathUtils::GetAppDirectory() + _T("TortoiseProc.exe");
463 if (CreateProcess(tortoiseProcPath, procCmd.GetBuffer(), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))
465 CloseHandle(process.hThread);
466 CloseHandle(process.hProcess);