#include "PropDlg.h"\r
#include "SVNProgressDlg.h"\r
#include "ProgressDlg.h"\r
+#include "SysProgressDlg.h"\r
//#include "RepositoryBrowser.h"\r
//#include "CopyDlg.h"\r
//#include "StatGraphDlg.h"\r
\r
IMPLEMENT_DYNAMIC(CGitLogList, CHintListCtrl)\r
\r
+int CGitLogList::CherryPickFrom(CString from, CString to)\r
+{\r
+ CLogDataVector logs;\r
+ if(logs.ParserFromLog(NULL,-1,0,&from,&to))\r
+ return -1;\r
+\r
+ if(logs.size() == 0)\r
+ return 0;\r
+\r
+ CSysProgressDlg progress;\r
+ if (progress.IsValid())\r
+ {\r
+ progress.SetTitle(_T("Cherry Pick"));\r
+ progress.SetAnimation(IDR_MOVEANI);\r
+ progress.SetTime(true);\r
+ progress.ShowModeless(this);\r
+ }\r
+\r
+ for(int i=logs.size()-1;i>=0;i--)\r
+ {\r
+ if (progress.IsValid())\r
+ {\r
+ progress.FormatPathLine(1, _T("Pick up %s"), logs[i].m_CommitHash);\r
+ progress.FormatPathLine(2, _T("%s"), logs[i].m_Subject);\r
+ progress.SetProgress(logs.size()-i, logs.size());\r
+ }\r
+ if ((progress.IsValid())&&(progress.HasUserCancelled()))\r
+ {\r
+ //CMessageBox::Show(hwndExplorer, IDS_SVN_USERCANCELLED, IDS_APPNAME, MB_ICONINFORMATION);\r
+ throw std::exception(CUnicodeUtils::GetUTF8(_T("User canceled\r\n\r\n")));\r
+ return -1;\r
+ }\r
+ CString cmd,out;\r
+ cmd.Format(_T("git.exe cherry-pick %s"),logs[i].m_CommitHash);\r
+ out.Empty();\r
+ if(g_Git.Run(cmd,&out,CP_UTF8))\r
+ {\r
+ throw std::exception(CUnicodeUtils::GetUTF8(CString(_T("Cherry Pick Failure\r\n\r\n"))+out));\r
+ return -1;\r
+ }\r
+ }\r
+ \r
+ return 0;\r
+}\r
+\r
void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)\r
{ \r
POSITION pos = GetFirstSelectedItemPosition();\r
\r
theApp.DoWaitCursor(1);\r
bool bOpenWith = false;\r
- switch (cmd)\r
+ switch (cmd&0xFFFF)\r
{\r
case ID_GNUDIFF1:\r
{\r
{\r
CString head;\r
CString headhash;\r
- \r
- head.Format(_T("HEAD~%d"),LastSelect);\r
- CString hash=g_Git.GetHash(head);\r
- hash=hash.Left(40);\r
+ CString hashFirst,hashLast;\r
+\r
+ int headindex=GetHeadIndex();\r
+ if(headindex>=0) //incase show all branch, head is not the first commits. \r
+ {\r
+ head.Format(_T("HEAD~%d"),FirstSelect-headindex);\r
+ hashFirst=g_Git.GetHash(head);\r
+\r
+ head.Format(_T("HEAD~%d"),LastSelect-headindex);\r
+ hashLast=g_Git.GetHash(head);\r
+ }\r
+ \r
+ GitRev* pFirstEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
+ GitRev* pLastEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
+ if(pFirstEntry->m_CommitHash != hashFirst || pLastEntry->m_CommitHash != hashLast)\r
+ {\r
+ CMessageBox::Show(NULL,_T(\r
+ "Cannot combine commits now.\r\n\\r
+ Make sure you are viewing the log of your current branch and \\r
+ no filters are applied."),_T("TortoiseGit"),MB_OK);\r
+ break;\r
+ }\r
\r
headhash=g_Git.GetHash(CString(_T("HEAD")));\r
- headhash=headhash.Left(40); \r
\r
- GitRev* pFirstEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
- GitRev* pLastEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
-// if(pLastEntry->m_CommitHash != hash)\r
-// {\r
-// CMessageBox::Show(NULL,_T("Only combine top continuous commit"),_T("TortoiseGit"),MB_OK);\r
-// }\r
if(!g_Git.CheckCleanWorkTree())\r
{\r
CMessageBox::Show(NULL,_T("Combine needs a clean work tree"),_T("TortoiseGit"),MB_OK);\r
CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to first commit (first step) aborting...\r\n\r\n")+out));\r
}\r
- cmd.Format(_T("git.exe reset --mixed %s"),hash);\r
+ cmd.Format(_T("git.exe reset --mixed %s"),hashLast);\r
if(g_Git.Run(cmd,&out,CP_UTF8))\r
{\r
CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
//\r
//Later the progress dialog could be used to execute these steps.\r
\r
+ if(CherryPickFrom(pFirstEntry->m_CommitHash,headhash))\r
+ {\r
+ CString msg;\r
+ msg.Format(_T("Error while cherry pick commits on top of combined commits. Aborting.\r\n\r\n"));\r
+ throw std::exception(CUnicodeUtils::GetUTF8(msg));\r
+ }\r
+#if 0\r
CString currentBranch=g_Git.GetCurrentBranch();\r
cmd.Format(_T("git.exe rebase --onto \"%s\" %s %s"),\r
currentBranch,\r
cmd.Format(_T("git.exe reset --hard %s"),newHead);\r
if(g_Git.Run(cmd,&out,CP_UTF8))\r
throw std::exception(CUnicodeUtils::GetUTF8(_T("Could not reset to new head. Aborting...\r\n\r\n")+out));\r
+#endif\r
}\r
}\r
else\r
case ID_CHERRY_PICK:\r
if(!g_Git.CheckCleanWorkTree())\r
{\r
- CMessageBox::Show(NULL,_T("Cherry Pick Require Clean Working Tree"),_T("TortoiseGit"),MB_OK);\r
+ CMessageBox::Show(NULL,_T("Cherry Pick requires a clean working tree"),_T("TortoiseGit"),MB_OK);\r
\r
}else\r
{\r
dlg.m_CommitList.m_logEntries.push_back(*(GitRev*)m_arShownList[indexNext]);\r
dlg.m_CommitList.m_logEntries.at(dlg.m_CommitList.m_logEntries.size()-1).m_Action |= CTGitPath::LOGACTIONS_REBASE_PICK;\r
}\r
-\r
+ \r
if(dlg.DoModal() == IDOK)\r
{\r
Refresh();\r
case ID_REBASE_TO_VERSION:\r
if(!g_Git.CheckCleanWorkTree())\r
{\r
- CMessageBox::Show(NULL,_T("Rebase Require Clean Working Tree"),_T("TortoiseGit"),MB_OK);\r
+ CMessageBox::Show(NULL,_T("Rebase requires a clean working tree"),_T("TortoiseGit"),MB_OK);\r
\r
}else\r
{\r
\r
break;\r
\r
+ case ID_STASH_APPLY:\r
+ CAppUtils::StashApply(pSelLogEntry->m_Ref);\r
+ break;\r
+ \r
+ case ID_REFLOG_DEL:\r
+ { \r
+ CString str;\r
+ 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);\r
+ if(CMessageBox::Show(NULL,str,_T("TortoiseGit"),MB_YESNO|MB_ICONWARNING) == IDYES)\r
+ {\r
+ CString cmd,out;\r
+ cmd.Format(_T("git.exe reflog delete %s"),pSelLogEntry->m_Ref);\r
+ if(g_Git.Run(cmd,&out,CP_ACP))\r
+ {\r
+ CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
+ } \r
+ ::PostMessage(this->GetParent()->m_hWnd,MSG_REFLOG_CHANGED,0,0);\r
+ }\r
+ }\r
+ break;\r
+ case ID_CREATE_PATCH:\r
+ {\r
+ int select=this->GetSelectedCount();\r
+ CString cmd;\r
+ cmd = CPathUtils::GetAppDirectory()+_T("TortoiseProc.exe");\r
+ cmd += _T(" /command:formatpatch");\r
+\r
+ cmd += _T(" /path:")+g_Git.m_CurrentDir+_T(" ");\r
+\r
+ GitRev * r1 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(FirstSelect));\r
+ GitRev * r2 = NULL;\r
+ if(select == 1)\r
+ {\r
+ cmd += _T(" /startrev:")+r1->m_CommitHash;\r
+ }\r
+ else \r
+ {\r
+ r2 = reinterpret_cast<GitRev*>(m_arShownList.GetAt(LastSelect));\r
+ if( this->m_IsOldFirst )\r
+ { \r
+ cmd += _T(" /startrev:")+r1->m_CommitHash+_T("~1");\r
+ cmd += _T(" /endrev:")+r2->m_CommitHash;\r
+ \r
+ }else\r
+ { \r
+ cmd += _T(" /startrev:")+r2->m_CommitHash+_T("~1");\r
+ cmd += _T(" /endrev:")+r1->m_CommitHash; \r
+ } \r
+ \r
+ }\r
+\r
+ CAppUtils::LaunchApplication(cmd,IDS_ERR_PROC,false);\r
+ }\r
+ break;\r
+ case ID_DELETE:\r
+ {\r
+ int index = cmd>>16;\r
+ if( this->m_HashMap.find(pSelLogEntry->m_CommitHash) == m_HashMap.end() )\r
+ {\r
+ CMessageBox::Show(NULL,IDS_ERROR_NOREF,IDS_APPNAME,MB_OK|MB_ICONERROR);\r
+ return;\r
+ }\r
+ if( index >= m_HashMap[pSelLogEntry->m_CommitHash].size())\r
+ {\r
+ CMessageBox::Show(NULL,IDS_ERROR_INDEX,IDS_APPNAME,MB_OK|MB_ICONERROR);\r
+ return; \r
+ }\r
+ CString ref,msg;\r
+ ref=m_HashMap[pSelLogEntry->m_CommitHash][index];\r
+ \r
+ msg=CString(_T("<ct=0x0000FF>Delete</ct> <b>"))+ref;\r
+ msg+=_T("</b>\n\n Are you sure?");\r
+ if( CMessageBox::Show(NULL,msg,_T("TortoiseGit"),MB_YESNO) == IDYES )\r
+ {\r
+ CString shortname;\r
+ CString cmd;\r
+ if(this->GetShortName(ref,shortname,_T("refs/heads/")))\r
+ {\r
+ cmd.Format(_T("git.exe branch -D %s"),shortname);\r
+ }\r
+\r
+ if(this->GetShortName(ref,shortname,_T("refs/remotes/")))\r
+ {\r
+ cmd.Format(_T("git.exe branch -r -D %s"),shortname);\r
+ }\r
+\r
+ if(this->GetShortName(ref,shortname,_T("refs/tags/")))\r
+ {\r
+ cmd.Format(_T("git.exe tag -d %s"),shortname);\r
+ }\r
+\r
+ CString out;\r
+ if(g_Git.Run(cmd,&out,CP_UTF8))\r
+ {\r
+ CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);\r
+ }\r
+ this->ReloadHashMap();\r
+ CRect rect;\r
+ this->GetItemRect(FirstSelect,&rect,LVIR_BOUNDS);\r
+ this->InvalidateRect(rect);\r
+ }\r
+ }\r
+ break;\r
default:\r
//CMessageBox::Show(NULL,_T("Have not implemented"),_T("TortoiseGit"),MB_OK);\r
break;\r