OSDN Git Service

Fixed issue #139: "Format patch" with a range of revisions doesn't export the first...
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / GitLogListAction.cpp
index a05fe37..7bf709b 100644 (file)
@@ -20,6 +20,7 @@
 #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
@@ -61,7 +107,7 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
 \r
        theApp.DoWaitCursor(1);\r
        bool bOpenWith = false;\r
-       switch (cmd)\r
+       switch (cmd&0xFFFF)\r
                {\r
                        case ID_GNUDIFF1:\r
                        {\r
@@ -194,20 +240,31 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
                {\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
@@ -224,7 +281,7 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
                                        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
@@ -259,6 +316,13 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
                                                //\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
@@ -291,6 +355,7 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
                                                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
@@ -313,7 +378,7 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
                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
@@ -327,7 +392,7 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
                                        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
@@ -337,7 +402,7 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
                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
@@ -352,6 +417,109 @@ void CGitLogList::ContextMenuAction(int cmd,int FirstSelect, int LastSelect)
 \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