Fixed issue #444: Crash rebase dialog when press ESC and move split bar
[TortoiseGit.git] / src / TortoiseProc / RebaseDlg.cpp
blob60f02208f07356bcb8f5db0ab13cbf08f324ef8d
1 // RebaseDlg.cpp : implementation file
2 //
4 #include "stdafx.h"
5 #include "TortoiseProc.h"
6 #include "RebaseDlg.h"
7 #include "AppUtils.h"
8 #include "MessageBox.h"
9 #include "UnicodeUtils.h"
10 #include "BrowseRefsDlg.h"
11 #include "ProgressDlg.h"
12 // CRebaseDlg dialog
14 IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)
16 CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/)
17 : CResizableStandAloneDialog(CRebaseDlg::IDD, pParent)
18 , m_bPickAll(FALSE)
19 , m_bSquashAll(FALSE)
20 , m_bEditAll(FALSE)
22 m_RebaseStage=CHOOSE_BRANCH;
23 m_CurrentRebaseIndex=-1;
24 m_bThreadRunning =FALSE;
25 this->m_IsCherryPick = FALSE;
26 m_bForce=FALSE;
27 m_IsFastForward=FALSE;
30 CRebaseDlg::~CRebaseDlg()
34 void CRebaseDlg::DoDataExchange(CDataExchange* pDX)
36 CDialog::DoDataExchange(pDX);
37 DDX_Control(pDX, IDC_REBASE_PROGRESS, m_ProgressBar);
38 DDX_Control(pDX, IDC_STATUS_STATIC, m_CtrlStatusText);
39 DDX_Check(pDX, IDC_PICK_ALL, m_bPickAll);
40 DDX_Check(pDX, IDC_SQUASH_ALL, m_bSquashAll);
41 DDX_Check(pDX, IDC_EDIT_ALL, m_bEditAll);
42 DDX_Control(pDX, IDC_REBASE_SPLIT, m_wndSplitter);
43 DDX_Control(pDX,IDC_COMMIT_LIST,m_CommitList);
44 DDX_Control(pDX,IDC_REBASE_COMBOXEX_BRANCH, this->m_BranchCtrl);
45 DDX_Control(pDX,IDC_REBASE_COMBOXEX_UPSTREAM, this->m_UpstreamCtrl);
46 DDX_Check(pDX, IDC_REBASE_CHECK_FORCE,m_bForce);
47 DDX_Control(pDX,IDC_REBASE_POST_BUTTON,m_PostButton);
51 BEGIN_MESSAGE_MAP(CRebaseDlg, CResizableStandAloneDialog)
52 ON_BN_CLICKED(IDC_PICK_ALL, &CRebaseDlg::OnBnClickedPickAll)
53 ON_BN_CLICKED(IDC_SQUASH_ALL, &CRebaseDlg::OnBnClickedSquashAll)
54 ON_BN_CLICKED(IDC_EDIT_ALL, &CRebaseDlg::OnBnClickedEditAll)
55 ON_BN_CLICKED(IDC_REBASE_SPLIT, &CRebaseDlg::OnBnClickedRebaseSplit)
56 ON_BN_CLICKED(IDC_REBASE_CONTINUE,OnBnClickedContinue)
57 ON_BN_CLICKED(IDC_REBASE_ABORT, OnBnClickedAbort)
58 ON_WM_SIZE()
59 ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH, &CRebaseDlg::OnCbnSelchangeBranch)
60 ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream)
61 ON_MESSAGE(MSG_REBASE_UPDATE_UI, OnRebaseUpdateUI)
62 ON_BN_CLICKED(IDC_BUTTON_BROWSE, &CRebaseDlg::OnBnClickedButtonBrowse)
63 ON_BN_CLICKED(IDC_REBASE_CHECK_FORCE, &CRebaseDlg::OnBnClickedRebaseCheckForce)
64 ON_STN_CLICKED(IDC_STATUS_STATIC, &CRebaseDlg::OnStnClickedStatusStatic)
65 ON_BN_CLICKED(IDC_REBASE_POST_BUTTON, &CRebaseDlg::OnBnClickedRebasePostButton)
66 END_MESSAGE_MAP()
68 void CRebaseDlg::AddRebaseAnchor()
70 AddAnchor(IDC_REBASE_TAB,TOP_LEFT,BOTTOM_RIGHT);
71 AddAnchor(IDC_COMMIT_LIST,TOP_LEFT, TOP_RIGHT);
72 AddAnchor(IDC_REBASE_SPLIT,TOP_LEFT, TOP_RIGHT);
73 AddAnchor(IDC_STATUS_STATIC, BOTTOM_LEFT,BOTTOM_RIGHT);
74 AddAnchor(IDC_REBASE_CONTINUE,BOTTOM_RIGHT);
75 AddAnchor(IDC_REBASE_ABORT, BOTTOM_RIGHT);
76 AddAnchor(IDC_REBASE_PROGRESS,BOTTOM_LEFT, BOTTOM_RIGHT);
77 AddAnchor(IDC_PICK_ALL,TOP_LEFT);
78 AddAnchor(IDC_SQUASH_ALL,TOP_LEFT);
79 AddAnchor(IDC_EDIT_ALL,TOP_LEFT);
80 AddAnchor(IDC_REBASE_COMBOXEX_UPSTREAM,TOP_LEFT);
81 AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT);
82 AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT);
83 AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT);
84 AddAnchor(IDHELP, BOTTOM_RIGHT);
85 AddAnchor(IDC_REBASE_CHECK_FORCE,TOP_RIGHT);
86 AddAnchor(IDC_REBASE_POST_BUTTON,BOTTOM_LEFT);
88 this->AddOthersToAnchor();
91 BOOL CRebaseDlg::OnInitDialog()
93 CResizableStandAloneDialog::OnInitDialog();
95 CRect rectDummy;
96 //IDC_REBASE_DUMY_TAB
98 GetClientRect(m_DlgOrigRect);
99 m_CommitList.GetClientRect(m_CommitListOrigRect);
101 CWnd *pwnd=this->GetDlgItem(IDC_REBASE_DUMY_TAB);
102 pwnd->GetWindowRect(&rectDummy);
103 this->ScreenToClient(rectDummy);
105 if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_REBASE_TAB))
107 TRACE0("Failed to create output tab window\n");
108 return FALSE; // fail to create
110 m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);
111 // Create output panes:
112 //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
113 DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;
115 if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) )
117 TRACE0("Failed to create output windows\n");
118 return FALSE; // fail to create
121 if( ! this->m_LogMessageCtrl.Create(_T("Scintilla"),_T("source"),0,rectDummy,&m_ctrlTabCtrl,0,0) )
123 TRACE0("Failed to create log message control");
124 return FALSE;
126 m_LogMessageCtrl.Init(0);
128 dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
130 if (!m_wndOutputRebase.Create(_T("Scintilla"),_T("source"),0,rectDummy, &m_ctrlTabCtrl, 0,0) )
132 TRACE0("Failed to create output windows\n");
133 return -1; // fail to create
135 m_wndOutputRebase.Init(0);
136 m_wndOutputRebase.Call(SCI_SETREADONLY, TRUE);
138 m_tooltips.Create(this);
140 m_tooltips.AddTool(IDC_REBASE_CHECK_FORCE,IDS_REBASE_FORCE_TT);
141 m_tooltips.AddTool(IDC_REBASE_ABORT,IDS_REBASE_ABORT_TT);
145 m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS |SVNSLC_COLADD|SVNSLC_COLDEL , _T("RebaseDlg"),(SVNSLC_POPALL ^ SVNSLC_POPCOMMIT),false);
147 m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Conflict File"));
148 m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Commit Message"),1);
149 m_ctrlTabCtrl.AddTab(&m_wndOutputRebase,_T("Log"),2);
150 AddRebaseAnchor();
153 EnableSaveRestore(_T("RebaseDlg"));
155 DWORD yPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));
156 RECT rcDlg, rcLogMsg, rcFileList;
157 GetClientRect(&rcDlg);
158 m_CommitList.GetWindowRect(&rcLogMsg);
159 ScreenToClient(&rcLogMsg);
160 this->m_ctrlTabCtrl.GetWindowRect(&rcFileList);
161 ScreenToClient(&rcFileList);
162 if (yPos)
164 RECT rectSplitter;
165 m_wndSplitter.GetWindowRect(&rectSplitter);
166 ScreenToClient(&rectSplitter);
167 int delta = yPos - rectSplitter.top;
168 if ((rcLogMsg.bottom + delta > rcLogMsg.top)&&(rcLogMsg.bottom + delta < rcFileList.bottom - 30))
170 m_wndSplitter.SetWindowPos(NULL, 0, yPos, 0, 0, SWP_NOSIZE);
171 DoSize(delta);
175 if( this->m_RebaseStage == CHOOSE_BRANCH)
177 this->LoadBranchInfo();
179 }else
181 this->m_BranchCtrl.EnableWindow(FALSE);
182 this->m_UpstreamCtrl.EnableWindow(FALSE);
185 m_CommitList.m_IsIDReplaceAction = TRUE;
186 // m_CommitList.m_IsOldFirst = TRUE;
187 m_CommitList.m_IsRebaseReplaceGraph = TRUE;
189 m_CommitList.InsertGitColumn();
191 this->SetControlEnable();
193 if(!this->m_PreCmd.IsEmpty())
195 CProgressDlg progress;
196 progress.m_GitCmd=m_PreCmd;
197 progress.m_bAutoCloseOnSuccess=true;
198 progress.DoModal();
201 if(m_IsCherryPick)
203 this->m_BranchCtrl.SetCurSel(-1);
204 this->m_BranchCtrl.EnableWindow(FALSE);
205 this->m_UpstreamCtrl.EnableWindow(FALSE);
206 this->SetWindowText(_T("Cherry Pick"));
207 this->m_CommitList.StartFilter();
209 }else
211 SetContinueButtonText();
212 m_CommitList.DeleteAllItems();
213 FetchLogList();
216 m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_CHERRY_PICK)|
217 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_SWITCHTOREV)|
218 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_RESET)|
219 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTREV)|
220 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_TO_VERSION)|
221 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTTOREV)|
222 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_COMBINE_COMMIT));
224 if(m_CommitList.m_IsOldFirst)
225 this->m_CurrentRebaseIndex = -1;
226 else
227 this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();
230 if(this->CheckRebaseCondition())
232 /* Disable Start Rebase */
233 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);
236 return TRUE;
238 // CRebaseDlg message handlers
240 void CRebaseDlg::OnBnClickedPickAll()
242 // TODO: Add your control notification handler code here
243 this->UpdateData();
244 if(this->m_bPickAll)
245 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK);
247 this->m_bEditAll=FALSE;
248 this->m_bSquashAll=FALSE;
249 this->UpdateData(FALSE);
253 void CRebaseDlg::OnBnClickedSquashAll()
255 // TODO: Add your control notification handler code here
256 this->UpdateData();
257 if(this->m_bSquashAll)
258 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH);
260 this->m_bEditAll=FALSE;
261 this->m_bPickAll=FALSE;
262 this->UpdateData(FALSE);
266 void CRebaseDlg::OnBnClickedEditAll()
268 // TODO: Add your control notification handler code here
269 this->UpdateData();
270 if( this->m_bEditAll )
271 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT);
273 this->m_bPickAll=FALSE;
274 this->m_bSquashAll=FALSE;
275 this->UpdateData(FALSE);
279 void CRebaseDlg::SetAllRebaseAction(int action)
281 for(int i=0;i<this->m_CommitList.m_logEntries.size();i++)
283 m_CommitList.m_logEntries.GetGitRevAt(i).m_Action=action;
285 m_CommitList.Invalidate();
288 void CRebaseDlg::OnBnClickedRebaseSplit()
290 this->UpdateData();
291 // TODO: Add your control notification handler code here
294 LRESULT CRebaseDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
296 switch (message) {
297 case WM_NOTIFY:
298 if (wParam == IDC_REBASE_SPLIT)
300 SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;
301 DoSize(pHdr->delta);
303 break;
306 return __super::DefWindowProc(message, wParam, lParam);
309 void CRebaseDlg::DoSize(int delta)
312 this->RemoveAllAnchors();
314 CSplitterControl::ChangeHeight(GetDlgItem(IDC_COMMIT_LIST), delta, CW_TOPALIGN);
315 //CSplitterControl::ChangeHeight(GetDlgItem(), delta, CW_TOPALIGN);
316 CSplitterControl::ChangeHeight(GetDlgItem(IDC_REBASE_TAB), -delta, CW_BOTTOMALIGN);
317 //CSplitterControl::ChangeHeight(GetDlgItem(), -delta, CW_BOTTOMALIGN);
318 CSplitterControl::ChangePos(GetDlgItem(IDC_SQUASH_ALL),0,delta);
319 CSplitterControl::ChangePos(GetDlgItem(IDC_PICK_ALL),0,delta);
320 CSplitterControl::ChangePos(GetDlgItem(IDC_EDIT_ALL),0,delta);
321 CSplitterControl::ChangePos(GetDlgItem(IDC_REBASE_CHECK_FORCE),0,delta);
323 this->AddRebaseAnchor();
324 // adjust the minimum size of the dialog to prevent the resizing from
325 // moving the list control too far down.
326 CRect rcLogMsg;
327 m_CommitList.GetClientRect(rcLogMsg);
328 SetMinTrackSize(CSize(m_DlgOrigRect.Width(), m_DlgOrigRect.Height()-m_CommitListOrigRect.Height()+rcLogMsg.Height()));
330 SetSplitterRange();
331 // m_CommitList.Invalidate();
333 // GetDlgItem(IDC_LOGMESSAGE)->Invalidate();
335 this->m_ctrlTabCtrl.Invalidate();
336 this->m_CommitList.Invalidate();
337 this->m_FileListCtrl.Invalidate();
338 this->m_LogMessageCtrl.Invalidate();
342 void CRebaseDlg::SetSplitterRange()
344 if ((m_CommitList)&&(m_ctrlTabCtrl))
346 CRect rcTop;
347 m_CommitList.GetWindowRect(rcTop);
348 ScreenToClient(rcTop);
349 CRect rcMiddle;
350 m_ctrlTabCtrl.GetWindowRect(rcMiddle);
351 ScreenToClient(rcMiddle);
352 if (rcMiddle.Height() && rcMiddle.Width())
353 m_wndSplitter.SetRange(rcTop.top+60, rcMiddle.bottom-80);
357 void CRebaseDlg::OnSize(UINT nType,int cx, int cy)
359 // first, let the resizing take place
360 __super::OnSize(nType, cx, cy);
362 //set range
363 SetSplitterRange();
366 void CRebaseDlg::SaveSplitterPos()
368 if (!IsIconic())
370 CRegDWORD regPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));
371 RECT rectSplitter;
372 m_wndSplitter.GetWindowRect(&rectSplitter);
373 ScreenToClient(&rectSplitter);
374 regPos = rectSplitter.top;
378 void CRebaseDlg::LoadBranchInfo()
380 m_BranchCtrl.SetMaxHistoryItems(0x7FFFFFFF);
381 m_UpstreamCtrl.SetMaxHistoryItems(0x7FFFFFFF);
383 STRING_VECTOR list;
384 list.clear();
385 int current;
386 g_Git.GetBranchList(list,&current,CGit::BRANCH_ALL);
387 m_BranchCtrl.AddString(list);
388 m_UpstreamCtrl.AddString(list);
390 m_BranchCtrl.SetCurSel(current);
392 AddBranchToolTips(&m_BranchCtrl);
393 AddBranchToolTips(&m_UpstreamCtrl);
395 if(!m_Upstream.IsEmpty())
397 m_UpstreamCtrl.AddString(m_Upstream);
398 m_UpstreamCtrl.SetCurSel(m_UpstreamCtrl.GetCount()-1);
400 else
402 //Select pull-remote from current branch
403 CString currentBranch = g_Git.GetSymbolicRef();
404 CString configName;
405 configName.Format(L"branch.%s.remote", currentBranch);
406 CString pullRemote = g_Git.GetConfigValue(configName);
408 //Select pull-branch from current branch
409 configName.Format(L"branch.%s.merge", currentBranch);
410 CString pullBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));
412 CString defaultUpstream;
413 defaultUpstream.Format(L"remotes/%s/%s", pullRemote, pullBranch);
414 int found = m_UpstreamCtrl.FindStringExact(0, defaultUpstream);
415 if(found >= 0)
416 m_UpstreamCtrl.SetCurSel(found);
420 void CRebaseDlg::OnCbnSelchangeBranch()
422 FetchLogList();
425 void CRebaseDlg::OnCbnSelchangeUpstream()
427 FetchLogList();
430 void CRebaseDlg::FetchLogList()
432 CString base,hash;
433 CString cmd;
434 m_IsFastForward=FALSE;
435 cmd.Format(_T("git.exe merge-base %s %s"), m_UpstreamCtrl.GetString(),m_BranchCtrl.GetString());
436 if(g_Git.Run(cmd,&base,CP_ACP))
438 CMessageBox::Show(NULL,base,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
439 return;
441 base=base.Left(40);
443 hash=g_Git.GetHash(m_BranchCtrl.GetString());
445 if(hash == g_Git.GetHash(this->m_UpstreamCtrl.GetString()))
447 m_CommitList.Clear();
448 CString text,fmt;
449 fmt.LoadString(IDS_REBASE_EQUAL_FMT);
450 text.Format(fmt,m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString());
452 m_CommitList.ShowText(text);
453 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(false);
454 return;
457 hash=hash.Left(40);
459 if(hash == base )
461 //fast forword
462 this->m_IsFastForward=TRUE;
464 m_CommitList.Clear();
465 CString text,fmt;
466 fmt.LoadString(IDS_REBASE_FASTFORWARD_FMT);
467 text.Format(fmt,m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString(),
468 m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString());
470 m_CommitList.ShowText(text);
471 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(true);
472 SetContinueButtonText();
474 return ;
477 hash.Empty();
479 if(!this->m_bForce)
481 cmd.Format(_T("git.exe rev-parse %s"), m_UpstreamCtrl.GetString());
482 if( g_Git.Run(cmd,&hash,CP_ACP))
484 CMessageBox::Show(NULL,base,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
485 return;
487 hash=hash.Left(40);
489 if( base == hash )
491 m_CommitList.Clear();
492 CString text,fmt;
493 fmt.LoadString(IDS_REBASE_UPTODATE_FMT);
494 text.Format(fmt,m_BranchCtrl.GetString());
495 m_CommitList.ShowText(text);
496 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(m_CommitList.GetItemCount());
497 SetContinueButtonText();
498 return;
502 m_CommitList.Clear();
503 this->m_CommitList.FillGitLog(NULL,0,&m_UpstreamCtrl.GetString(),&m_BranchCtrl.GetString());
504 if( m_CommitList.GetItemCount() == 0 )
505 m_CommitList.ShowText(_T("Nothing to Rebase"));
507 hash=g_Git.GetHash(m_UpstreamCtrl.GetString());
509 #if 0
510 if(m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash.size() >=0 )
512 if(hash == m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash[0])
514 m_CommitList.Clear();
515 m_CommitList.ShowText(_T("Nothing Rebase"));
518 #endif
520 m_tooltips.Pop();
521 AddBranchToolTips(&this->m_BranchCtrl);
522 AddBranchToolTips(&this->m_UpstreamCtrl);
524 for(int i=0;i<m_CommitList.m_logEntries.size();i++)
526 m_CommitList.m_logEntries.GetGitRevAt(i).m_Action = CTGitPath::LOGACTIONS_REBASE_PICK;
529 m_CommitList.Invalidate();
531 if(m_CommitList.m_IsOldFirst)
532 this->m_CurrentRebaseIndex = -1;
533 else
534 this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();
536 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(m_CommitList.GetItemCount());
537 SetContinueButtonText();
540 void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)
542 if(pBranch)
544 CString text=pBranch->GetString();
545 CString tooltip;
546 BYTE_VECTOR data;
547 g_Git.GetLog(data,text,NULL,1,0);
548 GitRev rev;
549 rev.ParserFromLog(data);
550 tooltip.Format(_T("CommitHash:%s\nCommit by: %s %s\n <b>%s</b> \n %s"),
551 rev.m_CommitHash.ToString(),
552 rev.m_AuthorName,
553 CAppUtils::FormatDateAndTime(rev.m_AuthorDate,DATE_LONGDATE),
554 rev.m_Subject,
555 rev.m_Body);
557 pBranch->DisableTooltip();
558 this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip);
562 BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg)
564 if (pMsg->message == WM_KEYDOWN)
566 switch (pMsg->wParam)
569 case VK_F5:
571 Refresh();
572 return TRUE;
574 break;
575 /* Avoid TAB control destroy but dialog exist*/
576 case VK_ESCAPE:
577 case VK_CANCEL:
579 TCHAR buff[128];
580 ::GetClassName(pMsg->hwnd,buff,128);
583 if(_tcsnicmp(buff,_T("RichEdit20W"),128)==0 ||
584 _tcsnicmp(buff,_T("Scintilla"),128)==0 ||
585 _tcsnicmp(buff,_T("SysListView32"),128)==0||
586 ::GetParent(pMsg->hwnd) == this->m_ctrlTabCtrl.m_hWnd)
588 this->PostMessage(WM_KEYDOWN,VK_ESCAPE,0);
589 return TRUE;
594 m_tooltips.RelayEvent(pMsg);
595 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
597 int CRebaseDlg::CheckRebaseCondition()
599 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
601 if( !g_Git.CheckCleanWorkTree() )
603 if(CMessageBox::Show(NULL, IDS_ERROR_NOCLEAN_STASH,IDS_APPNAME,MB_YESNO|MB_ICONINFORMATION)==IDYES)
605 CString cmd,out;
606 cmd=_T("git.exe stash");
607 this->AddLogString(cmd);
608 if(g_Git.Run(cmd,&out,CP_ACP))
610 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);
611 return -1;
614 }else
615 return -1;
617 //Todo Check $REBASE_ROOT
618 //Todo Check $DOTEST
620 CString cmd;
621 cmd=_T("git.exe var GIT_COMMITTER_IDENT");
622 if(g_Git.Run(cmd,NULL,CP_UTF8))
623 return -1;
625 //Todo call pre_rebase_hook
626 return 0;
628 int CRebaseDlg::StartRebase()
630 CString cmd,out;
631 m_FileListCtrl.m_bIsRevertTheirMy = !m_IsCherryPick;
632 if(!this->m_IsCherryPick)
634 //Todo call comment_for_reflog
635 cmd.Format(_T("git.exe checkout %s"),this->m_BranchCtrl.GetString());
636 this->AddLogString(cmd);
638 if(g_Git.Run(cmd,&out,CP_UTF8))
639 return -1;
641 this->AddLogString(out);
644 cmd=_T("git.exe rev-parse --verify HEAD");
645 if(g_Git.Run(cmd,&out,CP_UTF8))
647 AddLogString(_T("No Head"));
648 return -1;
650 //Todo
651 //git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
652 // echo "detached HEAD" > "$DOTEST"/head-name
654 cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));
655 if(g_Git.Run(cmd,&out,CP_UTF8))
657 AddLogString(_T("update ORIG_HEAD Fail"));
658 return -1;
661 if( !this->m_IsCherryPick )
663 cmd.Format(_T("git.exe checkout %s"),this->m_UpstreamCtrl.GetString());
664 this->AddLogString(cmd);
666 out.Empty();
667 if(g_Git.Run(cmd,&out,CP_UTF8))
669 return -1;
673 m_OrigUpstreamHash.Empty();
674 m_OrigUpstreamHash= g_Git.GetHash(this->m_UpstreamCtrl.GetString());
675 if(m_OrigUpstreamHash.IsEmpty())
677 this->AddLogString(m_OrigUpstreamHash);
678 return -1;
681 if( !this->m_IsCherryPick )
683 cmd.Format(_T("git.exe rev-parse %s"),this->m_BranchCtrl.GetString());
684 if(g_Git.Run(cmd,&this->m_OrigBranchHash,CP_UTF8))
686 this->AddLogString(m_OrigBranchHash);
687 return -1;
689 this->AddLogString(_T("Start Rebase\r\n"));
691 }else
692 this->AddLogString(_T("Start Cherry-pick\r\n"));
694 return 0;
696 int CRebaseDlg::VerifyNoConflict()
698 CTGitPathList list;
699 if(g_Git.ListConflictFile(list))
701 AddLogString(_T("Get conflict files fail"));
702 return -1;
704 if( list.GetCount() != 0 )
706 CMessageBox::Show(NULL,_T("There are conflict file, you should mark it resolve"),_T("TortoiseGit"),MB_OK);
707 return -1;
709 return 0;
712 int CRebaseDlg::FinishRebase()
714 if(this->m_IsCherryPick) //cherry pick mode no "branch", working at upstream branch
715 return 0;
717 CString cmd,out;
718 cmd.Format(_T("git.exe branch -f %s"),this->m_BranchCtrl.GetString());
719 if(g_Git.Run(cmd,&out,CP_UTF8))
721 AddLogString(out);
722 return -1;
724 out.Empty();
725 cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash);
726 if(g_Git.Run(cmd,&out,CP_UTF8))
728 AddLogString(out);
729 return -1;
731 out.Empty();
732 cmd.Format(_T("git.exe checkout -f %s"),this->m_BranchCtrl.GetString());
733 if(g_Git.Run(cmd,&out,CP_UTF8))
735 AddLogString(out);
736 return -1;
738 return 0;
740 void CRebaseDlg::OnBnClickedContinue()
742 if( m_RebaseStage == REBASE_DONE)
744 OnOK();
745 return;
748 if( this->m_IsFastForward )
750 CString cmd,out;
751 CString oldbranch = g_Git.GetCurrentBranch();
752 if( oldbranch != m_BranchCtrl.GetString() )
754 cmd.Format(_T("git.exe checkout %s"),m_BranchCtrl.GetString());
755 AddLogString(cmd);
756 if( g_Git.Run(cmd,&out,CP_ACP) )
758 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
759 AddLogString(out);
760 return;
763 AddLogString(out);
764 out.Empty();
765 m_OrigBranchHash = g_Git.GetHash(m_BranchCtrl.GetString());
766 m_OrigUpstreamHash = g_Git.GetHash(this->m_UpstreamCtrl.GetString());
768 if(!g_Git.IsFastForward(this->m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString()))
770 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
771 AddLogString(_T("No fast forward\r\nMaybe repository changed"));
772 return;
775 cmd.Format(_T("git.exe reset --hard %s"),this->m_UpstreamCtrl.GetString());
776 this->AddLogString(CString(_T("Fast forward to "))+m_UpstreamCtrl.GetString());
778 AddLogString(cmd);
779 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
780 if(g_Git.Run(cmd,&out,CP_ACP))
782 AddLogString(_T("Fail"));
783 AddLogString(out);
784 return;
786 AddLogString(out);
787 AddLogString(_T("Done"));
788 m_RebaseStage = REBASE_DONE;
789 UpdateCurrentStatus();
790 return;
793 if( m_RebaseStage == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE )
795 if(CheckRebaseCondition())
796 return ;
797 m_RebaseStage = REBASE_START;
801 if( m_RebaseStage == REBASE_FINISH )
803 if(FinishRebase())
804 return ;
806 OnOK();
809 if( m_RebaseStage == REBASE_SQUASH_CONFLICT)
811 if(VerifyNoConflict())
812 return;
813 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
814 if(this->CheckNextCommitIsSquash())
815 {//next commit is not squash;
816 m_RebaseStage = REBASE_SQUASH_EDIT;
817 this->OnRebaseUpdateUI(0,0);
818 this->UpdateCurrentStatus();
819 return ;
822 m_RebaseStage=REBASE_CONTINUE;
823 curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;
824 this->UpdateCurrentStatus();
828 if( m_RebaseStage == REBASE_CONFLICT )
830 if(VerifyNoConflict())
831 return;
833 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
835 CString out =_T("");
836 CString cmd;
837 cmd.Format(_T("git.exe commit -C %s"), curRev->m_CommitHash.ToString());
839 if(g_Git.Run(cmd,&out,CP_UTF8))
841 if(!g_Git.CheckCleanWorkTree())
843 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
844 return;
848 AddLogString(out);
849 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
850 if( curRev->m_Action & CTGitPath::LOGACTIONS_REBASE_EDIT)
852 m_RebaseStage=REBASE_EDIT;
853 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);
854 this->UpdateCurrentStatus();
855 return;
857 else
859 m_RebaseStage=REBASE_CONTINUE;
860 curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;
861 this->UpdateCurrentStatus();
866 if( m_RebaseStage == REBASE_EDIT || m_RebaseStage == REBASE_SQUASH_EDIT )
868 CString str;
869 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
871 str=this->m_LogMessageCtrl.GetText();
872 if(str.Trim().IsEmpty())
874 CMessageBox::Show(NULL,_T("Commit Message Is Empty"),_T("TortoiseGit"),MB_OK|MB_ICONERROR);
875 return;
878 CString tempfile=::GetTempFile();
879 CFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );
880 CStringA log=CUnicodeUtils::GetUTF8( str);
881 file.Write(log,log.GetLength());
882 //file.WriteString(m_sLogMessage);
883 file.Close();
885 CString out,cmd;
887 if( m_RebaseStage == REBASE_SQUASH_EDIT )
888 cmd.Format(_T("git.exe commit -F \"%s\""), tempfile);
889 else
890 cmd.Format(_T("git.exe commit --amend -F \"%s\""), tempfile);
892 if(g_Git.Run(cmd,&out,CP_UTF8))
894 if(!g_Git.CheckCleanWorkTree())
896 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
897 return;
901 CFile::Remove(tempfile);
902 AddLogString(out);
903 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
904 m_RebaseStage=REBASE_CONTINUE;
905 curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;
906 this->UpdateCurrentStatus();
910 InterlockedExchange(&m_bThreadRunning, TRUE);
911 SetControlEnable();
913 if (AfxBeginThread(RebaseThreadEntry, this)==NULL)
915 InterlockedExchange(&m_bThreadRunning, FALSE);
916 CMessageBox::Show(NULL, _T("Create Rebase Thread Fail"), _T("TortoiseGit"), MB_OK | MB_ICONERROR);
917 SetControlEnable();
920 int CRebaseDlg::CheckNextCommitIsSquash()
922 int index;
923 if(m_CommitList.m_IsOldFirst)
924 index=m_CurrentRebaseIndex+1;
925 else
926 index=m_CurrentRebaseIndex-1;
928 GitRev *curRev;
931 if(index<0)
932 return -1;
933 if(index>= m_CommitList.GetItemCount())
934 return -1;
936 curRev=(GitRev*)m_CommitList.m_arShownList[index];
938 if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SQUASH )
939 return 0;
940 if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP)
942 if(m_CommitList.m_IsOldFirst)
943 index++;
944 else
945 index--;
946 }else
947 return -1;
949 }while(curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP);
951 return -1;
954 int CRebaseDlg::GoNext()
956 if(m_CommitList.m_IsOldFirst)
957 m_CurrentRebaseIndex++;
958 else
959 m_CurrentRebaseIndex--;
960 return 0;
963 int CRebaseDlg::StateAction()
965 switch(this->m_RebaseStage)
967 case CHOOSE_BRANCH:
968 case CHOOSE_COMMIT_PICK_MODE:
969 if(StartRebase())
970 return -1;
971 m_RebaseStage = REBASE_START;
972 GoNext();
973 break;
976 return 0;
978 void CRebaseDlg::SetContinueButtonText()
980 CString Text;
981 switch(this->m_RebaseStage)
983 case CHOOSE_BRANCH:
984 case CHOOSE_COMMIT_PICK_MODE:
985 if(this->m_IsFastForward)
986 Text = _T("Start(FastFwd)");
987 else
988 Text = _T("Start");
989 break;
991 case REBASE_START:
992 case REBASE_CONTINUE:
993 case REBASE_SQUASH_CONFLICT:
994 Text = _T("Continue");
995 break;
997 case REBASE_CONFLICT:
998 Text = _T("Commit");
999 break;
1000 case REBASE_EDIT:
1001 Text = _T("Amend");
1002 break;
1004 case REBASE_SQUASH_EDIT:
1005 Text = _T("Commit");
1006 break;
1008 case REBASE_ABORT:
1009 case REBASE_FINISH:
1010 Text = _T("Finish");
1011 break;
1013 case REBASE_DONE:
1014 Text = _T("Done");
1015 break;
1017 this->GetDlgItem(IDC_REBASE_CONTINUE)->SetWindowText(Text);
1020 void CRebaseDlg::SetControlEnable()
1022 switch(this->m_RebaseStage)
1024 case CHOOSE_BRANCH:
1025 case CHOOSE_COMMIT_PICK_MODE:
1027 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(TRUE);
1028 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(TRUE);
1029 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(TRUE);
1031 if(!m_IsCherryPick)
1033 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE);
1034 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE);
1035 this->GetDlgItem(IDC_REBASE_CHECK_FORCE)->EnableWindow(TRUE);
1037 //this->m_CommitList.m_IsEnableRebaseMenu=TRUE;
1038 this->m_CommitList.m_ContextMenuMask |= m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|
1039 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|
1040 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|
1041 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP);
1042 break;
1044 case REBASE_START:
1045 case REBASE_CONTINUE:
1046 case REBASE_ABORT:
1047 case REBASE_FINISH:
1048 case REBASE_CONFLICT:
1049 case REBASE_EDIT:
1050 case REBASE_SQUASH_CONFLICT:
1051 case REBASE_DONE:
1052 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(FALSE);
1053 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(FALSE);
1054 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(FALSE);
1055 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(FALSE);
1056 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(FALSE);
1057 this->GetDlgItem(IDC_REBASE_CHECK_FORCE)->EnableWindow(FALSE);
1058 //this->m_CommitList.m_IsEnableRebaseMenu=FALSE;
1059 this->m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|
1060 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|
1061 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|
1062 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP));
1064 if( m_RebaseStage == REBASE_DONE && (this->m_PostButtonTexts.GetCount() != 0) )
1066 this->GetDlgItem(IDC_STATUS_STATIC)->ShowWindow(SW_HIDE);
1067 this->GetDlgItem(IDC_REBASE_POST_BUTTON)->ShowWindow(SW_SHOWNORMAL);
1068 this->m_PostButton.RemoveAll();
1069 this->m_PostButton.AddEntries(m_PostButtonTexts);
1070 //this->GetDlgItem(IDC_REBASE_POST_BUTTON)->SetWindowText(this->m_PostButtonText);
1072 break;
1075 if(m_bThreadRunning)
1077 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);
1078 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(FALSE);
1080 }else
1082 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(TRUE);
1083 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(TRUE);
1087 void CRebaseDlg::UpdateProgress()
1089 int index;
1090 CRect rect;
1092 if(m_CommitList.m_IsOldFirst)
1093 index = m_CurrentRebaseIndex+1;
1094 else
1095 index = m_CommitList.GetItemCount()-m_CurrentRebaseIndex;
1097 m_ProgressBar.SetRange(1,m_CommitList.GetItemCount());
1098 m_ProgressBar.SetPos(index);
1100 if(m_CurrentRebaseIndex>=0 && m_CurrentRebaseIndex< m_CommitList.GetItemCount())
1102 CString text;
1103 text.Format(_T("Rebasing...(%d/%d)"),index,m_CommitList.GetItemCount());
1104 m_CtrlStatusText.SetWindowText(text);
1108 GitRev *prevRev=NULL, *curRev=NULL;
1110 if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize())
1112 curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
1115 for(int i=0;i<m_CommitList.m_arShownList.GetSize();i++)
1117 prevRev=(GitRev*)m_CommitList.m_arShownList[i];
1118 if(prevRev->m_Action & CTGitPath::LOGACTIONS_REBASE_CURRENT)
1120 prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;
1121 m_CommitList.GetItemRect(i,&rect,LVIR_BOUNDS);
1122 m_CommitList.InvalidateRect(rect);
1126 if(curRev)
1128 curRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_CURRENT;
1129 m_CommitList.GetItemRect(m_CurrentRebaseIndex,&rect,LVIR_BOUNDS);
1130 m_CommitList.InvalidateRect(rect);
1132 m_CommitList.EnsureVisible(m_CurrentRebaseIndex,FALSE);
1136 void CRebaseDlg::UpdateCurrentStatus()
1138 if( m_CurrentRebaseIndex < 0 && m_RebaseStage!= REBASE_DONE)
1140 if(m_CommitList.m_IsOldFirst)
1141 m_RebaseStage = CRebaseDlg::REBASE_START;
1142 else
1143 m_RebaseStage = CRebaseDlg::REBASE_FINISH;
1146 if( m_CurrentRebaseIndex == m_CommitList.m_arShownList.GetSize() && m_RebaseStage!= REBASE_DONE)
1148 if(m_CommitList.m_IsOldFirst)
1149 m_RebaseStage = CRebaseDlg::REBASE_DONE;
1150 else
1151 m_RebaseStage = CRebaseDlg::REBASE_FINISH;
1154 SetContinueButtonText();
1155 SetControlEnable();
1156 UpdateProgress();
1159 void CRebaseDlg::AddLogString(CString str)
1161 this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, FALSE);
1162 CStringA sTextA = m_wndOutputRebase.StringForControl(str);//CUnicodeUtils::GetUTF8(str);
1163 this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)sTextA);
1164 this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)"\n");
1165 this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, TRUE);
1168 int CRebaseDlg::GetCurrentCommitID()
1170 if(m_CommitList.m_IsOldFirst)
1172 return this->m_CurrentRebaseIndex+1;
1174 }else
1176 return m_CommitList.GetItemCount()-m_CurrentRebaseIndex;
1180 int CRebaseDlg::DoRebase()
1182 CString cmd,out;
1183 if(m_CurrentRebaseIndex <0)
1184 return 0;
1185 if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )
1186 return 0;
1188 GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
1189 int mode=pRev->m_Action & CTGitPath::LOGACTIONS_REBASE_MODE_MASK;
1190 CString nocommit;
1192 if( mode== CTGitPath::LOGACTIONS_REBASE_SKIP)
1194 pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;
1195 return 0;
1198 if( mode != CTGitPath::LOGACTIONS_REBASE_PICK )
1200 this->m_SquashMessage+= pRev->m_Subject;
1201 this->m_SquashMessage+= _T("\n");
1202 this->m_SquashMessage+= pRev->m_Body;
1204 else
1205 this->m_SquashMessage.Empty();
1207 if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)
1208 nocommit=_T(" --no-commit ");
1210 CString log;
1211 log.Format(_T("%s %d:%s"),CTGitPath::GetActionName(mode),this->GetCurrentCommitID(),pRev->m_CommitHash.ToString());
1212 AddLogString(log);
1213 AddLogString(pRev->m_Subject);
1214 cmd.Format(_T("git.exe cherry-pick %s %s"),nocommit,pRev->m_CommitHash.ToString());
1216 if(g_Git.Run(cmd,&out,CP_UTF8))
1218 AddLogString(out);
1219 CTGitPathList list;
1220 if(g_Git.ListConflictFile(list))
1222 AddLogString(_T("Get conflict files fail"));
1223 return -1;
1225 if(list.GetCount() == 0 )
1227 if(mode == CTGitPath::LOGACTIONS_REBASE_PICK)
1229 pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;
1230 return 0;
1232 if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)
1234 this->m_RebaseStage = REBASE_EDIT ;
1235 return -1; // Edit return -1 to stop rebase.
1237 // Squash Case
1238 if(CheckNextCommitIsSquash())
1239 { // no squash
1240 // let user edit last commmit message
1241 this->m_RebaseStage = REBASE_SQUASH_EDIT;
1242 return -1;
1245 if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)
1246 m_RebaseStage = REBASE_SQUASH_CONFLICT;
1247 else
1248 m_RebaseStage = REBASE_CONFLICT;
1249 return -1;
1251 }else
1253 AddLogString(out);
1254 if(mode == CTGitPath::LOGACTIONS_REBASE_PICK)
1256 pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;
1257 return 0;
1259 if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)
1261 this->m_RebaseStage = REBASE_EDIT ;
1262 return -1; // Edit return -1 to stop rebase.
1265 // Squash Case
1266 if(CheckNextCommitIsSquash())
1267 { // no squash
1268 // let user edit last commmit message
1269 this->m_RebaseStage = REBASE_SQUASH_EDIT;
1270 return -1;
1274 return 0;
1277 BOOL CRebaseDlg::IsEnd()
1279 if(m_CommitList.m_IsOldFirst)
1280 return m_CurrentRebaseIndex>= this->m_CommitList.GetItemCount();
1281 else
1282 return m_CurrentRebaseIndex<0;
1285 int CRebaseDlg::RebaseThread()
1287 int ret=0;
1288 while(1)
1290 if( m_RebaseStage == REBASE_START )
1292 if( this->StartRebase() )
1294 InterlockedExchange(&m_bThreadRunning, FALSE);
1295 ret = -1;
1296 break;
1298 m_RebaseStage = REBASE_CONTINUE;
1300 }else if( m_RebaseStage == REBASE_CONTINUE )
1302 this->GoNext();
1303 if(IsEnd())
1305 ret = 0;
1306 m_RebaseStage = REBASE_FINISH;
1308 }else
1310 ret = DoRebase();
1312 if( ret )
1314 break;
1318 }else if( m_RebaseStage == REBASE_FINISH )
1320 FinishRebase();
1321 m_RebaseStage = REBASE_DONE;
1322 break;
1324 }else
1326 break;
1328 this->PostMessage(MSG_REBASE_UPDATE_UI);
1329 //this->UpdateCurrentStatus();
1332 InterlockedExchange(&m_bThreadRunning, FALSE);
1333 this->PostMessage(MSG_REBASE_UPDATE_UI);
1334 return ret;
1337 void CRebaseDlg::ListConflictFile()
1339 this->m_FileListCtrl.Clear();
1340 CTGitPathList list;
1341 CTGitPath path;
1342 list.AddPath(path);
1344 m_FileListCtrl.m_bIsRevertTheirMy = !m_IsCherryPick;
1346 this->m_FileListCtrl.GetStatus(&list,true);
1347 this->m_FileListCtrl.Show(CTGitPath::LOGACTIONS_UNMERGED|CTGitPath::LOGACTIONS_MODIFIED|CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_DELETED,
1348 CTGitPath::LOGACTIONS_UNMERGED);
1349 if( this->m_FileListCtrl.GetItemCount() == 0 )
1355 LRESULT CRebaseDlg::OnRebaseUpdateUI(WPARAM,LPARAM)
1357 UpdateCurrentStatus();
1358 if(m_CurrentRebaseIndex <0)
1359 return 0;
1360 if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )
1361 return 0;
1362 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
1364 switch(m_RebaseStage)
1366 case REBASE_CONFLICT:
1367 case REBASE_SQUASH_CONFLICT:
1368 ListConflictFile();
1369 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_CONFLICT);
1370 this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body);
1371 break;
1372 case REBASE_EDIT:
1373 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);
1374 this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body);
1375 break;
1376 case REBASE_SQUASH_EDIT:
1377 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);
1378 this->m_LogMessageCtrl.SetText(this->m_SquashMessage);
1379 break;
1380 default:
1381 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
1383 return 0;
1385 void CRebaseDlg::OnCancel()
1387 OnBnClickedAbort();
1389 void CRebaseDlg::OnBnClickedAbort()
1391 CString cmd,out;
1392 if(m_OrigUpstreamHash.IsEmpty())
1394 __super::OnCancel();
1397 if(m_RebaseStage == CHOOSE_BRANCH || m_RebaseStage== CHOOSE_COMMIT_PICK_MODE)
1399 return;
1402 if(CMessageBox::Show(NULL,_T("Are you sure you want to abort the rebase process?"),_T("TortoiseGit"),MB_YESNO) != IDYES)
1403 return;
1405 if(this->m_IsFastForward)
1407 cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigBranchHash.Left(40));
1408 if(g_Git.Run(cmd,&out,CP_UTF8))
1410 AddLogString(out);
1411 return ;
1413 __super::OnCancel();
1414 return;
1416 cmd.Format(_T("git.exe checkout -f %s"),this->m_UpstreamCtrl.GetString());
1417 if(g_Git.Run(cmd,&out,CP_UTF8))
1419 AddLogString(out);
1420 return ;
1423 cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash.Left(40));
1424 if(g_Git.Run(cmd,&out,CP_UTF8))
1426 AddLogString(out);
1427 return ;
1430 if(this->m_IsCherryPick) //there are not "branch" at cherry pick mode
1432 __super::OnCancel();
1433 return;
1436 cmd.Format(_T("git checkout -f %s"),this->m_BranchCtrl.GetString());
1437 if(g_Git.Run(cmd,&out,CP_UTF8))
1439 AddLogString(out);
1440 return ;
1443 cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigBranchHash.Left(40));
1444 if(g_Git.Run(cmd,&out,CP_UTF8))
1446 AddLogString(out);
1447 return ;
1449 __super::OnCancel();
1452 void CRebaseDlg::OnBnClickedButtonBrowse()
1454 if(CBrowseRefsDlg::PickRefForCombo(&m_UpstreamCtrl, gPickRef_NoTag))
1455 OnCbnSelchangeUpstream();
1458 void CRebaseDlg::OnBnClickedRebaseCheckForce()
1460 // TODO: Add your control notification handler code here
1461 this->UpdateData();
1462 this->FetchLogList();
1463 if(this->CheckRebaseCondition())
1465 /* Disable Start Rebase */
1466 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);
1470 void CRebaseDlg::OnStnClickedStatusStatic()
1472 // TODO: Add your control notification handler code here
1475 void CRebaseDlg::OnBnClickedRebasePostButton()
1477 // TODO: Add your control notification handler code here
1478 this->m_Upstream=this->m_UpstreamCtrl.GetString();
1479 this->m_Branch=this->m_BranchCtrl.GetString();
1481 this->EndDialog(IDC_REBASE_POST_BUTTON+this->m_PostButton.GetCurrentEntry());
1484 void CRebaseDlg::Refresh()
1486 if(this->m_IsCherryPick)
1487 return ;
1489 if(this->m_RebaseStage == CHOOSE_BRANCH )
1491 this->UpdateData();
1492 this->FetchLogList();
1493 if(this->CheckRebaseCondition())
1495 /* Disable Start Rebase */
1496 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);