#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
// 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
}\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_WM_SIZE()\r
+ ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH, &CRebaseDlg::OnCbnSelchangeBranch)\r
+ ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream)\r
END_MESSAGE_MAP()\r
\r
void CRebaseDlg::AddRebaseAnchor()\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 | LVS_OWNERDATA | 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
\r
- m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Modified File"));\r
- m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Log Message"),1);\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
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.DeleteAllItems();\r
+ m_CommitList.InsertGitColumn();\r
+\r
+ FetchLogList();\r
+ SetContinueButtonText();\r
return TRUE;\r
}\r
// CRebaseDlg message handlers\r
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
\r
m_BranchCtrl.SetCurSel(current);\r
\r
+ AddBranchToolTips(&m_BranchCtrl);\r
+ AddBranchToolTips(&m_UpstreamCtrl);\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
+ 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 Rebase"));\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
+ {\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
+}\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
+}\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(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
+ 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
+ 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
+ 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
+ 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::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
+ Text = _T("Continue");\r
+ break;\r
+ case REBASE_ABORT:\r
+ case REBASE_FINISH:\r
+ Text = _T("Finish");\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
+ this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE);\r
+ this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE);\r
+ this->m_CommitList.m_IsEnableRebaseMenu=TRUE;\r
+ break;\r
+\r
+ case REBASE_START:\r
+ case REBASE_CONTINUE:\r
+ case REBASE_ABORT:\r
+ case REBASE_FINISH:\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
+ 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
+ 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
+ prevRev=(GitRev*)m_CommitList.m_arShownList[prevIndex];\r
+ }\r
+\r
+ if(prevRev)\r
+ {\r
+ prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;\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
+{\r
+ if( m_CurrentRebaseIndex < 0)\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())\r
+ {\r
+ if(m_CommitList.m_IsOldFirst)\r
+ m_RebaseStage = CRebaseDlg::REBASE_FINISH;\r
+ else\r
+ m_RebaseStage = CRebaseDlg::REBASE_START;\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::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