OSDN Git Service

Fixed issue #187: Allow start new rebase after finish rebase
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / RebaseDlg.cpp
index f717127..0e6d8eb 100644 (file)
@@ -4,8 +4,11 @@
 #include "stdafx.h"\r
 #include "TortoiseProc.h"\r
 #include "RebaseDlg.h"\r
-\r
-\r
+#include "AppUtils.h"\r
+#include "MessageBox.h"\r
+#include "UnicodeUtils.h"\r
+#include "BrowseRefsDlg.h"\r
+#include "ProgressDlg.h"\r
 // CRebaseDlg dialog\r
 \r
 IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)\r
@@ -17,6 +20,11 @@ CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/)
     , m_bEditAll(FALSE)\r
 {\r
        m_RebaseStage=CHOOSE_BRANCH;\r
+       m_CurrentRebaseIndex=-1;\r
+       m_bThreadRunning =FALSE;\r
+       this->m_IsCherryPick = FALSE;\r
+       m_bForce=FALSE;\r
+       m_IsFastForward=FALSE;\r
 }\r
 \r
 CRebaseDlg::~CRebaseDlg()\r
@@ -35,7 +43,8 @@ void CRebaseDlg::DoDataExchange(CDataExchange* pDX)
        DDX_Control(pDX,IDC_COMMIT_LIST,m_CommitList);\r
        DDX_Control(pDX,IDC_REBASE_COMBOXEX_BRANCH, this->m_BranchCtrl);\r
        DDX_Control(pDX,IDC_REBASE_COMBOXEX_UPSTREAM,   this->m_UpstreamCtrl);\r
-\r
+       DDX_Check(pDX, IDC_REBASE_CHECK_FORCE,m_bForce);\r
+       DDX_Control(pDX,IDC_REBASE_POST_BUTTON,m_PostButton);\r
 }\r
 \r
 \r
@@ -44,7 +53,16 @@ BEGIN_MESSAGE_MAP(CRebaseDlg, CResizableStandAloneDialog)
     ON_BN_CLICKED(IDC_SQUASH_ALL, &CRebaseDlg::OnBnClickedSquashAll)\r
     ON_BN_CLICKED(IDC_EDIT_ALL, &CRebaseDlg::OnBnClickedEditAll)\r
     ON_BN_CLICKED(IDC_REBASE_SPLIT, &CRebaseDlg::OnBnClickedRebaseSplit)\r
+       ON_BN_CLICKED(IDC_REBASE_CONTINUE,OnBnClickedContinue)\r
+       ON_BN_CLICKED(IDC_REBASE_ABORT,  OnBnClickedAbort)\r
        ON_WM_SIZE()\r
+       ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH,   &CRebaseDlg::OnCbnSelchangeBranch)\r
+       ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream)\r
+       ON_MESSAGE(MSG_REBASE_UPDATE_UI, OnRebaseUpdateUI)\r
+       ON_BN_CLICKED(IDC_BUTTON_BROWSE, &CRebaseDlg::OnBnClickedButtonBrowse)\r
+       ON_BN_CLICKED(IDC_REBASE_CHECK_FORCE, &CRebaseDlg::OnBnClickedRebaseCheckForce)\r
+       ON_STN_CLICKED(IDC_STATUS_STATIC, &CRebaseDlg::OnStnClickedStatusStatic)\r
+       ON_BN_CLICKED(IDC_REBASE_POST_BUTTON, &CRebaseDlg::OnBnClickedRebasePostButton)\r
 END_MESSAGE_MAP()\r
 \r
 void CRebaseDlg::AddRebaseAnchor()\r
@@ -63,7 +81,11 @@ void CRebaseDlg::AddRebaseAnchor()
        AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT);\r
        AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT);\r
        AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT);\r
+       AddAnchor(IDHELP, BOTTOM_RIGHT);\r
+       AddAnchor(IDC_REBASE_CHECK_FORCE,TOP_RIGHT);\r
+       AddAnchor(IDC_REBASE_POST_BUTTON,BOTTOM_LEFT);\r
        \r
+       this->AddOthersToAnchor();\r
 }\r
 \r
 BOOL CRebaseDlg::OnInitDialog()\r
@@ -78,13 +100,8 @@ BOOL CRebaseDlg::OnInitDialog()
 \r
        CWnd *pwnd=this->GetDlgItem(IDC_REBASE_DUMY_TAB);\r
        pwnd->GetWindowRect(&rectDummy);\r
+       this->ScreenToClient(rectDummy);\r
 \r
-       rectDummy.top-=20;\r
-       rectDummy.bottom-=20;\r
-\r
-       rectDummy.left-=5;\r
-       rectDummy.right-=5;\r
-       \r
        if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_REBASE_TAB))\r
        {\r
                TRACE0("Failed to create output tab window\n");\r
@@ -93,7 +110,7 @@ BOOL CRebaseDlg::OnInitDialog()
        m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);\r
        // Create output panes:\r
        //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;\r
-       const DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;\r
+       DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;\r
 \r
        if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) )\r
        {\r
@@ -106,11 +123,30 @@ BOOL CRebaseDlg::OnInitDialog()
                TRACE0("Failed to create log message control");\r
                return FALSE;\r
        }\r
