1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2012 - TortoiseGit
4 // Copyright (C) 2011-2012 - Sven Strickroth <email@cs-ware.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 // RebaseDlg.cpp : implementation file
25 #include "TortoiseProc.h"
26 #include "RebaseDlg.h"
28 #include "LoglistUtils.h"
29 #include "MessageBox.h"
30 #include "UnicodeUtils.h"
31 #include "BrowseRefsDlg.h"
32 #include "ProgressDlg.h"
33 #include "SmartHandle.h"
34 #include "../TGitCache/CacheInterface.h"
38 IMPLEMENT_DYNAMIC(CRebaseDlg
, CResizableStandAloneDialog
)
40 CRebaseDlg::CRebaseDlg(CWnd
* pParent
/*=NULL*/)
41 : CResizableStandAloneDialog(CRebaseDlg::IDD
, pParent
)
46 m_RebaseStage
=CHOOSE_BRANCH
;
47 m_CurrentRebaseIndex
=-1;
48 m_bThreadRunning
=FALSE
;
49 this->m_IsCherryPick
= FALSE
;
51 m_IsFastForward
=FALSE
;
54 CRebaseDlg::~CRebaseDlg()
58 void CRebaseDlg::DoDataExchange(CDataExchange
* pDX
)
60 CDialog::DoDataExchange(pDX
);
61 DDX_Control(pDX
, IDC_REBASE_PROGRESS
, m_ProgressBar
);
62 DDX_Control(pDX
, IDC_STATUS_STATIC
, m_CtrlStatusText
);
63 DDX_Check(pDX
, IDC_PICK_ALL
, m_bPickAll
);
64 DDX_Check(pDX
, IDC_SQUASH_ALL
, m_bSquashAll
);
65 DDX_Check(pDX
, IDC_EDIT_ALL
, m_bEditAll
);
66 DDX_Control(pDX
, IDC_REBASE_SPLIT
, m_wndSplitter
);
67 DDX_Control(pDX
,IDC_COMMIT_LIST
,m_CommitList
);
68 DDX_Control(pDX
,IDC_REBASE_COMBOXEX_BRANCH
, this->m_BranchCtrl
);
69 DDX_Control(pDX
,IDC_REBASE_COMBOXEX_UPSTREAM
, this->m_UpstreamCtrl
);
70 DDX_Check(pDX
, IDC_REBASE_CHECK_FORCE
,m_bForce
);
71 DDX_Control(pDX
,IDC_REBASE_POST_BUTTON
,m_PostButton
);
75 BEGIN_MESSAGE_MAP(CRebaseDlg
, CResizableStandAloneDialog
)
76 ON_BN_CLICKED(IDC_PICK_ALL
, &CRebaseDlg::OnBnClickedPickAll
)
77 ON_BN_CLICKED(IDC_SQUASH_ALL
, &CRebaseDlg::OnBnClickedSquashAll
)
78 ON_BN_CLICKED(IDC_EDIT_ALL
, &CRebaseDlg::OnBnClickedEditAll
)
79 ON_BN_CLICKED(IDC_REBASE_SPLIT
, &CRebaseDlg::OnBnClickedRebaseSplit
)
80 ON_BN_CLICKED(IDC_REBASE_CONTINUE
,OnBnClickedContinue
)
81 ON_BN_CLICKED(IDC_REBASE_ABORT
, OnBnClickedAbort
)
83 ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH
, &CRebaseDlg::OnCbnSelchangeBranch
)
84 ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM
, &CRebaseDlg::OnCbnSelchangeUpstream
)
85 ON_MESSAGE(MSG_REBASE_UPDATE_UI
, OnRebaseUpdateUI
)
86 ON_BN_CLICKED(IDC_BUTTON_BROWSE
, &CRebaseDlg::OnBnClickedButtonBrowse
)
87 ON_BN_CLICKED(IDC_REBASE_CHECK_FORCE
, &CRebaseDlg::OnBnClickedRebaseCheckForce
)
88 ON_BN_CLICKED(IDC_REBASE_POST_BUTTON
, &CRebaseDlg::OnBnClickedRebasePostButton
)
89 ON_BN_CLICKED(IDC_BUTTON_UP2
, &CRebaseDlg::OnBnClickedButtonUp2
)
90 ON_BN_CLICKED(IDC_BUTTON_DOWN2
, &CRebaseDlg::OnBnClickedButtonDown2
)
91 ON_REGISTERED_MESSAGE(WM_TASKBARBTNCREATED
, OnTaskbarBtnCreated
)
92 ON_NOTIFY(LVN_ITEMCHANGED
, IDC_COMMIT_LIST
, OnLvnItemchangedLoglist
)
95 void CRebaseDlg::AddRebaseAnchor()
97 AddAnchor(IDC_REBASE_TAB
,TOP_LEFT
,BOTTOM_RIGHT
);
98 AddAnchor(IDC_COMMIT_LIST
,TOP_LEFT
, TOP_RIGHT
);
99 AddAnchor(IDC_REBASE_SPLIT
,TOP_LEFT
, TOP_RIGHT
);
100 AddAnchor(IDC_STATUS_STATIC
, BOTTOM_LEFT
,BOTTOM_RIGHT
);
101 AddAnchor(IDC_REBASE_CONTINUE
,BOTTOM_RIGHT
);
102 AddAnchor(IDC_REBASE_ABORT
, BOTTOM_RIGHT
);
103 AddAnchor(IDC_REBASE_PROGRESS
,BOTTOM_LEFT
, BOTTOM_RIGHT
);
104 AddAnchor(IDC_PICK_ALL
,TOP_LEFT
);
105 AddAnchor(IDC_SQUASH_ALL
,TOP_LEFT
);
106 AddAnchor(IDC_EDIT_ALL
,TOP_LEFT
);
107 AddAnchor(IDC_BUTTON_UP2
,TOP_LEFT
);
108 AddAnchor(IDC_BUTTON_DOWN2
,TOP_LEFT
);
109 AddAnchor(IDC_REBASE_COMBOXEX_UPSTREAM
,TOP_LEFT
);
110 AddAnchor(IDC_REBASE_COMBOXEX_BRANCH
,TOP_LEFT
);
111 AddAnchor(IDC_REBASE_STATIC_UPSTREAM
,TOP_LEFT
);
112 AddAnchor(IDC_REBASE_STATIC_BRANCH
,TOP_LEFT
);
113 AddAnchor(IDHELP
, BOTTOM_RIGHT
);
114 AddAnchor(IDC_REBASE_CHECK_FORCE
,TOP_RIGHT
);
115 AddAnchor(IDC_REBASE_POST_BUTTON
,BOTTOM_LEFT
);
117 this->AddOthersToAnchor();
120 BOOL
CRebaseDlg::OnInitDialog()
122 CResizableStandAloneDialog::OnInitDialog();
123 CAppUtils::MarkWindowAsUnpinnable(m_hWnd
);
125 // Let the TaskbarButtonCreated message through the UIPI filter. If we don't
126 // do this, Explorer would be unable to send that message to our window if we
127 // were running elevated. It's OK to make the call all the time, since if we're
128 // not elevated, this is a no-op.
129 CHANGEFILTERSTRUCT cfs
= { sizeof(CHANGEFILTERSTRUCT
) };
130 typedef BOOL STDAPICALLTYPE
ChangeWindowMessageFilterExDFN(HWND hWnd
, UINT message
, DWORD action
, PCHANGEFILTERSTRUCT pChangeFilterStruct
);
131 CAutoLibrary hUser
= ::LoadLibrary(_T("user32.dll"));
134 ChangeWindowMessageFilterExDFN
*pfnChangeWindowMessageFilterEx
= (ChangeWindowMessageFilterExDFN
*)GetProcAddress(hUser
, "ChangeWindowMessageFilterEx");
135 if (pfnChangeWindowMessageFilterEx
)
137 pfnChangeWindowMessageFilterEx(m_hWnd
, WM_TASKBARBTNCREATED
, MSGFLT_ALLOW
, &cfs
);
140 m_pTaskbarList
.Release();
141 m_pTaskbarList
.CoCreateInstance(CLSID_TaskbarList
);
144 //IDC_REBASE_DUMY_TAB
146 GetClientRect(m_DlgOrigRect
);
147 m_CommitList
.GetClientRect(m_CommitListOrigRect
);
149 CWnd
*pwnd
=this->GetDlgItem(IDC_REBASE_DUMY_TAB
);
150 pwnd
->GetWindowRect(&rectDummy
);
151 this->ScreenToClient(rectDummy
);
153 if (!m_ctrlTabCtrl
.Create(CMFCTabCtrl::STYLE_FLAT
, rectDummy
, this, IDC_REBASE_TAB
))
155 TRACE0("Failed to create output tab window\n");
156 return FALSE
; // fail to create
158 m_ctrlTabCtrl
.SetResizeMode(CMFCTabCtrl::RESIZE_NO
);
159 // Create output panes:
160 //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
161 DWORD dwStyle
=LVS_REPORT
| LVS_SHOWSELALWAYS
| LVS_ALIGNLEFT
| WS_BORDER
| WS_TABSTOP
| WS_CHILD
| WS_VISIBLE
;
163 if (! this->m_FileListCtrl
.Create(dwStyle
,rectDummy
,&this->m_ctrlTabCtrl
,0) )
165 TRACE0("Failed to create output windows\n");
166 return FALSE
; // fail to create
169 if( ! this->m_LogMessageCtrl
.Create(_T("Scintilla"),_T("source"),0,rectDummy
,&m_ctrlTabCtrl
,0,0) )
171 TRACE0("Failed to create log message control");
174 m_LogMessageCtrl
.Init(0);
175 m_LogMessageCtrl
.Call(SCI_SETREADONLY
, TRUE
);
177 dwStyle
= LBS_NOINTEGRALHEIGHT
| WS_CHILD
| WS_VISIBLE
| WS_HSCROLL
| WS_VSCROLL
;
179 if (!m_wndOutputRebase
.Create(_T("Scintilla"),_T("source"),0,rectDummy
, &m_ctrlTabCtrl
, 0,0) )
181 TRACE0("Failed to create output windows\n");
182 return -1; // fail to create
184 m_wndOutputRebase
.Init(0);
185 m_wndOutputRebase
.Call(SCI_SETREADONLY
, TRUE
);
187 m_tooltips
.Create(this);
189 m_tooltips
.AddTool(IDC_REBASE_CHECK_FORCE
,IDS_REBASE_FORCE_TT
);
190 m_tooltips
.AddTool(IDC_REBASE_ABORT
,IDS_REBASE_ABORT_TT
);
194 m_FileListCtrl
.Init(GITSLC_COLEXT
| GITSLC_COLSTATUS
|GITSLC_COLADD
|GITSLC_COLDEL
, _T("RebaseDlg"),(GITSLC_POPALL
^ (GITSLC_POPCOMMIT
|GITSLC_POPRESTORE
)),false);
196 m_ctrlTabCtrl
.AddTab(&m_FileListCtrl
,_T("Revision Files"));
197 m_ctrlTabCtrl
.AddTab(&m_LogMessageCtrl
,_T("Commit Message"),1);
200 CString sWindowTitle
;
201 GetWindowText(sWindowTitle
);
202 CAppUtils::SetWindowTitle(m_hWnd
, g_Git
.m_CurrentDir
, sWindowTitle
);
204 EnableSaveRestore(_T("RebaseDlg"));
206 DWORD yPos
= CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));
207 RECT rcDlg
, rcLogMsg
, rcFileList
;
208 GetClientRect(&rcDlg
);
209 m_CommitList
.GetWindowRect(&rcLogMsg
);
210 ScreenToClient(&rcLogMsg
);
211 this->m_ctrlTabCtrl
.GetWindowRect(&rcFileList
);
212 ScreenToClient(&rcFileList
);
216 m_wndSplitter
.GetWindowRect(&rectSplitter
);
217 ScreenToClient(&rectSplitter
);
218 int delta
= yPos
- rectSplitter
.top
;
219 if ((rcLogMsg
.bottom
+ delta
> rcLogMsg
.top
)&&(rcLogMsg
.bottom
+ delta
< rcFileList
.bottom
- 30))
221 m_wndSplitter
.SetWindowPos(NULL
, 0, yPos
, 0, 0, SWP_NOSIZE
);
226 if( this->m_RebaseStage
== CHOOSE_BRANCH
)
228 this->LoadBranchInfo();
233 this->m_BranchCtrl
.EnableWindow(FALSE
);
234 this->m_UpstreamCtrl
.EnableWindow(FALSE
);
237 m_CommitList
.m_ColumnRegKey
= _T("Rebase");
238 m_CommitList
.m_IsIDReplaceAction
= TRUE
;
239 // m_CommitList.m_IsOldFirst = TRUE;
240 m_CommitList
.m_IsRebaseReplaceGraph
= TRUE
;
242 m_CommitList
.InsertGitColumn();
244 this->SetControlEnable();
246 if(!this->m_PreCmd
.IsEmpty())
248 CProgressDlg progress
;
249 progress
.m_GitCmd
=m_PreCmd
;
250 progress
.m_bAutoCloseOnSuccess
=true;
256 this->m_BranchCtrl
.SetCurSel(-1);
257 this->m_BranchCtrl
.EnableWindow(FALSE
);
258 this->m_UpstreamCtrl
.AddString(_T("HEAD"));
259 this->m_UpstreamCtrl
.EnableWindow(FALSE
);
260 this->SetWindowText(_T("Cherry Pick"));
261 this->m_CommitList
.StartFilter();
266 SetContinueButtonText();
267 m_CommitList
.DeleteAllItems();
271 m_CommitList
.m_ContextMenuMask
&= ~(m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_CHERRY_PICK
)|
272 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_SWITCHTOREV
)|
273 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_RESET
)|
274 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REVERTREV
)|
275 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_TO_VERSION
)|
276 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REVERTTOREV
)|
277 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_COMBINE_COMMIT
));
279 if(m_CommitList
.m_IsOldFirst
)
280 this->m_CurrentRebaseIndex
= -1;
282 this->m_CurrentRebaseIndex
= m_CommitList
.m_logEntries
.size();
285 if(this->CheckRebaseCondition())
287 /* Disable Start Rebase */
288 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(FALSE
);
293 // CRebaseDlg message handlers
295 void CRebaseDlg::OnBnClickedPickAll()
299 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK
);
301 this->m_bEditAll
=FALSE
;
302 this->m_bSquashAll
=FALSE
;
303 this->UpdateData(FALSE
);
306 void CRebaseDlg::OnBnClickedSquashAll()
309 if(this->m_bSquashAll
)
310 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH
);
312 this->m_bEditAll
=FALSE
;
313 this->m_bPickAll
=FALSE
;
314 this->UpdateData(FALSE
);
317 void CRebaseDlg::OnBnClickedEditAll()
320 if( this->m_bEditAll
)
321 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT
);
323 this->m_bPickAll
=FALSE
;
324 this->m_bSquashAll
=FALSE
;
325 this->UpdateData(FALSE
);
328 void CRebaseDlg::SetAllRebaseAction(int action
)
330 for(int i
=0;i
<this->m_CommitList
.m_logEntries
.size();i
++)
332 m_CommitList
.m_logEntries
.GetGitRevAt(i
).GetAction(&m_CommitList
)=action
;
334 m_CommitList
.Invalidate();
337 void CRebaseDlg::OnBnClickedRebaseSplit()
342 LRESULT
CRebaseDlg::DefWindowProc(UINT message
, WPARAM wParam
, LPARAM lParam
)
346 if (wParam
== IDC_REBASE_SPLIT
)
348 SPC_NMHDR
* pHdr
= (SPC_NMHDR
*) lParam
;
354 return __super::DefWindowProc(message
, wParam
, lParam
);
357 void CRebaseDlg::DoSize(int delta
)
359 this->RemoveAllAnchors();
361 CSplitterControl::ChangeHeight(GetDlgItem(IDC_COMMIT_LIST
), delta
, CW_TOPALIGN
);
362 //CSplitterControl::ChangeHeight(GetDlgItem(), delta, CW_TOPALIGN);
363 CSplitterControl::ChangeHeight(GetDlgItem(IDC_REBASE_TAB
), -delta
, CW_BOTTOMALIGN
);
364 //CSplitterControl::ChangeHeight(GetDlgItem(), -delta, CW_BOTTOMALIGN);
365 CSplitterControl::ChangePos(GetDlgItem(IDC_SQUASH_ALL
),0,delta
);
366 CSplitterControl::ChangePos(GetDlgItem(IDC_PICK_ALL
),0,delta
);
367 CSplitterControl::ChangePos(GetDlgItem(IDC_EDIT_ALL
),0,delta
);
368 CSplitterControl::ChangePos(GetDlgItem(IDC_BUTTON_UP2
),0,delta
);
369 CSplitterControl::ChangePos(GetDlgItem(IDC_BUTTON_DOWN2
),0,delta
);
370 CSplitterControl::ChangePos(GetDlgItem(IDC_REBASE_CHECK_FORCE
),0,delta
);
372 this->AddRebaseAnchor();
373 // adjust the minimum size of the dialog to prevent the resizing from
374 // moving the list control too far down.
376 m_CommitList
.GetClientRect(rcLogMsg
);
377 SetMinTrackSize(CSize(m_DlgOrigRect
.Width(), m_DlgOrigRect
.Height()-m_CommitListOrigRect
.Height()+rcLogMsg
.Height()));
380 // m_CommitList.Invalidate();
382 // GetDlgItem(IDC_LOGMESSAGE)->Invalidate();
384 this->m_ctrlTabCtrl
.Invalidate();
385 this->m_CommitList
.Invalidate();
386 this->m_FileListCtrl
.Invalidate();
387 this->m_LogMessageCtrl
.Invalidate();
391 void CRebaseDlg::SetSplitterRange()
393 if ((m_CommitList
)&&(m_ctrlTabCtrl
))
396 m_CommitList
.GetWindowRect(rcTop
);
397 ScreenToClient(rcTop
);
399 m_ctrlTabCtrl
.GetWindowRect(rcMiddle
);
400 ScreenToClient(rcMiddle
);
401 if (rcMiddle
.Height() && rcMiddle
.Width())
402 m_wndSplitter
.SetRange(rcTop
.top
+60, rcMiddle
.bottom
-80);
406 void CRebaseDlg::OnSize(UINT nType
,int cx
, int cy
)
408 // first, let the resizing take place
409 __super::OnSize(nType
, cx
, cy
);
415 void CRebaseDlg::SaveSplitterPos()
419 CRegDWORD regPos
= CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));
421 m_wndSplitter
.GetWindowRect(&rectSplitter
);
422 ScreenToClient(&rectSplitter
);
423 regPos
= rectSplitter
.top
;
427 void CRebaseDlg::LoadBranchInfo()
429 m_BranchCtrl
.SetMaxHistoryItems(0x7FFFFFFF);
430 m_UpstreamCtrl
.SetMaxHistoryItems(0x7FFFFFFF);
435 g_Git
.GetBranchList(list
,¤t
,CGit::BRANCH_ALL
);
436 m_BranchCtrl
.AddString(list
);
438 g_Git
.GetBranchList(list
,¤t
,CGit::BRANCH_ALL_F
);
439 m_UpstreamCtrl
.AddString(list
);
441 m_BranchCtrl
.SetCurSel(current
);
443 AddBranchToolTips(&m_BranchCtrl
);
444 AddBranchToolTips(&m_UpstreamCtrl
);
446 if(!m_Upstream
.IsEmpty())
448 m_UpstreamCtrl
.AddString(m_Upstream
);
449 m_UpstreamCtrl
.SetCurSel(m_UpstreamCtrl
.GetCount()-1);
453 //Select pull-remote from current branch
454 CString currentBranch
= g_Git
.GetSymbolicRef();
456 configName
.Format(L
"branch.%s.remote", currentBranch
);
457 CString pullRemote
= g_Git
.GetConfigValue(configName
);
459 //Select pull-branch from current branch
460 configName
.Format(L
"branch.%s.merge", currentBranch
);
461 CString pullBranch
= CGit::StripRefName(g_Git
.GetConfigValue(configName
));
463 CString defaultUpstream
;
464 defaultUpstream
.Format(L
"remotes/%s/%s", pullRemote
, pullBranch
);
465 int found
= m_UpstreamCtrl
.FindStringExact(0, defaultUpstream
);
467 m_UpstreamCtrl
.SetCurSel(found
);
471 void CRebaseDlg::OnCbnSelchangeBranch()
476 void CRebaseDlg::OnCbnSelchangeUpstream()
481 void CRebaseDlg::FetchLogList()
484 CString basestr
, err
;
486 m_IsFastForward
=FALSE
;
487 cmd
.Format(_T("git.exe merge-base %s %s"), g_Git
.FixBranchName(m_UpstreamCtrl
.GetString()),
488 g_Git
.FixBranchName(m_BranchCtrl
.GetString()));
489 if (g_Git
.Run(cmd
, &basestr
, &err
, CP_ACP
))
491 CMessageBox::Show(NULL
, basestr
+ L
"\n" + err
, _T("TortoiseGit"), MB_OK
|MB_ICONERROR
);
496 hash
=g_Git
.GetHash(m_BranchCtrl
.GetString());
498 if(hash
== g_Git
.GetHash(this->m_UpstreamCtrl
.GetString()))
500 m_CommitList
.Clear();
502 fmt
.LoadString(IDS_REBASE_EQUAL_FMT
);
503 text
.Format(fmt
,m_BranchCtrl
.GetString(),this->m_UpstreamCtrl
.GetString());
505 m_CommitList
.ShowText(text
);
506 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(false);
513 this->m_IsFastForward
=TRUE
;
515 m_CommitList
.Clear();
517 fmt
.LoadString(IDS_REBASE_FASTFORWARD_FMT
);
518 text
.Format(fmt
,m_BranchCtrl
.GetString(),this->m_UpstreamCtrl
.GetString(),
519 m_BranchCtrl
.GetString(),this->m_UpstreamCtrl
.GetString());
521 m_CommitList
.ShowText(text
);
522 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(true);
523 SetContinueButtonText();
532 hash
=g_Git
.GetHash(m_UpstreamCtrl
.GetString());
536 m_CommitList
.Clear();
538 fmt
.LoadString(IDS_REBASE_UPTODATE_FMT
);
539 text
.Format(fmt
,m_BranchCtrl
.GetString());
540 m_CommitList
.ShowText(text
);
541 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(m_CommitList
.GetItemCount());
542 SetContinueButtonText();
547 m_CommitList
.Clear();
549 from
= m_UpstreamCtrl
.GetString();
550 to
= m_BranchCtrl
.GetString();
551 this->m_CommitList
.FillGitLog(NULL
,0,&from
,&to
);
553 if( m_CommitList
.GetItemCount() == 0 )
554 m_CommitList
.ShowText(_T("Nothing to Rebase"));
556 hash
=g_Git
.GetHash(m_UpstreamCtrl
.GetString());
559 if(m_CommitList
.m_logEntries
[m_CommitList
.m_logEntries
.size()-1].m_ParentHash
.size() >=0 )
561 if(hash
== m_CommitList
.m_logEntries
[m_CommitList
.m_logEntries
.size()-1].m_ParentHash
[0])
563 m_CommitList
.Clear();
564 m_CommitList
.ShowText(_T("Nothing Rebase"));
570 AddBranchToolTips(&this->m_BranchCtrl
);
571 AddBranchToolTips(&this->m_UpstreamCtrl
);
573 for(int i
=0;i
<m_CommitList
.m_logEntries
.size();i
++)
575 m_CommitList
.m_logEntries
.GetGitRevAt(i
).GetAction(&m_CommitList
) = CTGitPath::LOGACTIONS_REBASE_PICK
;
578 m_CommitList
.Invalidate();
580 if(m_CommitList
.m_IsOldFirst
)
581 this->m_CurrentRebaseIndex
= -1;
583 this->m_CurrentRebaseIndex
= m_CommitList
.m_logEntries
.size();
585 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(m_CommitList
.GetItemCount());
586 SetContinueButtonText();
589 void CRebaseDlg::AddBranchToolTips(CHistoryCombo
*pBranch
)
593 CString text
=pBranch
->GetString();
599 tooltip
.Format(_T("CommitHash:%s\nCommit by: %s %s\n <b>%s</b> \n %s"),
600 rev
.m_CommitHash
.ToString(),
602 CLoglistUtils::FormatDateAndTime(rev
.GetAuthorDate(), DATE_LONGDATE
),
606 pBranch
->DisableTooltip();
607 this->m_tooltips
.AddTool(pBranch
->GetComboBoxCtrl(),tooltip
);
611 BOOL
CRebaseDlg::PreTranslateMessage(MSG
*pMsg
)
613 if (pMsg
->message
== WM_KEYDOWN
)
615 switch (pMsg
->wParam
)
618 if(LogListHasFocus(pMsg
->hwnd
))
620 m_CommitList
.ShiftSelectedAction();
625 if(LogListHasFocus(pMsg
->hwnd
))
627 m_CommitList
.SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_PICK
);
632 if(LogListHasFocus(pMsg
->hwnd
))
634 m_CommitList
.SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_SKIP
);
639 if(LogListHasFocus(pMsg
->hwnd
))
641 m_CommitList
.SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_SQUASH
);
646 if(LogListHasFocus(pMsg
->hwnd
))
648 m_CommitList
.SetSelectedAction(CTGitPath::LOGACTIONS_REBASE_EDIT
);
653 if(LogListHasFocus(pMsg
->hwnd
) && GetAsyncKeyState(VK_CONTROL
) & 0x8000)
655 // select all entries
656 for (int i
= 0; i
< m_CommitList
.GetItemCount(); ++i
)
658 m_CommitList
.SetItemState(i
, LVIS_SELECTED
, LVIS_SELECTED
);
669 /* Avoid TAB control destroy but dialog exist*/
674 ::GetClassName(pMsg
->hwnd
,buff
,128);
677 if(_tcsnicmp(buff
,_T("RichEdit20W"),128)==0 ||
678 _tcsnicmp(buff
,_T("Scintilla"),128)==0 ||
679 _tcsnicmp(buff
,_T("SysListView32"),128)==0||
680 ::GetParent(pMsg
->hwnd
) == this->m_ctrlTabCtrl
.m_hWnd
)
682 this->PostMessage(WM_KEYDOWN
,VK_ESCAPE
,0);
688 m_tooltips
.RelayEvent(pMsg
);
689 return CResizableStandAloneDialog::PreTranslateMessage(pMsg
);
692 bool CRebaseDlg::LogListHasFocus(HWND hwnd
)
695 ::GetClassName(hwnd
, buff
, 128);
697 if(_tcsnicmp(buff
, _T("SysListView32"), 128) == 0)
702 int CRebaseDlg::CheckRebaseCondition()
704 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
706 if( !g_Git
.CheckCleanWorkTree() )
708 if(CMessageBox::Show(NULL
, IDS_ERROR_NOCLEAN_STASH
,IDS_APPNAME
,MB_YESNO
|MB_ICONINFORMATION
)==IDYES
)
711 cmd
=_T("git.exe stash");
712 this->AddLogString(cmd
);
713 if(g_Git
.Run(cmd
,&out
,CP_ACP
))
715 CMessageBox::Show(NULL
,out
,_T("TortoiseGit"),MB_OK
);
723 //Todo Check $REBASE_ROOT
727 cmd
=_T("git.exe var GIT_COMMITTER_IDENT");
728 if(g_Git
.Run(cmd
,NULL
,CP_UTF8
))
731 //Todo call pre_rebase_hook
734 int CRebaseDlg::StartRebase()
737 m_FileListCtrl
.m_bIsRevertTheirMy
= !m_IsCherryPick
;
738 if(!this->m_IsCherryPick
)
740 //Todo call comment_for_reflog
741 cmd
.Format(_T("git.exe checkout %s"),this->m_BranchCtrl
.GetString());
742 this->AddLogString(cmd
);
744 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
746 this->AddLogString(out
);
750 this->AddLogString(out
);
753 cmd
=_T("git.exe rev-parse --verify HEAD");
754 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
756 AddLogString(_T("No Head"));
760 //git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
761 // echo "detached HEAD" > "$DOTEST"/head-name
763 cmd
.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));
764 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
766 AddLogString(_T("update ORIG_HEAD Fail"));
770 m_OrigUpstreamHash
.Empty();
771 m_OrigUpstreamHash
= g_Git
.GetHash(this->m_UpstreamCtrl
.GetString());
772 if(m_OrigUpstreamHash
.IsEmpty())
774 this->AddLogString(m_OrigUpstreamHash
);
778 if( !this->m_IsCherryPick
)
780 cmd
.Format(_T("git.exe checkout -f %s"), m_OrigUpstreamHash
.ToString());
781 this->AddLogString(cmd
);
784 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
786 this->AddLogString(out
);
791 if( !this->m_IsCherryPick
)
793 m_OrigBranchHash
= g_Git
.GetHash(this->m_BranchCtrl
.GetString());
794 if(m_OrigBranchHash
.IsEmpty())
796 this->AddLogString(m_OrigBranchHash
.ToString());
799 this->AddLogString(_T("Start Rebase\r\n"));
803 this->AddLogString(_T("Start Cherry-pick\r\n"));
807 int CRebaseDlg::VerifyNoConflict()
810 if(g_Git
.ListConflictFile(list
))
812 AddLogString(_T("Get conflict files fail"));
815 if( list
.GetCount() != 0 )
817 CMessageBox::Show(NULL
,_T("There are conflict file, you should mark it resolve"),_T("TortoiseGit"),MB_OK
);
823 int CRebaseDlg::FinishRebase()
825 if(this->m_IsCherryPick
) //cherry pick mode no "branch", working at upstream branch
828 git_revnum_t head
= g_Git
.GetHash(_T("HEAD"));
832 cmd
.Format(_T("git.exe checkout -f %s"),this->m_BranchCtrl
.GetString());
834 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
842 cmd
.Format(_T("git.exe reset --hard %s"),head
);
844 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
851 m_ctrlTabCtrl
.RemoveTab(0);
852 m_ctrlTabCtrl
.RemoveTab(0);
853 m_CtrlStatusText
.SetWindowText(_T("Finished rebasing."));
857 void CRebaseDlg::OnBnClickedContinue()
859 if( m_RebaseStage
== REBASE_DONE
)
865 if( this->m_IsFastForward
)
868 CString oldbranch
= g_Git
.GetCurrentBranch();
869 if( oldbranch
!= m_BranchCtrl
.GetString() )
871 cmd
.Format(_T("git.exe checkout %s"),m_BranchCtrl
.GetString());
873 if( g_Git
.Run(cmd
,&out
,CP_ACP
) )
875 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
882 m_OrigBranchHash
= g_Git
.GetHash(m_BranchCtrl
.GetString());
883 m_OrigUpstreamHash
= g_Git
.GetHash(this->m_UpstreamCtrl
.GetString());
885 if(!g_Git
.IsFastForward(this->m_BranchCtrl
.GetString(),this->m_UpstreamCtrl
.GetString()))
887 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
888 AddLogString(_T("No fast forward\r\nMaybe repository changed"));
892 cmd
.Format(_T("git.exe reset --hard %s"),g_Git
.FixBranchName(this->m_UpstreamCtrl
.GetString()));
893 this->AddLogString(CString(_T("Fast forward to "))+m_UpstreamCtrl
.GetString());
896 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
897 if(g_Git
.Run(cmd
,&out
,CP_ACP
))
899 AddLogString(_T("Fail"));
904 AddLogString(_T("Done"));
905 m_RebaseStage
= REBASE_DONE
;
906 UpdateCurrentStatus();
910 if( m_RebaseStage
== CHOOSE_BRANCH
|| m_RebaseStage
== CHOOSE_COMMIT_PICK_MODE
)
912 if(CheckRebaseCondition())
914 m_RebaseStage
= REBASE_START
;
915 m_FileListCtrl
.Clear();
916 m_FileListCtrl
.m_CurrentVersion
= L
"";
917 m_ctrlTabCtrl
.SetTabLabel(REBASE_TAB_CONFLICT
, _T("Conflict Files"));
918 m_ctrlTabCtrl
.AddTab(&m_wndOutputRebase
,_T("Log"),2);
921 if( m_RebaseStage
== REBASE_FINISH
)
929 if( m_RebaseStage
== REBASE_SQUASH_CONFLICT
)
931 if(VerifyNoConflict())
933 GitRev
*curRev
=(GitRev
*)m_CommitList
.m_arShownList
[m_CurrentRebaseIndex
];
934 if(this->CheckNextCommitIsSquash())
935 {//next commit is not squash;
936 m_RebaseStage
= REBASE_SQUASH_EDIT
;
937 this->OnRebaseUpdateUI(0,0);
938 this->UpdateCurrentStatus();
942 m_RebaseStage
=REBASE_CONTINUE
;
943 curRev
->GetAction(&m_CommitList
)|=CTGitPath::LOGACTIONS_REBASE_DONE
;
944 this->UpdateCurrentStatus();
948 if( m_RebaseStage
== REBASE_CONFLICT
)
950 if(VerifyNoConflict())
953 GitRev
*curRev
=(GitRev
*)m_CommitList
.m_arShownList
[m_CurrentRebaseIndex
];
957 cmd
.Format(_T("git.exe commit -a -C %s"), curRev
->m_CommitHash
.ToString());
961 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
964 if(!g_Git
.CheckCleanWorkTree())
966 CMessageBox::Show(NULL
,out
,_T("TortoiseGit"),MB_OK
|MB_ICONERROR
);
972 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
973 if( curRev
->GetAction(&m_CommitList
) & CTGitPath::LOGACTIONS_REBASE_EDIT
)
975 m_RebaseStage
=REBASE_EDIT
;
976 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_MESSAGE
);
977 this->UpdateCurrentStatus();
982 m_RebaseStage
=REBASE_CONTINUE
;
983 curRev
->GetAction(&m_CommitList
)|=CTGitPath::LOGACTIONS_REBASE_DONE
;
984 this->UpdateCurrentStatus();
988 if( m_RebaseStage
== REBASE_EDIT
|| m_RebaseStage
== REBASE_SQUASH_EDIT
)
991 GitRev
*curRev
=(GitRev
*)m_CommitList
.m_arShownList
[m_CurrentRebaseIndex
];
993 str
=this->m_LogMessageCtrl
.GetText();
994 if(str
.Trim().IsEmpty())
996 CMessageBox::Show(NULL
,_T("Commit Message Is Empty"),_T("TortoiseGit"),MB_OK
|MB_ICONERROR
);
1000 CString tempfile
=::GetTempFile();
1001 CFile
file(tempfile
,CFile::modeReadWrite
|CFile::modeCreate
);
1002 CStringA log
=CUnicodeUtils::GetUTF8( str
);
1003 file
.Write(log
,log
.GetLength());
1004 //file.WriteString(m_sLogMessage);
1009 if( m_RebaseStage
== REBASE_SQUASH_EDIT
)
1010 cmd
.Format(_T("git.exe commit -F \"%s\""), tempfile
);
1012 cmd
.Format(_T("git.exe commit --amend -F \"%s\""), tempfile
);
1014 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
1016 if(!g_Git
.CheckCleanWorkTree())
1018 CMessageBox::Show(NULL
,out
,_T("TortoiseGit"),MB_OK
|MB_ICONERROR
);
1023 CFile::Remove(tempfile
);
1025 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
1026 m_RebaseStage
=REBASE_CONTINUE
;
1027 curRev
->GetAction(&m_CommitList
)|=CTGitPath::LOGACTIONS_REBASE_DONE
;
1028 this->UpdateCurrentStatus();
1032 InterlockedExchange(&m_bThreadRunning
, TRUE
);
1035 if (AfxBeginThread(RebaseThreadEntry
, this)==NULL
)
1037 InterlockedExchange(&m_bThreadRunning
, FALSE
);
1038 CMessageBox::Show(NULL
, _T("Create Rebase Thread Fail"), _T("TortoiseGit"), MB_OK
| MB_ICONERROR
);
1042 int CRebaseDlg::CheckNextCommitIsSquash()
1045 if(m_CommitList
.m_IsOldFirst
)
1046 index
=m_CurrentRebaseIndex
+1;
1048 index
=m_CurrentRebaseIndex
-1;
1055 if(index
>= m_CommitList
.GetItemCount())
1058 curRev
=(GitRev
*)m_CommitList
.m_arShownList
[index
];
1060 if( curRev
->GetAction(&m_CommitList
)&CTGitPath::LOGACTIONS_REBASE_SQUASH
)
1062 if( curRev
->GetAction(&m_CommitList
)&CTGitPath::LOGACTIONS_REBASE_SKIP
)
1064 if(m_CommitList
.m_IsOldFirst
)
1072 }while(curRev
->GetAction(&m_CommitList
)&CTGitPath::LOGACTIONS_REBASE_SKIP
);
1077 int CRebaseDlg::GoNext()
1079 if(m_CommitList
.m_IsOldFirst
)
1080 m_CurrentRebaseIndex
++;
1082 m_CurrentRebaseIndex
--;
1086 int CRebaseDlg::StateAction()
1088 switch(this->m_RebaseStage
)
1091 case CHOOSE_COMMIT_PICK_MODE
:
1094 m_RebaseStage
= REBASE_START
;
1101 void CRebaseDlg::SetContinueButtonText()
1104 switch(this->m_RebaseStage
)
1107 case CHOOSE_COMMIT_PICK_MODE
:
1108 if(this->m_IsFastForward
)
1109 Text
= _T("Start (FastFwd)");
1111 Text
= _T("Start Rebase");
1115 case REBASE_CONTINUE
:
1116 case REBASE_SQUASH_CONFLICT
:
1117 Text
= _T("Continue");
1120 case REBASE_CONFLICT
:
1121 Text
= _T("Commit");
1127 case REBASE_SQUASH_EDIT
:
1128 Text
= _T("Commit");
1133 Text
= _T("Finish");
1140 this->GetDlgItem(IDC_REBASE_CONTINUE
)->SetWindowText(Text
);
1143 void CRebaseDlg::SetControlEnable()
1145 switch(this->m_RebaseStage
)
1148 case CHOOSE_COMMIT_PICK_MODE
:
1150 this->GetDlgItem(IDC_PICK_ALL
)->EnableWindow(TRUE
);
1151 this->GetDlgItem(IDC_EDIT_ALL
)->EnableWindow(TRUE
);
1152 this->GetDlgItem(IDC_SQUASH_ALL
)->EnableWindow(TRUE
);
1153 this->GetDlgItem(IDC_BUTTON_UP2
)->EnableWindow(TRUE
);
1154 this->GetDlgItem(IDC_BUTTON_DOWN2
)->EnableWindow(TRUE
);
1158 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH
)->EnableWindow(TRUE
);
1159 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM
)->EnableWindow(TRUE
);
1160 this->GetDlgItem(IDC_REBASE_CHECK_FORCE
)->EnableWindow(TRUE
);
1162 //this->m_CommitList.m_IsEnableRebaseMenu=TRUE;
1163 this->m_CommitList
.m_ContextMenuMask
|= m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK
)|
1164 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH
)|
1165 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT
)|
1166 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP
);
1170 case REBASE_CONTINUE
:
1173 case REBASE_CONFLICT
:
1175 case REBASE_SQUASH_CONFLICT
:
1177 this->GetDlgItem(IDC_PICK_ALL
)->EnableWindow(FALSE
);
1178 this->GetDlgItem(IDC_EDIT_ALL
)->EnableWindow(FALSE
);
1179 this->GetDlgItem(IDC_SQUASH_ALL
)->EnableWindow(FALSE
);
1180 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH
)->EnableWindow(FALSE
);
1181 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM
)->EnableWindow(FALSE
);
1182 this->GetDlgItem(IDC_REBASE_CHECK_FORCE
)->EnableWindow(FALSE
);
1183 this->GetDlgItem(IDC_BUTTON_UP2
)->EnableWindow(FALSE
);
1184 this->GetDlgItem(IDC_BUTTON_DOWN2
)->EnableWindow(FALSE
);
1185 //this->m_CommitList.m_IsEnableRebaseMenu=FALSE;
1186 this->m_CommitList
.m_ContextMenuMask
&= ~(m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK
)|
1187 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH
)|
1188 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT
)|
1189 m_CommitList
.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP
));
1191 if( m_RebaseStage
== REBASE_DONE
&& (this->m_PostButtonTexts
.GetCount() != 0) )
1193 this->GetDlgItem(IDC_STATUS_STATIC
)->ShowWindow(SW_HIDE
);
1194 this->GetDlgItem(IDC_REBASE_POST_BUTTON
)->ShowWindow(SW_SHOWNORMAL
);
1195 this->m_PostButton
.RemoveAll();
1196 this->m_PostButton
.AddEntries(m_PostButtonTexts
);
1197 //this->GetDlgItem(IDC_REBASE_POST_BUTTON)->SetWindowText(this->m_PostButtonText);
1202 if(m_bThreadRunning
)
1204 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(FALSE
);
1209 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(TRUE
);
1213 void CRebaseDlg::UpdateProgress()
1218 if(m_CommitList
.m_IsOldFirst
)
1219 index
= m_CurrentRebaseIndex
+1;
1221 index
= m_CommitList
.GetItemCount()-m_CurrentRebaseIndex
;
1223 m_ProgressBar
.SetRange(1,m_CommitList
.GetItemCount());
1224 m_ProgressBar
.SetPos(index
);
1227 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NORMAL
);
1228 m_pTaskbarList
->SetProgressValue(m_hWnd
, index
, m_CommitList
.GetItemCount());
1231 if(m_CurrentRebaseIndex
>=0 && m_CurrentRebaseIndex
< m_CommitList
.GetItemCount())
1234 text
.Format(_T("Rebasing... (%d/%d)"),index
,m_CommitList
.GetItemCount());
1235 m_CtrlStatusText
.SetWindowText(text
);
1239 GitRev
*prevRev
=NULL
, *curRev
=NULL
;
1241 if( m_CurrentRebaseIndex
>= 0 && m_CurrentRebaseIndex
< m_CommitList
.m_arShownList
.GetSize())
1243 curRev
=(GitRev
*)m_CommitList
.m_arShownList
[m_CurrentRebaseIndex
];
1246 for(int i
=0;i
<m_CommitList
.m_arShownList
.GetSize();i
++)
1248 prevRev
=(GitRev
*)m_CommitList
.m_arShownList
[i
];
1249 if(prevRev
->GetAction(&m_CommitList
) & CTGitPath::LOGACTIONS_REBASE_CURRENT
)
1251 prevRev
->GetAction(&m_CommitList
) &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT
;
1252 m_CommitList
.GetItemRect(i
,&rect
,LVIR_BOUNDS
);
1253 m_CommitList
.InvalidateRect(rect
);
1259 curRev
->GetAction(&m_CommitList
) |= CTGitPath::LOGACTIONS_REBASE_CURRENT
;
1260 m_CommitList
.GetItemRect(m_CurrentRebaseIndex
,&rect
,LVIR_BOUNDS
);
1261 m_CommitList
.InvalidateRect(rect
);
1263 m_CommitList
.EnsureVisible(m_CurrentRebaseIndex
,FALSE
);
1266 void CRebaseDlg::UpdateCurrentStatus()
1268 SetContinueButtonText();
1273 void CRebaseDlg::AddLogString(CString str
)
1275 this->m_wndOutputRebase
.SendMessage(SCI_SETREADONLY
, FALSE
);
1276 CStringA sTextA
= m_wndOutputRebase
.StringForControl(str
);//CUnicodeUtils::GetUTF8(str);
1277 this->m_wndOutputRebase
.SendMessage(SCI_DOCUMENTEND
);
1278 this->m_wndOutputRebase
.SendMessage(SCI_REPLACESEL
, 0, (LPARAM
)(LPCSTR
)sTextA
);
1279 this->m_wndOutputRebase
.SendMessage(SCI_REPLACESEL
, 0, (LPARAM
)(LPCSTR
)"\n");
1280 this->m_wndOutputRebase
.SendMessage(SCI_SETREADONLY
, TRUE
);
1283 int CRebaseDlg::GetCurrentCommitID()
1285 if(m_CommitList
.m_IsOldFirst
)
1287 return this->m_CurrentRebaseIndex
+1;
1292 return m_CommitList
.GetItemCount()-m_CurrentRebaseIndex
;
1296 int CRebaseDlg::DoRebase()
1299 if(m_CurrentRebaseIndex
<0)
1301 if(m_CurrentRebaseIndex
>= m_CommitList
.GetItemCount() )
1304 GitRev
*pRev
= (GitRev
*)m_CommitList
.m_arShownList
[m_CurrentRebaseIndex
];
1305 int mode
=pRev
->GetAction(&m_CommitList
) & CTGitPath::LOGACTIONS_REBASE_MODE_MASK
;
1308 if( mode
== CTGitPath::LOGACTIONS_REBASE_SKIP
)
1310 pRev
->GetAction(&m_CommitList
)|= CTGitPath::LOGACTIONS_REBASE_DONE
;
1314 if( mode
!= CTGitPath::LOGACTIONS_REBASE_PICK
)
1316 this->m_SquashMessage
+= pRev
->GetSubject();
1317 this->m_SquashMessage
+= _T("\n");
1318 this->m_SquashMessage
+= pRev
->GetBody();
1321 this->m_SquashMessage
.Empty();
1323 if(mode
== CTGitPath::LOGACTIONS_REBASE_SQUASH
)
1324 nocommit
=_T(" --no-commit ");
1327 log
.Format(_T("%s %d: %s"),CTGitPath::GetActionName(mode
),this->GetCurrentCommitID(),pRev
->m_CommitHash
.ToString());
1329 AddLogString(pRev
->GetSubject());
1330 if (pRev
->GetSubject().IsEmpty())
1332 CMessageBox::Show(m_hWnd
, _T("Found an empty commit message. You have to enter one or rebase cannot proceed."), _T("TortoiseGit"), MB_OK
| MB_ICONEXCLAMATION
);
1333 mode
= CTGitPath::LOGACTIONS_REBASE_EDIT
;
1336 cmd
.Format(_T("git.exe cherry-pick %s %s"),nocommit
,pRev
->m_CommitHash
.ToString());
1338 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
1342 if(g_Git
.ListConflictFile(list
))
1344 AddLogString(_T("Get conflict files fail"));
1347 if(list
.GetCount() == 0 )
1349 if(mode
== CTGitPath::LOGACTIONS_REBASE_PICK
)
1351 pRev
->GetAction(&m_CommitList
)|= CTGitPath::LOGACTIONS_REBASE_DONE
;
1354 if(mode
== CTGitPath::LOGACTIONS_REBASE_EDIT
)
1356 this->m_RebaseStage
= REBASE_EDIT
;
1357 return -1; // Edit return -1 to stop rebase.
1360 if(CheckNextCommitIsSquash())
1362 // let user edit last commmit message
1363 this->m_RebaseStage
= REBASE_SQUASH_EDIT
;
1367 if(mode
== CTGitPath::LOGACTIONS_REBASE_SQUASH
)
1368 m_RebaseStage
= REBASE_SQUASH_CONFLICT
;
1370 m_RebaseStage
= REBASE_CONFLICT
;
1377 if(mode
== CTGitPath::LOGACTIONS_REBASE_PICK
)
1379 pRev
->GetAction(&m_CommitList
)|= CTGitPath::LOGACTIONS_REBASE_DONE
;
1382 if(mode
== CTGitPath::LOGACTIONS_REBASE_EDIT
)
1384 this->m_RebaseStage
= REBASE_EDIT
;
1385 return -1; // Edit return -1 to stop rebase.
1389 if(CheckNextCommitIsSquash())
1391 // let user edit last commmit message
1392 this->m_RebaseStage
= REBASE_SQUASH_EDIT
;
1395 else if(mode
== CTGitPath::LOGACTIONS_REBASE_SQUASH
)
1396 pRev
->GetAction(&m_CommitList
)|= CTGitPath::LOGACTIONS_REBASE_DONE
;
1402 BOOL
CRebaseDlg::IsEnd()
1404 if(m_CommitList
.m_IsOldFirst
)
1405 return m_CurrentRebaseIndex
>= this->m_CommitList
.GetItemCount();
1407 return m_CurrentRebaseIndex
<0;
1410 int CRebaseDlg::RebaseThread()
1412 CBlockCacheForPath
cacheBlock(g_Git
.m_CurrentDir
);
1417 if( m_RebaseStage
== REBASE_START
)
1419 if( this->StartRebase() )
1421 InterlockedExchange(&m_bThreadRunning
, FALSE
);
1423 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
1426 m_RebaseStage
= REBASE_CONTINUE
;
1429 else if( m_RebaseStage
== REBASE_CONTINUE
)
1432 UpdateCurrentStatus();
1436 m_RebaseStage
= REBASE_FINISH
;
1450 else if( m_RebaseStage
== REBASE_FINISH
)
1453 m_RebaseStage
= REBASE_DONE
;
1455 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NOPROGRESS
);
1463 this->PostMessage(MSG_REBASE_UPDATE_UI
);
1464 //this->UpdateCurrentStatus();
1467 InterlockedExchange(&m_bThreadRunning
, FALSE
);
1468 this->PostMessage(MSG_REBASE_UPDATE_UI
);
1472 void CRebaseDlg::ListConflictFile()
1474 this->m_FileListCtrl
.Clear();
1479 m_FileListCtrl
.m_bIsRevertTheirMy
= !m_IsCherryPick
;
1481 this->m_FileListCtrl
.GetStatus(&list
,true);
1482 this->m_FileListCtrl
.Show(CTGitPath::LOGACTIONS_UNMERGED
|CTGitPath::LOGACTIONS_MODIFIED
|CTGitPath::LOGACTIONS_ADDED
|CTGitPath::LOGACTIONS_DELETED
,
1483 CTGitPath::LOGACTIONS_UNMERGED
);
1486 LRESULT
CRebaseDlg::OnRebaseUpdateUI(WPARAM
,LPARAM
)
1488 UpdateCurrentStatus();
1489 if(m_CurrentRebaseIndex
<0)
1491 if(m_CurrentRebaseIndex
>= m_CommitList
.GetItemCount() )
1493 GitRev
*curRev
=(GitRev
*)m_CommitList
.m_arShownList
[m_CurrentRebaseIndex
];
1495 switch(m_RebaseStage
)
1497 case REBASE_CONFLICT
:
1498 case REBASE_SQUASH_CONFLICT
:
1500 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_CONFLICT
);
1502 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_ERROR
);
1503 this->m_LogMessageCtrl
.Call(SCI_SETREADONLY
, FALSE
);
1504 this->m_LogMessageCtrl
.SetText(curRev
->GetSubject()+_T("\n")+curRev
->GetBody());
1507 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_MESSAGE
);
1509 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_PAUSED
);
1510 this->m_LogMessageCtrl
.Call(SCI_SETREADONLY
, FALSE
);
1511 this->m_LogMessageCtrl
.SetText(curRev
->GetSubject()+_T("\n")+curRev
->GetBody());
1513 case REBASE_SQUASH_EDIT
:
1514 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_MESSAGE
);
1515 this->m_LogMessageCtrl
.Call(SCI_SETREADONLY
, FALSE
);
1516 this->m_LogMessageCtrl
.SetText(this->m_SquashMessage
);
1518 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_PAUSED
);
1521 this->m_ctrlTabCtrl
.SetActiveTab(REBASE_TAB_LOG
);
1525 void CRebaseDlg::OnCancel()
1529 void CRebaseDlg::OnBnClickedAbort()
1532 m_pTaskbarList
->SetProgressState(m_hWnd
, TBPF_NOPROGRESS
);
1535 CString pron
= m_OrigUpstreamHash
.ToString();
1536 if(m_OrigUpstreamHash
.IsEmpty())
1538 __super::OnCancel();
1541 if(m_RebaseStage
== CHOOSE_BRANCH
|| m_RebaseStage
== CHOOSE_COMMIT_PICK_MODE
)
1546 if(CMessageBox::Show(NULL
,_T("Are you sure you want to abort the rebase process?"),_T("TortoiseGit"),MB_YESNO
) != IDYES
)
1549 if(this->m_IsFastForward
)
1551 cmd
.Format(_T("git.exe reset --hard %s"),this->m_OrigBranchHash
.ToString());
1552 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
1557 __super::OnCancel();
1560 cmd
.Format(_T("git.exe checkout -f %s"),g_Git
.FixBranchName(this->m_UpstreamCtrl
.GetString()));
1561 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
1567 cmd
.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash
.ToString());
1568 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
1574 if(this->m_IsCherryPick
) //there are not "branch" at cherry pick mode
1576 __super::OnCancel();
1580 cmd
.Format(_T("git checkout -f %s"),this->m_BranchCtrl
.GetString());
1581 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
1587 cmd
.Format(_T("git.exe reset --hard %s"),this->m_OrigBranchHash
.ToString());
1588 if(g_Git
.Run(cmd
,&out
,CP_UTF8
))
1593 __super::OnCancel();
1596 void CRebaseDlg::OnBnClickedButtonBrowse()
1598 if(CBrowseRefsDlg::PickRefForCombo(&m_UpstreamCtrl
, gPickRef_NoTag
))
1599 OnCbnSelchangeUpstream();
1602 void CRebaseDlg::OnBnClickedRebaseCheckForce()
1605 this->FetchLogList();
1606 if(this->CheckRebaseCondition())
1608 /* Disable Start Rebase */
1609 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(FALSE
);
1613 void CRebaseDlg::OnBnClickedRebasePostButton()
1615 this->m_Upstream
=this->m_UpstreamCtrl
.GetString();
1616 this->m_Branch
=this->m_BranchCtrl
.GetString();
1618 this->EndDialog(IDC_REBASE_POST_BUTTON
+this->m_PostButton
.GetCurrentEntry());
1621 void CRebaseDlg::Refresh()
1623 if(this->m_IsCherryPick
)
1626 if(this->m_RebaseStage
== CHOOSE_BRANCH
)
1629 this->FetchLogList();
1630 if(this->CheckRebaseCondition())
1632 /* Disable Start Rebase */
1633 this->GetDlgItem(IDC_REBASE_CONTINUE
)->EnableWindow(FALSE
);
1638 void CRebaseDlg::OnBnClickedButtonUp2()
1641 pos
= m_CommitList
.GetFirstSelectedItemPosition();
1643 // do nothing if the first selected item is the first item in the list
1644 if (m_CommitList
.GetNextSelectedItem(pos
) == 0)
1647 pos
= m_CommitList
.GetFirstSelectedItemPosition();
1649 bool changed
= false;
1652 int index
=m_CommitList
.GetNextSelectedItem(pos
);
1655 CGitHash old
= m_CommitList
.m_logEntries
[index
-1];
1656 m_CommitList
.m_logEntries
[index
-1] = m_CommitList
.m_logEntries
[index
];
1657 m_CommitList
.m_logEntries
[index
] = old
;
1658 m_CommitList
.SetItemState(index
-1, LVIS_SELECTED
, LVIS_SELECTED
);
1659 m_CommitList
.SetItemState(index
, 0, LVIS_SELECTED
);
1665 m_CommitList
.RecalculateShownList(&m_CommitList
.m_arShownList
);
1666 m_CommitList
.Invalidate();
1667 m_CommitList
.SetFocus();
1671 void CRebaseDlg::OnBnClickedButtonDown2()
1673 if (m_CommitList
.GetSelectedCount() == 0)
1677 pos
= m_CommitList
.GetFirstSelectedItemPosition();
1678 bool changed
= false;
1679 // use an array to store all selected item indexes; the user won't select too much items
1680 int* indexes
= NULL
;
1681 indexes
= new int[m_CommitList
.GetSelectedCount()];
1685 indexes
[i
++] = m_CommitList
.GetNextSelectedItem(pos
);
1687 // don't move any item if the last selected item is the last item in the m_CommitList
1688 // (that would change the order of the selected items)
1689 if(indexes
[m_CommitList
.GetSelectedCount() - 1] < m_CommitList
.GetItemCount() - 1)
1691 // iterate over the indexes backwards in order to correctly move multiselected items
1692 for (i
= m_CommitList
.GetSelectedCount() - 1; i
>= 0; i
--)
1694 int index
= indexes
[i
];
1695 CGitHash old
= m_CommitList
.m_logEntries
[index
+1];
1696 m_CommitList
.m_logEntries
[index
+1] = m_CommitList
.m_logEntries
[index
];
1697 m_CommitList
.m_logEntries
[index
] = old
;
1698 m_CommitList
.SetItemState(index
, 0, LVIS_SELECTED
);
1699 m_CommitList
.SetItemState(index
+1, LVIS_SELECTED
, LVIS_SELECTED
);
1707 m_CommitList
.RecalculateShownList(&m_CommitList
.m_arShownList
);
1708 m_CommitList
.Invalidate();
1709 m_CommitList
.SetFocus();
1713 LRESULT
CRebaseDlg::OnTaskbarBtnCreated(WPARAM
/*wParam*/, LPARAM
/*lParam*/)
1715 m_pTaskbarList
.Release();
1716 m_pTaskbarList
.CoCreateInstance(CLSID_TaskbarList
);
1720 void CRebaseDlg::OnLvnItemchangedLoglist(NMHDR
*pNMHDR
, LRESULT
*pResult
)
1722 LPNMLISTVIEW pNMLV
= reinterpret_cast<LPNMLISTVIEW
>(pNMHDR
);
1724 if(m_CommitList
.m_bNoDispUpdates
)
1726 if (pNMLV
->iItem
>= 0)
1728 this->m_CommitList
.m_nSearchIndex
= pNMLV
->iItem
;
1729 if (pNMLV
->iSubItem
!= 0)
1731 if ((pNMLV
->iItem
== m_CommitList
.m_arShownList
.GetCount()))
1733 // remove the selected state
1734 if (pNMLV
->uChanged
& LVIF_STATE
)
1736 m_CommitList
.SetItemState(pNMLV
->iItem
, 0, LVIS_SELECTED
);
1737 FillLogMessageCtrl();
1741 if (pNMLV
->uChanged
& LVIF_STATE
)
1743 FillLogMessageCtrl();
1748 FillLogMessageCtrl();
1752 void CRebaseDlg::FillLogMessageCtrl()
1754 int selCount
= m_CommitList
.GetSelectedCount();
1755 if (selCount
== 1 && (m_RebaseStage
== CHOOSE_BRANCH
|| m_RebaseStage
== CHOOSE_COMMIT_PICK_MODE
))
1757 POSITION pos
= m_CommitList
.GetFirstSelectedItemPosition();
1758 int selIndex
= m_CommitList
.GetNextSelectedItem(pos
);
1759 GitRev
* pLogEntry
= reinterpret_cast<GitRev
*>(m_CommitList
.m_arShownList
.SafeGetAt(selIndex
));
1760 m_FileListCtrl
.UpdateWithGitPathList(pLogEntry
->GetFiles(&m_CommitList
));
1761 m_FileListCtrl
.m_CurrentVersion
= pLogEntry
->m_CommitHash
;
1762 m_FileListCtrl
.Show(GITSLC_SHOWVERSIONED
);
1763 m_LogMessageCtrl
.Call(SCI_SETREADONLY
, FALSE
);
1764 m_LogMessageCtrl
.SetText(pLogEntry
->GetSubject() + _T("\n") + pLogEntry
->GetBody());
1765 m_LogMessageCtrl
.Call(SCI_SETREADONLY
, TRUE
);