#include "TortoiseProc.h"\r
#include "RebaseDlg.h"\r
#include "AppUtils.h"\r
-\r
+#include "MessageBox.h"\r
+#include "UnicodeUtils.h"\r
+#include "BrowseRefsDlg.h"\r
// CRebaseDlg dialog\r
\r
IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)\r
, m_bEditAll(FALSE)\r
{\r
m_RebaseStage=CHOOSE_BRANCH;\r
+ m_CurrentRebaseIndex=-1;\r
+ m_bThreadRunning =FALSE;\r
+ this->m_IsCherryPick = FALSE;\r
}\r
\r
CRebaseDlg::~CRebaseDlg()\r
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
END_MESSAGE_MAP()\r
\r
void CRebaseDlg::AddRebaseAnchor()\r
AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT);\r
AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT);\r
AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT);\r
- \r
+ this->AddOthersToAnchor();\r
}\r
\r
BOOL CRebaseDlg::OnInitDialog()\r
\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
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
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_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS , _T("RebaseDlg"));\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
}\r
\r
m_CommitList.m_IsIDReplaceAction = TRUE;\r
- m_CommitList.m_IsOldFirst = TRUE;\r
+// m_CommitList.m_IsOldFirst = TRUE;\r
m_CommitList.m_IsRebaseReplaceGraph = TRUE;\r
\r
- m_CommitList.DeleteAllItems();\r
m_CommitList.InsertGitColumn();\r
\r
- FetchLogList();\r
+ this->SetControlEnable();\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
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
}\r
\r
void CRebaseDlg::OnCbnSelchangeBranch()\r
\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
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
}\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
}\r
\r
void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)\r
{\r
m_tooltips.RelayEvent(pMsg);\r
return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
-}
\ No newline at end of file
+}\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
+\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 == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE )\r
+ {\r
+ if(CheckRebaseCondition())\r
+ return ;\r
+ m_RebaseStage = REBASE_START;\r
+ }\r
+\r
+ if( m_RebaseStage == REBASE_DONE)\r
+ {\r
+ OnOK();\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
+ 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
+ if(!m_IsCherryPick)\r
+ {\r
+ this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE);\r
+ this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->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->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
+ 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
+ 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 abort rebase"),_T("TortoiseGit"),MB_YESNO) != IDYES)\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
+ CBrowseRefsDlg::PickRefForCombo(&m_UpstreamCtrl, gPickRef_NoTag);\r
+}\r