fixed missing space
[TortoiseGit.git] / src / TortoiseProc / RebaseDlg.cpp
blobb5fe36a31a67f48aed453a369c002a13d4aa5206
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2011 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 // RebaseDlg.cpp : implementation file
23 #include "stdafx.h"
24 #include "TortoiseProc.h"
25 #include "RebaseDlg.h"
26 #include "AppUtils.h"
27 #include "MessageBox.h"
28 #include "UnicodeUtils.h"
29 #include "BrowseRefsDlg.h"
30 #include "ProgressDlg.h"
31 // CRebaseDlg dialog
33 IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)
35 CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/)
36 : CResizableStandAloneDialog(CRebaseDlg::IDD, pParent)
37 , m_bPickAll(FALSE)
38 , m_bSquashAll(FALSE)
39 , m_bEditAll(FALSE)
41 m_RebaseStage=CHOOSE_BRANCH;
42 m_CurrentRebaseIndex=-1;
43 m_bThreadRunning =FALSE;
44 this->m_IsCherryPick = FALSE;
45 m_bForce=FALSE;
46 m_IsFastForward=FALSE;
49 CRebaseDlg::~CRebaseDlg()
53 void CRebaseDlg::DoDataExchange(CDataExchange* pDX)
55 CDialog::DoDataExchange(pDX);
56 DDX_Control(pDX, IDC_REBASE_PROGRESS, m_ProgressBar);
57 DDX_Control(pDX, IDC_STATUS_STATIC, m_CtrlStatusText);
58 DDX_Check(pDX, IDC_PICK_ALL, m_bPickAll);
59 DDX_Check(pDX, IDC_SQUASH_ALL, m_bSquashAll);
60 DDX_Check(pDX, IDC_EDIT_ALL, m_bEditAll);
61 DDX_Control(pDX, IDC_REBASE_SPLIT, m_wndSplitter);
62 DDX_Control(pDX,IDC_COMMIT_LIST,m_CommitList);
63 DDX_Control(pDX,IDC_REBASE_COMBOXEX_BRANCH, this->m_BranchCtrl);
64 DDX_Control(pDX,IDC_REBASE_COMBOXEX_UPSTREAM, this->m_UpstreamCtrl);
65 DDX_Check(pDX, IDC_REBASE_CHECK_FORCE,m_bForce);
66 DDX_Control(pDX,IDC_REBASE_POST_BUTTON,m_PostButton);
70 BEGIN_MESSAGE_MAP(CRebaseDlg, CResizableStandAloneDialog)
71 ON_BN_CLICKED(IDC_PICK_ALL, &CRebaseDlg::OnBnClickedPickAll)
72 ON_BN_CLICKED(IDC_SQUASH_ALL, &CRebaseDlg::OnBnClickedSquashAll)
73 ON_BN_CLICKED(IDC_EDIT_ALL, &CRebaseDlg::OnBnClickedEditAll)
74 ON_BN_CLICKED(IDC_REBASE_SPLIT, &CRebaseDlg::OnBnClickedRebaseSplit)
75 ON_BN_CLICKED(IDC_REBASE_CONTINUE,OnBnClickedContinue)
76 ON_BN_CLICKED(IDC_REBASE_ABORT, OnBnClickedAbort)
77 ON_WM_SIZE()
78 ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH, &CRebaseDlg::OnCbnSelchangeBranch)
79 ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream)
80 ON_MESSAGE(MSG_REBASE_UPDATE_UI, OnRebaseUpdateUI)
81 ON_BN_CLICKED(IDC_BUTTON_BROWSE, &CRebaseDlg::OnBnClickedButtonBrowse)
82 ON_BN_CLICKED(IDC_REBASE_CHECK_FORCE, &CRebaseDlg::OnBnClickedRebaseCheckForce)
83 ON_BN_CLICKED(IDC_REBASE_POST_BUTTON, &CRebaseDlg::OnBnClickedRebasePostButton)
84 ON_BN_CLICKED(IDC_BUTTON_UP2, &CRebaseDlg::OnBnClickedButtonUp2)
85 ON_BN_CLICKED(IDC_BUTTON_DOWN2, &CRebaseDlg::OnBnClickedButtonDown2)
86 ON_REGISTERED_MESSAGE(WM_TASKBARBTNCREATED, OnTaskbarBtnCreated)
87 END_MESSAGE_MAP()
89 void CRebaseDlg::AddRebaseAnchor()
91 AddAnchor(IDC_REBASE_TAB,TOP_LEFT,BOTTOM_RIGHT);
92 AddAnchor(IDC_COMMIT_LIST,TOP_LEFT, TOP_RIGHT);
93 AddAnchor(IDC_REBASE_SPLIT,TOP_LEFT, TOP_RIGHT);
94 AddAnchor(IDC_STATUS_STATIC, BOTTOM_LEFT,BOTTOM_RIGHT);
95 AddAnchor(IDC_REBASE_CONTINUE,BOTTOM_RIGHT);
96 AddAnchor(IDC_REBASE_ABORT, BOTTOM_RIGHT);
97 AddAnchor(IDC_REBASE_PROGRESS,BOTTOM_LEFT, BOTTOM_RIGHT);
98 AddAnchor(IDC_PICK_ALL,TOP_LEFT);
99 AddAnchor(IDC_SQUASH_ALL,TOP_LEFT);
100 AddAnchor(IDC_EDIT_ALL,TOP_LEFT);
101 AddAnchor(IDC_BUTTON_UP2,TOP_LEFT);
102 AddAnchor(IDC_BUTTON_DOWN2,TOP_LEFT);
103 AddAnchor(IDC_REBASE_COMBOXEX_UPSTREAM,TOP_LEFT);
104 AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT);
105 AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT);
106 AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT);
107 AddAnchor(IDHELP, BOTTOM_RIGHT);
108 AddAnchor(IDC_REBASE_CHECK_FORCE,TOP_RIGHT);
109 AddAnchor(IDC_REBASE_POST_BUTTON,BOTTOM_LEFT);
111 this->AddOthersToAnchor();
114 BOOL CRebaseDlg::OnInitDialog()
116 CResizableStandAloneDialog::OnInitDialog();
118 // Let the TaskbarButtonCreated message through the UIPI filter. If we don't
119 // do this, Explorer would be unable to send that message to our window if we
120 // were running elevated. It's OK to make the call all the time, since if we're
121 // not elevated, this is a no-op.
122 CHANGEFILTERSTRUCT cfs = { sizeof(CHANGEFILTERSTRUCT) };
123 typedef BOOL STDAPICALLTYPE ChangeWindowMessageFilterExDFN(HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct);
124 HMODULE hUser = ::LoadLibrary(_T("user32.dll"));
125 if (hUser)
127 ChangeWindowMessageFilterExDFN *pfnChangeWindowMessageFilterEx = (ChangeWindowMessageFilterExDFN*)GetProcAddress(hUser, "ChangeWindowMessageFilterEx");
128 if (pfnChangeWindowMessageFilterEx)
130 pfnChangeWindowMessageFilterEx(m_hWnd, WM_TASKBARBTNCREATED, MSGFLT_ALLOW, &cfs);
132 FreeLibrary(hUser);
134 m_pTaskbarList.Release();
135 m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList);
137 CRect rectDummy;
138 //IDC_REBASE_DUMY_TAB
140 GetClientRect(m_DlgOrigRect);
141 m_CommitList.GetClientRect(m_CommitListOrigRect);
143 CWnd *pwnd=this->GetDlgItem(IDC_REBASE_DUMY_TAB);
144 pwnd->GetWindowRect(&rectDummy);
145 this->ScreenToClient(rectDummy);
147 if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_REBASE_TAB))
149 TRACE0("Failed to create output tab window\n");
150 return FALSE; // fail to create
152 m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);
153 // Create output panes:
154 //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
155 DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;
157 if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) )
159 TRACE0("Failed to create output windows\n");
160 return FALSE; // fail to create
163 if( ! this->m_LogMessageCtrl.Create(_T("Scintilla"),_T("source"),0,rectDummy,&m_ctrlTabCtrl,0,0) )
165 TRACE0("Failed to create log message control");
166 return FALSE;
168 m_LogMessageCtrl.Init(0);
170 dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
172 if (!m_wndOutputRebase.Create(_T("Scintilla"),_T("source"),0,rectDummy, &m_ctrlTabCtrl, 0,0) )
174 TRACE0("Failed to create output windows\n");
175 return -1; // fail to create
177 m_wndOutputRebase.Init(0);
178 m_wndOutputRebase.Call(SCI_SETREADONLY, TRUE);
180 m_tooltips.Create(this);
182 m_tooltips.AddTool(IDC_REBASE_CHECK_FORCE,IDS_REBASE_FORCE_TT);
183 m_tooltips.AddTool(IDC_REBASE_ABORT,IDS_REBASE_ABORT_TT);
187 m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS |SVNSLC_COLADD|SVNSLC_COLDEL , _T("RebaseDlg"),(SVNSLC_POPALL ^ SVNSLC_POPCOMMIT),false);
189 m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Conflict File"));
190 m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Commit Message"),1);
191 m_ctrlTabCtrl.AddTab(&m_wndOutputRebase,_T("Log"),2);
192 AddRebaseAnchor();
195 EnableSaveRestore(_T("RebaseDlg"));
197 DWORD yPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));
198 RECT rcDlg, rcLogMsg, rcFileList;
199 GetClientRect(&rcDlg);
200 m_CommitList.GetWindowRect(&rcLogMsg);
201 ScreenToClient(&rcLogMsg);
202 this->m_ctrlTabCtrl.GetWindowRect(&rcFileList);
203 ScreenToClient(&rcFileList);
204 if (yPos)
206 RECT rectSplitter;
207 m_wndSplitter.GetWindowRect(&rectSplitter);
208 ScreenToClient(&rectSplitter);
209 int delta = yPos - rectSplitter.top;
210 if ((rcLogMsg.bottom + delta > rcLogMsg.top)&&(rcLogMsg.bottom + delta < rcFileList.bottom - 30))
212 m_wndSplitter.SetWindowPos(NULL, 0, yPos, 0, 0, SWP_NOSIZE);
213 DoSize(delta);
217 if( this->m_RebaseStage == CHOOSE_BRANCH)
219 this->LoadBranchInfo();
221 }else
223 this->m_BranchCtrl.EnableWindow(FALSE);
224 this->m_UpstreamCtrl.EnableWindow(FALSE);
227 m_CommitList.m_ColumnRegKey = _T("Rebase");
228 m_CommitList.m_IsIDReplaceAction = TRUE;
229 // m_CommitList.m_IsOldFirst = TRUE;
230 m_CommitList.m_IsRebaseReplaceGraph = TRUE;
232 m_CommitList.InsertGitColumn();
234 this->SetControlEnable();
236 if(!this->m_PreCmd.IsEmpty())
238 CProgressDlg progress;
239 progress.m_GitCmd=m_PreCmd;
240 progress.m_bAutoCloseOnSuccess=true;
241 progress.DoModal();
244 if(m_IsCherryPick)
246 this->m_BranchCtrl.SetCurSel(-1);
247 this->m_BranchCtrl.EnableWindow(FALSE);
248 this->m_UpstreamCtrl.EnableWindow(FALSE);
249 this->SetWindowText(_T("Cherry Pick"));
250 this->m_CommitList.StartFilter();
252 }else
254 SetContinueButtonText();
255 m_CommitList.DeleteAllItems();
256 FetchLogList();
259 m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_CHERRY_PICK)|
260 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_SWITCHTOREV)|
261 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_RESET)|
262 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTREV)|
263 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_TO_VERSION)|
264 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTTOREV)|
265 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_COMBINE_COMMIT));
267 if(m_CommitList.m_IsOldFirst)
268 this->m_CurrentRebaseIndex = -1;
269 else
270 this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();
273 if(this->CheckRebaseCondition())
275 /* Disable Start Rebase */
276 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);
279 return TRUE;
281 // CRebaseDlg message handlers
283 void CRebaseDlg::OnBnClickedPickAll()
285 this->UpdateData();
286 if(this->m_bPickAll)
287 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK);
289 this->m_bEditAll=FALSE;
290 this->m_bSquashAll=FALSE;
291 this->UpdateData(FALSE);
294 void CRebaseDlg::OnBnClickedSquashAll()
296 this->UpdateData();
297 if(this->m_bSquashAll)
298 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH);
300 this->m_bEditAll=FALSE;
301 this->m_bPickAll=FALSE;
302 this->UpdateData(FALSE);
305 void CRebaseDlg::OnBnClickedEditAll()
307 this->UpdateData();
308 if( this->m_bEditAll )
309 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT);
311 this->m_bPickAll=FALSE;
312 this->m_bSquashAll=FALSE;
313 this->UpdateData(FALSE);
316 void CRebaseDlg::SetAllRebaseAction(int action)
318 for(int i=0;i<this->m_CommitList.m_logEntries.size();i++)
320 m_CommitList.m_logEntries.GetGitRevAt(i).GetAction(&m_CommitList)=action;
322 m_CommitList.Invalidate();
325 void CRebaseDlg::OnBnClickedRebaseSplit()
327 this->UpdateData();
330 LRESULT CRebaseDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
332 switch (message) {
333 case WM_NOTIFY:
334 if (wParam == IDC_REBASE_SPLIT)
336 SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;
337 DoSize(pHdr->delta);
339 break;
342 return __super::DefWindowProc(message, wParam, lParam);
345 void CRebaseDlg::DoSize(int delta)
347 this->RemoveAllAnchors();
349 CSplitterControl::ChangeHeight(GetDlgItem(IDC_COMMIT_LIST), delta, CW_TOPALIGN);
350 //CSplitterControl::ChangeHeight(GetDlgItem(), delta, CW_TOPALIGN);
351 CSplitterControl::ChangeHeight(GetDlgItem(IDC_REBASE_TAB), -delta, CW_BOTTOMALIGN);
352 //CSplitterControl::ChangeHeight(GetDlgItem(), -delta, CW_BOTTOMALIGN);
353 CSplitterControl::ChangePos(GetDlgItem(IDC_SQUASH_ALL),0,delta);
354 CSplitterControl::ChangePos(GetDlgItem(IDC_PICK_ALL),0,delta);
355 CSplitterControl::ChangePos(GetDlgItem(IDC_EDIT_ALL),0,delta);
356 CSplitterControl::ChangePos(GetDlgItem(IDC_BUTTON_UP2),0,delta);
357 CSplitterControl::ChangePos(GetDlgItem(IDC_BUTTON_DOWN2),0,delta);
358 CSplitterControl::ChangePos(GetDlgItem(IDC_REBASE_CHECK_FORCE),0,delta);
360 this->AddRebaseAnchor();
361 // adjust the minimum size of the dialog to prevent the resizing from
362 // moving the list control too far down.
363 CRect rcLogMsg;
364 m_CommitList.GetClientRect(rcLogMsg);
365 SetMinTrackSize(CSize(m_DlgOrigRect.Width(), m_DlgOrigRect.Height()-m_CommitListOrigRect.Height()+rcLogMsg.Height()));
367 SetSplitterRange();
368 // m_CommitList.Invalidate();
370 // GetDlgItem(IDC_LOGMESSAGE)->Invalidate();
372 this->m_ctrlTabCtrl.Invalidate();
373 this->m_CommitList.Invalidate();
374 this->m_FileListCtrl.Invalidate();
375 this->m_LogMessageCtrl.Invalidate();
379 void CRebaseDlg::SetSplitterRange()
381 if ((m_CommitList)&&(m_ctrlTabCtrl))
383 CRect rcTop;
384 m_CommitList.GetWindowRect(rcTop);
385 ScreenToClient(rcTop);
386 CRect rcMiddle;
387 m_ctrlTabCtrl.GetWindowRect(rcMiddle);
388 ScreenToClient(rcMiddle);
389 if (rcMiddle.Height() && rcMiddle.Width())
390 m_wndSplitter.SetRange(rcTop.top+60, rcMiddle.bottom-80);
394 void CRebaseDlg::OnSize(UINT nType,int cx, int cy)
396 // first, let the resizing take place
397 __super::OnSize(nType, cx, cy);
399 //set range
400 SetSplitterRange();
403 void CRebaseDlg::SaveSplitterPos()
405 if (!IsIconic())
407 CRegDWORD regPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));
408 RECT rectSplitter;
409 m_wndSplitter.GetWindowRect(&rectSplitter);
410 ScreenToClient(&rectSplitter);
411 regPos = rectSplitter.top;
415 void CRebaseDlg::LoadBranchInfo()
417 m_BranchCtrl.SetMaxHistoryItems(0x7FFFFFFF);
418 m_UpstreamCtrl.SetMaxHistoryItems(0x7FFFFFFF);
420 STRING_VECTOR list;
421 list.clear();
422 int current;
423 g_Git.GetBranchList(list,&current,CGit::BRANCH_ALL);
424 m_BranchCtrl.AddString(list);
425 list.clear();
426 g_Git.GetBranchList(list,&current,CGit::BRANCH_ALL_F);
427 m_UpstreamCtrl.AddString(list);
429 m_BranchCtrl.SetCurSel(current);
431 AddBranchToolTips(&m_BranchCtrl);
432 AddBranchToolTips(&m_UpstreamCtrl);
434 if(!m_Upstream.IsEmpty())
436 m_UpstreamCtrl.AddString(m_Upstream);
437 m_UpstreamCtrl.SetCurSel(m_UpstreamCtrl.GetCount()-1);
439 else
441 //Select pull-remote from current branch
442 CString currentBranch = g_Git.GetSymbolicRef();
443 CString configName;
444 configName.Format(L"branch.%s.remote", currentBranch);
445 CString pullRemote = g_Git.GetConfigValue(configName);
447 //Select pull-branch from current branch
448 configName.Format(L"branch.%s.merge", currentBranch);
449 CString pullBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));
451 CString defaultUpstream;
452 defaultUpstream.Format(L"remotes/%s/%s", pullRemote, pullBranch);
453 int found = m_UpstreamCtrl.FindStringExact(0, defaultUpstream);
454 if(found >= 0)
455 m_UpstreamCtrl.SetCurSel(found);
459 void CRebaseDlg::OnCbnSelchangeBranch()
461 FetchLogList();
464 void CRebaseDlg::OnCbnSelchangeUpstream()
466 FetchLogList();
469 void CRebaseDlg::FetchLogList()
471 CGitHash base,hash;
472 CString basestr;
473 CString cmd;
474 m_IsFastForward=FALSE;
475 cmd.Format(_T("git.exe merge-base %s %s"), g_Git.FixBranchName(m_UpstreamCtrl.GetString()),
476 g_Git.FixBranchName(m_BranchCtrl.GetString()));
477 if(g_Git.Run(cmd,&basestr,CP_ACP))
479 CMessageBox::Show(NULL,basestr,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
480 return;
482 base=basestr;
484 hash=g_Git.GetHash(m_BranchCtrl.GetString());
486 if(hash == g_Git.GetHash(this->m_UpstreamCtrl.GetString()))
488 m_CommitList.Clear();
489 CString text,fmt;
490 fmt.LoadString(IDS_REBASE_EQUAL_FMT);
491 text.Format(fmt,m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString());
493 m_CommitList.ShowText(text);
494 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(false);
495 return;
498 if(hash == base )
500 //fast forword
501 this->m_IsFastForward=TRUE;
503 m_CommitList.Clear();
504 CString text,fmt;
505 fmt.LoadString(IDS_REBASE_FASTFORWARD_FMT);
506 text.Format(fmt,m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString(),
507 m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString());
509 m_CommitList.ShowText(text);
510 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(true);
511 SetContinueButtonText();
513 return ;
516 hash.Empty();
518 if(!this->m_bForce)
520 hash=g_Git.GetHash(m_UpstreamCtrl.GetString());
522 if( base == hash )
524 m_CommitList.Clear();
525 CString text,fmt;
526 fmt.LoadString(IDS_REBASE_UPTODATE_FMT);
527 text.Format(fmt,m_BranchCtrl.GetString());
528 m_CommitList.ShowText(text);
529 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(m_CommitList.GetItemCount());
530 SetContinueButtonText();
531 return;
535 m_CommitList.Clear();
536 CString from,to;
537 from = m_UpstreamCtrl.GetString();
538 to = m_BranchCtrl.GetString();
539 this->m_CommitList.FillGitLog(NULL,0,&from,&to);
541 if( m_CommitList.GetItemCount() == 0 )
542 m_CommitList.ShowText(_T("Nothing to Rebase"));
544 hash=g_Git.GetHash(m_UpstreamCtrl.GetString());
546 #if 0
547 if(m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash.size() >=0 )
549 if(hash == m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash[0])
551 m_CommitList.Clear();
552 m_CommitList.ShowText(_T("Nothing Rebase"));
555 #endif
557 m_tooltips.Pop();
558 AddBranchToolTips(&this->m_BranchCtrl);
559 AddBranchToolTips(&this->m_UpstreamCtrl);
561 for(int i=0;i<m_CommitList.m_logEntries.size();i++)
563 m_CommitList.m_logEntries.GetGitRevAt(i).GetAction(&m_CommitList) = CTGitPath::LOGACTIONS_REBASE_PICK;
566 m_CommitList.Invalidate();
568 if(m_CommitList.m_IsOldFirst)
569 this->m_CurrentRebaseIndex = -1;
570 else
571 this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();
573 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(m_CommitList.GetItemCount());
574 SetContinueButtonText();
577 void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)
579 if(pBranch)
581 CString text=pBranch->GetString();
582 CString tooltip;
584 GitRev rev;
585 rev.GetCommit(text);
587 tooltip.Format(_T("CommitHash:%s\nCommit by: %s %s\n <b>%s</b> \n %s"),
588 rev.m_CommitHash.ToString(),
589 rev.GetAuthorName(),
590 CAppUtils::FormatDateAndTime(rev.GetAuthorDate(),DATE_LONGDATE),
591 rev.GetSubject(),
592 rev.GetBody());
594 pBranch->DisableTooltip();
595 this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip);
599 BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg)
601 if (pMsg->message == WM_KEYDOWN)
603 switch (pMsg->wParam)
606 case VK_F5:
608 Refresh();
609 return TRUE;
611 break;
612 /* Avoid TAB control destroy but dialog exist*/
613 case VK_ESCAPE:
614 case VK_CANCEL:
616 TCHAR buff[128];
617 ::GetClassName(pMsg->hwnd,buff,128);
620 if(_tcsnicmp(buff,_T("RichEdit20W"),128)==0 ||
621 _tcsnicmp(buff,_T("Scintilla"),128)==0 ||
622 _tcsnicmp(buff,_T("SysListView32"),128)==0||
623 ::GetParent(pMsg->hwnd) == this->m_ctrlTabCtrl.m_hWnd)
625 this->PostMessage(WM_KEYDOWN,VK_ESCAPE,0);
626 return TRUE;
631 m_tooltips.RelayEvent(pMsg);
632 return CResizableStandAloneDialog::PreTranslateMessage(pMsg);
634 int CRebaseDlg::CheckRebaseCondition()
636 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
638 if( !g_Git.CheckCleanWorkTree() )
640 if(CMessageBox::Show(NULL, IDS_ERROR_NOCLEAN_STASH,IDS_APPNAME,MB_YESNO|MB_ICONINFORMATION)==IDYES)
642 CString cmd,out;
643 cmd=_T("git.exe stash");
644 this->AddLogString(cmd);
645 if(g_Git.Run(cmd,&out,CP_ACP))
647 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK);
648 return -1;
651 }else
652 return -1;
654 //Todo Check $REBASE_ROOT
655 //Todo Check $DOTEST
657 CString cmd;
658 cmd=_T("git.exe var GIT_COMMITTER_IDENT");
659 if(g_Git.Run(cmd,NULL,CP_UTF8))
660 return -1;
662 //Todo call pre_rebase_hook
663 return 0;
665 int CRebaseDlg::StartRebase()
667 CString cmd,out;
668 m_FileListCtrl.m_bIsRevertTheirMy = !m_IsCherryPick;
669 if(!this->m_IsCherryPick)
671 //Todo call comment_for_reflog
672 cmd.Format(_T("git.exe checkout %s"),this->m_BranchCtrl.GetString());
673 this->AddLogString(cmd);
675 if(g_Git.Run(cmd,&out,CP_UTF8))
676 return -1;
678 this->AddLogString(out);
681 cmd=_T("git.exe rev-parse --verify HEAD");
682 if(g_Git.Run(cmd,&out,CP_UTF8))
684 AddLogString(_T("No Head"));
685 return -1;
687 //Todo
688 //git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
689 // echo "detached HEAD" > "$DOTEST"/head-name
691 cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));
692 if(g_Git.Run(cmd,&out,CP_UTF8))
694 AddLogString(_T("update ORIG_HEAD Fail"));
695 return -1;
698 m_OrigUpstreamHash.Empty();
699 m_OrigUpstreamHash= g_Git.GetHash(this->m_UpstreamCtrl.GetString());
700 if(m_OrigUpstreamHash.IsEmpty())
702 this->AddLogString(m_OrigUpstreamHash);
703 return -1;
706 if( !this->m_IsCherryPick )
708 cmd.Format(_T("git.exe checkout -f %s"), m_OrigUpstreamHash.ToString());
709 this->AddLogString(cmd);
711 out.Empty();
712 if(g_Git.Run(cmd,&out,CP_UTF8))
714 this->AddLogString(out);
715 return -1;
719 if( !this->m_IsCherryPick )
721 m_OrigBranchHash = g_Git.GetHash(this->m_BranchCtrl.GetString());
722 if(m_OrigBranchHash.IsEmpty())
724 this->AddLogString(m_OrigBranchHash.ToString());
725 return -1;
727 this->AddLogString(_T("Start Rebase\r\n"));
729 }else
730 this->AddLogString(_T("Start Cherry-pick\r\n"));
732 return 0;
734 int CRebaseDlg::VerifyNoConflict()
736 CTGitPathList list;
737 if(g_Git.ListConflictFile(list))
739 AddLogString(_T("Get conflict files fail"));
740 return -1;
742 if( list.GetCount() != 0 )
744 CMessageBox::Show(NULL,_T("There are conflict file, you should mark it resolve"),_T("TortoiseGit"),MB_OK);
745 return -1;
747 return 0;
750 int CRebaseDlg::FinishRebase()
752 if(this->m_IsCherryPick) //cherry pick mode no "branch", working at upstream branch
753 return 0;
755 git_revnum_t head = g_Git.GetHash(_T("HEAD"));
756 CString out,cmd;
758 out.Empty();
759 cmd.Format(_T("git.exe checkout -f %s"),this->m_BranchCtrl.GetString());
760 AddLogString(cmd);
761 if(g_Git.Run(cmd,&out,CP_UTF8))
763 AddLogString(out);
764 return -1;
766 AddLogString(out);
768 out.Empty();
769 cmd.Format(_T("git.exe reset --hard %s"),head);
770 AddLogString(cmd);
771 if(g_Git.Run(cmd,&out,CP_UTF8))
773 AddLogString(out);
774 return -1;
776 AddLogString(out);
778 return 0;
780 void CRebaseDlg::OnBnClickedContinue()
782 if( m_RebaseStage == REBASE_DONE)
784 OnOK();
785 return;
788 if( this->m_IsFastForward )
790 CString cmd,out;
791 CString oldbranch = g_Git.GetCurrentBranch();
792 if( oldbranch != m_BranchCtrl.GetString() )
794 cmd.Format(_T("git.exe checkout %s"),m_BranchCtrl.GetString());
795 AddLogString(cmd);
796 if( g_Git.Run(cmd,&out,CP_ACP) )
798 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
799 AddLogString(out);
800 return;
803 AddLogString(out);
804 out.Empty();
805 m_OrigBranchHash = g_Git.GetHash(m_BranchCtrl.GetString());
806 m_OrigUpstreamHash = g_Git.GetHash(this->m_UpstreamCtrl.GetString());
808 if(!g_Git.IsFastForward(this->m_BranchCtrl.GetString(),this->m_UpstreamCtrl.GetString()))
810 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
811 AddLogString(_T("No fast forward\r\nMaybe repository changed"));
812 return;
815 cmd.Format(_T("git.exe reset --hard %s"),g_Git.FixBranchName(this->m_UpstreamCtrl.GetString()));
816 this->AddLogString(CString(_T("Fast forward to "))+m_UpstreamCtrl.GetString());
818 AddLogString(cmd);
819 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
820 if(g_Git.Run(cmd,&out,CP_ACP))
822 AddLogString(_T("Fail"));
823 AddLogString(out);
824 return;
826 AddLogString(out);
827 AddLogString(_T("Done"));
828 m_RebaseStage = REBASE_DONE;
829 UpdateCurrentStatus();
830 return;
833 if( m_RebaseStage == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE )
835 if(CheckRebaseCondition())
836 return ;
837 m_RebaseStage = REBASE_START;
840 if( m_RebaseStage == REBASE_FINISH )
842 if(FinishRebase())
843 return ;
845 OnOK();
848 if( m_RebaseStage == REBASE_SQUASH_CONFLICT)
850 if(VerifyNoConflict())
851 return;
852 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
853 if(this->CheckNextCommitIsSquash())
854 {//next commit is not squash;
855 m_RebaseStage = REBASE_SQUASH_EDIT;
856 this->OnRebaseUpdateUI(0,0);
857 this->UpdateCurrentStatus();
858 return ;
861 m_RebaseStage=REBASE_CONTINUE;
862 curRev->GetAction(&m_CommitList)|=CTGitPath::LOGACTIONS_REBASE_DONE;
863 this->UpdateCurrentStatus();
867 if( m_RebaseStage == REBASE_CONFLICT )
869 if(VerifyNoConflict())
870 return;
872 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
874 CString out =_T("");
875 CString cmd;
876 cmd.Format(_T("git.exe commit -C %s"), curRev->m_CommitHash.ToString());
878 AddLogString(cmd);
880 if(g_Git.Run(cmd,&out,CP_UTF8))
882 AddLogString(out);
883 if(!g_Git.CheckCleanWorkTree())
885 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
886 return;
890 AddLogString(out);
891 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
892 if( curRev->GetAction(&m_CommitList) & CTGitPath::LOGACTIONS_REBASE_EDIT)
894 m_RebaseStage=REBASE_EDIT;
895 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);
896 this->UpdateCurrentStatus();
897 return;
899 else
901 m_RebaseStage=REBASE_CONTINUE;
902 curRev->GetAction(&m_CommitList)|=CTGitPath::LOGACTIONS_REBASE_DONE;
903 this->UpdateCurrentStatus();
907 if( m_RebaseStage == REBASE_EDIT || m_RebaseStage == REBASE_SQUASH_EDIT )
909 CString str;
910 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
912 str=this->m_LogMessageCtrl.GetText();
913 if(str.Trim().IsEmpty())
915 CMessageBox::Show(NULL,_T("Commit Message Is Empty"),_T("TortoiseGit"),MB_OK|MB_ICONERROR);
916 return;
919 CString tempfile=::GetTempFile();
920 CFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );
921 CStringA log=CUnicodeUtils::GetUTF8( str);
922 file.Write(log,log.GetLength());
923 //file.WriteString(m_sLogMessage);
924 file.Close();
926 CString out,cmd;
928 if( m_RebaseStage == REBASE_SQUASH_EDIT )
929 cmd.Format(_T("git.exe commit -F \"%s\""), tempfile);
930 else
931 cmd.Format(_T("git.exe commit --amend -F \"%s\""), tempfile);
933 if(g_Git.Run(cmd,&out,CP_UTF8))
935 if(!g_Git.CheckCleanWorkTree())
937 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);
938 return;
942 CFile::Remove(tempfile);
943 AddLogString(out);
944 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
945 m_RebaseStage=REBASE_CONTINUE;
946 curRev->GetAction(&m_CommitList)|=CTGitPath::LOGACTIONS_REBASE_DONE;
947 this->UpdateCurrentStatus();
951 InterlockedExchange(&m_bThreadRunning, TRUE);
952 SetControlEnable();
954 if (AfxBeginThread(RebaseThreadEntry, this)==NULL)
956 InterlockedExchange(&m_bThreadRunning, FALSE);
957 CMessageBox::Show(NULL, _T("Create Rebase Thread Fail"), _T("TortoiseGit"), MB_OK | MB_ICONERROR);
958 SetControlEnable();
961 int CRebaseDlg::CheckNextCommitIsSquash()
963 int index;
964 if(m_CommitList.m_IsOldFirst)
965 index=m_CurrentRebaseIndex+1;
966 else
967 index=m_CurrentRebaseIndex-1;
969 GitRev *curRev;
972 if(index<0)
973 return -1;
974 if(index>= m_CommitList.GetItemCount())
975 return -1;
977 curRev=(GitRev*)m_CommitList.m_arShownList[index];
979 if( curRev->GetAction(&m_CommitList)&CTGitPath::LOGACTIONS_REBASE_SQUASH )
980 return 0;
981 if( curRev->GetAction(&m_CommitList)&CTGitPath::LOGACTIONS_REBASE_SKIP)
983 if(m_CommitList.m_IsOldFirst)
984 index++;
985 else
986 index--;
987 }else
988 return -1;
990 }while(curRev->GetAction(&m_CommitList)&CTGitPath::LOGACTIONS_REBASE_SKIP);
992 return -1;
995 int CRebaseDlg::GoNext()
997 if(m_CommitList.m_IsOldFirst)
998 m_CurrentRebaseIndex++;
999 else
1000 m_CurrentRebaseIndex--;
1001 return 0;
1004 int CRebaseDlg::StateAction()
1006 switch(this->m_RebaseStage)
1008 case CHOOSE_BRANCH:
1009 case CHOOSE_COMMIT_PICK_MODE:
1010 if(StartRebase())
1011 return -1;
1012 m_RebaseStage = REBASE_START;
1013 GoNext();
1014 break;
1017 return 0;
1019 void CRebaseDlg::SetContinueButtonText()
1021 CString Text;
1022 switch(this->m_RebaseStage)
1024 case CHOOSE_BRANCH:
1025 case CHOOSE_COMMIT_PICK_MODE:
1026 if(this->m_IsFastForward)
1027 Text = _T("Start(FastFwd)");
1028 else
1029 Text = _T("Start");
1030 break;
1032 case REBASE_START:
1033 case REBASE_CONTINUE:
1034 case REBASE_SQUASH_CONFLICT:
1035 Text = _T("Continue");
1036 break;
1038 case REBASE_CONFLICT:
1039 Text = _T("Commit");
1040 break;
1041 case REBASE_EDIT:
1042 Text = _T("Amend");
1043 break;
1045 case REBASE_SQUASH_EDIT:
1046 Text = _T("Commit");
1047 break;
1049 case REBASE_ABORT:
1050 case REBASE_FINISH:
1051 Text = _T("Finish");
1052 break;
1054 case REBASE_DONE:
1055 Text = _T("Done");
1056 break;
1058 this->GetDlgItem(IDC_REBASE_CONTINUE)->SetWindowText(Text);
1061 void CRebaseDlg::SetControlEnable()
1063 switch(this->m_RebaseStage)
1065 case CHOOSE_BRANCH:
1066 case CHOOSE_COMMIT_PICK_MODE:
1068 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(TRUE);
1069 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(TRUE);
1070 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(TRUE);
1071 this->GetDlgItem(IDC_BUTTON_UP2)->EnableWindow(TRUE);
1072 this->GetDlgItem(IDC_BUTTON_DOWN2)->EnableWindow(TRUE);
1074 if(!m_IsCherryPick)
1076 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE);
1077 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE);
1078 this->GetDlgItem(IDC_REBASE_CHECK_FORCE)->EnableWindow(TRUE);
1080 //this->m_CommitList.m_IsEnableRebaseMenu=TRUE;
1081 this->m_CommitList.m_ContextMenuMask |= m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|
1082 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|
1083 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|
1084 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP);
1085 break;
1087 case REBASE_START:
1088 case REBASE_CONTINUE:
1089 case REBASE_ABORT:
1090 case REBASE_FINISH:
1091 case REBASE_CONFLICT:
1092 case REBASE_EDIT:
1093 case REBASE_SQUASH_CONFLICT:
1094 case REBASE_DONE:
1095 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(FALSE);
1096 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(FALSE);
1097 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(FALSE);
1098 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(FALSE);
1099 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(FALSE);
1100 this->GetDlgItem(IDC_REBASE_CHECK_FORCE)->EnableWindow(FALSE);
1101 this->GetDlgItem(IDC_BUTTON_UP2)->EnableWindow(FALSE);
1102 this->GetDlgItem(IDC_BUTTON_DOWN2)->EnableWindow(FALSE);
1103 //this->m_CommitList.m_IsEnableRebaseMenu=FALSE;
1104 this->m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|
1105 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|
1106 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|
1107 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP));
1109 if( m_RebaseStage == REBASE_DONE && (this->m_PostButtonTexts.GetCount() != 0) )
1111 this->GetDlgItem(IDC_STATUS_STATIC)->ShowWindow(SW_HIDE);
1112 this->GetDlgItem(IDC_REBASE_POST_BUTTON)->ShowWindow(SW_SHOWNORMAL);
1113 this->m_PostButton.RemoveAll();
1114 this->m_PostButton.AddEntries(m_PostButtonTexts);
1115 //this->GetDlgItem(IDC_REBASE_POST_BUTTON)->SetWindowText(this->m_PostButtonText);
1117 break;
1120 if(m_bThreadRunning)
1122 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);
1123 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(FALSE);
1125 }else
1127 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(TRUE);
1128 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(TRUE);
1132 void CRebaseDlg::UpdateProgress()
1134 int index;
1135 CRect rect;
1137 if(m_CommitList.m_IsOldFirst)
1138 index = m_CurrentRebaseIndex+1;
1139 else
1140 index = m_CommitList.GetItemCount()-m_CurrentRebaseIndex;
1142 m_ProgressBar.SetRange(1,m_CommitList.GetItemCount());
1143 m_ProgressBar.SetPos(index);
1144 if (m_pTaskbarList)
1146 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NORMAL);
1147 m_pTaskbarList->SetProgressValue(m_hWnd, index, m_CommitList.GetItemCount());
1150 if(m_CurrentRebaseIndex>=0 && m_CurrentRebaseIndex< m_CommitList.GetItemCount())
1152 CString text;
1153 text.Format(_T("Rebasing...(%d/%d)"),index,m_CommitList.GetItemCount());
1154 m_CtrlStatusText.SetWindowText(text);
1158 GitRev *prevRev=NULL, *curRev=NULL;
1160 if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize())
1162 curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
1165 for(int i=0;i<m_CommitList.m_arShownList.GetSize();i++)
1167 prevRev=(GitRev*)m_CommitList.m_arShownList[i];
1168 if(prevRev->GetAction(&m_CommitList) & CTGitPath::LOGACTIONS_REBASE_CURRENT)
1170 prevRev->GetAction(&m_CommitList) &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;
1171 m_CommitList.GetItemRect(i,&rect,LVIR_BOUNDS);
1172 m_CommitList.InvalidateRect(rect);
1176 if(curRev)
1178 curRev->GetAction(&m_CommitList) |= CTGitPath::LOGACTIONS_REBASE_CURRENT;
1179 m_CommitList.GetItemRect(m_CurrentRebaseIndex,&rect,LVIR_BOUNDS);
1180 m_CommitList.InvalidateRect(rect);
1182 m_CommitList.EnsureVisible(m_CurrentRebaseIndex,FALSE);
1185 void CRebaseDlg::UpdateCurrentStatus()
1187 SetContinueButtonText();
1188 SetControlEnable();
1189 UpdateProgress();
1192 void CRebaseDlg::AddLogString(CString str)
1194 this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, FALSE);
1195 CStringA sTextA = m_wndOutputRebase.StringForControl(str);//CUnicodeUtils::GetUTF8(str);
1196 this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)sTextA);
1197 this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)"\n");
1198 this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, TRUE);
1201 int CRebaseDlg::GetCurrentCommitID()
1203 if(m_CommitList.m_IsOldFirst)
1205 return this->m_CurrentRebaseIndex+1;
1207 }else
1209 return m_CommitList.GetItemCount()-m_CurrentRebaseIndex;
1213 int CRebaseDlg::DoRebase()
1215 CString cmd,out;
1216 if(m_CurrentRebaseIndex <0)
1217 return 0;
1218 if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )
1219 return 0;
1221 GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
1222 int mode=pRev->GetAction(&m_CommitList) & CTGitPath::LOGACTIONS_REBASE_MODE_MASK;
1223 CString nocommit;
1225 if( mode== CTGitPath::LOGACTIONS_REBASE_SKIP)
1227 pRev->GetAction(&m_CommitList)|= CTGitPath::LOGACTIONS_REBASE_DONE;
1228 return 0;
1231 if( mode != CTGitPath::LOGACTIONS_REBASE_PICK )
1233 this->m_SquashMessage+= pRev->GetSubject();
1234 this->m_SquashMessage+= _T("\n");
1235 this->m_SquashMessage+= pRev->GetBody();
1237 else
1238 this->m_SquashMessage.Empty();
1240 if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)
1241 nocommit=_T(" --no-commit ");
1243 CString log;
1244 log.Format(_T("%s %d: %s"),CTGitPath::GetActionName(mode),this->GetCurrentCommitID(),pRev->m_CommitHash.ToString());
1245 AddLogString(log);
1246 AddLogString(pRev->GetSubject());
1247 cmd.Format(_T("git.exe cherry-pick %s %s"),nocommit,pRev->m_CommitHash.ToString());
1249 if(g_Git.Run(cmd,&out,CP_UTF8))
1251 AddLogString(out);
1252 CTGitPathList list;
1253 if(g_Git.ListConflictFile(list))
1255 AddLogString(_T("Get conflict files fail"));
1256 return -1;
1258 if(list.GetCount() == 0 )
1260 if(mode == CTGitPath::LOGACTIONS_REBASE_PICK)
1262 pRev->GetAction(&m_CommitList)|= CTGitPath::LOGACTIONS_REBASE_DONE;
1263 return 0;
1265 if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)
1267 this->m_RebaseStage = REBASE_EDIT ;
1268 return -1; // Edit return -1 to stop rebase.
1270 // Squash Case
1271 if(CheckNextCommitIsSquash())
1272 { // no squash
1273 // let user edit last commmit message
1274 this->m_RebaseStage = REBASE_SQUASH_EDIT;
1275 return -1;
1278 if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)
1279 m_RebaseStage = REBASE_SQUASH_CONFLICT;
1280 else
1281 m_RebaseStage = REBASE_CONFLICT;
1282 return -1;
1284 }else
1286 AddLogString(out);
1287 if(mode == CTGitPath::LOGACTIONS_REBASE_PICK)
1289 pRev->GetAction(&m_CommitList)|= CTGitPath::LOGACTIONS_REBASE_DONE;
1290 return 0;
1292 if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)
1294 this->m_RebaseStage = REBASE_EDIT ;
1295 return -1; // Edit return -1 to stop rebase.
1298 // Squash Case
1299 if(CheckNextCommitIsSquash())
1300 { // no squash
1301 // let user edit last commmit message
1302 this->m_RebaseStage = REBASE_SQUASH_EDIT;
1303 return -1;
1307 return 0;
1310 BOOL CRebaseDlg::IsEnd()
1312 if(m_CommitList.m_IsOldFirst)
1313 return m_CurrentRebaseIndex>= this->m_CommitList.GetItemCount();
1314 else
1315 return m_CurrentRebaseIndex<0;
1318 int CRebaseDlg::RebaseThread()
1320 int ret=0;
1321 while(1)
1323 if( m_RebaseStage == REBASE_START )
1325 if( this->StartRebase() )
1327 InterlockedExchange(&m_bThreadRunning, FALSE);
1328 ret = -1;
1329 break;
1331 m_RebaseStage = REBASE_CONTINUE;
1333 }else if( m_RebaseStage == REBASE_CONTINUE )
1335 this->GoNext();
1336 if(IsEnd())
1338 ret = 0;
1339 m_RebaseStage = REBASE_FINISH;
1341 }else
1343 ret = DoRebase();
1345 if( ret )
1347 break;
1351 }else if( m_RebaseStage == REBASE_FINISH )
1353 FinishRebase();
1354 m_RebaseStage = REBASE_DONE;
1355 if (m_pTaskbarList)
1356 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
1357 break;
1359 }else
1361 break;
1363 this->PostMessage(MSG_REBASE_UPDATE_UI);
1364 //this->UpdateCurrentStatus();
1367 InterlockedExchange(&m_bThreadRunning, FALSE);
1368 this->PostMessage(MSG_REBASE_UPDATE_UI);
1369 return ret;
1372 void CRebaseDlg::ListConflictFile()
1374 this->m_FileListCtrl.Clear();
1375 CTGitPathList list;
1376 CTGitPath path;
1377 list.AddPath(path);
1379 m_FileListCtrl.m_bIsRevertTheirMy = !m_IsCherryPick;
1381 this->m_FileListCtrl.GetStatus(&list,true);
1382 this->m_FileListCtrl.Show(CTGitPath::LOGACTIONS_UNMERGED|CTGitPath::LOGACTIONS_MODIFIED|CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_DELETED,
1383 CTGitPath::LOGACTIONS_UNMERGED);
1386 LRESULT CRebaseDlg::OnRebaseUpdateUI(WPARAM,LPARAM)
1388 UpdateCurrentStatus();
1389 if(m_CurrentRebaseIndex <0)
1390 return 0;
1391 if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )
1392 return 0;
1393 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];
1395 switch(m_RebaseStage)
1397 case REBASE_CONFLICT:
1398 case REBASE_SQUASH_CONFLICT:
1399 ListConflictFile();
1400 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_CONFLICT);
1401 if (m_pTaskbarList)
1402 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_ERROR);
1403 this->m_LogMessageCtrl.SetText(curRev->GetSubject()+_T("\n")+curRev->GetBody());
1404 break;
1405 case REBASE_EDIT:
1406 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);
1407 if (m_pTaskbarList)
1408 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_PAUSED);
1409 this->m_LogMessageCtrl.SetText(curRev->GetSubject()+_T("\n")+curRev->GetBody());
1410 break;
1411 case REBASE_SQUASH_EDIT:
1412 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);
1413 this->m_LogMessageCtrl.SetText(this->m_SquashMessage);
1414 if (m_pTaskbarList)
1415 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_PAUSED);
1416 break;
1417 default:
1418 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);
1420 return 0;
1422 void CRebaseDlg::OnCancel()
1424 OnBnClickedAbort();
1426 void CRebaseDlg::OnBnClickedAbort()
1428 if (m_pTaskbarList)
1429 m_pTaskbarList->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
1431 CString cmd,out;
1432 if(m_OrigUpstreamHash.IsEmpty())
1434 __super::OnCancel();
1437 if(m_RebaseStage == CHOOSE_BRANCH || m_RebaseStage== CHOOSE_COMMIT_PICK_MODE)
1439 return;
1442 if(CMessageBox::Show(NULL,_T("Are you sure you want to abort the rebase process?"),_T("TortoiseGit"),MB_YESNO) != IDYES)
1443 return;
1445 if(this->m_IsFastForward)
1447 cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigBranchHash.ToString());
1448 if(g_Git.Run(cmd,&out,CP_UTF8))
1450 AddLogString(out);
1451 return ;
1453 __super::OnCancel();
1454 return;
1456 cmd.Format(_T("git.exe checkout -f %s"),g_Git.FixBranchName(this->m_UpstreamCtrl.GetString()));
1457 if(g_Git.Run(cmd,&out,CP_UTF8))
1459 AddLogString(out);
1460 return ;
1463 cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash.ToString());
1464 if(g_Git.Run(cmd,&out,CP_UTF8))
1466 AddLogString(out);
1467 return ;
1470 if(this->m_IsCherryPick) //there are not "branch" at cherry pick mode
1472 __super::OnCancel();
1473 return;
1476 cmd.Format(_T("git checkout -f %s"),this->m_BranchCtrl.GetString());
1477 if(g_Git.Run(cmd,&out,CP_UTF8))
1479 AddLogString(out);
1480 return ;
1483 cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigBranchHash.ToString());
1484 if(g_Git.Run(cmd,&out,CP_UTF8))
1486 AddLogString(out);
1487 return ;
1489 __super::OnCancel();
1492 void CRebaseDlg::OnBnClickedButtonBrowse()
1494 if(CBrowseRefsDlg::PickRefForCombo(&m_UpstreamCtrl, gPickRef_NoTag))
1495 OnCbnSelchangeUpstream();
1498 void CRebaseDlg::OnBnClickedRebaseCheckForce()
1500 this->UpdateData();
1501 this->FetchLogList();
1502 if(this->CheckRebaseCondition())
1504 /* Disable Start Rebase */
1505 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);
1509 void CRebaseDlg::OnBnClickedRebasePostButton()
1511 this->m_Upstream=this->m_UpstreamCtrl.GetString();
1512 this->m_Branch=this->m_BranchCtrl.GetString();
1514 this->EndDialog(IDC_REBASE_POST_BUTTON+this->m_PostButton.GetCurrentEntry());
1517 void CRebaseDlg::Refresh()
1519 if(this->m_IsCherryPick)
1520 return ;
1522 if(this->m_RebaseStage == CHOOSE_BRANCH )
1524 this->UpdateData();
1525 this->FetchLogList();
1526 if(this->CheckRebaseCondition())
1528 /* Disable Start Rebase */
1529 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);
1534 void CRebaseDlg::OnBnClickedButtonUp2()
1536 POSITION pos;
1537 pos = m_CommitList.GetFirstSelectedItemPosition();
1538 bool changed = false;
1539 while(pos)
1541 int index=m_CommitList.GetNextSelectedItem(pos);
1542 if(index>=1)
1544 CGitHash old = m_CommitList.m_logEntries[index-1];
1545 m_CommitList.m_logEntries[index-1] = m_CommitList.m_logEntries[index];
1546 m_CommitList.m_logEntries[index] = old;
1547 m_CommitList.SetItemState(index-1, LVIS_SELECTED, LVIS_SELECTED);
1548 m_CommitList.SetItemState(index, 0, LVIS_SELECTED);
1549 changed = true;
1552 if (changed)
1554 m_CommitList.RecalculateShownList(&m_CommitList.m_arShownList);
1555 m_CommitList.Invalidate();
1556 m_CommitList.SetFocus();
1560 void CRebaseDlg::OnBnClickedButtonDown2()
1562 POSITION pos;
1563 pos = m_CommitList.GetFirstSelectedItemPosition();
1564 bool changed = false;
1565 while(pos)
1567 int index=m_CommitList.GetNextSelectedItem(pos);
1568 if(index<m_CommitList.GetItemCount()-1)
1570 CGitHash old = m_CommitList.m_logEntries[index+1];
1571 m_CommitList.m_logEntries[index+1] = m_CommitList.m_logEntries[index];
1572 m_CommitList.m_logEntries[index] = old;
1573 m_CommitList.SetItemState(index, 0, LVIS_SELECTED);
1574 m_CommitList.SetItemState(index+1, LVIS_SELECTED, LVIS_SELECTED);
1575 changed = true;
1578 if (changed)
1580 m_CommitList.RecalculateShownList(&m_CommitList.m_arShownList);
1581 m_CommitList.Invalidate();
1582 m_CommitList.SetFocus();
1586 LRESULT CRebaseDlg::OnTaskbarBtnCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
1588 m_pTaskbarList.Release();
1589 m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList);
1590 return 0;