X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=src%2FTortoiseProc%2FRebaseDlg.cpp;h=abf30b371cbae5c91e7af73a11a733256752ea33;hb=bd3a4565dca26bc92fde0139a58bfbc6676b50ee;hp=f717127b1e4b1ae06aa038026c8ce2e825aaf8f3;hpb=438ebd3876f4dd50c055f89f6855efeb42cf9d9f;p=tortoisegit%2FTortoiseGitJp.git diff --git a/src/TortoiseProc/RebaseDlg.cpp b/src/TortoiseProc/RebaseDlg.cpp index f717127..abf30b3 100644 --- a/src/TortoiseProc/RebaseDlg.cpp +++ b/src/TortoiseProc/RebaseDlg.cpp @@ -4,8 +4,9 @@ #include "stdafx.h" #include "TortoiseProc.h" #include "RebaseDlg.h" - - +#include "AppUtils.h" +#include "MessageBox.h" +#include "UnicodeUtils.h" // CRebaseDlg dialog IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog) @@ -17,6 +18,8 @@ CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/) , m_bEditAll(FALSE) { m_RebaseStage=CHOOSE_BRANCH; + m_CurrentRebaseIndex=-1; + m_bThreadRunning =FALSE; } CRebaseDlg::~CRebaseDlg() @@ -44,7 +47,10 @@ BEGIN_MESSAGE_MAP(CRebaseDlg, CResizableStandAloneDialog) ON_BN_CLICKED(IDC_SQUASH_ALL, &CRebaseDlg::OnBnClickedSquashAll) ON_BN_CLICKED(IDC_EDIT_ALL, &CRebaseDlg::OnBnClickedEditAll) ON_BN_CLICKED(IDC_REBASE_SPLIT, &CRebaseDlg::OnBnClickedRebaseSplit) + ON_BN_CLICKED(IDC_REBASE_CONTINUE,OnBnClickedContinue) ON_WM_SIZE() + ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH, &CRebaseDlg::OnCbnSelchangeBranch) + ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream) END_MESSAGE_MAP() void CRebaseDlg::AddRebaseAnchor() @@ -93,7 +99,7 @@ BOOL CRebaseDlg::OnInitDialog() m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO); // Create output panes: //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL; - const DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE; + DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE; if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) ) { @@ -106,11 +112,25 @@ BOOL CRebaseDlg::OnInitDialog() TRACE0("Failed to create log message control"); return FALSE; } + m_LogMessageCtrl.Init(0); + + dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL; + + if (!m_wndOutputRebase.Create(_T("Scintilla"),_T("source"),0,rectDummy, &m_ctrlTabCtrl, 0,0) ) + { + TRACE0("Failed to create output windows\n"); + return -1; // fail to create + } + m_wndOutputRebase.Init(0); + m_wndOutputRebase.Call(SCI_SETREADONLY, TRUE); + + m_tooltips.Create(this); m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS , _T("RebaseDlg")); - m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Modified File")); - m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Log Message"),1); + m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Conflict File")); + m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Commit Message"),1); + m_ctrlTabCtrl.AddTab(&m_wndOutputRebase,_T("Log"),2); AddRebaseAnchor(); @@ -146,6 +166,15 @@ BOOL CRebaseDlg::OnInitDialog() this->m_UpstreamCtrl.EnableWindow(FALSE); } + m_CommitList.m_IsIDReplaceAction = TRUE; +// m_CommitList.m_IsOldFirst = TRUE; + m_CommitList.m_IsRebaseReplaceGraph = TRUE; + + m_CommitList.DeleteAllItems(); + m_CommitList.InsertGitColumn(); + + FetchLogList(); + SetContinueButtonText(); return TRUE; } // CRebaseDlg message handlers @@ -153,20 +182,54 @@ BOOL CRebaseDlg::OnInitDialog() void CRebaseDlg::OnBnClickedPickAll() { // TODO: Add your control notification handler code here + this->UpdateData(); + if(this->m_bPickAll) + this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK); + + this->m_bEditAll=FALSE; + this->m_bSquashAll=FALSE; + this->UpdateData(FALSE); + } void CRebaseDlg::OnBnClickedSquashAll() { // TODO: Add your control notification handler code here + this->UpdateData(); + if(this->m_bSquashAll) + this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH); + + this->m_bEditAll=FALSE; + this->m_bPickAll=FALSE; + this->UpdateData(FALSE); + } void CRebaseDlg::OnBnClickedEditAll() { // TODO: Add your control notification handler code here + this->UpdateData(); + if( this->m_bEditAll ) + this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT); + + this->m_bPickAll=FALSE; + this->m_bSquashAll=FALSE; + this->UpdateData(FALSE); + +} + +void CRebaseDlg::SetAllRebaseAction(int action) +{ + for(int i=0;im_CommitList.m_logEntries.size();i++) + { + m_CommitList.m_logEntries[i].m_Action=action; + } + m_CommitList.Invalidate(); } void CRebaseDlg::OnBnClickedRebaseSplit() { + this->UpdateData(); // TODO: Add your control notification handler code here } @@ -267,4 +330,420 @@ void CRebaseDlg::LoadBranchInfo() m_BranchCtrl.SetCurSel(current); + AddBranchToolTips(&m_BranchCtrl); + AddBranchToolTips(&m_UpstreamCtrl); + +} + +void CRebaseDlg::OnCbnSelchangeBranch() +{ + FetchLogList(); +} + +void CRebaseDlg::OnCbnSelchangeUpstream() +{ + FetchLogList(); +} + +void CRebaseDlg::FetchLogList() +{ + m_CommitList.Clear(); + this->m_CommitList.FillGitLog(NULL,0,&m_UpstreamCtrl.GetString(),&m_BranchCtrl.GetString()); + if( m_CommitList.GetItemCount() == 0 ) + m_CommitList.ShowText(_T("Nothing Rebase")); + + CString hash=g_Git.GetHash(m_UpstreamCtrl.GetString()); + +#if 0 + if(m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash.size() >=0 ) + { + if(hash == m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash[0]) + { + m_CommitList.Clear(); + m_CommitList.ShowText(_T("Nothing Rebase")); + } + } +#endif + + m_tooltips.Pop(); + AddBranchToolTips(&this->m_BranchCtrl); + AddBranchToolTips(&this->m_UpstreamCtrl); + + for(int i=0;im_CurrentRebaseIndex = -1; + else + this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size(); + +} + +void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch) +{ + if(pBranch) + { + CString text=pBranch->GetString(); + CString tooltip; + BYTE_VECTOR data; + g_Git.GetLog(data,text,NULL,1,0); + GitRev rev; + rev.ParserFromLog(data); + tooltip.Format(_T("CommitHash:%s\nCommit by: %s %s\n %s \n %s"), + rev.m_CommitHash, + rev.m_AuthorName, + CAppUtils::FormatDateAndTime(rev.m_AuthorDate,DATE_LONGDATE), + rev.m_Subject, + rev.m_Body); + + pBranch->DisableTooltip(); + this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip); + } +} + +BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg) +{ + m_tooltips.RelayEvent(pMsg); + return CResizableStandAloneDialog::PreTranslateMessage(pMsg); +} +int CRebaseDlg::CheckRebaseCondition() +{ + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG); + + if( !g_Git.CheckCleanWorkTree() ) + { + CMessageBox::Show(NULL,_T("Rebase Need Clean Working Tree"),_T("TortoiseGit"),MB_OK); + return -1; + } + //Todo Check $REBASE_ROOT + //Todo Check $DOTEST + + CString cmd; + cmd=_T("git.exe var GIT_COMMITTER_IDENT"); + if(g_Git.Run(cmd,NULL,CP_UTF8)) + return -1; + + //Todo call pre_rebase_hook +} +int CRebaseDlg::StartRebase() +{ + CString cmd,out; + //Todo call comment_for_reflog + cmd.Format(_T("git.exe checkout %s"),this->m_BranchCtrl.GetString()); + this->AddLogString(cmd); + + if(g_Git.Run(cmd,&out,CP_UTF8)) + return -1; + + this->AddLogString(out); + + cmd=_T("git.exe rev-parse --verify HEAD"); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(_T("No Head")); + return -1; + } + //Todo + //git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null || + // echo "detached HEAD" > "$DOTEST"/head-name + + cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD")); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(_T("update ORIG_HEAD Fail")); + return -1; + } + + cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD")); + + cmd.Format(_T("git.exe checkout %s"),this->m_UpstreamCtrl.GetString()); + this->AddLogString(cmd); + + out.Empty(); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + return -1; + } + + this->AddLogString(_T("Start Rebase\r\n")); + return 0; +} +void CRebaseDlg::OnBnClickedContinue() +{ + if( m_RebaseStage == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE ) + { + if(CheckRebaseCondition()) + return ; + m_RebaseStage = REBASE_START; + } + + InterlockedExchange(&m_bThreadRunning, TRUE); + SetControlEnable(); + + if (AfxBeginThread(RebaseThreadEntry, this)==NULL) + { + InterlockedExchange(&m_bThreadRunning, FALSE); + CMessageBox::Show(NULL, _T("Create Rebase Thread Fail"), _T("TortoiseGit"), MB_OK | MB_ICONERROR); + SetControlEnable(); + } +} +int CRebaseDlg::GoNext() +{ + if(m_CommitList.m_IsOldFirst) + m_CurrentRebaseIndex++; + else + m_CurrentRebaseIndex--; + return 0; + +} +int CRebaseDlg::StateAction() +{ + switch(this->m_RebaseStage) + { + case CHOOSE_BRANCH: + case CHOOSE_COMMIT_PICK_MODE: + if(StartRebase()) + return -1; + m_RebaseStage = REBASE_START; + GoNext(); + break; + } + + return 0; +} +void CRebaseDlg::SetContinueButtonText() +{ + CString Text; + switch(this->m_RebaseStage) + { + case CHOOSE_BRANCH: + case CHOOSE_COMMIT_PICK_MODE: + Text = _T("Start"); + break; + + case REBASE_START: + case REBASE_CONTINUE: + Text = _T("Continue"); + break; + case REBASE_ABORT: + case REBASE_FINISH: + Text = _T("Finish"); + break; + } + this->GetDlgItem(IDC_REBASE_CONTINUE)->SetWindowText(Text); +} + +void CRebaseDlg::SetControlEnable() +{ + switch(this->m_RebaseStage) + { + case CHOOSE_BRANCH: + case CHOOSE_COMMIT_PICK_MODE: + + this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(TRUE); + this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(TRUE); + this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(TRUE); + this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE); + this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE); + this->m_CommitList.m_IsEnableRebaseMenu=TRUE; + break; + + case REBASE_START: + case REBASE_CONTINUE: + case REBASE_ABORT: + case REBASE_FINISH: + this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(FALSE); + this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(FALSE); + this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(FALSE); + this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(FALSE); + this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(FALSE); + this->m_CommitList.m_IsEnableRebaseMenu=FALSE; + break; + } + + if(m_bThreadRunning) + { + this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE); + this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(FALSE); + + }else + { + this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(TRUE); + this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(TRUE); + } +} + +void CRebaseDlg::UpdateProgress() +{ + int index; + CRect rect; + + if(m_CommitList.m_IsOldFirst) + index = m_CurrentRebaseIndex+1; + else + index = m_CommitList.GetItemCount()-m_CurrentRebaseIndex; + + m_ProgressBar.SetRange(1,m_CommitList.GetItemCount()); + m_ProgressBar.SetPos(index); + + if(m_CurrentRebaseIndex>0 && m_CurrentRebaseIndex< m_CommitList.GetItemCount()) + { + CString text; + text.Format(_T("Rebasing...(%d/%d)"),index,m_CommitList.GetItemCount()); + m_CtrlStatusText.SetWindowText(text); + + } + + GitRev *prevRev=NULL, *curRev=NULL; + int prevIndex; + + if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize()) + { + curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + } + + if(m_CommitList.m_IsOldFirst) + prevIndex=m_CurrentRebaseIndex-1; + else + prevIndex=m_CurrentRebaseIndex+1; + + if(prevIndex >= 0 && prevIndexm_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT; + m_CommitList.GetItemRect(prevIndex,&rect,LVIR_BOUNDS); + m_CommitList.InvalidateRect(rect); + } + + if(curRev) + { + curRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_CURRENT; + m_CommitList.GetItemRect(m_CurrentRebaseIndex,&rect,LVIR_BOUNDS); + m_CommitList.InvalidateRect(rect); + } + m_CommitList.EnsureVisible(m_CurrentRebaseIndex,FALSE); + +} + +void CRebaseDlg::UpdateCurrentStatus() +{ + if( m_CurrentRebaseIndex < 0) + { + if(m_CommitList.m_IsOldFirst) + m_RebaseStage = CRebaseDlg::REBASE_START; + else + m_RebaseStage = CRebaseDlg::REBASE_FINISH; + } + + if( m_CurrentRebaseIndex == m_CommitList.m_arShownList.GetSize()) + { + if(m_CommitList.m_IsOldFirst) + m_RebaseStage = CRebaseDlg::REBASE_FINISH; + else + m_RebaseStage = CRebaseDlg::REBASE_START; + } + + SetContinueButtonText(); + SetControlEnable(); + UpdateProgress(); +} + +void CRebaseDlg::AddLogString(CString str) +{ + this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, FALSE); + CStringA sTextA = m_wndOutputRebase.StringForControl(str);//CUnicodeUtils::GetUTF8(str); + this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)sTextA); + this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)"\n"); + this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, TRUE); +} + +int CRebaseDlg::DoRebase() +{ + if(m_CurrentRebaseIndex <0) + return 0; + if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() ) + return 0; + + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG); + + GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + int mode=pRev->m_Action & CTGitPath::LOGACTIONS_REBASE_MODE_MASK; + switch(mode) + { + case CTGitPath::LOGACTIONS_REBASE_PICK: + AddLogString(CString(_T("Pick "))+pRev->m_CommitHash); + pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE; + break; + case CTGitPath::LOGACTIONS_REBASE_SQUASH: + break; + case CTGitPath::LOGACTIONS_REBASE_EDIT: + break; + case CTGitPath::LOGACTIONS_REBASE_SKIP: + pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE; + return 0; + break; + default: + AddLogString(CString(_T("Unknow Action for "))+pRev->m_CommitHash); + break; + } + return 0; +} + +BOOL CRebaseDlg::IsEnd() +{ + if(m_CommitList.m_IsOldFirst) + return m_CurrentRebaseIndex>= this->m_CommitList.GetItemCount(); + else + return m_CurrentRebaseIndex<0; +} + +int CRebaseDlg::RebaseThread() +{ + int ret=0; + while(1) + { + if( m_RebaseStage == REBASE_START ) + { + if( this->StartRebase() ) + { + InterlockedExchange(&m_bThreadRunning, FALSE); + ret = -1; + break; + } + m_RebaseStage = REBASE_CONTINUE; + } + + if( m_RebaseStage == REBASE_CONTINUE ) + { + this->GoNext(); + if(IsEnd()) + { + ret = 0; + m_RebaseStage = REBASE_FINISH; + break; + } + + ret = DoRebase(); + + if( ret ) + { + break; + } + } + this->UpdateCurrentStatus(); + } + + InterlockedExchange(&m_bThreadRunning, FALSE); + this->UpdateCurrentStatus(); + this->SetControlEnable(); + this->SetContinueButtonText(); + return ret; } \ No newline at end of file