+       m_LogMessageCtrl.Init(0);\r
+\r
+       dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;\r
+\r
+       if (!m_wndOutputRebase.Create(_T("Scintilla"),_T("source"),0,rectDummy, &m_ctrlTabCtrl, 0,0) )\r
+       {\r
+               TRACE0("Failed to create output windows\n");\r
+               return -1;      // fail to create\r
+       }\r
+       m_wndOutputRebase.Init(0);\r
+       m_wndOutputRebase.Call(SCI_SETREADONLY, TRUE);\r
+       \r
+       m_tooltips.Create(this);\r
+       \r
+       m_tooltips.AddTool(IDC_REBASE_CHECK_FORCE,IDS_REBASE_FORCE_TT);\r
+       m_tooltips.AddTool(IDC_REBASE_ABORT,IDS_REBASE_ABORT_TT);\r
+       \r
 \r
-       m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS , _T("RebaseDlg"));\r
 \r
-       m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Modified File"));\r
-       m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Log Message"),1);\r
+       m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS |SVNSLC_COLADD|SVNSLC_COLDEL , _T("RebaseDlg"),(SVNSLC_POPALL ^ SVNSLC_POPCOMMIT),false);\r
+\r
+       m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Conflict File"));\r
+       m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Commit Message"),1);\r
+       m_ctrlTabCtrl.AddTab(&m_wndOutputRebase,_T("Log"),2);\r
        AddRebaseAnchor();\r
 \r
 \r
@@ -146,6 +182,51 @@ BOOL CRebaseDlg::OnInitDialog()
                this->m_UpstreamCtrl.EnableWindow(FALSE);\r
        }\r
 \r
+       m_CommitList.m_IsIDReplaceAction = TRUE;\r
+//     m_CommitList.m_IsOldFirst = TRUE;\r
+       m_CommitList.m_IsRebaseReplaceGraph = TRUE;\r
+\r
+       m_CommitList.InsertGitColumn();\r
+\r
+       this->SetControlEnable();\r
+\r
+       if(!this->m_PreCmd.IsEmpty())\r
+       {\r
+               CProgressDlg progress;\r
+               progress.m_GitCmd=m_PreCmd;\r
+               progress.m_bAutoCloseOnSuccess=true;\r
+               progress.DoModal();\r
+       }\r
+\r
+       if(m_IsCherryPick)\r
+       {\r
+               this->m_BranchCtrl.SetCurSel(-1);\r
+               this->m_BranchCtrl.EnableWindow(FALSE);\r
+               this->m_UpstreamCtrl.EnableWindow(FALSE);\r
+               this->SetWindowText(_T("Cherry Pick"));\r
+               this->m_CommitList.StartFilter();\r
+\r
+       }else\r
+       {\r
+               SetContinueButtonText();\r
+               m_CommitList.DeleteAllItems();\r
+               FetchLogList();\r
+       }\r
+\r
+       m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_CHERRY_PICK)|\r
+                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_SWITCHTOREV)|\r
+                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_RESET)|\r
+                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTREV)|\r
+                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_TO_VERSION)|\r
+                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTTOREV)|\r
+                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_COMBINE_COMMIT));\r
+\r
+       if(m_CommitList.m_IsOldFirst)\r
+               this->m_CurrentRebaseIndex = -1;\r
+       else\r
+               this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();\r
+\r
+\r
        return TRUE;\r
 }\r
 // CRebaseDlg message handlers\r
@@ -153,20 +234,54 @@ BOOL CRebaseDlg::OnInitDialog()
 void CRebaseDlg::OnBnClickedPickAll()\r
 {\r
     // TODO: Add your control notification handler code here\r
+       this->UpdateData();\r
+       if(this->m_bPickAll)\r
+               this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK);\r
+\r
+       this->m_bEditAll=FALSE;\r
+       this->m_bSquashAll=FALSE;\r
+       this->UpdateData(FALSE);\r
+       \r
 }\r
 \r
 void CRebaseDlg::OnBnClickedSquashAll()\r
 {\r
     // TODO: Add your control notification handler code here\r
+       this->UpdateData();\r
+       if(this->m_bSquashAll)\r
+               this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH);\r
+\r
+       this->m_bEditAll=FALSE;\r
+       this->m_bPickAll=FALSE;\r
+       this->UpdateData(FALSE);\r
+\r
 }\r
 \r
 void CRebaseDlg::OnBnClickedEditAll()\r
 {\r
     // TODO: Add your control notification handler code here\r
+       this->UpdateData();\r
+       if( this->m_bEditAll )\r
+               this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT);\r
+\r
+       this->m_bPickAll=FALSE;\r
+       this->m_bSquashAll=FALSE;\r
+       this->UpdateData(FALSE);\r
+\r
+}\r
+\r
+void CRebaseDlg::SetAllRebaseAction(int action)\r
+{\r
+       for(int i=0;i<this->m_CommitList.m_logEntries.size();i++)\r
+       {\r
+               m_CommitList.m_logEntries[i].m_Action=action;\r
+       }\r
+       m_CommitList.Invalidate();\r
 }\r
 \r
 void CRebaseDlg::OnBnClickedRebaseSplit()\r
 {\r
+       this->UpdateData();\r
     // TODO: Add your control notification handler code here\r
 }\r
 \r
@@ -197,6 +312,7 @@ void CRebaseDlg::DoSize(int delta)
        CSplitterControl::ChangePos(GetDlgItem(IDC_SQUASH_ALL),0,delta);\r
        CSplitterControl::ChangePos(GetDlgItem(IDC_PICK_ALL),0,delta);\r
        CSplitterControl::ChangePos(GetDlgItem(IDC_EDIT_ALL),0,delta);\r
