X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=src%2FTortoiseProc%2FRebaseDlg.cpp;h=51125f3b5fa22aa494f9688999d065795500aa1b;hb=bdb42c3bd436de186978463d9dc0afeb88526a7c;hp=8159247829c062b0ce58c43d160ac547758e316d;hpb=cf73c8997a81b6fd8fc8e3d9c7d59606bd135b47;p=tortoisegit%2FTortoiseGitJp.git diff --git a/src/TortoiseProc/RebaseDlg.cpp b/src/TortoiseProc/RebaseDlg.cpp index 8159247..51125f3 100644 --- a/src/TortoiseProc/RebaseDlg.cpp +++ b/src/TortoiseProc/RebaseDlg.cpp @@ -5,7 +5,8 @@ #include "TortoiseProc.h" #include "RebaseDlg.h" #include "AppUtils.h" - +#include "MessageBox.h" +#include "UnicodeUtils.h" // CRebaseDlg dialog IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog) @@ -17,6 +18,9 @@ CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/) , m_bEditAll(FALSE) { m_RebaseStage=CHOOSE_BRANCH; + m_CurrentRebaseIndex=-1; + m_bThreadRunning =FALSE; + this->m_IsCherryPick = FALSE; } CRebaseDlg::~CRebaseDlg() @@ -44,9 +48,12 @@ 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_BN_CLICKED(IDC_REBASE_ABORT, OnBnClickedAbort) ON_WM_SIZE() ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH, &CRebaseDlg::OnCbnSelchangeBranch) ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream) + ON_MESSAGE(MSG_REBASE_UPDATE_UI, OnRebaseUpdateUI) END_MESSAGE_MAP() void CRebaseDlg::AddRebaseAnchor() @@ -65,7 +72,7 @@ void CRebaseDlg::AddRebaseAnchor() AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT); AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT); AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT); - + this->AddOthersToAnchor(); } BOOL CRebaseDlg::OnInitDialog() @@ -80,13 +87,8 @@ BOOL CRebaseDlg::OnInitDialog() CWnd *pwnd=this->GetDlgItem(IDC_REBASE_DUMY_TAB); pwnd->GetWindowRect(&rectDummy); + this->ScreenToClient(rectDummy); - rectDummy.top-=20; - rectDummy.bottom-=20; - - rectDummy.left-=5; - rectDummy.right-=5; - if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_REBASE_TAB)) { TRACE0("Failed to create output tab window\n"); @@ -95,7 +97,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 | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE; if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) ) { @@ -108,13 +110,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_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS |SVNSLC_COLADD|SVNSLC_COLDEL , _T("RebaseDlg"),(SVNSLC_POPALL ^ SVNSLC_POPCOMMIT),false); 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(); @@ -151,13 +165,42 @@ BOOL CRebaseDlg::OnInitDialog() } m_CommitList.m_IsIDReplaceAction = TRUE; - m_CommitList.m_IsOldFirst = TRUE; +// m_CommitList.m_IsOldFirst = TRUE; m_CommitList.m_IsRebaseReplaceGraph = TRUE; - m_CommitList.DeleteAllItems(); m_CommitList.InsertGitColumn(); - FetchLogList(); + this->SetControlEnable(); + + if(m_IsCherryPick) + { + this->m_BranchCtrl.SetCurSel(-1); + this->m_BranchCtrl.EnableWindow(FALSE); + this->m_UpstreamCtrl.EnableWindow(FALSE); + this->SetWindowText(_T("Cherry Pick")); + this->m_CommitList.StartFilter(); + + }else + { + SetContinueButtonText(); + m_CommitList.DeleteAllItems(); + FetchLogList(); + } + + m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_CHERRY_PICK)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_SWITCHTOREV)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_RESET)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTREV)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_TO_VERSION)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTTOREV)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_COMBINE_COMMIT)); + + if(m_CommitList.m_IsOldFirst) + this->m_CurrentRebaseIndex = -1; + else + this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size(); + + return TRUE; } // CRebaseDlg message handlers @@ -316,6 +359,11 @@ void CRebaseDlg::LoadBranchInfo() AddBranchToolTips(&m_BranchCtrl); AddBranchToolTips(&m_UpstreamCtrl); + if(!m_Upstream.IsEmpty()) + { + m_UpstreamCtrl.AddString(m_Upstream); + m_UpstreamCtrl.SetCurSel(m_UpstreamCtrl.GetCount()-1); + } } void CRebaseDlg::OnCbnSelchangeBranch() @@ -337,6 +385,7 @@ void CRebaseDlg::FetchLogList() 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]) @@ -345,7 +394,8 @@ void CRebaseDlg::FetchLogList() m_CommitList.ShowText(_T("Nothing Rebase")); } } - +#endif + m_tooltips.Pop(); AddBranchToolTips(&this->m_BranchCtrl); AddBranchToolTips(&this->m_UpstreamCtrl); @@ -356,6 +406,12 @@ void CRebaseDlg::FetchLogList() } m_CommitList.Invalidate(); + + if(m_CommitList.m_IsOldFirst) + this->m_CurrentRebaseIndex = -1; + else + this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size(); + } void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch) @@ -384,4 +440,769 @@ BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg) { m_tooltips.RelayEvent(pMsg); return CResizableStandAloneDialog::PreTranslateMessage(pMsg); -} \ No newline at end of file +} +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 + return 0; +} +int CRebaseDlg::StartRebase() +{ + CString cmd,out; + + if(!this->m_IsCherryPick) + { + //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; + } + + if( !this->m_IsCherryPick ) + { + 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; + } + } + + m_OrigUpstreamHash.Empty(); + m_OrigUpstreamHash= g_Git.GetHash(this->m_UpstreamCtrl.GetString()); + if(m_OrigUpstreamHash.IsEmpty()) + { + this->AddLogString(m_OrigUpstreamHash); + return -1; + } + + if( !this->m_IsCherryPick ) + { + cmd.Format(_T("git.exe rev-parse %s"),this->m_BranchCtrl.GetString()); + if(g_Git.Run(cmd,&this->m_OrigBranchHash,CP_UTF8)) + { + this->AddLogString(m_OrigBranchHash); + return -1; + } + this->AddLogString(_T("Start Rebase\r\n")); + + }else + this->AddLogString(_T("Start Cherry-pick\r\n")); + + return 0; +} +int CRebaseDlg::VerifyNoConflict() +{ + CTGitPathList list; + if(g_Git.ListConflictFile(list)) + { + AddLogString(_T("Get conflict files fail")); + return -1; + } + if( list.GetCount() != 0 ) + { + CMessageBox::Show(NULL,_T("There are conflict file, you should mark it resolve"),_T("TortoiseGit"),MB_OK); + return -1; + } + return 0; + +} +int CRebaseDlg::FinishRebase() +{ + if(this->m_IsCherryPick) //cherry pick mode no "branch", working at upstream branch + return 0; + + CString cmd,out; + cmd.Format(_T("git.exe branch -f %s"),this->m_BranchCtrl.GetString()); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + return -1; + } + out.Empty(); + cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + return -1; + } + out.Empty(); + cmd.Format(_T("git.exe checkout -f %s"),this->m_BranchCtrl.GetString()); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + return -1; + } + return 0; +} +void CRebaseDlg::OnBnClickedContinue() +{ + if( m_RebaseStage == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE ) + { + if(CheckRebaseCondition()) + return ; + m_RebaseStage = REBASE_START; + } + + if( m_RebaseStage == REBASE_DONE) + { + OnOK(); + } + + if( m_RebaseStage == REBASE_FINISH ) + { + if(FinishRebase()) + return ; + + OnOK(); + } + + if( m_RebaseStage == REBASE_SQUASH_CONFLICT) + { + if(VerifyNoConflict()) + return; + GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + if(this->CheckNextCommitIsSquash()) + {//next commit is not squash; + m_RebaseStage = REBASE_SQUASH_EDIT; + this->OnRebaseUpdateUI(0,0); + this->UpdateCurrentStatus(); + return ; + + } + m_RebaseStage=REBASE_CONTINUE; + curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE; + this->UpdateCurrentStatus(); + + } + + if( m_RebaseStage == REBASE_CONFLICT ) + { + if(VerifyNoConflict()) + return; + + GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + + CString out =_T(""); + CString cmd; + cmd.Format(_T("git.exe commit -C %s"), curRev->m_CommitHash); + + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + if(!g_Git.CheckCleanWorkTree()) + { + CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR); + return; + } + } + + AddLogString(out); + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG); + if( curRev->m_Action & CTGitPath::LOGACTIONS_REBASE_EDIT) + { + m_RebaseStage=REBASE_EDIT; + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE); + this->UpdateCurrentStatus(); + return; + } + else + { + m_RebaseStage=REBASE_CONTINUE; + curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE; + this->UpdateCurrentStatus(); + } + + } + + if( m_RebaseStage == REBASE_EDIT || m_RebaseStage == REBASE_SQUASH_EDIT ) + { + CString str; + GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + + str=this->m_LogMessageCtrl.GetText(); + if(str.Trim().IsEmpty()) + { + CMessageBox::Show(NULL,_T("Commit Message Is Empty"),_T("TortoiseGit"),MB_OK|MB_ICONERROR); + return; + } + + CString tempfile=::GetTempFile(); + CFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate ); + CStringA log=CUnicodeUtils::GetUTF8( str); + file.Write(log,log.GetLength()); + //file.WriteString(m_sLogMessage); + file.Close(); + + CString out,cmd; + + if( m_RebaseStage == REBASE_SQUASH_EDIT ) + cmd.Format(_T("git.exe commit -F \"%s\""), tempfile); + else + cmd.Format(_T("git.exe commit --amend -F \"%s\""), tempfile); + + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + if(!g_Git.CheckCleanWorkTree()) + { + CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR); + return; + } + } + + CFile::Remove(tempfile); + AddLogString(out); + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG); + m_RebaseStage=REBASE_CONTINUE; + curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE; + this->UpdateCurrentStatus(); + } + + + 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::CheckNextCommitIsSquash() +{ + int index; + if(m_CommitList.m_IsOldFirst) + index=m_CurrentRebaseIndex+1; + else + index=m_CurrentRebaseIndex-1; + + GitRev *curRev; + do + { + if(index<0) + return -1; + if(index>= m_CommitList.GetItemCount()) + return -1; + + curRev=(GitRev*)m_CommitList.m_arShownList[index]; + + if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SQUASH ) + return 0; + if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP) + { + if(m_CommitList.m_IsOldFirst) + index++; + else + index--; + }else + return -1; + + }while(curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP); + + return -1; + +} +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: + case REBASE_SQUASH_CONFLICT: + Text = _T("Continue"); + break; + + case REBASE_CONFLICT: + Text = _T("Commit"); + break; + case REBASE_EDIT: + Text = _T("Amend"); + break; + + case REBASE_SQUASH_EDIT: + Text = _T("Commit"); + break; + + case REBASE_ABORT: + case REBASE_FINISH: + Text = _T("Finish"); + break; + + case REBASE_DONE: + Text = _T("Done"); + 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); + if(!m_IsCherryPick) + { + this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE); + this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE); + } + //this->m_CommitList.m_IsEnableRebaseMenu=TRUE; + this->m_CommitList.m_ContextMenuMask |= m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP); + break; + + case REBASE_START: + case REBASE_CONTINUE: + case REBASE_ABORT: + case REBASE_FINISH: + case REBASE_CONFLICT: + case REBASE_EDIT: + case REBASE_SQUASH_CONFLICT: + case REBASE_DONE: + 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; + this->m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)| + m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP)); + 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; + + if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize()) + { + curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + } + + for(int i=0;im_Action & CTGitPath::LOGACTIONS_REBASE_CURRENT) + { + prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT; + m_CommitList.GetItemRect(i,&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 && m_RebaseStage!= REBASE_DONE) + { + if(m_CommitList.m_IsOldFirst) + m_RebaseStage = CRebaseDlg::REBASE_START; + else + m_RebaseStage = CRebaseDlg::REBASE_FINISH; + } + + if( m_CurrentRebaseIndex == m_CommitList.m_arShownList.GetSize() && m_RebaseStage!= REBASE_DONE) + { + if(m_CommitList.m_IsOldFirst) + m_RebaseStage = CRebaseDlg::REBASE_DONE; + else + m_RebaseStage = CRebaseDlg::REBASE_FINISH; + } + + 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::GetCurrentCommitID() +{ + if(m_CommitList.m_IsOldFirst) + { + return this->m_CurrentRebaseIndex+1; + + }else + { + return m_CommitList.GetItemCount()-m_CurrentRebaseIndex; + } +} + +int CRebaseDlg::DoRebase() +{ + CString cmd,out; + if(m_CurrentRebaseIndex <0) + return 0; + if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() ) + return 0; + + GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + int mode=pRev->m_Action & CTGitPath::LOGACTIONS_REBASE_MODE_MASK; + CString nocommit; + + if( mode== CTGitPath::LOGACTIONS_REBASE_SKIP) + { + pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE; + return 0; + } + + if( mode != CTGitPath::LOGACTIONS_REBASE_PICK ) + { + this->m_SquashMessage+= pRev->m_Subject; + this->m_SquashMessage+= _T("\n"); + this->m_SquashMessage+= pRev->m_Body; + } + else + this->m_SquashMessage.Empty(); + + if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH) + nocommit=_T(" --no-commit "); + + CString log; + log.Format(_T("%s %d:%s"),CTGitPath::GetActionName(mode),this->GetCurrentCommitID(),pRev->m_CommitHash); + AddLogString(log); + AddLogString(pRev->m_Subject); + cmd.Format(_T("git.exe cherry-pick %s %s"),nocommit,pRev->m_CommitHash); + + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + CTGitPathList list; + if(g_Git.ListConflictFile(list)) + { + AddLogString(_T("Get conflict files fail")); + return -1; + } + if(list.GetCount() == 0 ) + { + if(mode == CTGitPath::LOGACTIONS_REBASE_PICK) + { + pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE; + return 0; + } + if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT) + { + this->m_RebaseStage = REBASE_EDIT ; + return -1; // Edit return -1 to stop rebase. + } + // Squash Case + if(CheckNextCommitIsSquash()) + { // no squash + // let user edit last commmit message + this->m_RebaseStage = REBASE_SQUASH_EDIT; + return -1; + } + } + if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH) + m_RebaseStage = REBASE_SQUASH_CONFLICT; + else + m_RebaseStage = REBASE_CONFLICT; + return -1; + + }else + { + AddLogString(out); + if(mode == CTGitPath::LOGACTIONS_REBASE_PICK) + { + pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE; + return 0; + } + if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT) + { + this->m_RebaseStage = REBASE_EDIT ; + return -1; // Edit return -1 to stop rebase. + } + + // Squash Case + if(CheckNextCommitIsSquash()) + { // no squash + // let user edit last commmit message + this->m_RebaseStage = REBASE_SQUASH_EDIT; + return -1; + } + } + + 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; + + }else if( m_RebaseStage == REBASE_CONTINUE ) + { + this->GoNext(); + if(IsEnd()) + { + ret = 0; + m_RebaseStage = REBASE_FINISH; + + }else + { + ret = DoRebase(); + + if( ret ) + { + break; + } + } + + }else if( m_RebaseStage == REBASE_FINISH ) + { + FinishRebase(); + m_RebaseStage = REBASE_DONE; + break; + + }else + { + break; + } + this->PostMessage(MSG_REBASE_UPDATE_UI); + //this->UpdateCurrentStatus(); + } + + InterlockedExchange(&m_bThreadRunning, FALSE); + this->PostMessage(MSG_REBASE_UPDATE_UI); + return ret; +} + +void CRebaseDlg::ListConflictFile() +{ + this->m_FileListCtrl.Clear(); + CTGitPathList list; + CTGitPath path; + list.AddPath(path); + + this->m_FileListCtrl.GetStatus(&list,true); + this->m_FileListCtrl.Show(CTGitPath::LOGACTIONS_UNMERGED|CTGitPath::LOGACTIONS_MODIFIED|CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_DELETED, + CTGitPath::LOGACTIONS_UNMERGED); + if( this->m_FileListCtrl.GetItemCount() == 0 ) + { + + } +} + +LRESULT CRebaseDlg::OnRebaseUpdateUI(WPARAM,LPARAM) +{ + UpdateCurrentStatus(); + if(m_CurrentRebaseIndex <0) + return 0; + if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() ) + return 0; + GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex]; + + switch(m_RebaseStage) + { + case REBASE_CONFLICT: + case REBASE_SQUASH_CONFLICT: + ListConflictFile(); + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_CONFLICT); + this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body); + break; + case REBASE_EDIT: + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE); + this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body); + break; + case REBASE_SQUASH_EDIT: + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE); + this->m_LogMessageCtrl.SetText(this->m_SquashMessage); + break; + default: + this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG); + } + return 0; +} +void CRebaseDlg::OnCancel() +{ + OnBnClickedAbort(); +} +void CRebaseDlg::OnBnClickedAbort() +{ + CString cmd,out; + if(m_OrigUpstreamHash.IsEmpty()) + { + __super::OnCancel(); + } + + if(m_RebaseStage == CHOOSE_BRANCH || m_RebaseStage== CHOOSE_COMMIT_PICK_MODE) + { + return; + } + + if(CMessageBox::Show(NULL,_T("Are you sure abort rebase"),_T("TortoiseGit"),MB_YESNO) != IDYES) + return; + + cmd.Format(_T("git.exe checkout -f %s"),this->m_UpstreamCtrl.GetString()); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + return ; + } + + cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash.Left(40)); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + return ; + } + + if(this->m_IsCherryPick) //there are not "branch" at cherry pick mode + return; + + cmd.Format(_T("git checkout -f %s"),this->m_BranchCtrl.GetString()); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + return ; + } + + cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigBranchHash.Left(40)); + if(g_Git.Run(cmd,&out,CP_UTF8)) + { + AddLogString(out); + return ; + } + __super::OnCancel(); +}