OSDN Git Service

RebaseDlg: Use Thread To Handle Rebase process.
authorFrank Li <lznuaa@gmail.com>
Mon, 16 Feb 2009 03:20:40 +0000 (11:20 +0800)
committerFrank Li <lznuaa@gmail.com>
Mon, 16 Feb 2009 03:20:40 +0000 (11:20 +0800)
Signed-off-by: Frank Li <lznuaa@gmail.com>
src/Git/Git.cpp
src/Git/Git.h
src/TortoiseProc/RebaseDlg.cpp
src/TortoiseProc/RebaseDlg.h
src/Utils/MiscUI/SciEdit.cpp

index d08d0b0..8b58778 100644 (file)
@@ -218,6 +218,9 @@ void CGit::StringAppend(CString *str,BYTE *p,int code,int length)
 {\r
      //USES_CONVERSION;\r
         //str->Append(A2W_CP((LPCSTR)p,code));\r
+       if(str == NULL)\r
+               return ;\r
+\r
        WCHAR * buf;\r
 \r
        int len ;\r
@@ -930,3 +933,27 @@ BOOL CGit::EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigne
 \r
        return TRUE;\r
 }\r
+\r
+BOOL CGit::CheckCleanWorkTree()\r
+{\r
+       CString out;\r
+       CString cmd;\r
+       cmd=_T("git.exe rev-parse --verify HEAD");\r
+\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               return FALSE;\r
+\r
+       cmd=_T("git.exe update-index --ignore-submodules --refresh");\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               return FALSE;\r
+\r
+       cmd=_T("git.exe diff-files --quiet --ignore-submodules");\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               return FALSE;\r
+\r
+       cmd=_T("git diff-index --cached --quiet HEAD --ignore-submodules");\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               return FALSE;\r
+\r
+       return TRUE;\r
+}
\ No newline at end of file
index f453a40..99c41a1 100644 (file)
@@ -47,6 +47,7 @@ public:
        CString GetUserName(void);\r
        CString GetUserEmail(void);\r
        CString GetCurrentBranch(void);\r
+       BOOL CheckCleanWorkTree();\r
 \r
        bool SetCurrentDir(CString path)\r
        {\r
index bb9bef6..d2a072a 100644 (file)
@@ -5,7 +5,8 @@
 #include "TortoiseProc.h"\r
 #include "RebaseDlg.h"\r
 #include "AppUtils.h"\r
-\r
+#include "MessageBox.h"\r
+#include "UnicodeUtils.h"\r
 // CRebaseDlg dialog\r
 \r
 IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)\r
@@ -18,6 +19,7 @@ CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/)
 {\r
        m_RebaseStage=CHOOSE_BRANCH;\r
        m_CurrentRebaseIndex=-1;\r
+       m_bThreadRunning =FALSE;\r
 }\r
 \r
 CRebaseDlg::~CRebaseDlg()\r
@@ -352,6 +354,7 @@ void CRebaseDlg::FetchLogList()
 \r
        CString hash=g_Git.GetHash(m_UpstreamCtrl.GetString());\r
        \r
+#if 0\r
        if(m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash.size() >=0 )\r
        {\r
                if(hash ==  m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash[0])\r
@@ -360,7 +363,8 @@ void CRebaseDlg::FetchLogList()
                        m_CommitList.ShowText(_T("Nothing Rebase"));\r
                }\r
        }\r
-       \r
+#endif\r
+\r
        m_tooltips.Pop();\r
        AddBranchToolTips(&this->m_BranchCtrl);\r
        AddBranchToolTips(&this->m_UpstreamCtrl);\r
@@ -406,58 +410,111 @@ BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg)
        m_tooltips.RelayEvent(pMsg);\r
        return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
 }\r