+       CSplitterControl::ChangePos(GetDlgItem(IDC_REBASE_CHECK_FORCE),0,delta);\r
        \r
        this->AddRebaseAnchor();\r
        // adjust the minimum size of the dialog to prevent the resizing from\r
@@ -267,4 +383,1045 @@ void CRebaseDlg::LoadBranchInfo()
 \r
        m_BranchCtrl.SetCurSel(current);\r
 \r
-}
\ No newline at end of file
+       AddBranchToolTips(&m_BranchCtrl);\r
+       AddBranchToolTips(&m_UpstreamCtrl);\r
+\r
+       if(!m_Upstream.IsEmpty())\r
+       {\r
+               m_UpstreamCtrl.AddString(m_Upstream);\r
+               m_UpstreamCtrl.SetCurSel(m_UpstreamCtrl.GetCount()-1);\r
+       }\r
+       else\r
+       {\r
+               //Select pull-remote from current branch\r
+               CString currentBranch = g_Git.GetSymbolicRef();\r
+               CString configName;\r
+               configName.Format(L"branch.%s.remote", currentBranch);\r
+               CString pullRemote = g_Git.GetConfigValue(configName);\r
+\r
+               //Select pull-branch from current branch\r
+               configName.Format(L"branch.%s.merge", currentBranch);\r
+               CString pullBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));\r
+\r
+               CString defaultUpstream;\r
+               defaultUpstream.Format(L"remotes/%s/%s", pullRemote, pullBranch);\r
+               int found = m_UpstreamCtrl.FindStringExact(0, defaultUpstream);\r
+               if(found >= 0)\r
+                       m_UpstreamCtrl.SetCurSel(found);\r
+       }\r
+}\r
+\r
+void CRebaseDlg::OnCbnSelchangeBranch()\r
+{\r
+       FetchLogList();\r
+}\r
+\r
+void CRebaseDlg::OnCbnSelchangeUpstream()\r
+{\r
+       FetchLogList();\r
+}\r
+\r
+void CRebaseDlg::FetchLogList()\r
+{\r
+       CString base,hash;\r
+       CString cmd;\r
+       m_IsFastForward=FALSE;\r
+       cmd.Format(_T("git.exe merge-base %s %s"), m_UpstreamCtrl.GetString(),m_BranchCtrl.GetString());\r
+       if(g_Git.Run(cmd,&base,CP_ACP))\r
+       {\r
+               CMessageBox::Show(NULL,base,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
+               return;\r
+       }\r
+       base=base.Left(40);\r
+\r
+       hash=g_Git.GetHash(m_BranchCtrl.GetString());\r
+\r
+       if(hash == g_Git.GetHash(this->m_UpstreamCtrl.GetString()))\r
+       {\r
+               m_CommitList.Clear();\r
+               CString text,fmt;\r
+               fmt.LoadString(IDS_REBASE_EQUAL_FMT);\r
+               text.Format(fmt,m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString());\r
+\r
+               m_CommitList.ShowText(text);\r
+               this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(false);\r
+               return;\r
+       }\r
+\r
+       hash=hash.Left(40);\r
+       \r
+       if(hash == base )\r
+       {\r
+               //fast forword\r
+               this->m_IsFastForward=TRUE;\r
+\r
+               m_CommitList.Clear();\r
+               CString text,fmt;\r
+               fmt.LoadString(IDS_REBASE_FASTFORWARD_FMT);\r
+               text.Format(fmt,m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString(),\r
+                                               m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString());\r
+\r
+               m_CommitList.ShowText(text);\r
+               this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(true);\r
+               SetContinueButtonText();\r
+               \r
+               return ;\r
+       }\r
+\r
+       hash.Empty();\r
+\r
+       if(!this->m_bForce)\r
+       {\r
+               cmd.Format(_T("git.exe rev-parse %s"), m_UpstreamCtrl.GetString());\r
+               if( g_Git.Run(cmd,&hash,CP_ACP))\r
+               {\r
+                       CMessageBox::Show(NULL,base,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
+                       return;\r
+               }\r
+               hash=hash.Left(40);\r
+               \r
+               if( base == hash )\r
+               {\r
+                       m_CommitList.Clear();\r
+                       CString text,fmt;\r
+                       fmt.LoadString(IDS_REBASE_UPTODATE_FMT);\r
+                       text.Format(fmt,m_BranchCtrl.GetString());\r
+                       m_CommitList.ShowText(text);\r
+                       this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(m_CommitList.GetItemCount());\r
+                       SetContinueButtonText();\r
+                       return;\r
+               }\r
+       }\r
+\r
+       m_CommitList.Clear();\r
+       this->m_CommitList.FillGitLog(NULL,0,&m_UpstreamCtrl.GetString(),&m_BranchCtrl.GetString());\r
+       if( m_CommitList.GetItemCount() == 0 )\r
+               m_CommitList.ShowText(_T("Nothing to Rebase"));\r
+\r
+       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
+               {\r
+                       m_CommitList.Clear();\r
+                       m_CommitList.ShowText(_T("Nothing Rebase"));\r
+               }\r
+       }\r
+#endif\r
+\r
+       m_tooltips.Pop();\r
+       AddBranchToolTips(&this->m_BranchCtrl);\r
+       AddBranchToolTips(&this->m_UpstreamCtrl);\r
+       \r
+       for(int i=0;i<m_CommitList.m_logEntries.size();i++)\r
+       {\r
+               m_CommitList.m_logEntries[i].m_Action = CTGitPath::LOGACTIONS_REBASE_PICK;\r
+       }\r
+\r
+       m_CommitList.Invalidate();\r
+\r
+       if(m_CommitList.m_IsOldFirst)\r
+               this->m_CurrentRebaseIndex = -1;\r
+       else\r
+               this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();\r
+       \r
+       this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(m_CommitList.GetItemCount());\r
+       SetContinueButtonText();\r
+}\r
+\r
+void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)\r
+{\r
+       if(pBranch)\r
+       {\r
+               CString text=pBranch->GetString();\r
+               CString tooltip;\r
+               BYTE_VECTOR data;\r
+               g_Git.GetLog(data,text,NULL,1,0);\r
+               GitRev rev;\r
+               rev.ParserFromLog(data);\r
+               tooltip.Format(_T("CommitHash:%s\nCommit by: %s  %s\n <b>%s</b> \n %s"),\r
+                       rev.m_CommitHash,\r
+                       rev.m_AuthorName,\r
+                       CAppUtils::FormatDateAndTime(rev.m_AuthorDate,DATE_LONGDATE),\r
+                       rev.m_Subject,\r
+                       rev.m_Body);\r
+\r
+               pBranch->DisableTooltip();\r
+               this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip);\r
+       }\r
+}\r
+\r
+BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg)\r
+{\r
+       m_tooltips.RelayEvent(pMsg);\r
+       return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
+}\r
+int CRebaseDlg::CheckRebaseCondition()\r
+{\r
+       this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+\r
+       if( !g_Git.CheckCleanWorkTree()  )\r
+       {\r
+               CMessageBox::Show(NULL,_T("Rebase Need Clean Working Tree"),_T("TortoiseGit"),MB_OK);\r
+               return -1;\r
+       }\r
+       //Todo Check $REBASE_ROOT\r
+       //Todo Check $DOTEST\r
+\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
+       //Todo call pre_rebase_hook\r
+       return 0;\r
+}\r
+int CRebaseDlg::StartRebase()\r
+{\r
+       CString cmd,out;\r
+       m_FileListCtrl.m_bIsRevertTheirMy = !m_IsCherryPick;\r
+       if(!this->m_IsCherryPick)\r
+       {\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(g_Git.Run(cmd,&out,CP_UTF8))\r
+                       return -1;\r
+\r
+               this->AddLogString(out);\r
+       }\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 ||\r
+       //              echo "detached HEAD" > "$DOTEST"/head-name\r
+\r
+       cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(_T("update ORIG_HEAD Fail"));\r
+               return -1;\r
+       }\r
+       \r
+       if( !this->m_IsCherryPick )\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
+       \r
+       m_OrigUpstreamHash.Empty();\r
+       m_OrigUpstreamHash= g_Git.GetHash(this->m_UpstreamCtrl.GetString());\r
+       if(m_OrigUpstreamHash.IsEmpty())\r
+       {\r
+               this->AddLogString(m_OrigUpstreamHash);\r
+               return -1;\r
+       }\r
+\r
+       if( !this->m_IsCherryPick )\r
+       {\r
+               cmd.Format(_T("git.exe rev-parse %s"),this->m_BranchCtrl.GetString());\r
+               if(g_Git.Run(cmd,&this->m_OrigBranchHash,CP_UTF8))\r
+               {\r
+                       this->AddLogString(m_OrigBranchHash);\r
+                       return -1;\r
+               }\r
+               this->AddLogString(_T("Start Rebase\r\n"));\r
+\r
+       }else\r
+               this->AddLogString(_T("Start Cherry-pick\r\n"));\r
+       \r
+       return 0;\r
+}\r
+int  CRebaseDlg::VerifyNoConflict()\r
+{\r
+       CTGitPathList list;\r
+       if(g_Git.ListConflictFile(list))\r
+       {\r
+               AddLogString(_T("Get conflict files fail"));\r
+               return -1;\r
+       }\r
+       if( list.GetCount() != 0 )\r
+       {\r
+               CMessageBox::Show(NULL,_T("There are conflict file, you should mark it resolve"),_T("TortoiseGit"),MB_OK);\r
+               return -1;\r
+       }\r
+       return 0;\r
+\r
+}\r
+int CRebaseDlg::FinishRebase()\r
+{\r
+       if(this->m_IsCherryPick) //cherry pick mode no "branch", working at upstream branch\r
+               return 0;\r
+\r
+       CString cmd,out;\r
+       cmd.Format(_T("git.exe branch -f %s"),this->m_BranchCtrl.GetString());\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               return -1;\r
+       }\r
+       out.Empty();\r
+       cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash);\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               return -1;\r
+       }\r
+       out.Empty();\r
+       cmd.Format(_T("git.exe checkout -f %s"),this->m_BranchCtrl.GetString());\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               return -1;\r
+       }\r
+       return 0;\r
+}\r
+void CRebaseDlg::OnBnClickedContinue()\r
+{\r
+       if( m_RebaseStage == REBASE_DONE)\r
+       {\r
+               OnOK();\r
+               return;\r
+       }\r
+\r
+       if( this->m_IsFastForward )\r
+       {\r
+               CString cmd,out;\r
+               CString oldbranch = g_Git.GetCurrentBranch();\r
+               if( oldbranch != m_BranchCtrl.GetString() )\r
+               {\r
+                       cmd.Format(_T("git.exe checkout %s"),m_BranchCtrl.GetString());\r
+                       AddLogString(cmd);\r
+                       if( g_Git.Run(cmd,&out,CP_ACP) )\r
+                       {\r
+                               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+                               AddLogString(out);\r
+                               return;\r
+                       }\r
+               }\r
+               AddLogString(out);\r
+               out.Empty();\r
+               m_OrigBranchHash = g_Git.GetHash(m_BranchCtrl.GetString());\r
+               m_OrigUpstreamHash = g_Git.GetHash(this->m_UpstreamCtrl.GetString());\r
+                       \r
+               if(!g_Git.IsFastForward(this->m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString()))\r
+               {\r
+                       this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+                       AddLogString(_T("No fast forward\r\nMaybe repository changed"));\r
+                       return;\r
+               }\r
+               \r
+               cmd.Format(_T("git.exe reset --hard %s"),this->m_UpstreamCtrl.GetString());\r
+               this->AddLogString(CString(_T("Fast forward to "))+m_UpstreamCtrl.GetString());\r
+\r
+               AddLogString(cmd);\r
+               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+               if(g_Git.Run(cmd,&out,CP_ACP))\r
+               {\r
+                       AddLogString(_T("Fail"));\r
+                       AddLogString(out);\r
+                       return;\r
+               }\r
+               AddLogString(out);\r
+               AddLogString(_T("Done"));\r
+               m_RebaseStage = REBASE_DONE;\r
+               UpdateCurrentStatus();\r
+               return;\r
+\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
+\r
+       if( m_RebaseStage == REBASE_FINISH )\r
+       {\r
+               if(FinishRebase())\r
+                       return ;\r
+\r
+               OnOK();\r
+       }\r
+\r
+       if( m_RebaseStage == REBASE_SQUASH_CONFLICT)\r
+       {\r
+               if(VerifyNoConflict())\r
+                       return;\r
+               GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+               if(this->CheckNextCommitIsSquash())\r
+               {//next commit is not squash;\r
+                       m_RebaseStage = REBASE_SQUASH_EDIT;\r
+                       this->OnRebaseUpdateUI(0,0);\r
+                       this->UpdateCurrentStatus();\r
+                       return ;\r
+\r
+               }\r
+               m_RebaseStage=REBASE_CONTINUE;\r
+               curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;\r
+               this->UpdateCurrentStatus();\r
+\r
+       }\r
+\r
+       if( m_RebaseStage == REBASE_CONFLICT )\r
+       {\r
+               if(VerifyNoConflict())\r
+                       return;\r
+\r
+               GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+               \r
+               CString out =_T("");\r
+               CString cmd;\r
+               cmd.Format(_T("git.exe commit -C %s"), curRev->m_CommitHash);\r
+\r
+               if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               {\r
+                       if(!g_Git.CheckCleanWorkTree())\r
+                       {\r
+                               CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
+                               return;\r
+                       }\r
+               }\r
+\r
+               AddLogString(out);\r
+               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+               if( curRev->m_Action & CTGitPath::LOGACTIONS_REBASE_EDIT)\r
+               {\r
+                       m_RebaseStage=REBASE_EDIT;\r
+                       this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);\r
+                       this->UpdateCurrentStatus();\r
+                       return;\r
+               }\r
+               else\r
+               {\r
+                       m_RebaseStage=REBASE_CONTINUE;\r
+                       curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;\r
+                       this->UpdateCurrentStatus();\r
+               }\r
+               \r
+       }\r
+\r
+       if( m_RebaseStage == REBASE_EDIT ||  m_RebaseStage == REBASE_SQUASH_EDIT )\r
+       {\r
+               CString str;\r
+               GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+       \r
+               str=this->m_LogMessageCtrl.GetText();\r
+               if(str.Trim().IsEmpty())\r
+               {\r
+                       CMessageBox::Show(NULL,_T("Commit Message Is Empty"),_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
+                               return;\r
+               }\r
+\r
+               CString tempfile=::GetTempFile();\r
+               CFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );\r
+               CStringA log=CUnicodeUtils::GetUTF8( str);\r
+               file.Write(log,log.GetLength());\r
+               //file.WriteString(m_sLogMessage);\r
+               file.Close();\r
+       \r
+               CString out,cmd;\r
+               \r
+               if(  m_RebaseStage == REBASE_SQUASH_EDIT )\r
+                       cmd.Format(_T("git.exe commit -F \"%s\""), tempfile);\r
+               else\r
+                       cmd.Format(_T("git.exe commit --amend -F \"%s\""), tempfile);\r
+\r
+               if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               {\r
+                       if(!g_Git.CheckCleanWorkTree())\r
+                       {\r
+                               CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
+                               return;\r
+                       }\r
+               }\r
+\r
+               CFile::Remove(tempfile);\r
+               AddLogString(out);\r
+               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+               m_RebaseStage=REBASE_CONTINUE;\r
+               curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;\r
+               this->UpdateCurrentStatus();\r
+       }\r
+\r
+\r
+       InterlockedExchange(&m_bThreadRunning, TRUE);\r
+       SetControlEnable();\r
+       \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::CheckNextCommitIsSquash()\r
+{\r
+       int index;\r
+       if(m_CommitList.m_IsOldFirst)\r
+               index=m_CurrentRebaseIndex+1;\r
+       else\r
+               index=m_CurrentRebaseIndex-1;\r
+\r
+       GitRev *curRev;\r
+       do\r
+       {\r
+               if(index<0)\r
+                       return -1;\r
+               if(index>= m_CommitList.GetItemCount())\r
+                       return -1;\r
+\r
+               curRev=(GitRev*)m_CommitList.m_arShownList[index];\r
+               \r
+               if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SQUASH )\r
+                       return 0;\r
+               if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP)\r
+               {\r
+                       if(m_CommitList.m_IsOldFirst)\r
+                               index++;\r
+                       else\r
+                               index--;\r
+               }else\r
+                       return -1;              \r
+\r
+       }while(curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP);\r
+       \r
+       return -1;\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
+       switch(this->m_RebaseStage)\r
+       {\r
+       case CHOOSE_BRANCH:\r
+       case CHOOSE_COMMIT_PICK_MODE:\r
+               if(this->m_IsFastForward)\r
+                       Text = _T("Start(FastFwd)");\r
+               else\r
+                       Text = _T("Start");\r
+               break;\r
+\r
+       case REBASE_START:\r
+       case REBASE_CONTINUE:\r
+       case REBASE_SQUASH_CONFLICT:\r
+               Text = _T("Continue");\r
+               break;\r
+\r
+       case REBASE_CONFLICT:\r
+               Text = _T("Commit");\r
+               break;\r
+       case REBASE_EDIT:\r
+               Text = _T("Amend");\r
+               break;\r
+\r
+       case REBASE_SQUASH_EDIT:\r
+               Text = _T("Commit");\r
+               break;\r
+\r
+       case REBASE_ABORT:\r
+       case REBASE_FINISH:\r
+               Text = _T("Finish");\r
+               break;\r
+\r
+       case REBASE_DONE:\r
+               Text = _T("Done");\r
+               break;\r
+       }\r
+       this->GetDlgItem(IDC_REBASE_CONTINUE)->SetWindowText(Text);\r
+}\r
+\r
+void CRebaseDlg::SetControlEnable()\r
+{\r
+       switch(this->m_RebaseStage)\r
+       {\r
+       case CHOOSE_BRANCH:\r
+       case CHOOSE_COMMIT_PICK_MODE:\r
+               \r
+               this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(TRUE);\r
+               this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(TRUE);\r
+               this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(TRUE);\r
+               \r
+               if(!m_IsCherryPick)\r
+               {\r
+                       this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE);\r
+                       this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE);\r
+                       this->GetDlgItem(IDC_REBASE_CHECK_FORCE)->EnableWindow(TRUE);                   \r
+               }\r
+               //this->m_CommitList.m_IsEnableRebaseMenu=TRUE;\r
+               this->m_CommitList.m_ContextMenuMask |= m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|\r
+                                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|\r
+                                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|\r
+                                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP);\r
+               break;\r
+\r
+       case REBASE_START:\r
+       case REBASE_CONTINUE:\r
+       case REBASE_ABORT:\r
+       case REBASE_FINISH:\r
+       case REBASE_CONFLICT:\r
+       case REBASE_EDIT:\r
+       case REBASE_SQUASH_CONFLICT:\r
+       case REBASE_DONE:\r
+               this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(FALSE);\r
+               this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(FALSE);\r
+               this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(FALSE);\r
+               this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(FALSE);\r
+               this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(FALSE);\r
+               this->GetDlgItem(IDC_REBASE_CHECK_FORCE)->EnableWindow(FALSE);\r
+               //this->m_CommitList.m_IsEnableRebaseMenu=FALSE;\r
+               this->m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|\r
+                                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|\r
+                                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|\r
+                                                                                               m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP));\r
+\r
+               if( m_RebaseStage == REBASE_DONE && (this->m_PostButtonTexts.GetCount() != 0) )\r
+               {\r
+                       this->GetDlgItem(IDC_STATUS_STATIC)->ShowWindow(SW_HIDE);\r
+                       this->GetDlgItem(IDC_REBASE_POST_BUTTON)->ShowWindow(SW_SHOWNORMAL);\r
+                       this->m_PostButton.RemoveAll();\r
+                       this->m_PostButton.AddEntries(m_PostButtonTexts);\r
+                       //this->GetDlgItem(IDC_REBASE_POST_BUTTON)->SetWindowText(this->m_PostButtonText);\r
+               }\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
+       else\r
+               index = m_CommitList.GetItemCount()-m_CurrentRebaseIndex;\r
+\r
+       m_ProgressBar.SetRange(1,m_CommitList.GetItemCount());\r
+       m_ProgressBar.SetPos(index);\r
+\r
+       if(m_CurrentRebaseIndex>=0 && m_CurrentRebaseIndex< m_CommitList.GetItemCount())\r
+       {\r
+               CString text;\r
+               text.Format(_T("Rebasing...(%d/%d)"),index,m_CommitList.GetItemCount());\r
+               m_CtrlStatusText.SetWindowText(text);\r
+\r
+       }\r
+\r
+       GitRev *prevRev=NULL, *curRev=NULL;\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
+       for(int i=0;i<m_CommitList.m_arShownList.GetSize();i++)\r
+       {\r
+               prevRev=(GitRev*)m_CommitList.m_arShownList[i];\r
+               if(prevRev->m_Action & CTGitPath::LOGACTIONS_REBASE_CURRENT)\r
+               {       \r
+                       prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
+                       m_CommitList.GetItemRect(i,&rect,LVIR_BOUNDS);\r
+                       m_CommitList.InvalidateRect(rect);\r
+               }\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
+{\r
+       if( m_CurrentRebaseIndex < 0 && m_RebaseStage!= REBASE_DONE)\r
+       {\r
+               if(m_CommitList.m_IsOldFirst)\r
+                       m_RebaseStage = CRebaseDlg::REBASE_START;\r
+               else\r
+                       m_RebaseStage = CRebaseDlg::REBASE_FINISH;\r
+       }\r
+\r
+       if( m_CurrentRebaseIndex == m_CommitList.m_arShownList.GetSize() && m_RebaseStage!= REBASE_DONE)\r
+       {\r
+               if(m_CommitList.m_IsOldFirst)\r
+                       m_RebaseStage = CRebaseDlg::REBASE_DONE;\r
+               else\r
+                       m_RebaseStage = CRebaseDlg::REBASE_FINISH;\r
+       }\r
+\r
+       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::GetCurrentCommitID()\r
+{\r
+       if(m_CommitList.m_IsOldFirst)\r
+       {\r
+               return this->m_CurrentRebaseIndex+1;\r
+\r
+       }else\r
+       {\r
+               return m_CommitList.GetItemCount()-m_CurrentRebaseIndex;\r
+       }\r
+}\r
+\r
+int CRebaseDlg::DoRebase()\r
+{      \r
+       CString cmd,out;\r
+       if(m_CurrentRebaseIndex <0)\r
+               return 0;\r
+       if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )\r
+               return 0;\r
+\r
+       GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+       int mode=pRev->m_Action & CTGitPath::LOGACTIONS_REBASE_MODE_MASK;\r
+       CString nocommit;\r
+\r
+       if( mode== CTGitPath::LOGACTIONS_REBASE_SKIP)\r
+       {\r
+               pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
+               return 0;\r
+       }\r
+       \r
+       if( mode != CTGitPath::LOGACTIONS_REBASE_PICK )\r
+       {\r
+               this->m_SquashMessage+= pRev->m_Subject;\r
+               this->m_SquashMessage+= _T("\n");\r
+               this->m_SquashMessage+= pRev->m_Body;\r
+       }\r
+       else\r
+               this->m_SquashMessage.Empty();\r
+\r
+       if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)\r
+               nocommit=_T(" --no-commit ");\r
+\r
+       CString log;\r
+       log.Format(_T("%s %d:%s"),CTGitPath::GetActionName(mode),this->GetCurrentCommitID(),pRev->m_CommitHash);\r
+       AddLogString(log);\r
+       AddLogString(pRev->m_Subject);\r
+       cmd.Format(_T("git.exe cherry-pick %s %s"),nocommit,pRev->m_CommitHash);\r
+\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               CTGitPathList list;\r
+               if(g_Git.ListConflictFile(list))\r
+               {\r
+                       AddLogString(_T("Get conflict files fail"));\r
+                       return -1;\r
+               }\r
+               if(list.GetCount() == 0 )\r
+               {\r
+                       if(mode ==  CTGitPath::LOGACTIONS_REBASE_PICK)\r
+                       {\r
+                               pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
+                               return 0;\r
+                       }\r
+                       if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)\r
+                       {\r
+                               this->m_RebaseStage = REBASE_EDIT ;\r
+                               return -1; // Edit return -1 to stop rebase. \r
+                       }\r
+                       // Squash Case\r
+                       if(CheckNextCommitIsSquash())\r
+                       {   // no squash\r
+                               // let user edit last commmit message\r
+                               this->m_RebaseStage = REBASE_SQUASH_EDIT;\r
+                               return -1;\r
+                       }\r
+               }\r
+               if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)\r
+                       m_RebaseStage = REBASE_SQUASH_CONFLICT;\r
+               else\r
+                       m_RebaseStage = REBASE_CONFLICT;\r
+               return -1;      \r
+\r
+       }else\r
+       {\r
+               AddLogString(out);\r
+               if(mode ==  CTGitPath::LOGACTIONS_REBASE_PICK)\r
+               {\r
+                       pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
+                       return 0;\r
+               }\r
+               if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)\r
+               {\r
+                       this->m_RebaseStage = REBASE_EDIT ;\r
+                       return -1; // Edit return -1 to stop rebase. \r
+               }\r
+\r
+               // Squash Case\r
+               if(CheckNextCommitIsSquash())\r
+               {   // no squash\r
+                       // let user edit last commmit message\r
+                       this->m_RebaseStage = REBASE_SQUASH_EDIT;\r
+                       return -1;\r
+               }\r
+       }\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
+               }else if( m_RebaseStage == REBASE_CONTINUE )\r
+               {\r
+                       this->GoNext(); \r
+                       if(IsEnd())\r
+                       {\r
+                               ret = 0;\r
+                               m_RebaseStage = REBASE_FINISH;\r
+                               \r
+                       }else\r
+                       {\r
+                               ret = DoRebase();\r
+\r
+                               if( ret )\r
+                               {       \r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+               }else if( m_RebaseStage == REBASE_FINISH )\r
+               {                       \r
+                       FinishRebase();\r
+                       m_RebaseStage = REBASE_DONE;\r
+                       break;\r
+                       \r
+               }else\r
+               {\r
+                       break;\r
+               }\r
+               this->PostMessage(MSG_REBASE_UPDATE_UI);\r
+               //this->UpdateCurrentStatus();\r
+       }\r
+\r
+       InterlockedExchange(&m_bThreadRunning, FALSE);\r
+       this->PostMessage(MSG_REBASE_UPDATE_UI);\r
+       return ret;\r
+}\r
+\r
+void CRebaseDlg::ListConflictFile()\r
+{\r
+       this->m_FileListCtrl.Clear();   \r
+       CTGitPathList list;\r
+       CTGitPath path;\r
+       list.AddPath(path);\r
+\r
+       m_FileListCtrl.m_bIsRevertTheirMy = !m_IsCherryPick;\r
+\r
+       this->m_FileListCtrl.GetStatus(&list,true);\r
+       this->m_FileListCtrl.Show(CTGitPath::LOGACTIONS_UNMERGED|CTGitPath::LOGACTIONS_MODIFIED|CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_DELETED,\r
+                                                          CTGitPath::LOGACTIONS_UNMERGED);\r
+       if( this->m_FileListCtrl.GetItemCount() == 0 )\r
+       {\r
+               \r
+       }\r
+}\r
+\r
+LRESULT CRebaseDlg::OnRebaseUpdateUI(WPARAM,LPARAM)\r
+{\r
+       UpdateCurrentStatus();\r
+       if(m_CurrentRebaseIndex <0)\r
+               return 0;\r
+       if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )\r
+               return 0;\r
+       GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
+       \r
+       switch(m_RebaseStage)\r
+       {\r
+       case REBASE_CONFLICT:\r
+       case REBASE_SQUASH_CONFLICT:\r
+               ListConflictFile();                     \r
+               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_CONFLICT);\r
+               this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body);\r
+               break;\r
+       case REBASE_EDIT:\r
+               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);\r
+               this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body);\r
+               break;\r
+       case REBASE_SQUASH_EDIT:\r
+               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);\r
+               this->m_LogMessageCtrl.SetText(this->m_SquashMessage);\r
+               break;\r
+       default:\r
+               this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
+       }       \r
+       return 0;\r
+}\r
+void CRebaseDlg::OnCancel()\r
+{\r
+       OnBnClickedAbort();\r
+}\r
+void CRebaseDlg::OnBnClickedAbort()\r
+{\r
+       CString cmd,out;\r
+       if(m_OrigUpstreamHash.IsEmpty())\r
+       {\r
+               __super::OnCancel();\r
+       }\r
+       \r
+       if(m_RebaseStage == CHOOSE_BRANCH || m_RebaseStage== CHOOSE_COMMIT_PICK_MODE)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if(CMessageBox::Show(NULL,_T("Are you sure you want to abort the rebase process?"),_T("TortoiseGit"),MB_YESNO) != IDYES)\r
+               return;\r
+\r
+       if(this->m_IsFastForward)\r
+       {\r
+               cmd.Format(_T("git.exe reset --hard  %s"),this->m_OrigBranchHash.Left(40));\r
+               if(g_Git.Run(cmd,&out,CP_UTF8))\r
+               {\r
+                       AddLogString(out);\r
+                       return ;\r
+               }\r
+               __super::OnCancel();\r
+               return;\r
+       }\r
+       cmd.Format(_T("git.exe checkout -f %s"),this->m_UpstreamCtrl.GetString());\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               return ;\r
+       }\r
+\r
+       cmd.Format(_T("git.exe reset --hard  %s"),this->m_OrigUpstreamHash.Left(40));\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               return ;\r
+       }\r
+       \r
+       if(this->m_IsCherryPick) //there are not "branch" at cherry pick mode\r
+               return;\r
+\r
+       cmd.Format(_T("git checkout -f %s"),this->m_BranchCtrl.GetString());\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               return ;\r
+       }\r
+       \r
+       cmd.Format(_T("git.exe reset --hard  %s"),this->m_OrigBranchHash.Left(40));\r
+       if(g_Git.Run(cmd,&out,CP_UTF8))\r
+       {\r
+               AddLogString(out);\r
+               return ;\r
+       }\r
+       __super::OnCancel();\r
+}\r
+\r
+void CRebaseDlg::OnBnClickedButtonBrowse()\r
+{\r
+       if(CBrowseRefsDlg::PickRefForCombo(&m_UpstreamCtrl, gPickRef_NoTag))\r
+               OnCbnSelchangeUpstream();\r
+}\r
+\r
+void CRebaseDlg::OnBnClickedRebaseCheckForce()\r
+{\r
+       // TODO: Add your control notification handler code here\r
+       this->UpdateData();\r
+       this->FetchLogList();\r
+}\r
+\r
+void CRebaseDlg::OnStnClickedStatusStatic()\r
+{\r
+       // TODO: Add your control notification handler code here\r
+}\r
+\r
+void CRebaseDlg::OnBnClickedRebasePostButton()\r
+{\r
+       // TODO: Add your control notification handler code here\r
+       this->m_Upstream=this->m_UpstreamCtrl.GetString();\r
+       this->m_Branch=this->m_BranchCtrl.GetString();\r
+\r
+       this->EndDialog(IDC_REBASE_POST_BUTTON);\r
+}\r