Fixed issue #1220: ext/CrashServer/CommonLibs/Zlib/Zlib.vcproj immediate dir Win32...
[TortoiseGit.git] / src / TortoiseGitBlame / LogListBlameAction.cpp
blobb23bebb73aff87e0c27044163337016c56c9f2c0
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2012 - TortoiseGit
4 // Copyright (C) 2011-2012 Sven Strickroth <email@cs-ware.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "stdafx.h"
22 #include "GitBlameLogList.h"
23 #include "GitRev.h"
24 #include "TortoiseGitBlameDoc.h"
25 #include "TortoiseGitBlameView.h"
26 #include "MainFrm.h"
27 #include "CommonAppUtils.h"
29 IMPLEMENT_DYNAMIC(CGitBlameLogList, CHintListCtrl)
31 void CGitBlameLogList::hideUnimplementedCommands()
33 hideFromContextMenu(
34 GetContextMenuBit(ID_COMPAREWITHPREVIOUS) |
35 GetContextMenuBit(ID_COPYCLIPBOARD) |
36 GetContextMenuBit(ID_COPYHASH) |
37 GetContextMenuBit(ID_EXPORT) |
38 GetContextMenuBit(ID_CREATE_BRANCH) |
39 GetContextMenuBit(ID_CREATE_TAG) |
40 GetContextMenuBit(ID_SWITCHTOREV)
41 , true);
42 m_ContextMenuMask |= GetContextMenuBit(ID_LOG) | GetContextMenuBit(ID_BLAME) | GetContextMenuBit(ID_REPOBROWSE);
45 void CGitBlameLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect,CMenu * menu)
47 POSITION pos = GetFirstSelectedItemPosition();
48 int indexNext = GetNextSelectedItem(pos);
49 if (indexNext < 0)
50 return;
52 CString procCmd;
54 GitRev* pSelLogEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(indexNext));
56 bool bOpenWith = false;
58 procCmd += _T("/path:\"");
59 procCmd += ((CMainFrame*)::AfxGetApp()->GetMainWnd())->GetActiveView()->GetDocument()->GetPathName();
60 procCmd += _T("\" ");
61 procCmd += _T(" /rev:")+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
63 procCmd += _T(" /command:");
65 switch (cmd)
67 case ID_GNUDIFF1:
68 procCmd += _T("diff /udiff");
69 break;
71 #if 0
72 case ID_GNUDIFF2:
74 CString tempfile=GetTempFile();
75 CString cmd;
76 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
77 GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));
78 cmd.Format(_T("git.exe diff-tree -r -p --stat %s %s"),r1->m_CommitHash,r2->m_CommitHash);
79 g_Git.RunLogFile(cmd,tempfile);
80 CAppUtils::StartUnifiedDiffViewer(tempfile, r1->m_CommitHash.Left(g_Git.GetShortHASHLength()) + _T(":") + r2->m_CommitHash.Left(g_Git.GetShortHASHLength()));
83 break;
84 #endif
85 #if 0
86 case ID_COMPARETWO:
88 GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));
89 GitRev * r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));
90 CFileDiffDlg dlg;
91 dlg.SetDiff(NULL,*r1,*r2);
92 dlg.DoModal();
95 break;
96 #endif
97 #if 0
98 case ID_COMPARE:
100 GitRev * r1 = &m_wcRev;
101 GitRev * r2 = pSelLogEntry;
102 CFileDiffDlg dlg;
103 dlg.SetDiff(NULL,*r1,*r2);
104 dlg.DoModal();
106 //user clicked on the menu item "compare with working copy"
107 //if (PromptShown())
109 // GitDiff diff(this, m_hWnd, true);
110 // diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
111 // diff.SetHEADPeg(m_LogRevision);
112 // diff.ShowCompare(m_path, GitRev::REV_WC, m_path, revSelected);
114 //else
115 // CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_WC, m_path, revSelected, GitRev(), m_LogRevision, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
117 break;
118 case ID_COMPARE:
119 procCmd+=CString(_T("diff \rev1:"))+CString(GIT_REV_ZERO)+CString(_T(" \rev2:"))+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
120 break;
121 #endif
122 case ID_COMPAREWITHPREVIOUS:
123 if (indexNext + 1 < m_logEntries.size()) // cannot diff previous revision in first revision
125 procCmd+=CString(_T("diff /startrev:"))+this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString()+CString(_T(" /endrev:"))+this->m_logEntries.GetGitRevAt(indexNext+1).m_CommitHash.ToString();
127 else
129 return;
131 break;
132 case ID_COPYCLIPBOARD:
134 CopySelectionToClipBoard();
136 return;
137 case ID_COPYHASH:
139 CopySelectionToClipBoard(TRUE);
141 return;
142 case ID_EXPORT:
143 procCmd += _T("export");
144 break;
145 case ID_CREATE_BRANCH:
146 procCmd += _T("branch");
147 break;
148 case ID_CREATE_TAG:
149 procCmd += _T("tag");
150 break;
151 case ID_SWITCHTOREV:
152 procCmd += _T("switch");
153 break;
154 case ID_BLAME:
155 procCmd += _T("blame");
156 procCmd += _T(" /endrev:") + this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString();
157 break;
158 case ID_LOG:
159 procCmd += _T("log");
160 break;
161 case ID_REPOBROWSE:
162 procCmd.Format(_T("/command:repobrowser /path:\"%s\" /rev:%s"), g_Git.m_CurrentDir, this->m_logEntries.GetGitRevAt(indexNext).m_CommitHash.ToString());
163 break;
164 default:
165 //CMessageBox::Show(NULL,_T("Have not implemented"),_T("TortoiseGit"),MB_OK);
166 return;
168 #if 0
170 case ID_REVERTREV:
172 // we need an URL to complete this command, so error out if we can't get an URL
173 if (pathURL.IsEmpty())
175 CString strMessage;
176 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
177 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
178 TRACE(_T("could not retrieve the URL of the folder!\n"));
179 break; //exit
181 CString msg;
182 msg.Format(IDS_LOG_REVERT_CONFIRM, m_path.GetWinPath());
183 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
185 CGitProgressDlg dlg;
186 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
187 dlg.SetPathList(CTGitPathList(m_path));
188 dlg.SetUrl(pathURL);
189 dlg.SetSecondUrl(pathURL);
190 revisionRanges.AdjustForMerge(true);
191 dlg.SetRevisionRanges(revisionRanges);
192 dlg.SetPegRevision(m_LogRevision);
193 dlg.DoModal();
196 break;
197 case ID_MERGEREV:
199 // we need an URL to complete this command, so error out if we can't get an URL
200 if (pathURL.IsEmpty())
202 CString strMessage;
203 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
204 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
205 TRACE(_T("could not retrieve the URL of the folder!\n"));
206 break; //exit
209 CString path = m_path.GetWinPathString();
210 bool bGotSavePath = false;
211 if ((GetSelectedCount() == 1)&&(!m_path.IsDirectory()))
213 bGotSavePath = CAppUtils::FileOpenSave(path, NULL, IDS_LOG_MERGETO, IDS_COMMONFILEFILTER, true, GetSafeHwnd());
215 else
217 CBrowseFolder folderBrowser;
218 folderBrowser.SetInfo(CString(MAKEINTRESOURCE(IDS_LOG_MERGETO)));
219 bGotSavePath = (folderBrowser.Show(GetSafeHwnd(), path, path) == CBrowseFolder::OK);
221 if (bGotSavePath)
223 CGitProgressDlg dlg;
224 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
225 dlg.SetPathList(CTGitPathList(CTGitPath(path)));
226 dlg.SetUrl(pathURL);
227 dlg.SetSecondUrl(pathURL);
228 revisionRanges.AdjustForMerge(false);
229 dlg.SetRevisionRanges(revisionRanges);
230 dlg.SetPegRevision(m_LogRevision);
231 dlg.DoModal();
234 break;
235 case ID_REVERTTOREV:
237 // we need an URL to complete this command, so error out if we can't get an URL
238 if (pathURL.IsEmpty())
240 CString strMessage;
241 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
242 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
243 TRACE(_T("could not retrieve the URL of the folder!\n"));
244 break; //exit
247 CString msg;
248 msg.Format(IDS_LOG_REVERTTOREV_CONFIRM, m_path.GetWinPath());
249 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
251 CGitProgressDlg dlg;
252 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
253 dlg.SetPathList(CTGitPathList(m_path));
254 dlg.SetUrl(pathURL);
255 dlg.SetSecondUrl(pathURL);
256 GitRevRangeArray revarray;
257 revarray.AddRevRange(GitRev::REV_HEAD, revSelected);
258 dlg.SetRevisionRanges(revarray);
259 dlg.SetPegRevision(m_LogRevision);
260 dlg.DoModal();
263 break;
265 case ID_BLAMECOMPARE:
267 //user clicked on the menu item "compare with working copy"
268 //now first get the revision which is selected
269 if (PromptShown())
271 GitDiff diff(this, this->m_hWnd, true);
272 diff.SetHEADPeg(m_LogRevision);
273 diff.ShowCompare(m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), false, true);
275 else
276 CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), m_LogRevision, false, false, true);
278 break;
279 case ID_BLAMETWO:
281 //user clicked on the menu item "compare and blame revisions"
282 if (PromptShown())
284 GitDiff diff(this, this->m_hWnd, true);
285 diff.SetHEADPeg(m_LogRevision);
286 diff.ShowCompare(CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), false, true);
288 else
289 CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);
291 break;
292 case ID_BLAMEWITHPREVIOUS:
294 //user clicked on the menu item "Compare and Blame with previous revision"
295 if (PromptShown())
297 GitDiff diff(this, this->m_hWnd, true);
298 diff.SetHEADPeg(m_LogRevision);
299 diff.ShowCompare(CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), false, true);
301 else
302 CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);
304 break;
306 case ID_OPENWITH:
307 bOpenWith = true;
308 case ID_OPEN:
310 CProgressDlg progDlg;
311 progDlg.SetTitle(IDS_APPNAME);
312 progDlg.SetAnimation(IDR_DOWNLOAD);
313 CString sInfoLine;
314 sInfoLine.Format(IDS_PROGRESSGETFILEREVISION, m_path.GetWinPath(), (LPCTSTR)revSelected.ToString());
315 progDlg.SetLine(1, sInfoLine, true);
316 SetAndClearProgressInfo(&progDlg);
317 progDlg.ShowModeless(m_hWnd);
318 CTGitPath tempfile = CTempFiles::Instance().GetTempFilePath(false, m_path, revSelected);
319 bool bSuccess = true;
320 if (!Cat(m_path, GitRev(GitRev::REV_HEAD), revSelected, tempfile))
322 bSuccess = false;
323 // try again, but with the selected revision as the peg revision
324 if (!Cat(m_path, revSelected, revSelected, tempfile))
326 progDlg.Stop();
327 SetAndClearProgressInfo((HWND)NULL);
328 CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
329 EnableOKButton();
330 break;
332 bSuccess = true;
334 if (bSuccess)
336 progDlg.Stop();
337 SetAndClearProgressInfo((HWND)NULL);
338 SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
339 int ret = 0;
340 if (!bOpenWith)
341 ret = (int)ShellExecute(this->m_hWnd, NULL, tempfile.GetWinPath(), NULL, NULL, SW_SHOWNORMAL);
342 if ((ret <= HINSTANCE_ERROR)||bOpenWith)
344 CString cmd = _T("RUNDLL32 Shell32,OpenAs_RunDLL ");
345 cmd += tempfile.GetWinPathString() + _T(" ");
346 CAppUtils::LaunchApplication(cmd, NULL, false);
350 break;
351 case ID_BLAME:
353 CBlameDlg dlg;
354 dlg.EndRev = revSelected;
355 if (dlg.DoModal() == IDOK)
357 CBlame blame;
358 CString tempfile;
359 CString logfile;
360 tempfile = blame.BlameToTempFile(m_path, dlg.StartRev, dlg.EndRev, dlg.EndRev, logfile, _T(""), dlg.m_bIncludeMerge, TRUE, TRUE);
361 if (!tempfile.IsEmpty())
363 if (dlg.m_bTextView)
365 //open the default text editor for the result file
366 CAppUtils::StartTextViewer(tempfile);
368 else
370 CString sParams = _T("/path:\"") + m_path.GetGitPathString() + _T("\" ");
371 if(!CAppUtils::LaunchTortoiseBlame(tempfile, logfile, CPathUtils::GetFileNameFromPath(m_path.GetFileOrDirectoryName()),sParams))
373 break;
377 else
379 CMessageBox::Show(this->m_hWnd, blame.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
383 break;
384 case ID_UPDATE:
386 CString sCmd;
387 CString url = _T("tgit:")+pathURL;
388 sCmd.Format(_T("%s /command:update /path:\"%s\" /rev:%ld"),
389 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
390 (LPCTSTR)m_path.GetWinPath(), (LONG)revSelected);
391 CAppUtils::LaunchApplication(sCmd, NULL, false);
393 break;
394 case ID_FINDENTRY:
396 m_nSearchIndex = GetSelectionMark();
397 if (m_nSearchIndex < 0)
398 m_nSearchIndex = 0;
399 if (m_pFindDialog)
401 break;
403 else
405 m_pFindDialog = new CFindReplaceDialog();
406 m_pFindDialog->Create(TRUE, NULL, NULL, FR_HIDEUPDOWN | FR_HIDEWHOLEWORD, this);
409 break;
410 case ID_EDITLOG:
412 EditLogMessage(selIndex);
414 break;
415 case ID_EDITAUTHOR:
417 EditAuthor(selEntries);
419 break;
420 case ID_REVPROPS:
422 CEditPropertiesDlg dlg;
423 dlg.SetProjectProperties(&m_ProjectProperties);
424 CTGitPathList escapedlist;
425 dlg.SetPathList(CTGitPathList(CTGitPath(pathURL)));
426 dlg.SetRevision(revSelected);
427 dlg.RevProps(true);
428 dlg.DoModal();
430 break;
432 case ID_EXPORT:
434 CString sCmd;
435 sCmd.Format(_T("%s /command:export /path:\"%s\" /revision:%ld"),
436 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
437 (LPCTSTR)pathURL, (LONG)revSelected);
438 CAppUtils::LaunchApplication(sCmd, NULL, false);
440 break;
441 case ID_CHECKOUT:
443 CString sCmd;
444 CString url = _T("tgit:")+pathURL;
445 sCmd.Format(_T("%s /command:checkout /url:\"%s\" /revision:%ld"),
446 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
447 (LPCTSTR)url, (LONG)revSelected);
448 CAppUtils::LaunchApplication(sCmd, NULL, false);
450 break;
451 case ID_VIEWREV:
453 CString url = m_ProjectProperties.sWebViewerRev;
454 url = GetAbsoluteUrlFromRelativeUrl(url);
455 url.Replace(_T("%REVISION%"), revSelected.ToString());
456 if (!url.IsEmpty())
457 ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);
459 break;
460 case ID_VIEWPATHREV:
462 CString relurl = pathURL;
463 CString sRoot = GetRepositoryRoot(CTGitPath(relurl));
464 relurl = relurl.Mid(sRoot.GetLength());
465 CString url = m_ProjectProperties.sWebViewerPathRev;
466 url = GetAbsoluteUrlFromRelativeUrl(url);
467 url.Replace(_T("%REVISION%"), revSelected.ToString());
468 url.Replace(_T("%PATH%"), relurl);
469 if (!url.IsEmpty())
470 ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);
472 break;
473 #endif
475 } // switch (cmd)
477 CCommonAppUtils::RunTortoiseProc(procCmd);