-\r
-void CRebaseDlg::OnBnClickedContinue()\r
+int CRebaseDlg::CheckRebaseCondition()\r
 {\r
-       GitRev *prevRev,*curRev;\r
-       prevRev=curRev=NULL;\r
-       CRect rect;\r
-       int prevIndex=m_CurrentRebaseIndex;\r
-       \r
-       UpdateCurrentStatus();\r
+       this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
 \r
-       if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize())\r
+       if( !g_Git.CheckCleanWorkTree()  )\r
        {\r
-               prevRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+               CMessageBox::Show(NULL,_T("Rebase Need Clean Working Tree"),_T("TortoiseGit"),MB_OK);\r
+               return -1;\r
        }\r
-       \r
-       if(m_CommitList.m_IsOldFirst)\r
-               m_CurrentRebaseIndex++;\r
-       else\r
-               m_CurrentRebaseIndex--;\r
+       //Todo Check $REBASE_ROOT\r
+       //Todo Check $DOTEST\r
 \r
-       if(m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex<m_CommitList.m_arShownList.GetSize())\r
-       {\r
-               curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+       CString cmd;\r
+       cmd=_T("git.exe var GIT_COMMITTER_IDENT");\r
+       if(g_Git.Run(cmd,NULL,CP_UTF8))\r
+               return -1;\r
 \r
-       }\r
+       //Todo call pre_rebase_hook\r
+}\r
+int CRebaseDlg::StartRebase()\r
+{\r
+       CString cmd,out;\r
+       //Todo call comment_for_reflog\r
+       cmd.Format(_T("git.exe checkout %s"),this->m_BranchCtrl.GetString());\r
+       this->AddLogString(cmd);\r
 \r
-       if(prevRev)\r
-       {\r
-               prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
-               prevRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_DONE;\r
-               m_CommitList.GetItemRect(prevIndex,&rect,LVIR_BOUNDS);\r
-               m_CommitList.InvalidateRect(rect);\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               return -1;\r
+\r
+       this->AddLogString(out);\r
 \r
+       cmd=_T("git.exe rev-parse --verify HEAD");\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(_T("No Head"));\r
+               return -1;\r
        }\r
+       //Todo \r
+       //git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
+       //              echo "detached HEAD" > "$DOTEST"/head-name\r
 \r
-       if(curRev)\r
+       cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
        {\r
-               curRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
-               m_CommitList.GetItemRect(m_CurrentRebaseIndex,&rect,LVIR_BOUNDS);\r
-               m_CommitList.InvalidateRect(rect);\r
+               AddLogString(_T("update ORIG_HEAD Fail"));\r
+               return -1;\r
        }\r
+       \r
+       cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));\r
 \r
+       cmd.Format(_T("git.exe checkout %s"),this->m_UpstreamCtrl.GetString());\r
+       this->AddLogString(cmd);\r
+\r
+       out.Empty();\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               return -1;\r
+       }\r
 \r
-       UpdateCurrentStatus();\r
+       this->AddLogString(_T("Start Rebase\r\n"));\r
+       return 0;\r
+}\r
+void CRebaseDlg::OnBnClickedContinue()\r
+{\r
+       if( m_RebaseStage == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE )\r
+       {\r
+               if(CheckRebaseCondition())\r
+                       return ;\r
+               m_RebaseStage = REBASE_START;\r
+       }\r
 \r
-       m_CommitList.EnsureVisible(m_CurrentRebaseIndex,FALSE);\r
+       InterlockedExchange(&m_bThreadRunning, TRUE);\r
+       SetControlEnable();\r
        \r
-       this->SetContinueButtonText();\r
-       this->SetControlEnable();\r
-       UpdateProgress();\r
+       if (AfxBeginThread(RebaseThreadEntry, this)==NULL)\r
+       {\r
+               InterlockedExchange(&m_bThreadRunning, FALSE);\r
+               CMessageBox::Show(NULL, _T("Create Rebase Thread Fail"), _T("TortoiseGit"), MB_OK | MB_ICONERROR);\r
+               SetControlEnable();\r
+       }\r
+}\r
+int CRebaseDlg::GoNext()\r
+{\r
+       if(m_CommitList.m_IsOldFirst)\r
+               m_CurrentRebaseIndex++;\r
+       else\r
+               m_CurrentRebaseIndex--; \r
+       return 0;\r
+\r
 }\r
