some spaces-tabs code cleanup
[TortoiseGit.git] / src / TortoiseGitBlame / LogListBlameAction.cpp
blob1e0914a792049b32615f8f9cb9e901ebd2438ed0
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2011 - TortoiseGit
4 // Copyright (C) 2011 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 "PathUtils.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_BLAME);
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(6)+_T(":")+r2->m_CommitHash.Left(6));
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 default:
159 //CMessageBox::Show(NULL,_T("Have not implemented"),_T("TortoiseGit"),MB_OK);
160 return;
162 #if 0
164 case ID_REVERTREV:
166 // we need an URL to complete this command, so error out if we can't get an URL
167 if (pathURL.IsEmpty())
169 CString strMessage;
170 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
171 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
172 TRACE(_T("could not retrieve the URL of the folder!\n"));
173 break; //exit
175 CString msg;
176 msg.Format(IDS_LOG_REVERT_CONFIRM, m_path.GetWinPath());
177 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
179 CGitProgressDlg dlg;
180 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
181 dlg.SetPathList(CTGitPathList(m_path));
182 dlg.SetUrl(pathURL);
183 dlg.SetSecondUrl(pathURL);
184 revisionRanges.AdjustForMerge(true);
185 dlg.SetRevisionRanges(revisionRanges);
186 dlg.SetPegRevision(m_LogRevision);
187 dlg.DoModal();
190 break;
191 case ID_MERGEREV:
193 // we need an URL to complete this command, so error out if we can't get an URL
194 if (pathURL.IsEmpty())
196 CString strMessage;
197 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
198 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
199 TRACE(_T("could not retrieve the URL of the folder!\n"));
200 break; //exit
203 CString path = m_path.GetWinPathString();
204 bool bGotSavePath = false;
205 if ((GetSelectedCount() == 1)&&(!m_path.IsDirectory()))
207 bGotSavePath = CAppUtils::FileOpenSave(path, NULL, IDS_LOG_MERGETO, IDS_COMMONFILEFILTER, true, GetSafeHwnd());
209 else
211 CBrowseFolder folderBrowser;
212 folderBrowser.SetInfo(CString(MAKEINTRESOURCE(IDS_LOG_MERGETO)));
213 bGotSavePath = (folderBrowser.Show(GetSafeHwnd(), path, path) == CBrowseFolder::OK);
215 if (bGotSavePath)
217 CGitProgressDlg dlg;
218 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
219 dlg.SetPathList(CTGitPathList(CTGitPath(path)));
220 dlg.SetUrl(pathURL);
221 dlg.SetSecondUrl(pathURL);
222 revisionRanges.AdjustForMerge(false);
223 dlg.SetRevisionRanges(revisionRanges);
224 dlg.SetPegRevision(m_LogRevision);
225 dlg.DoModal();
228 break;
229 case ID_REVERTTOREV:
231 // we need an URL to complete this command, so error out if we can't get an URL
232 if (pathURL.IsEmpty())
234 CString strMessage;
235 strMessage.Format(IDS_ERR_NOURLOFFILE, (LPCTSTR)(m_path.GetUIPathString()));
236 CMessageBox::Show(this->m_hWnd, strMessage, _T("TortoiseGit"), MB_ICONERROR);
237 TRACE(_T("could not retrieve the URL of the folder!\n"));
238 break; //exit
241 CString msg;
242 msg.Format(IDS_LOG_REVERTTOREV_CONFIRM, m_path.GetWinPath());
243 if (CMessageBox::Show(this->m_hWnd, msg, _T("TortoiseGit"), MB_YESNO | MB_ICONQUESTION) == IDYES)
245 CGitProgressDlg dlg;
246 dlg.SetCommand(CGitProgressDlg::GitProgress_Merge);
247 dlg.SetPathList(CTGitPathList(m_path));
248 dlg.SetUrl(pathURL);
249 dlg.SetSecondUrl(pathURL);
250 GitRevRangeArray revarray;
251 revarray.AddRevRange(GitRev::REV_HEAD, revSelected);
252 dlg.SetRevisionRanges(revarray);
253 dlg.SetPegRevision(m_LogRevision);
254 dlg.DoModal();
257 break;
259 case ID_BLAMECOMPARE:
261 //user clicked on the menu item "compare with working copy"
262 //now first get the revision which is selected
263 if (PromptShown())
265 GitDiff diff(this, this->m_hWnd, true);
266 diff.SetHEADPeg(m_LogRevision);
267 diff.ShowCompare(m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), false, true);
269 else
270 CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_BASE, m_path, revSelected, GitRev(), m_LogRevision, false, false, true);
272 break;
273 case ID_BLAMETWO:
275 //user clicked on the menu item "compare and blame revisions"
276 if (PromptShown())
278 GitDiff diff(this, this->m_hWnd, true);
279 diff.SetHEADPeg(m_LogRevision);
280 diff.ShowCompare(CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), false, true);
282 else
283 CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revSelected2, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);
285 break;
286 case ID_BLAMEWITHPREVIOUS:
288 //user clicked on the menu item "Compare and Blame with previous revision"
289 if (PromptShown())
291 GitDiff diff(this, this->m_hWnd, true);
292 diff.SetHEADPeg(m_LogRevision);
293 diff.ShowCompare(CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), false, true);
295 else
296 CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, false, false, true);
298 break;
300 case ID_OPENWITH:
301 bOpenWith = true;
302 case ID_OPEN:
304 CProgressDlg progDlg;
305 progDlg.SetTitle(IDS_APPNAME);
306 progDlg.SetAnimation(IDR_DOWNLOAD);
307 CString sInfoLine;
308 sInfoLine.Format(IDS_PROGRESSGETFILEREVISION, m_path.GetWinPath(), (LPCTSTR)revSelected.ToString());
309 progDlg.SetLine(1, sInfoLine, true);
310 SetAndClearProgressInfo(&progDlg);
311 progDlg.ShowModeless(m_hWnd);
312 CTGitPath tempfile = CTempFiles::Instance().GetTempFilePath(false, m_path, revSelected);
313 bool bSuccess = true;
314 if (!Cat(m_path, GitRev(GitRev::REV_HEAD), revSelected, tempfile))
316 bSuccess = false;
317 // try again, but with the selected revision as the peg revision
318 if (!Cat(m_path, revSelected, revSelected, tempfile))
320 progDlg.Stop();
321 SetAndClearProgressInfo((HWND)NULL);
322 CMessageBox::Show(this->m_hWnd, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
323 EnableOKButton();
324 break;
326 bSuccess = true;
328 if (bSuccess)
330 progDlg.Stop();
331 SetAndClearProgressInfo((HWND)NULL);
332 SetFileAttributes(tempfile.GetWinPath(), FILE_ATTRIBUTE_READONLY);
333 int ret = 0;
334 if (!bOpenWith)
335 ret = (int)ShellExecute(this->m_hWnd, NULL, tempfile.GetWinPath(), NULL, NULL, SW_SHOWNORMAL);
336 if ((ret <= HINSTANCE_ERROR)||bOpenWith)
338 CString cmd = _T("RUNDLL32 Shell32,OpenAs_RunDLL ");
339 cmd += tempfile.GetWinPathString() + _T(" ");
340 CAppUtils::LaunchApplication(cmd, NULL, false);
344 break;
345 case ID_BLAME:
347 CBlameDlg dlg;
348 dlg.EndRev = revSelected;
349 if (dlg.DoModal() == IDOK)
351 CBlame blame;
352 CString tempfile;
353 CString logfile;
354 tempfile = blame.BlameToTempFile(m_path, dlg.StartRev, dlg.EndRev, dlg.EndRev, logfile, _T(""), dlg.m_bIncludeMerge, TRUE, TRUE);
355 if (!tempfile.IsEmpty())
357 if (dlg.m_bTextView)
359 //open the default text editor for the result file
360 CAppUtils::StartTextViewer(tempfile);
362 else
364 CString sParams = _T("/path:\"") + m_path.GetGitPathString() + _T("\" ");
365 if(!CAppUtils::LaunchTortoiseBlame(tempfile, logfile, CPathUtils::GetFileNameFromPath(m_path.GetFileOrDirectoryName()),sParams))
367 break;
371 else
373 CMessageBox::Show(this->m_hWnd, blame.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR);
377 break;
378 case ID_UPDATE:
380 CString sCmd;
381 CString url = _T("tgit:")+pathURL;
382 sCmd.Format(_T("%s /command:update /path:\"%s\" /rev:%ld"),
383 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
384 (LPCTSTR)m_path.GetWinPath(), (LONG)revSelected);
385 CAppUtils::LaunchApplication(sCmd, NULL, false);
387 break;
388 case ID_FINDENTRY:
390 m_nSearchIndex = GetSelectionMark();
391 if (m_nSearchIndex < 0)
392 m_nSearchIndex = 0;
393 if (m_pFindDialog)
395 break;
397 else
399 m_pFindDialog = new CFindReplaceDialog();
400 m_pFindDialog->Create(TRUE, NULL, NULL, FR_HIDEUPDOWN | FR_HIDEWHOLEWORD, this);
403 break;
404 case ID_REPOBROWSE:
406 CString sCmd;
407 sCmd.Format(_T("%s /command:repobrowser /path:\"%s\" /rev:%s"),
408 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
409 (LPCTSTR)pathURL, (LPCTSTR)revSelected.ToString());
411 CAppUtils::LaunchApplication(sCmd, NULL, false);
413 break;
414 case ID_EDITLOG:
416 EditLogMessage(selIndex);
418 break;
419 case ID_EDITAUTHOR:
421 EditAuthor(selEntries);
423 break;
424 case ID_REVPROPS:
426 CEditPropertiesDlg dlg;
427 dlg.SetProjectProperties(&m_ProjectProperties);
428 CTGitPathList escapedlist;
429 dlg.SetPathList(CTGitPathList(CTGitPath(pathURL)));
430 dlg.SetRevision(revSelected);
431 dlg.RevProps(true);
432 dlg.DoModal();
434 break;
436 case ID_EXPORT:
438 CString sCmd;
439 sCmd.Format(_T("%s /command:export /path:\"%s\" /revision:%ld"),
440 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
441 (LPCTSTR)pathURL, (LONG)revSelected);
442 CAppUtils::LaunchApplication(sCmd, NULL, false);
444 break;
445 case ID_CHECKOUT:
447 CString sCmd;
448 CString url = _T("tgit:")+pathURL;
449 sCmd.Format(_T("%s /command:checkout /url:\"%s\" /revision:%ld"),
450 (LPCTSTR)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
451 (LPCTSTR)url, (LONG)revSelected);
452 CAppUtils::LaunchApplication(sCmd, NULL, false);
454 break;
455 case ID_VIEWREV:
457 CString url = m_ProjectProperties.sWebViewerRev;
458 url = GetAbsoluteUrlFromRelativeUrl(url);
459 url.Replace(_T("%REVISION%"), revSelected.ToString());
460 if (!url.IsEmpty())
461 ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);
463 break;
464 case ID_VIEWPATHREV:
466 CString relurl = pathURL;
467 CString sRoot = GetRepositoryRoot(CTGitPath(relurl));
468 relurl = relurl.Mid(sRoot.GetLength());
469 CString url = m_ProjectProperties.sWebViewerPathRev;
470 url = GetAbsoluteUrlFromRelativeUrl(url);
471 url.Replace(_T("%REVISION%"), revSelected.ToString());
472 url.Replace(_T("%PATH%"), relurl);
473 if (!url.IsEmpty())
474 ShellExecute(this->m_hWnd, _T("open"), url, NULL, NULL, SW_SHOWDEFAULT);
476 break;
477 #endif
479 } // switch (cmd)
482 STARTUPINFO startup;
483 PROCESS_INFORMATION process;
484 memset(&startup, 0, sizeof(startup));
485 startup.cb = sizeof(startup);
486 memset(&process, 0, sizeof(process));
487 CString tortoiseProcPath = CPathUtils::GetAppDirectory() + _T("TortoiseProc.exe");
489 if (CreateProcess(tortoiseProcPath, procCmd.GetBuffer(), NULL, NULL, FALSE, 0, 0, 0, &startup, &process))
491 CloseHandle(process.hThread);
492 CloseHandle(process.hProcess);