1 // GitLogList.cpp : implementation file
4 Description: qgit revision list view
6 Author: Marco Costalba (C) 2005-2007
8 Copyright: See COPYING file that comes with this distribution
12 #include "TortoiseProc.h"
13 #include "GitLogList.h"
15 //#include "VssStyle.h"
21 #include "SVNProgressDlg.h"
22 #include "ProgressDlg.h"
23 #include "SysProgressDlg.h"
24 //#include "RepositoryBrowser.h"
25 //#include "CopyDlg.h"
26 //#include "StatGraphDlg.h"
28 #include "MessageBox.h"
31 #include "PathUtils.h"
32 #include "StringUtils.h"
33 #include "UnicodeUtils.h"
35 //#include "GitInfo.h"
36 //#include "GitDiff.h"
38 //#include "RevisionRangeDlg.h"
39 //#include "BrowseFolder.h"
40 //#include "BlameDlg.h"
42 //#include "GitHelpers.h"
43 #include "GitStatus.h"
44 //#include "LogDlgHelper.h"
45 //#include "CachedLogInfo.h"
46 //#include "RepositoryInfo.h"
47 //#include "EditPropertiesDlg.h"
48 #include "FileDiffDlg.h"
49 #include "CommitDlg.h"
50 #include "RebaseDlg.h"
53 IMPLEMENT_DYNAMIC(CGitLogList
, CHintListCtrl
)
55 int CGitLogList::CherryPickFrom(CString from
, CString to
)
57 CLogDataVector
logs(&m_LogCache
);
58 if(logs
.ParserFromLog(NULL
,-1,0,&from
,&to
))
64 CSysProgressDlg progress
;
65 if (progress
.IsValid())
67 progress
.SetTitle(_T("Cherry Pick"));
68 progress
.SetAnimation(IDR_MOVEANI
);
69 progress
.SetTime(true);
70 progress
.ShowModeless(this);
73 for(int i
=logs
.size()-1;i
>=0;i
--)
75 if (progress
.IsValid())
77 progress
.FormatPathLine(1, _T("Pick up %s"), logs
.GetGitRevAt(i
).m_CommitHash
.ToString());
78 progress
.FormatPathLine(2, _T("%s"), logs
.GetGitRevAt(i
).m_Subject
);
79 progress
.SetProgress(logs
.size()-i
, logs
.size());
81 if ((progress
.IsValid())&&(progress
.HasUserCancelled()))
83 //CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);
84 throw std::exception(CUnicodeUtils::GetUTF8(_T("User canceled\r\n\r\n")));
88 cmd
.Format(_T("git.exe cherry-pick %s"),logs
.GetGitRevAt(i
).m_CommitHash
.ToString());
90 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
92 throw std::exception(CUnicodeUtils::GetUTF8(CString(_T("Cherry Pick Failure\r\n\r\n"))+out
));
100 void CGitLogList::ContextMenuAction(int cmd
,int FirstSelect
, int LastSelect
)
102 POSITION pos
= GetFirstSelectedItemPosition();
103 int indexNext
= GetNextSelectedItem(pos
);
107 GitRev
* pSelLogEntry
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(indexNext
));
109 theApp
.DoWaitCursor(1);
110 bool bOpenWith
= false;
115 CTGitPathList pathlist
;
116 bool bSelectFilesForCommit
= !!DWORD(CRegStdWORD(_T("Software\\TortoiseGit\\SelectFilesForCommit"), TRUE
));
117 CAppUtils::Commit(CString(),true,CString(),
118 pathlist
,pathlist
,bSelectFilesForCommit
);
120 this->GetParent()->PostMessage(WM_COMMAND
,ID_LOGDLG_REFRESH
,0);
125 CString tempfile
=GetTempFile();
127 GitRev
* r1
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(FirstSelect
));
128 if(!r1
->m_CommitHash
.IsEmpty())
130 cmd
.Format(_T("git.exe diff-tree -r -p --stat %s"),r1
->m_CommitHash
.ToString());
132 cmd
.Format(_T("git.exe diff -r -p --stat"));
134 g_Git
.RunLogFile(cmd
,tempfile
);
135 CAppUtils::StartUnifiedDiffViewer(tempfile
,r1
->m_CommitHash
.ToString().Left(6)+_T(":")+r1
->m_Subject
);
141 CString tempfile
=GetTempFile();
143 GitRev
* r1
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(FirstSelect
));
144 GitRev
* r2
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(LastSelect
));
146 if( r1
->m_CommitHash
.IsEmpty())
148 cmd
.Format(_T("git.exe diff -r -p --stat %s"),r2
->m_CommitHash
.ToString());
149 }else if( r2
->m_CommitHash
.IsEmpty())
151 cmd
.Format(_T("git.exe diff -r -p --stat %s"),r1
->m_CommitHash
.ToString());
153 cmd
.Format(_T("git.exe diff-tree -r -p --stat %s %s"),r1
->m_CommitHash
.ToString(),r2
->m_CommitHash
.ToString());
155 g_Git
.RunLogFile(cmd
,tempfile
);
156 CAppUtils::StartUnifiedDiffViewer(tempfile
,r1
->m_CommitHash
.ToString().Left(6)+_T(":")+r2
->m_CommitHash
.ToString().Left(6));
163 GitRev
* r1
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(FirstSelect
));
164 GitRev
* r2
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(LastSelect
));
165 CGitDiff::DiffCommit(this->m_Path
, r1
,r2
);
173 GitRev
* r1
= &m_wcRev
;
174 GitRev
* r2
= pSelLogEntry
;
176 CGitDiff::DiffCommit(this->m_Path
, r1
,r2
);
178 //user clicked on the menu item "compare with working copy"
181 // GitDiff diff(this, m_hWnd, true);
182 // diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
183 // diff.SetHEADPeg(m_LogRevision);
184 // diff.ShowCompare(m_path, GitRev::REV_WC, m_path, revSelected);
187 // CAppUtils::StartShowCompare(m_hWnd, m_path, GitRev::REV_WC, m_path, revSelected, GitRev(), m_LogRevision, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
191 case ID_COMPAREWITHPREVIOUS
:
196 if(pSelLogEntry
->m_ParentHash
.size()>0)
197 //if(m_logEntries.m_HashMap[pSelLogEntry->m_ParentHash[0]]>=0)
199 CGitDiff::DiffCommit(this->m_Path
, pSelLogEntry
->m_CommitHash
.ToString(),pSelLogEntry
->m_ParentHash
[0].ToString());
203 CMessageBox::Show(NULL
,_T("No previous version"),_T("TortoiseGit"),MB_OK
);
207 // GitDiff diff(this, m_hWnd, true);
208 // diff.SetAlternativeTool(!!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
209 // diff.SetHEADPeg(m_LogRevision);
210 // diff.ShowCompare(CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected);
213 // CAppUtils::StartShowCompare(m_hWnd, CTGitPath(pathURL), revPrevious, CTGitPath(pathURL), revSelected, GitRev(), m_LogRevision, !!(GetAsyncKeyState(VK_SHIFT) & 0x8000));
216 case ID_COPYCLIPBOARD
:
218 CopySelectionToClipBoard();
223 CopySelectionToClipBoard(TRUE
);
227 CAppUtils::Export(&pSelLogEntry
->m_CommitHash
.ToString());
229 case ID_CREATE_BRANCH
:
230 CAppUtils::CreateBranchTag(FALSE
,&pSelLogEntry
->m_CommitHash
.ToString());
235 CAppUtils::CreateBranchTag(TRUE
,&pSelLogEntry
->m_CommitHash
.ToString());
240 CAppUtils::Switch(&pSelLogEntry
->m_CommitHash
.ToString());
245 CAppUtils::GitReset(&pSelLogEntry
->m_CommitHash
.ToString());
250 SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_PICK
);
253 SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_EDIT
);
255 case ID_REBASE_SQUASH
:
256 SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_SQUASH
);
259 SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_SKIP
);
261 case ID_COMBINE_COMMIT
:
265 CGitHash hashFirst
,hashLast
;
267 int headindex
=GetHeadIndex();
268 if(headindex
>=0) //incase show all branch, head is not the first commits.
270 head
.Format(_T("HEAD~%d"),FirstSelect
-headindex
);
271 hashFirst
=g_Git
.GetHash(head
);
273 head
.Format(_T("HEAD~%d"),LastSelect
-headindex
);
274 hashLast
=g_Git
.GetHash(head
);
277 GitRev
* pFirstEntry
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(FirstSelect
));
278 GitRev
* pLastEntry
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(LastSelect
));
279 if(pFirstEntry
->m_CommitHash
!= hashFirst
|| pLastEntry
->m_CommitHash
!= hashLast
)
281 CMessageBox::Show(NULL
,_T(
282 "Cannot combine commits now.\r\n\
283 Make sure you are viewing the log of your current branch and \
284 no filters are applied."),_T("TortoiseGit"),MB_OK
);
288 headhash
=g_Git
.GetHash(CString(_T("HEAD")));
290 if(!g_Git
.CheckCleanWorkTree())
292 CMessageBox::Show(NULL
,_T("Combine needs a clean work tree"),_T("TortoiseGit"),MB_OK
);
297 //Use throw to abort this process (reset back to original HEAD)
300 cmd
.Format(_T("git.exe reset --hard %s"),pFirstEntry
->m_CommitHash
.ToString());
301 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
303 CMessageBox::Show(NULL
,out
,_T("TortoiseGit"),MB_OK
);
304 throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to first commit (first step) aborting...\r\n\r\n")+out
));
306 cmd
.Format(_T("git.exe reset --mixed %s"),hashLast
.ToString());
307 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
309 CMessageBox::Show(NULL
,out
,_T("TortoiseGit"),MB_OK
);
310 throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to last commit (second step) aborting...\r\n\r\n")+out
));
313 for(int i
=FirstSelect
;i
<=LastSelect
;i
++)
315 GitRev
* pRev
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(i
));
316 dlg
.m_sLogMessage
+=pRev
->m_Subject
+_T("\n")+pRev
->m_Body
;
317 dlg
.m_sLogMessage
+=_T("\n");
319 dlg
.m_bWholeProject
=true;
320 dlg
.m_bSelectFilesForCommit
= true;
321 dlg
.m_bCommitAmend
=true;
322 dlg
.m_AmendStr
=dlg
.m_sLogMessage
;
325 if (dlg
.DoModal() == IDOK
)
327 if(pFirstEntry
->m_CommitHash
!=headhash
)
329 //Commitrange firstEntry..headhash (from top of combine to original head) needs to be 'cherry-picked'
330 //on top of new commit.
331 //Use the rebase --onto command for it.
333 //All this can be done in one step using the following command:
334 //cmd.Format(_T("git.exe format-patch --stdout --binary --full-index -k %s..%s | git am -k -3"),
335 // pFirstEntry->m_CommitHash,
337 //But I am not sure if a '|' is going to work in a CreateProcess() call.
339 //Later the progress dialog could be used to execute these steps.
341 if(CherryPickFrom(pFirstEntry
->m_CommitHash
.ToString(),headhash
))
344 msg
.Format(_T("Error while cherry pick commits on top of combined commits. Aborting.\r\n\r\n"));
345 throw std::exception(CUnicodeUtils::GetUTF8(msg
));
348 CString currentBranch
=g_Git
.GetCurrentBranch();
349 cmd
.Format(_T("git.exe rebase --onto \"%s\" %s %s"),
351 pFirstEntry
->m_CommitHash
,
353 if(g_Git
.Run(cmd
,&out
,CP_UTF8
)!=0)
356 msg
.Format(_T("Error while rebasing commits on top of combined commits. Aborting.\r\n\r\n%s"),out
);
357 // CMessageBox::Show(NULL,msg,_T("TortoiseGit"),MB_OK);
358 g_Git
.Run(_T("git.exe rebase --abort"),&out
,CP_UTF8
);
359 throw std::exception(CUnicodeUtils::GetUTF8(msg
));
362 //HEAD is now on <no branch>.
363 //The following steps are to get HEAD back on the original branch and reset the branch to the new HEAD
364 //To avoid 2 working copy changes, we could use git branch -f <original branch> <hash new head>
365 //And then git checkout <original branch>
366 //But I don't know if 'git branch -f' removes tracking options. So for now, do a checkout and a reset.
369 CString newHead
=g_Git
.GetHash(CString(_T("HEAD")));
371 //Checkout working branch
372 cmd
.Format(_T("git.exe checkout -f \"%s\""),currentBranch
);
373 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
374 throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not checkout original branch. Aborting...\r\n\r\n")+out
));
377 cmd
.Format(_T("git.exe reset --hard %s"),newHead
);
378 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
379 throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to new head. Aborting...\r\n\r\n")+out
));
384 throw std::exception("User aborted the combine process");
386 catch(std::exception
& e
)
388 CMessageBox::Show(NULL
,CUnicodeUtils::GetUnicode(CStringA(e
.what())),_T("TortoiseGit: Combine error"),MB_OK
|MB_ICONERROR
);
389 cmd
.Format(_T("git.exe reset --hard %s"),headhash
.ToString());
391 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
393 CMessageBox::Show(NULL
,_T("Could not reset to original HEAD\r\n\r\n")+out
,_T("TortoiseGit"),MB_OK
);
401 if(!g_Git
.CheckCleanWorkTree())
403 CMessageBox::Show(NULL
,_T("Cherry Pick requires a clean working tree"),_T("TortoiseGit"),MB_OK
);
408 dlg
.m_IsCherryPick
= TRUE
;
409 dlg
.m_Upstream
= this->m_CurrentBranch
;
410 POSITION pos
= GetFirstSelectedItemPosition();
413 int indexNext
= GetNextSelectedItem(pos
);
414 dlg
.m_CommitList
.m_logEntries
.push_back( ((GitRev
*)m_arShownList
[indexNext
])->m_CommitHash
);
415 dlg
.m_CommitList
.m_LogCache
.m_HashMap
[((GitRev
*)m_arShownList
[indexNext
])->m_CommitHash
]=*(GitRev
*)m_arShownList
[indexNext
];
416 dlg
.m_CommitList
.m_logEntries
.GetGitRevAt(dlg
.m_CommitList
.m_logEntries
.size()-1).m_Action
|= CTGitPath::LOGACTIONS_REBASE_PICK
;
419 if(dlg
.DoModal() == IDOK
)
425 case ID_REBASE_TO_VERSION
:
426 if(!g_Git
.CheckCleanWorkTree())
428 CMessageBox::Show(NULL
,_T("Rebase requires a clean working tree"),_T("TortoiseGit"),MB_OK
);
433 dlg
.m_Upstream
= pSelLogEntry
->m_CommitHash
;
435 if(dlg
.DoModal() == IDOK
)
444 CAppUtils::StashApply(pSelLogEntry
->m_Ref
);
450 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
);
451 if(CMessageBox::Show(NULL
,str
,_T("TortoiseGit"),MB_YESNO
|MB_ICONWARNING
) == IDYES
)
454 cmd
.Format(_T("git.exe reflog delete %s"),pSelLogEntry
->m_Ref
);
455 if(g_Git
.Run(cmd
,&out
,CP_ACP
))
457 CMessageBox::Show(NULL
,out
,_T("TortoiseGit"),MB_OK
);
459 ::PostMessage(this->GetParent()->m_hWnd
,MSG_REFLOG_CHANGED
,0,0);
463 case ID_CREATE_PATCH
:
465 int select
=this->GetSelectedCount();
467 cmd
= CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe");
468 cmd
+= _T(" /command:formatpatch");
470 cmd
+= _T(" /path:")+g_Git
.m_CurrentDir
+_T(" ");
472 GitRev
* r1
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(FirstSelect
));
476 cmd
+= _T(" /startrev:")+r1
->m_CommitHash
.ToString();
480 r2
= reinterpret_cast<GitRev
*>(m_arShownList
.GetAt(LastSelect
));
481 if( this->m_IsOldFirst
)
483 cmd
+= _T(" /startrev:")+r1
->m_CommitHash
.ToString()+_T("~1");
484 cmd
+= _T(" /endrev:")+r2
->m_CommitHash
.ToString();
488 cmd
+= _T(" /startrev:")+r2
->m_CommitHash
.ToString()+_T("~1");
489 cmd
+= _T(" /endrev:")+r1
->m_CommitHash
.ToString();
494 CAppUtils::LaunchApplication(cmd
,IDS_ERR_PROC
,false);
500 if( this->m_HashMap
.find(pSelLogEntry
->m_CommitHash
) == m_HashMap
.end() )
502 CMessageBox::Show(NULL
,IDS_ERROR_NOREF
,IDS_APPNAME
,MB_OK
|MB_ICONERROR
);
505 if( index
>= m_HashMap
[pSelLogEntry
->m_CommitHash
].size())
507 CMessageBox::Show(NULL
,IDS_ERROR_INDEX
,IDS_APPNAME
,MB_OK
|MB_ICONERROR
);
511 ref
=m_HashMap
[pSelLogEntry
->m_CommitHash
][index
];
513 msg
=CString(_T("<ct=0x0000FF>Delete</ct> <b>"))+ref
;
514 msg
+=_T("</b>\n\n Are you sure?");
515 if( CMessageBox::Show(NULL
,msg
,_T("TortoiseGit"),MB_YESNO
) == IDYES
)
519 if(this->GetShortName(ref
,shortname
,_T("refs/heads/")))
521 cmd
.Format(_T("git.exe branch -D %s"),shortname
);
524 if(this->GetShortName(ref
,shortname
,_T("refs/remotes/")))
526 cmd
.Format(_T("git.exe branch -r -D %s"),shortname
);
529 if(this->GetShortName(ref
,shortname
,_T("refs/tags/")))
531 cmd
.Format(_T("git.exe tag -d %s"),shortname
);
534 if(this->GetShortName(ref
,shortname
,_T("refs/stash")))
536 if(CMessageBox::Show(NULL
,_T("<ct=0x0000FF>Are you sure remove <b>ALL</b> stash?</ct>"),
537 _T("TortoiseGit"),MB_YESNO
)==IDYES
)
538 cmd
.Format(_T("git.exe stash clear"));
544 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
546 CMessageBox::Show(NULL
,out
,_T("TortoiseGit"),MB_OK
);
548 this->ReloadHashMap();
550 this->GetItemRect(FirstSelect
,&rect
,LVIR_BOUNDS
);
551 this->InvalidateRect(rect
);
558 m_nSearchIndex
= GetSelectionMark();
559 if (m_nSearchIndex
< 0)
567 m_pFindDialog
= new CFindReplaceDialog();
568 m_pFindDialog
->Create(TRUE
, NULL
, NULL
, FR_HIDEUPDOWN
| FR_HIDEWHOLEWORD
, this);
574 // we need an URL to complete this command, so error out if we can't get an URL
575 if(CAppUtils::Merge(&pSelLogEntry
->m_CommitHash
.ToString()))
583 if(!g_Git
.CheckCleanWorkTree())
585 CMessageBox::Show(NULL
,_T("Revert requires a clean working tree"),_T("TortoiseGit"),MB_OK
);
590 cmd
.Format(_T("git.exe revert --no-edit --no-commit %s"), pSelLogEntry
->m_CommitHash
.ToString());
591 if(g_Git
.Run(cmd
, &output
, CP_ACP
))
594 str
=_T("Revert fail\n");
596 str
+= _T("\n")+output
;
597 CMessageBox::Show(NULL
,str
, _T("TortoiseGit"),MB_OK
|MB_ICONERROR
);
607 //CMessageBox::Show(NULL,_T("Have not implemented"),_T("TortoiseGit"),MB_OK);
611 case ID_BLAMECOMPARE
:
613 //user clicked on the menu item "compare with working copy"
614 //now first get the revision which is selected
617 GitDiff
diff(this, this->m_hWnd
, true);
618 diff
.SetHEADPeg(m_LogRevision
);
619 diff
.ShowCompare(m_path
, GitRev::REV_BASE
, m_path
, revSelected
, GitRev(), false, true);
622 CAppUtils::StartShowCompare(m_hWnd
, m_path
, GitRev::REV_BASE
, m_path
, revSelected
, GitRev(), m_LogRevision
, false, false, true);
627 //user clicked on the menu item "compare and blame revisions"
630 GitDiff
diff(this, this->m_hWnd
, true);
631 diff
.SetHEADPeg(m_LogRevision
);
632 diff
.ShowCompare(CTGitPath(pathURL
), revSelected2
, CTGitPath(pathURL
), revSelected
, GitRev(), false, true);
635 CAppUtils::StartShowCompare(m_hWnd
, CTGitPath(pathURL
), revSelected2
, CTGitPath(pathURL
), revSelected
, GitRev(), m_LogRevision
, false, false, true);
638 case ID_BLAMEWITHPREVIOUS
:
640 //user clicked on the menu item "Compare and Blame with previous revision"
643 GitDiff
diff(this, this->m_hWnd
, true);
644 diff
.SetHEADPeg(m_LogRevision
);
645 diff
.ShowCompare(CTGitPath(pathURL
), revPrevious
, CTGitPath(pathURL
), revSelected
, GitRev(), false, true);
648 CAppUtils::StartShowCompare(m_hWnd
, CTGitPath(pathURL
), revPrevious
, CTGitPath(pathURL
), revSelected
, GitRev(), m_LogRevision
, false, false, true);
656 CProgressDlg progDlg
;
657 progDlg
.SetTitle(IDS_APPNAME
);
658 progDlg
.SetAnimation(IDR_DOWNLOAD
);
660 sInfoLine
.Format(IDS_PROGRESSGETFILEREVISION
, m_path
.GetWinPath(), (LPCTSTR
)revSelected
.ToString());
661 progDlg
.SetLine(1, sInfoLine
, true);
662 SetAndClearProgressInfo(&progDlg
);
663 progDlg
.ShowModeless(m_hWnd
);
664 CTGitPath tempfile
= CTempFiles::Instance().GetTempFilePath(false, m_path
, revSelected
);
665 bool bSuccess
= true;
666 if (!Cat(m_path
, GitRev(GitRev::REV_HEAD
), revSelected
, tempfile
))
669 // try again, but with the selected revision as the peg revision
670 if (!Cat(m_path
, revSelected
, revSelected
, tempfile
))
673 SetAndClearProgressInfo((HWND
)NULL
);
674 CMessageBox::Show(this->m_hWnd
, GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR
);
683 SetAndClearProgressInfo((HWND
)NULL
);
684 SetFileAttributes(tempfile
.GetWinPath(), FILE_ATTRIBUTE_READONLY
);
687 ret
= (int)ShellExecute(this->m_hWnd
, NULL
, tempfile
.GetWinPath(), NULL
, NULL
, SW_SHOWNORMAL
);
688 if ((ret
<= HINSTANCE_ERROR
)||bOpenWith
)
690 CString cmd
= _T("RUNDLL32 Shell32,OpenAs_RunDLL ");
691 cmd
+= tempfile
.GetWinPathString() + _T(" ");
692 CAppUtils::LaunchApplication(cmd
, NULL
, false);
700 dlg
.EndRev
= revSelected
;
701 if (dlg
.DoModal() == IDOK
)
706 tempfile
= blame
.BlameToTempFile(m_path
, dlg
.StartRev
, dlg
.EndRev
, dlg
.EndRev
, logfile
, _T(""), dlg
.m_bIncludeMerge
, TRUE
, TRUE
);
707 if (!tempfile
.IsEmpty())
711 //open the default text editor for the result file
712 CAppUtils::StartTextViewer(tempfile
);
716 CString sParams
= _T("/path:\"") + m_path
.GetGitPathString() + _T("\" ");
717 if(!CAppUtils::LaunchTortoiseBlame(tempfile
, logfile
, CPathUtils::GetFileNameFromPath(m_path
.GetFileOrDirectoryName()),sParams
))
725 CMessageBox::Show(this->m_hWnd
, blame
.GetLastErrorMessage(), _T("TortoiseGit"), MB_ICONERROR
);
733 CString url
= _T("tgit:")+pathURL
;
734 sCmd
.Format(_T("%s /command:update /path:\"%s\" /rev:%ld"),
735 (LPCTSTR
)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
736 (LPCTSTR
)m_path
.GetWinPath(), (LONG
)revSelected
);
737 CAppUtils::LaunchApplication(sCmd
, NULL
, false);
744 sCmd
.Format(_T("%s /command:repobrowser /path:\"%s\" /rev:%s"),
745 (LPCTSTR
)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
746 (LPCTSTR
)pathURL
, (LPCTSTR
)revSelected
.ToString());
748 CAppUtils::LaunchApplication(sCmd
, NULL
, false);
753 EditLogMessage(selIndex
);
758 EditAuthor(selEntries
);
763 CEditPropertiesDlg dlg
;
764 dlg
.SetProjectProperties(&m_ProjectProperties
);
765 CTGitPathList escapedlist
;
766 dlg
.SetPathList(CTGitPathList(CTGitPath(pathURL
)));
767 dlg
.SetRevision(revSelected
);
776 sCmd
.Format(_T("%s /command:export /path:\"%s\" /revision:%ld"),
777 (LPCTSTR
)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
778 (LPCTSTR
)pathURL
, (LONG
)revSelected
);
779 CAppUtils::LaunchApplication(sCmd
, NULL
, false);
785 CString url
= _T("tgit:")+pathURL
;
786 sCmd
.Format(_T("%s /command:checkout /url:\"%s\" /revision:%ld"),
787 (LPCTSTR
)(CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe")),
788 (LPCTSTR
)url
, (LONG
)revSelected
);
789 CAppUtils::LaunchApplication(sCmd
, NULL
, false);
794 CString url
= m_ProjectProperties
.sWebViewerRev
;
795 url
= GetAbsoluteUrlFromRelativeUrl(url
);
796 url
.Replace(_T("%REVISION%"), revSelected
.ToString());
798 ShellExecute(this->m_hWnd
, _T("open"), url
, NULL
, NULL
, SW_SHOWDEFAULT
);
803 CString relurl
= pathURL
;
804 CString sRoot
= GetRepositoryRoot(CTGitPath(relurl
));
805 relurl
= relurl
.Mid(sRoot
.GetLength());
806 CString url
= m_ProjectProperties
.sWebViewerPathRev
;
807 url
= GetAbsoluteUrlFromRelativeUrl(url
);
808 url
.Replace(_T("%REVISION%"), revSelected
.ToString());
809 url
.Replace(_T("%PATH%"), relurl
);
811 ShellExecute(this->m_hWnd
, _T("open"), url
, NULL
, NULL
, SW_SHOWDEFAULT
);
818 theApp
.DoWaitCursor(-1);
821 void CGitLogList::SetSelectedAction(int action
)
823 POSITION pos
= GetFirstSelectedItemPosition();
827 index
= GetNextSelectedItem(pos
);
828 ((GitRev
*)m_arShownList
[index
])->m_Action
= action
;
830 this->GetItemRect(index
,&rect
,LVIR_BOUNDS
);
831 this->InvalidateRect(rect
);