+int CRebaseDlg::StateAction()\r
+{\r
+       switch(this->m_RebaseStage)\r
+       {\r
+       case CHOOSE_BRANCH:\r
+       case CHOOSE_COMMIT_PICK_MODE:\r
+               if(StartRebase())\r
+                       return -1;\r
+               m_RebaseStage = REBASE_START;\r
+               GoNext();\r
+               break;\r
+       }\r
 \r
+       return 0;       \r
+}\r
 void CRebaseDlg::SetContinueButtonText()\r
 {\r
        CString Text;\r
@@ -507,11 +564,23 @@ void CRebaseDlg::SetControlEnable()
                this->m_CommitList.m_IsEnableRebaseMenu=FALSE;\r
                break;\r
        }\r
+\r
+       if(m_bThreadRunning)\r
+       {\r
+               this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);\r
+               this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(FALSE);\r
+\r
+       }else\r
+       {\r
+               this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(TRUE);\r
+               this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(TRUE);\r
+       }\r
 }\r
 \r
 void CRebaseDlg::UpdateProgress()\r
 {\r
        int index;\r
+       CRect rect;\r
 \r
        if(m_CommitList.m_IsOldFirst)\r
                index = m_CurrentRebaseIndex+1;\r
@@ -528,6 +597,41 @@ void CRebaseDlg::UpdateProgress()
                m_CtrlStatusText.SetWindowText(text);\r
 \r
        }\r
+\r
+       GitRev *prevRev=NULL, *curRev=NULL;\r
+       int prevIndex;\r
+\r
+       if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize())\r
+       {\r
+               curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+       }\r
+       \r
+       if(m_CommitList.m_IsOldFirst)\r
+               prevIndex=m_CurrentRebaseIndex+1;\r
+       else\r
+               prevIndex=m_CurrentRebaseIndex-1;\r
+\r
+       if(prevIndex >= 0 && prevIndex<m_CommitList.m_arShownList.GetSize())\r
+       {\r
+               curRev=(GitRev*)m_CommitList.m_arShownList[prevIndex];\r
+       }\r
+\r
+       if(prevRev)\r
+       {\r
+               prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
+               prevRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_DONE;\r
+               m_CommitList.GetItemRect(prevIndex,&rect,LVIR_BOUNDS);\r
+               m_CommitList.InvalidateRect(rect);\r
+       }\r
+\r
+       if(curRev)\r
+       {\r
+               curRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
+               m_CommitList.GetItemRect(m_CurrentRebaseIndex,&rect,LVIR_BOUNDS);\r
+               m_CommitList.InvalidateRect(rect);\r
+       }\r
+       m_CommitList.EnsureVisible(m_CurrentRebaseIndex,FALSE);\r
+\r
 }\r
 \r
 void CRebaseDlg::UpdateCurrentStatus()\r
@@ -551,4 +655,96 @@ void CRebaseDlg::UpdateCurrentStatus()
        SetContinueButtonText();\r
        SetControlEnable();\r
        UpdateProgress();\r
+}\r
+\r
+void CRebaseDlg::AddLogString(CString str)\r
+{\r
+       this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, FALSE);\r
+       CStringA sTextA = m_wndOutputRebase.StringForControl(str);//CUnicodeUtils::GetUTF8(str);\r
+       this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)sTextA);\r
+       this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)"\n");\r
+       this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, TRUE);\r
+}\r
+\r
+int CRebaseDlg::DoRebase()\r
+{      \r
+       if(m_CurrentRebaseIndex <0)\r
+               return 0;\r
+       if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )\r
+               return 0;\r
+\r
+       this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+\r
+       GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+       int mode=pRev->m_Action & CTGitPath::LOGACTIONS_REBASE_MODE_MASK;\r
+       switch(mode)\r
+       {\r
+       case CTGitPath::LOGACTIONS_REBASE_PICK:\r
+               AddLogString(CString(_T("Pick "))+pRev->m_CommitHash);\r
+               pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
+               break;\r
+       case CTGitPath::LOGACTIONS_REBASE_SQUASH:\r
+               break;\r
+       case CTGitPath::LOGACTIONS_REBASE_EDIT:\r
+               break;\r
+       case CTGitPath::LOGACTIONS_REBASE_SKIP:\r
+               pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
+               return 0;\r
+               break;\r
+       default:\r
+               AddLogString(CString(_T("Unknow Action for "))+pRev->m_CommitHash);\r
+               break;\r
+       }\r
+       return 0;\r
+}\r
+\r
+BOOL CRebaseDlg::IsEnd()\r
+{\r
+       if(m_CommitList.m_IsOldFirst)\r
+               return m_CurrentRebaseIndex>= this->m_CommitList.GetItemCount();\r
+       else\r
+               return m_CurrentRebaseIndex<0;\r
+}\r
+\r
+int CRebaseDlg::RebaseThread()\r
+{\r
+       int ret=0;\r
+       while(1)\r
+       {\r
+               if( m_RebaseStage == REBASE_START )\r
+               {\r
+                       if( this->StartRebase() )\r
+                       {\r
+                               InterlockedExchange(&m_bThreadRunning, FALSE);\r
+                               ret = -1;\r
+                               break;\r
+                       }\r
+                       m_RebaseStage = REBASE_CONTINUE;\r
+               }\r
+\r
+               if( m_RebaseStage == REBASE_CONTINUE )\r
+               {\r
+                       this->GoNext(); \r
+                       if(IsEnd())\r
+                       {\r
+                               ret = 0;\r
+                               m_RebaseStage = REBASE_FINISH;\r
+                               break;\r
+                       }\r
+\r
+                       ret = DoRebase();\r
+\r
+                       if( ret )\r
+                       {       \r
+                               break;\r
+                       }\r
+               }\r
+               this->UpdateCurrentStatus();\r
+       }\r
+\r
+       InterlockedExchange(&m_bThreadRunning, FALSE);\r
+       this->UpdateCurrentStatus();\r
+       this->SetControlEnable();\r
+       this->SetContinueButtonText();\r
+       return ret;\r
 }
\ No newline at end of file
index 9cfb567..e44ec83 100644 (file)
@@ -61,6 +61,11 @@ protected:
        void SetControlEnable();\r
        void UpdateProgress();\r
        void UpdateCurrentStatus();\r
+       int  DoRebase();\r
+       volatile LONG           m_bThreadRunning;\r
+       int  RebaseThread();\r
+       static UINT RebaseThreadEntry(LPVOID pVoid){return ((CRebaseDlg *)pVoid)->RebaseThread();};\r
+       BOOL IsEnd();\r
 \r
 public:\r
    \r
@@ -94,7 +99,10 @@ public:
        REBASE_STAGE       m_RebaseStage;\r
 \r
        void AddBranchToolTips(CHistoryCombo *pBranch);\r
-       \r
-       int m_CurrentRebaseIndex;\r
-\r
+       void AddLogString(CString str);\r
+       int      StartRebase();\r
+       int  CheckRebaseCondition();\r
+       int  m_CurrentRebaseIndex;\r
+       int  StateAction();\r
+       int  GoNext();\r
 };\r
index dce2b6a..4df7d50 100644 (file)
@@ -289,7 +289,7 @@ CStringA CSciEdit::StringForControl(const CString& text)
 {\r
        CStringA sTextA;\r
 #ifdef UNICODE\r
-       int codepage = Call(SCI_GETCODEPAGE);\r
+       int codepage = SendMessage(SCI_GETCODEPAGE);\r
        int reslen = WideCharToMultiByte(codepage, 0, text, text.GetLength(), 0, 0, 0, 0);\r
        WideCharToMultiByte(codepage, 0, text, text.GetLength(), sTextA.GetBuffer(reslen), reslen, 0, 0);\r
        sTextA.ReleaseBuffer(reslen);\r