OSDN Git Service

Enhance Rebase dialog. Add force rebase checkbox.
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / RebaseDlg.cpp
1 // RebaseDlg.cpp : implementation file\r
2 //\r
3 \r
4 #include "stdafx.h"\r
5 #include "TortoiseProc.h"\r
6 #include "RebaseDlg.h"\r
7 #include "AppUtils.h"\r
8 #include "MessageBox.h"\r
9 #include "UnicodeUtils.h"\r
10 #include "BrowseRefsDlg.h"\r
11 #include "ProgressDlg.h"\r
12 // CRebaseDlg dialog\r
13 \r
14 IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)\r
15 \r
16 CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/)\r
17         : CResizableStandAloneDialog(CRebaseDlg::IDD, pParent)\r
18     , m_bPickAll(FALSE)\r
19     , m_bSquashAll(FALSE)\r
20     , m_bEditAll(FALSE)\r
21 {\r
22         m_RebaseStage=CHOOSE_BRANCH;\r
23         m_CurrentRebaseIndex=-1;\r
24         m_bThreadRunning =FALSE;\r
25         this->m_IsCherryPick = FALSE;\r
26         m_bForce=FALSE;\r
27 }\r
28 \r
29 CRebaseDlg::~CRebaseDlg()\r
30 {\r
31 }\r
32 \r
33 void CRebaseDlg::DoDataExchange(CDataExchange* pDX)\r
34 {\r
35     CDialog::DoDataExchange(pDX);\r
36     DDX_Control(pDX, IDC_REBASE_PROGRESS, m_ProgressBar);\r
37     DDX_Control(pDX, IDC_STATUS_STATIC, m_CtrlStatusText);\r
38     DDX_Check(pDX, IDC_PICK_ALL, m_bPickAll);\r
39     DDX_Check(pDX, IDC_SQUASH_ALL, m_bSquashAll);\r
40     DDX_Check(pDX, IDC_EDIT_ALL, m_bEditAll);\r
41         DDX_Control(pDX, IDC_REBASE_SPLIT, m_wndSplitter);\r
42         DDX_Control(pDX,IDC_COMMIT_LIST,m_CommitList);\r
43         DDX_Control(pDX,IDC_REBASE_COMBOXEX_BRANCH, this->m_BranchCtrl);\r
44         DDX_Control(pDX,IDC_REBASE_COMBOXEX_UPSTREAM,   this->m_UpstreamCtrl);\r
45         DDX_Check(pDX, IDC_REBASE_CHECK_FORCE,m_bForce);\r
46 \r
47 }\r
48 \r
49 \r
50 BEGIN_MESSAGE_MAP(CRebaseDlg, CResizableStandAloneDialog)\r
51     ON_BN_CLICKED(IDC_PICK_ALL, &CRebaseDlg::OnBnClickedPickAll)\r
52     ON_BN_CLICKED(IDC_SQUASH_ALL, &CRebaseDlg::OnBnClickedSquashAll)\r
53     ON_BN_CLICKED(IDC_EDIT_ALL, &CRebaseDlg::OnBnClickedEditAll)\r
54     ON_BN_CLICKED(IDC_REBASE_SPLIT, &CRebaseDlg::OnBnClickedRebaseSplit)\r
55         ON_BN_CLICKED(IDC_REBASE_CONTINUE,OnBnClickedContinue)\r
56         ON_BN_CLICKED(IDC_REBASE_ABORT,  OnBnClickedAbort)\r
57         ON_WM_SIZE()\r
58         ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH,   &CRebaseDlg::OnCbnSelchangeBranch)\r
59         ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream)\r
60         ON_MESSAGE(MSG_REBASE_UPDATE_UI, OnRebaseUpdateUI)\r
61         ON_BN_CLICKED(IDC_BUTTON_BROWSE, &CRebaseDlg::OnBnClickedButtonBrowse)\r
62         ON_BN_CLICKED(IDC_REBASE_CHECK_FORCE, &CRebaseDlg::OnBnClickedRebaseCheckForce)\r
63 END_MESSAGE_MAP()\r
64 \r
65 void CRebaseDlg::AddRebaseAnchor()\r
66 {\r
67         AddAnchor(IDC_REBASE_TAB,TOP_LEFT,BOTTOM_RIGHT);\r
68         AddAnchor(IDC_COMMIT_LIST,TOP_LEFT, TOP_RIGHT);\r
69         AddAnchor(IDC_REBASE_SPLIT,TOP_LEFT, TOP_RIGHT);\r
70         AddAnchor(IDC_STATUS_STATIC, BOTTOM_LEFT,BOTTOM_RIGHT);\r
71         AddAnchor(IDC_REBASE_CONTINUE,BOTTOM_RIGHT);\r
72         AddAnchor(IDC_REBASE_ABORT, BOTTOM_RIGHT);\r
73         AddAnchor(IDC_REBASE_PROGRESS,BOTTOM_LEFT, BOTTOM_RIGHT);\r
74         AddAnchor(IDC_PICK_ALL,TOP_LEFT);\r
75         AddAnchor(IDC_SQUASH_ALL,TOP_LEFT);\r
76         AddAnchor(IDC_EDIT_ALL,TOP_LEFT);       \r
77         AddAnchor(IDC_REBASE_COMBOXEX_UPSTREAM,TOP_LEFT);\r
78         AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT);\r
79         AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT);\r
80         AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT);\r
81         AddAnchor(IDHELP, BOTTOM_RIGHT);\r
82         AddAnchor(IDC_REBASE_CHECK_FORCE,TOP_RIGHT);\r
83         this->AddOthersToAnchor();\r
84 }\r
85 \r
86 BOOL CRebaseDlg::OnInitDialog()\r
87 {\r
88         CResizableStandAloneDialog::OnInitDialog();\r
89 \r
90         CRect rectDummy;\r
91         //IDC_REBASE_DUMY_TAB\r
92         \r
93         GetClientRect(m_DlgOrigRect);\r
94         m_CommitList.GetClientRect(m_CommitListOrigRect);\r
95 \r
96         CWnd *pwnd=this->GetDlgItem(IDC_REBASE_DUMY_TAB);\r
97         pwnd->GetWindowRect(&rectDummy);\r
98         this->ScreenToClient(rectDummy);\r
99 \r
100         if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_REBASE_TAB))\r
101         {\r
102                 TRACE0("Failed to create output tab window\n");\r
103                 return FALSE;      // fail to create\r
104         }\r
105         m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);\r
106         // Create output panes:\r
107         //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;\r
108         DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;\r
109 \r
110         if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) )\r
111         {\r
112                 TRACE0("Failed to create output windows\n");\r
113                 return FALSE;      // fail to create\r
114         }\r
115 \r
116         if( ! this->m_LogMessageCtrl.Create(_T("Scintilla"),_T("source"),0,rectDummy,&m_ctrlTabCtrl,0,0) )\r
117         {\r
118                 TRACE0("Failed to create log message control");\r
119                 return FALSE;\r
120         }\r
121         m_LogMessageCtrl.Init(0);\r
122 \r
123         dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;\r
124 \r
125         if (!m_wndOutputRebase.Create(_T("Scintilla"),_T("source"),0,rectDummy, &m_ctrlTabCtrl, 0,0) )\r
126         {\r
127                 TRACE0("Failed to create output windows\n");\r
128                 return -1;      // fail to create\r
129         }\r
130         m_wndOutputRebase.Init(0);\r
131         m_wndOutputRebase.Call(SCI_SETREADONLY, TRUE);\r
132         \r
133         m_tooltips.Create(this);\r
134         \r
135         m_tooltips.AddTool(IDC_REBASE_CHECK_FORCE,IDS_REBASE_FORCE_TT);\r
136 \r
137         m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS |SVNSLC_COLADD|SVNSLC_COLDEL , _T("RebaseDlg"),(SVNSLC_POPALL ^ SVNSLC_POPCOMMIT),false);\r
138 \r
139         m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Conflict File"));\r
140         m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Commit Message"),1);\r
141         m_ctrlTabCtrl.AddTab(&m_wndOutputRebase,_T("Log"),2);\r
142         AddRebaseAnchor();\r
143 \r
144 \r
145         EnableSaveRestore(_T("RebaseDlg"));\r
146 \r
147         DWORD yPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));\r
148         RECT rcDlg, rcLogMsg, rcFileList;\r
149         GetClientRect(&rcDlg);\r
150         m_CommitList.GetWindowRect(&rcLogMsg);\r
151         ScreenToClient(&rcLogMsg);\r
152         this->m_ctrlTabCtrl.GetWindowRect(&rcFileList);\r
153         ScreenToClient(&rcFileList);\r
154         if (yPos)\r
155         {\r
156                 RECT rectSplitter;\r
157                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
158                 ScreenToClient(&rectSplitter);\r
159                 int delta = yPos - rectSplitter.top;\r
160                 if ((rcLogMsg.bottom + delta > rcLogMsg.top)&&(rcLogMsg.bottom + delta < rcFileList.bottom - 30))\r
161                 {\r
162                         m_wndSplitter.SetWindowPos(NULL, 0, yPos, 0, 0, SWP_NOSIZE);\r
163                         DoSize(delta);\r
164                 }\r
165         }\r
166 \r
167         if( this->m_RebaseStage == CHOOSE_BRANCH)\r
168         {\r
169                 this->LoadBranchInfo();\r
170 \r
171         }else\r
172         {\r
173                 this->m_BranchCtrl.EnableWindow(FALSE);\r
174                 this->m_UpstreamCtrl.EnableWindow(FALSE);\r
175         }\r
176 \r
177         m_CommitList.m_IsIDReplaceAction = TRUE;\r
178 //      m_CommitList.m_IsOldFirst = TRUE;\r
179         m_CommitList.m_IsRebaseReplaceGraph = TRUE;\r
180 \r
181         m_CommitList.InsertGitColumn();\r
182 \r
183         this->SetControlEnable();\r
184 \r
185         if(!this->m_PreCmd.IsEmpty())\r
186         {\r
187                 CProgressDlg progress;\r
188                 progress.m_GitCmd=m_PreCmd;\r
189                 progress.m_bAutoCloseOnSuccess=true;\r
190                 progress.DoModal();\r
191         }\r
192 \r
193         if(m_IsCherryPick)\r
194         {\r
195                 this->m_BranchCtrl.SetCurSel(-1);\r
196                 this->m_BranchCtrl.EnableWindow(FALSE);\r
197                 this->m_UpstreamCtrl.EnableWindow(FALSE);\r
198                 this->SetWindowText(_T("Cherry Pick"));\r
199                 this->m_CommitList.StartFilter();\r
200 \r
201         }else\r
202         {\r
203                 SetContinueButtonText();\r
204                 m_CommitList.DeleteAllItems();\r
205                 FetchLogList();\r
206         }\r
207 \r
208         m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_CHERRY_PICK)|\r
209                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_SWITCHTOREV)|\r
210                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_RESET)|\r
211                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTREV)|\r
212                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_TO_VERSION)|\r
213                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REVERTTOREV)|\r
214                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_COMBINE_COMMIT));\r
215 \r
216         if(m_CommitList.m_IsOldFirst)\r
217                 this->m_CurrentRebaseIndex = -1;\r
218         else\r
219                 this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();\r
220 \r
221 \r
222         return TRUE;\r
223 }\r
224 // CRebaseDlg message handlers\r
225 \r
226 void CRebaseDlg::OnBnClickedPickAll()\r
227 {\r
228     // TODO: Add your control notification handler code here\r
229         this->UpdateData();\r
230         if(this->m_bPickAll)\r
231                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK);\r
232 \r
233         this->m_bEditAll=FALSE;\r
234         this->m_bSquashAll=FALSE;\r
235         this->UpdateData(FALSE);\r
236         \r
237 }\r
238 \r
239 void CRebaseDlg::OnBnClickedSquashAll()\r
240 {\r
241     // TODO: Add your control notification handler code here\r
242         this->UpdateData();\r
243         if(this->m_bSquashAll)\r
244                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH);\r
245 \r
246         this->m_bEditAll=FALSE;\r
247         this->m_bPickAll=FALSE;\r
248         this->UpdateData(FALSE);\r
249 \r
250 }\r
251 \r
252 void CRebaseDlg::OnBnClickedEditAll()\r
253 {\r
254     // TODO: Add your control notification handler code here\r
255         this->UpdateData();\r
256         if( this->m_bEditAll )\r
257                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT);\r
258 \r
259         this->m_bPickAll=FALSE;\r
260         this->m_bSquashAll=FALSE;\r
261         this->UpdateData(FALSE);\r
262 \r
263 }\r
264 \r
265 void CRebaseDlg::SetAllRebaseAction(int action)\r
266 {\r
267         for(int i=0;i<this->m_CommitList.m_logEntries.size();i++)\r
268         {\r
269                 m_CommitList.m_logEntries[i].m_Action=action;\r
270         }\r
271         m_CommitList.Invalidate();\r
272 }\r
273 \r
274 void CRebaseDlg::OnBnClickedRebaseSplit()\r
275 {\r
276         this->UpdateData();\r
277     // TODO: Add your control notification handler code here\r
278 }\r
279 \r
280 LRESULT CRebaseDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)\r
281 {\r
282         switch (message) {\r
283         case WM_NOTIFY:\r
284                 if (wParam == IDC_REBASE_SPLIT)\r
285                 { \r
286                         SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;\r
287                         DoSize(pHdr->delta);\r
288                 }\r
289                 break;\r
290         }\r
291 \r
292         return __super::DefWindowProc(message, wParam, lParam);\r
293 }\r
294 \r
295 void CRebaseDlg::DoSize(int delta)\r
296 {\r
297         \r
298         this->RemoveAllAnchors();\r
299 \r
300         CSplitterControl::ChangeHeight(GetDlgItem(IDC_COMMIT_LIST), delta, CW_TOPALIGN);\r
301         //CSplitterControl::ChangeHeight(GetDlgItem(), delta, CW_TOPALIGN);\r
302         CSplitterControl::ChangeHeight(GetDlgItem(IDC_REBASE_TAB), -delta, CW_BOTTOMALIGN);\r
303         //CSplitterControl::ChangeHeight(GetDlgItem(), -delta, CW_BOTTOMALIGN);\r
304         CSplitterControl::ChangePos(GetDlgItem(IDC_SQUASH_ALL),0,delta);\r
305         CSplitterControl::ChangePos(GetDlgItem(IDC_PICK_ALL),0,delta);\r
306         CSplitterControl::ChangePos(GetDlgItem(IDC_EDIT_ALL),0,delta);\r
307         \r
308         this->AddRebaseAnchor();\r
309         // adjust the minimum size of the dialog to prevent the resizing from\r
310         // moving the list control too far down.\r
311         CRect rcLogMsg;\r
312         m_CommitList.GetClientRect(rcLogMsg);\r
313         SetMinTrackSize(CSize(m_DlgOrigRect.Width(), m_DlgOrigRect.Height()-m_CommitListOrigRect.Height()+rcLogMsg.Height()));\r
314 \r
315         SetSplitterRange();\r
316 //      m_CommitList.Invalidate();\r
317 \r
318 //      GetDlgItem(IDC_LOGMESSAGE)->Invalidate();\r
319 \r
320         this->m_ctrlTabCtrl.Invalidate();\r
321         this->m_CommitList.Invalidate();\r
322         this->m_FileListCtrl.Invalidate();\r
323         this->m_LogMessageCtrl.Invalidate();\r
324 \r
325 }\r
326 \r
327 void CRebaseDlg::SetSplitterRange()\r
328 {\r
329         if ((m_CommitList)&&(m_ctrlTabCtrl))\r
330         {\r
331                 CRect rcTop;\r
332                 m_CommitList.GetWindowRect(rcTop);\r
333                 ScreenToClient(rcTop);\r
334                 CRect rcMiddle;\r
335                 m_ctrlTabCtrl.GetWindowRect(rcMiddle);\r
336                 ScreenToClient(rcMiddle);\r
337                 if (rcMiddle.Height() && rcMiddle.Width())\r
338                         m_wndSplitter.SetRange(rcTop.top+60, rcMiddle.bottom-80);\r
339         }\r
340 }\r
341 \r
342 void CRebaseDlg::OnSize(UINT nType,int cx, int cy)\r
343 {\r
344          // first, let the resizing take place\r
345     __super::OnSize(nType, cx, cy);\r
346 \r
347     //set range\r
348     SetSplitterRange();\r
349 }\r
350 \r
351 void CRebaseDlg::SaveSplitterPos()\r
352 {\r
353         if (!IsIconic())\r
354         {\r
355                 CRegDWORD regPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));\r
356                 RECT rectSplitter;\r
357                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
358                 ScreenToClient(&rectSplitter);\r
359                 regPos = rectSplitter.top;\r
360         }\r
361 }\r
362 \r
363 void CRebaseDlg::LoadBranchInfo()\r
364 {\r
365         m_BranchCtrl.SetMaxHistoryItems(0x7FFFFFFF);\r
366         m_UpstreamCtrl.SetMaxHistoryItems(0x7FFFFFFF);\r
367 \r
368         STRING_VECTOR list;\r
369         list.clear();\r
370         int current;\r
371         g_Git.GetBranchList(list,&current,CGit::BRANCH_ALL);\r
372         m_BranchCtrl.AddString(list);\r
373         m_UpstreamCtrl.AddString(list);\r
374 \r
375         m_BranchCtrl.SetCurSel(current);\r
376 \r
377         AddBranchToolTips(&m_BranchCtrl);\r
378         AddBranchToolTips(&m_UpstreamCtrl);\r
379 \r
380         if(!m_Upstream.IsEmpty())\r
381         {\r
382                 m_UpstreamCtrl.AddString(m_Upstream);\r
383                 m_UpstreamCtrl.SetCurSel(m_UpstreamCtrl.GetCount()-1);\r
384         }\r
385         else\r
386         {\r
387                 //Select pull-remote from current branch\r
388                 CString currentBranch = g_Git.GetSymbolicRef();\r
389                 CString configName;\r
390                 configName.Format(L"branch.%s.remote", currentBranch);\r
391                 CString pullRemote = g_Git.GetConfigValue(configName);\r
392 \r
393                 //Select pull-branch from current branch\r
394                 configName.Format(L"branch.%s.merge", currentBranch);\r
395                 CString pullBranch = CGit::StripRefName(g_Git.GetConfigValue(configName));\r
396 \r
397                 CString defaultUpstream;\r
398                 defaultUpstream.Format(L"remotes/%s/%s", pullRemote, pullBranch);\r
399                 int found = m_UpstreamCtrl.FindStringExact(0, defaultUpstream);\r
400                 if(found >= 0)\r
401                         m_UpstreamCtrl.SetCurSel(found);\r
402         }\r
403 }\r
404 \r
405 void CRebaseDlg::OnCbnSelchangeBranch()\r
406 {\r
407         FetchLogList();\r
408 }\r
409 \r
410 void CRebaseDlg::OnCbnSelchangeUpstream()\r
411 {\r
412         FetchLogList();\r
413 }\r
414 \r
415 void CRebaseDlg::FetchLogList()\r
416 {\r
417         if(!this->m_bForce)\r
418         {\r
419                 CString base,hash;\r
420                 CString cmd;\r
421                 cmd.Format(_T("git.exe merge-base %s %s"), m_UpstreamCtrl.GetString(),m_BranchCtrl.GetString());\r
422                 if(g_Git.Run(cmd,&base,CP_ACP))\r
423                 {\r
424                         CMessageBox::Show(NULL,base,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
425                         return;\r
426                 }\r
427                 base=base.Left(40);\r
428 \r
429                 cmd.Format(_T("git.exe rev-parse %s"), m_UpstreamCtrl.GetString());\r
430                 if( g_Git.Run(cmd,&hash,CP_ACP))\r
431                 {\r
432                         CMessageBox::Show(NULL,base,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
433                         return;\r
434                 }\r
435                 hash=hash.Left(40);\r
436                 \r
437                 if( base == hash )\r
438                 {\r
439                         m_CommitList.Clear();\r
440                         CString text,fmt;\r
441                         fmt.LoadString(IDS_REBASE_UPTODATE_FMT);\r
442                         text.Format(fmt,m_BranchCtrl.GetString());\r
443                         m_CommitList.ShowText(text);\r
444                 }\r
445                 \r
446         }else\r
447         {\r
448                 m_CommitList.Clear();\r
449                 this->m_CommitList.FillGitLog(NULL,0,&m_UpstreamCtrl.GetString(),&m_BranchCtrl.GetString());\r
450                 if( m_CommitList.GetItemCount() == 0 )\r
451                         m_CommitList.ShowText(_T("Nothing to Rebase"));\r
452 \r
453                 CString hash=g_Git.GetHash(m_UpstreamCtrl.GetString());\r
454         \r
455 #if 0\r
456                 if(m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash.size() >=0 )\r
457                 {\r
458                         if(hash ==  m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash[0])\r
459                         {\r
460                                 m_CommitList.Clear();\r
461                                 m_CommitList.ShowText(_T("Nothing Rebase"));\r
462                         }\r
463                 }\r
464 #endif\r
465 \r
466                 m_tooltips.Pop();\r
467                 AddBranchToolTips(&this->m_BranchCtrl);\r
468                 AddBranchToolTips(&this->m_UpstreamCtrl);\r
469         \r
470                 for(int i=0;i<m_CommitList.m_logEntries.size();i++)\r
471                 {\r
472                         m_CommitList.m_logEntries[i].m_Action = CTGitPath::LOGACTIONS_REBASE_PICK;\r
473                 }\r
474         \r
475                 m_CommitList.Invalidate();\r
476 \r
477                 if(m_CommitList.m_IsOldFirst)\r
478                         this->m_CurrentRebaseIndex = -1;\r
479                 else\r
480                         this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();\r
481         \r
482         }\r
483 \r
484         this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(m_CommitList.GetItemCount());\r
485 }\r
486 \r
487 void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)\r
488 {\r
489         if(pBranch)\r
490         {\r
491                 CString text=pBranch->GetString();\r
492                 CString tooltip;\r
493                 BYTE_VECTOR data;\r
494                 g_Git.GetLog(data,text,NULL,1,0);\r
495                 GitRev rev;\r
496                 rev.ParserFromLog(data);\r
497                 tooltip.Format(_T("CommitHash:%s\nCommit by: %s  %s\n <b>%s</b> \n %s"),\r
498                         rev.m_CommitHash,\r
499                         rev.m_AuthorName,\r
500                         CAppUtils::FormatDateAndTime(rev.m_AuthorDate,DATE_LONGDATE),\r
501                         rev.m_Subject,\r
502                         rev.m_Body);\r
503 \r
504                 pBranch->DisableTooltip();\r
505                 this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip);\r
506         }\r
507 }\r
508 \r
509 BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg)\r
510 {\r
511         m_tooltips.RelayEvent(pMsg);\r
512         return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
513 }\r
514 int CRebaseDlg::CheckRebaseCondition()\r
515 {\r
516         this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
517 \r
518         if( !g_Git.CheckCleanWorkTree()  )\r
519         {\r
520                 CMessageBox::Show(NULL,_T("Rebase Need Clean Working Tree"),_T("TortoiseGit"),MB_OK);\r
521                 return -1;\r
522         }\r
523         //Todo Check $REBASE_ROOT\r
524         //Todo Check $DOTEST\r
525 \r
526         CString cmd;\r
527         cmd=_T("git.exe var GIT_COMMITTER_IDENT");\r
528         if(g_Git.Run(cmd,NULL,CP_UTF8))\r
529                 return -1;\r
530 \r
531         //Todo call pre_rebase_hook\r
532         return 0;\r
533 }\r
534 int CRebaseDlg::StartRebase()\r
535 {\r
536         CString cmd,out;\r
537 \r
538         if(!this->m_IsCherryPick)\r
539         {\r
540                 //Todo call comment_for_reflog\r
541                 cmd.Format(_T("git.exe checkout %s"),this->m_BranchCtrl.GetString());\r
542                 this->AddLogString(cmd);\r
543 \r
544                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
545                         return -1;\r
546 \r
547                 this->AddLogString(out);\r
548         }\r
549 \r
550         cmd=_T("git.exe rev-parse --verify HEAD");\r
551         if(g_Git.Run(cmd,&out,CP_UTF8))\r
552         {\r
553                 AddLogString(_T("No Head"));\r
554                 return -1;\r
555         }\r
556         //Todo \r
557         //git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||\r
558         //              echo "detached HEAD" > "$DOTEST"/head-name\r
559 \r
560         cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));\r
561         if(g_Git.Run(cmd,&out,CP_UTF8))\r
562         {\r
563                 AddLogString(_T("update ORIG_HEAD Fail"));\r
564                 return -1;\r
565         }\r
566         \r
567         if( !this->m_IsCherryPick )\r
568         {\r
569                 cmd.Format(_T("git.exe checkout %s"),this->m_UpstreamCtrl.GetString());\r
570                 this->AddLogString(cmd);\r
571 \r
572                 out.Empty();\r
573                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
574                 {\r
575                         return -1;\r
576                 }\r
577         }\r
578         \r
579         m_OrigUpstreamHash.Empty();\r
580         m_OrigUpstreamHash= g_Git.GetHash(this->m_UpstreamCtrl.GetString());\r
581         if(m_OrigUpstreamHash.IsEmpty())\r
582         {\r
583                 this->AddLogString(m_OrigUpstreamHash);\r
584                 return -1;\r
585         }\r
586 \r
587         if( !this->m_IsCherryPick )\r
588         {\r
589                 cmd.Format(_T("git.exe rev-parse %s"),this->m_BranchCtrl.GetString());\r
590                 if(g_Git.Run(cmd,&this->m_OrigBranchHash,CP_UTF8))\r
591                 {\r
592                         this->AddLogString(m_OrigBranchHash);\r
593                         return -1;\r
594                 }\r
595                 this->AddLogString(_T("Start Rebase\r\n"));\r
596 \r
597         }else\r
598                 this->AddLogString(_T("Start Cherry-pick\r\n"));\r
599         \r
600         return 0;\r
601 }\r
602 int  CRebaseDlg::VerifyNoConflict()\r
603 {\r
604         CTGitPathList list;\r
605         if(g_Git.ListConflictFile(list))\r
606         {\r
607                 AddLogString(_T("Get conflict files fail"));\r
608                 return -1;\r
609         }\r
610         if( list.GetCount() != 0 )\r
611         {\r
612                 CMessageBox::Show(NULL,_T("There are conflict file, you should mark it resolve"),_T("TortoiseGit"),MB_OK);\r
613                 return -1;\r
614         }\r
615         return 0;\r
616 \r
617 }\r
618 int CRebaseDlg::FinishRebase()\r
619 {\r
620         if(this->m_IsCherryPick) //cherry pick mode no "branch", working at upstream branch\r
621                 return 0;\r
622 \r
623         CString cmd,out;\r
624         cmd.Format(_T("git.exe branch -f %s"),this->m_BranchCtrl.GetString());\r
625         if(g_Git.Run(cmd,&out,CP_UTF8))\r
626         {\r
627                 AddLogString(out);\r
628                 return -1;\r
629         }\r
630         out.Empty();\r
631         cmd.Format(_T("git.exe reset --hard %s"),this->m_OrigUpstreamHash);\r
632         if(g_Git.Run(cmd,&out,CP_UTF8))\r
633         {\r
634                 AddLogString(out);\r
635                 return -1;\r
636         }\r
637         out.Empty();\r
638         cmd.Format(_T("git.exe checkout -f %s"),this->m_BranchCtrl.GetString());\r
639         if(g_Git.Run(cmd,&out,CP_UTF8))\r
640         {\r
641                 AddLogString(out);\r
642                 return -1;\r
643         }\r
644         return 0;\r
645 }\r
646 void CRebaseDlg::OnBnClickedContinue()\r
647 {\r
648         if( m_RebaseStage == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE )\r
649         {\r
650                 if(CheckRebaseCondition())\r
651                         return ;\r
652                 m_RebaseStage = REBASE_START;\r
653         }\r
654 \r
655         if( m_RebaseStage == REBASE_DONE)\r
656         {\r
657                 OnOK();\r
658         }\r
659 \r
660         if( m_RebaseStage == REBASE_FINISH )\r
661         {\r
662                 if(FinishRebase())\r
663                         return ;\r
664 \r
665                 OnOK();\r
666         }\r
667 \r
668         if( m_RebaseStage == REBASE_SQUASH_CONFLICT)\r
669         {\r
670                 if(VerifyNoConflict())\r
671                         return;\r
672                 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
673                 if(this->CheckNextCommitIsSquash())\r
674                 {//next commit is not squash;\r
675                         m_RebaseStage = REBASE_SQUASH_EDIT;\r
676                         this->OnRebaseUpdateUI(0,0);\r
677                         this->UpdateCurrentStatus();\r
678                         return ;\r
679 \r
680                 }\r
681                 m_RebaseStage=REBASE_CONTINUE;\r
682                 curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;\r
683                 this->UpdateCurrentStatus();\r
684 \r
685         }\r
686 \r
687         if( m_RebaseStage == REBASE_CONFLICT )\r
688         {\r
689                 if(VerifyNoConflict())\r
690                         return;\r
691 \r
692                 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
693                 \r
694                 CString out =_T("");\r
695                 CString cmd;\r
696                 cmd.Format(_T("git.exe commit -C %s"), curRev->m_CommitHash);\r
697 \r
698                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
699                 {\r
700                         if(!g_Git.CheckCleanWorkTree())\r
701                         {\r
702                                 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
703                                 return;\r
704                         }\r
705                 }\r
706 \r
707                 AddLogString(out);\r
708                 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
709                 if( curRev->m_Action & CTGitPath::LOGACTIONS_REBASE_EDIT)\r
710                 {\r
711                         m_RebaseStage=REBASE_EDIT;\r
712                         this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);\r
713                         this->UpdateCurrentStatus();\r
714                         return;\r
715                 }\r
716                 else\r
717                 {\r
718                         m_RebaseStage=REBASE_CONTINUE;\r
719                         curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;\r
720                         this->UpdateCurrentStatus();\r
721                 }\r
722                 \r
723         }\r
724 \r
725         if( m_RebaseStage == REBASE_EDIT ||  m_RebaseStage == REBASE_SQUASH_EDIT )\r
726         {\r
727                 CString str;\r
728                 GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
729         \r
730                 str=this->m_LogMessageCtrl.GetText();\r
731                 if(str.Trim().IsEmpty())\r
732                 {\r
733                         CMessageBox::Show(NULL,_T("Commit Message Is Empty"),_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
734                                 return;\r
735                 }\r
736 \r
737                 CString tempfile=::GetTempFile();\r
738                 CFile file(tempfile,CFile::modeReadWrite|CFile::modeCreate );\r
739                 CStringA log=CUnicodeUtils::GetUTF8( str);\r
740                 file.Write(log,log.GetLength());\r
741                 //file.WriteString(m_sLogMessage);\r
742                 file.Close();\r
743         \r
744                 CString out,cmd;\r
745                 \r
746                 if(  m_RebaseStage == REBASE_SQUASH_EDIT )\r
747                         cmd.Format(_T("git.exe commit -F \"%s\""), tempfile);\r
748                 else\r
749                         cmd.Format(_T("git.exe commit --amend -F \"%s\""), tempfile);\r
750 \r
751                 if(g_Git.Run(cmd,&out,CP_UTF8))\r
752                 {\r
753                         if(!g_Git.CheckCleanWorkTree())\r
754                         {\r
755                                 CMessageBox::Show(NULL,out,_T("TortoiseGit"),MB_OK|MB_ICONERROR);\r
756                                 return;\r
757                         }\r
758                 }\r
759 \r
760                 CFile::Remove(tempfile);\r
761                 AddLogString(out);\r
762                 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
763                 m_RebaseStage=REBASE_CONTINUE;\r
764                 curRev->m_Action|=CTGitPath::LOGACTIONS_REBASE_DONE;\r
765                 this->UpdateCurrentStatus();\r
766         }\r
767 \r
768 \r
769         InterlockedExchange(&m_bThreadRunning, TRUE);\r
770         SetControlEnable();\r
771         \r
772         if (AfxBeginThread(RebaseThreadEntry, this)==NULL)\r
773         {\r
774                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
775                 CMessageBox::Show(NULL, _T("Create Rebase Thread Fail"), _T("TortoiseGit"), MB_OK | MB_ICONERROR);\r
776                 SetControlEnable();\r
777         }\r
778 }\r
779 int CRebaseDlg::CheckNextCommitIsSquash()\r
780 {\r
781         int index;\r
782         if(m_CommitList.m_IsOldFirst)\r
783                 index=m_CurrentRebaseIndex+1;\r
784         else\r
785                 index=m_CurrentRebaseIndex-1;\r
786 \r
787         GitRev *curRev;\r
788         do\r
789         {\r
790                 if(index<0)\r
791                         return -1;\r
792                 if(index>= m_CommitList.GetItemCount())\r
793                         return -1;\r
794 \r
795                 curRev=(GitRev*)m_CommitList.m_arShownList[index];\r
796                 \r
797                 if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SQUASH )\r
798                         return 0;\r
799                 if( curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP)\r
800                 {\r
801                         if(m_CommitList.m_IsOldFirst)\r
802                                 index++;\r
803                         else\r
804                                 index--;\r
805                 }else\r
806                         return -1;              \r
807 \r
808         }while(curRev->m_Action&CTGitPath::LOGACTIONS_REBASE_SKIP);\r
809         \r
810         return -1;\r
811 \r
812 }\r
813 int CRebaseDlg::GoNext()\r
814 {\r
815         if(m_CommitList.m_IsOldFirst)\r
816                 m_CurrentRebaseIndex++;\r
817         else\r
818                 m_CurrentRebaseIndex--; \r
819         return 0;\r
820 \r
821 }\r
822 int CRebaseDlg::StateAction()\r
823 {\r
824         switch(this->m_RebaseStage)\r
825         {\r
826         case CHOOSE_BRANCH:\r
827         case CHOOSE_COMMIT_PICK_MODE:\r
828                 if(StartRebase())\r
829                         return -1;\r
830                 m_RebaseStage = REBASE_START;\r
831                 GoNext();\r
832                 break;\r
833         }\r
834 \r
835         return 0;       \r
836 }\r
837 void CRebaseDlg::SetContinueButtonText()\r
838 {\r
839         CString Text;\r
840         switch(this->m_RebaseStage)\r
841         {\r
842         case CHOOSE_BRANCH:\r
843         case CHOOSE_COMMIT_PICK_MODE:\r
844                 Text = _T("Start");\r
845                 break;\r
846 \r
847         case REBASE_START:\r
848         case REBASE_CONTINUE:\r
849         case REBASE_SQUASH_CONFLICT:\r
850                 Text = _T("Continue");\r
851                 break;\r
852 \r
853         case REBASE_CONFLICT:\r
854                 Text = _T("Commit");\r
855                 break;\r
856         case REBASE_EDIT:\r
857                 Text = _T("Amend");\r
858                 break;\r
859 \r
860         case REBASE_SQUASH_EDIT:\r
861                 Text = _T("Commit");\r
862                 break;\r
863 \r
864         case REBASE_ABORT:\r
865         case REBASE_FINISH:\r
866                 Text = _T("Finish");\r
867                 break;\r
868 \r
869         case REBASE_DONE:\r
870                 Text = _T("Done");\r
871                 break;\r
872         }\r
873         this->GetDlgItem(IDC_REBASE_CONTINUE)->SetWindowText(Text);\r
874 }\r
875 \r
876 void CRebaseDlg::SetControlEnable()\r
877 {\r
878         switch(this->m_RebaseStage)\r
879         {\r
880         case CHOOSE_BRANCH:\r
881         case CHOOSE_COMMIT_PICK_MODE:\r
882                 \r
883                 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(TRUE);\r
884                 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(TRUE);\r
885                 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(TRUE);\r
886                 if(!m_IsCherryPick)\r
887                 {\r
888                         this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE);\r
889                         this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE);\r
890                 }\r
891                 //this->m_CommitList.m_IsEnableRebaseMenu=TRUE;\r
892                 this->m_CommitList.m_ContextMenuMask |= m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|\r
893                                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|\r
894                                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|\r
895                                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP);\r
896                 break;\r
897 \r
898         case REBASE_START:\r
899         case REBASE_CONTINUE:\r
900         case REBASE_ABORT:\r
901         case REBASE_FINISH:\r
902         case REBASE_CONFLICT:\r
903         case REBASE_EDIT:\r
904         case REBASE_SQUASH_CONFLICT:\r
905         case REBASE_DONE:\r
906                 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(FALSE);\r
907                 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(FALSE);\r
908                 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(FALSE);\r
909                 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(FALSE);\r
910                 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(FALSE);\r
911                 //this->m_CommitList.m_IsEnableRebaseMenu=FALSE;\r
912                 this->m_CommitList.m_ContextMenuMask &= ~(m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_PICK)|\r
913                                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SQUASH)|\r
914                                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_EDIT)|\r
915                                                                                                 m_CommitList.GetContextMenuBit(CGitLogListBase::ID_REBASE_SKIP));\r
916                 break;\r
917         }\r
918 \r
919         if(m_bThreadRunning)\r
920         {\r
921                 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);\r
922                 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(FALSE);\r
923 \r
924         }else\r
925         {\r
926                 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(TRUE);\r
927                 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(TRUE);\r
928         }\r
929 }\r
930 \r
931 void CRebaseDlg::UpdateProgress()\r
932 {\r
933         int index;\r
934         CRect rect;\r
935 \r
936         if(m_CommitList.m_IsOldFirst)\r
937                 index = m_CurrentRebaseIndex+1;\r
938         else\r
939                 index = m_CommitList.GetItemCount()-m_CurrentRebaseIndex;\r
940 \r
941         m_ProgressBar.SetRange(1,m_CommitList.GetItemCount());\r
942         m_ProgressBar.SetPos(index);\r
943 \r
944         if(m_CurrentRebaseIndex>=0 && m_CurrentRebaseIndex< m_CommitList.GetItemCount())\r
945         {\r
946                 CString text;\r
947                 text.Format(_T("Rebasing...(%d/%d)"),index,m_CommitList.GetItemCount());\r
948                 m_CtrlStatusText.SetWindowText(text);\r
949 \r
950         }\r
951 \r
952         GitRev *prevRev=NULL, *curRev=NULL;\r
953 \r
954         if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize())\r
955         {\r
956                 curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
957         }\r
958         \r
959         for(int i=0;i<m_CommitList.m_arShownList.GetSize();i++)\r
960         {\r
961                 prevRev=(GitRev*)m_CommitList.m_arShownList[i];\r
962                 if(prevRev->m_Action & CTGitPath::LOGACTIONS_REBASE_CURRENT)\r
963                 {       \r
964                         prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
965                         m_CommitList.GetItemRect(i,&rect,LVIR_BOUNDS);\r
966                         m_CommitList.InvalidateRect(rect);\r
967                 }\r
968         }\r
969 \r
970         if(curRev)\r
971         {\r
972                 curRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
973                 m_CommitList.GetItemRect(m_CurrentRebaseIndex,&rect,LVIR_BOUNDS);\r
974                 m_CommitList.InvalidateRect(rect);\r
975         }\r
976         m_CommitList.EnsureVisible(m_CurrentRebaseIndex,FALSE);\r
977 \r
978 }\r
979 \r
980 void CRebaseDlg::UpdateCurrentStatus()\r
981 {\r
982         if( m_CurrentRebaseIndex < 0 && m_RebaseStage!= REBASE_DONE)\r
983         {\r
984                 if(m_CommitList.m_IsOldFirst)\r
985                         m_RebaseStage = CRebaseDlg::REBASE_START;\r
986                 else\r
987                         m_RebaseStage = CRebaseDlg::REBASE_FINISH;\r
988         }\r
989 \r
990         if( m_CurrentRebaseIndex == m_CommitList.m_arShownList.GetSize() && m_RebaseStage!= REBASE_DONE)\r
991         {\r
992                 if(m_CommitList.m_IsOldFirst)\r
993                         m_RebaseStage = CRebaseDlg::REBASE_DONE;\r
994                 else\r
995                         m_RebaseStage = CRebaseDlg::REBASE_FINISH;\r
996         }\r
997 \r
998         SetContinueButtonText();\r
999         SetControlEnable();\r
1000         UpdateProgress();\r
1001 }\r
1002 \r
1003 void CRebaseDlg::AddLogString(CString str)\r
1004 {\r
1005         this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, FALSE);\r
1006         CStringA sTextA = m_wndOutputRebase.StringForControl(str);//CUnicodeUtils::GetUTF8(str);\r
1007         this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)sTextA);\r
1008         this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)"\n");\r
1009         this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, TRUE);\r
1010 }\r
1011 \r
1012 int CRebaseDlg::GetCurrentCommitID()\r
1013 {\r
1014         if(m_CommitList.m_IsOldFirst)\r
1015         {\r
1016                 return this->m_CurrentRebaseIndex+1;\r
1017 \r
1018         }else\r
1019         {\r
1020                 return m_CommitList.GetItemCount()-m_CurrentRebaseIndex;\r
1021         }\r
1022 }\r
1023 \r
1024 int CRebaseDlg::DoRebase()\r
1025 {       \r
1026         CString cmd,out;\r
1027         if(m_CurrentRebaseIndex <0)\r
1028                 return 0;\r
1029         if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )\r
1030                 return 0;\r
1031 \r
1032         GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
1033         int mode=pRev->m_Action & CTGitPath::LOGACTIONS_REBASE_MODE_MASK;\r
1034         CString nocommit;\r
1035 \r
1036         if( mode== CTGitPath::LOGACTIONS_REBASE_SKIP)\r
1037         {\r
1038                 pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
1039                 return 0;\r
1040         }\r
1041         \r
1042         if( mode != CTGitPath::LOGACTIONS_REBASE_PICK )\r
1043         {\r
1044                 this->m_SquashMessage+= pRev->m_Subject;\r
1045                 this->m_SquashMessage+= _T("\n");\r
1046                 this->m_SquashMessage+= pRev->m_Body;\r
1047         }\r
1048         else\r
1049                 this->m_SquashMessage.Empty();\r
1050 \r
1051         if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)\r
1052                 nocommit=_T(" --no-commit ");\r
1053 \r
1054         CString log;\r
1055         log.Format(_T("%s %d:%s"),CTGitPath::GetActionName(mode),this->GetCurrentCommitID(),pRev->m_CommitHash);\r
1056         AddLogString(log);\r
1057         AddLogString(pRev->m_Subject);\r
1058         cmd.Format(_T("git.exe cherry-pick %s %s"),nocommit,pRev->m_CommitHash);\r
1059 \r
1060         if(g_Git.Run(cmd,&out,CP_UTF8))\r
1061         {\r
1062                 AddLogString(out);\r
1063                 CTGitPathList list;\r
1064                 if(g_Git.ListConflictFile(list))\r
1065                 {\r
1066                         AddLogString(_T("Get conflict files fail"));\r
1067                         return -1;\r
1068                 }\r
1069                 if(list.GetCount() == 0 )\r
1070                 {\r
1071                         if(mode ==  CTGitPath::LOGACTIONS_REBASE_PICK)\r
1072                         {\r
1073                                 pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
1074                                 return 0;\r
1075                         }\r
1076                         if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)\r
1077                         {\r
1078                                 this->m_RebaseStage = REBASE_EDIT ;\r
1079                                 return -1; // Edit return -1 to stop rebase. \r
1080                         }\r
1081                         // Squash Case\r
1082                         if(CheckNextCommitIsSquash())\r
1083                         {   // no squash\r
1084                                 // let user edit last commmit message\r
1085                                 this->m_RebaseStage = REBASE_SQUASH_EDIT;\r
1086                                 return -1;\r
1087                         }\r
1088                 }\r
1089                 if(mode == CTGitPath::LOGACTIONS_REBASE_SQUASH)\r
1090                         m_RebaseStage = REBASE_SQUASH_CONFLICT;\r
1091                 else\r
1092                         m_RebaseStage = REBASE_CONFLICT;\r
1093                 return -1;      \r
1094 \r
1095         }else\r
1096         {\r
1097                 AddLogString(out);\r
1098                 if(mode ==  CTGitPath::LOGACTIONS_REBASE_PICK)\r
1099                 {\r
1100                         pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
1101                         return 0;\r
1102                 }\r
1103                 if(mode == CTGitPath::LOGACTIONS_REBASE_EDIT)\r
1104                 {\r
1105                         this->m_RebaseStage = REBASE_EDIT ;\r
1106                         return -1; // Edit return -1 to stop rebase. \r
1107                 }\r
1108 \r
1109                 // Squash Case\r
1110                 if(CheckNextCommitIsSquash())\r
1111                 {   // no squash\r
1112                         // let user edit last commmit message\r
1113                         this->m_RebaseStage = REBASE_SQUASH_EDIT;\r
1114                         return -1;\r
1115                 }\r
1116         }\r
1117         \r
1118         return 0;\r
1119 }\r
1120 \r
1121 BOOL CRebaseDlg::IsEnd()\r
1122 {\r
1123         if(m_CommitList.m_IsOldFirst)\r
1124                 return m_CurrentRebaseIndex>= this->m_CommitList.GetItemCount();\r
1125         else\r
1126                 return m_CurrentRebaseIndex<0;\r
1127 }\r
1128 \r
1129 int CRebaseDlg::RebaseThread()\r
1130 {\r
1131         int ret=0;\r
1132         while(1)\r
1133         {\r
1134                 if( m_RebaseStage == REBASE_START )\r
1135                 {\r
1136                         if( this->StartRebase() )\r
1137                         {\r
1138                                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
1139                                 ret = -1;\r
1140                                 break;\r
1141                         }\r
1142                         m_RebaseStage = REBASE_CONTINUE;\r
1143 \r
1144                 }else if( m_RebaseStage == REBASE_CONTINUE )\r
1145                 {\r
1146                         this->GoNext(); \r
1147                         if(IsEnd())\r
1148                         {\r
1149                                 ret = 0;\r
1150                                 m_RebaseStage = REBASE_FINISH;\r
1151                                 \r
1152                         }else\r
1153                         {\r
1154                                 ret = DoRebase();\r
1155 \r
1156                                 if( ret )\r
1157                                 {       \r
1158                                         break;\r
1159                                 }\r
1160                         }\r
1161 \r
1162                 }else if( m_RebaseStage == REBASE_FINISH )\r
1163                 {                       \r
1164                         FinishRebase();\r
1165                         m_RebaseStage = REBASE_DONE;\r
1166                         break;\r
1167                         \r
1168                 }else\r
1169                 {\r
1170                         break;\r
1171                 }\r
1172                 this->PostMessage(MSG_REBASE_UPDATE_UI);\r
1173                 //this->UpdateCurrentStatus();\r
1174         }\r
1175 \r
1176         InterlockedExchange(&m_bThreadRunning, FALSE);\r
1177         this->PostMessage(MSG_REBASE_UPDATE_UI);\r
1178         return ret;\r
1179 }\r
1180 \r
1181 void CRebaseDlg::ListConflictFile()\r
1182 {\r
1183         this->m_FileListCtrl.Clear();   \r
1184         CTGitPathList list;\r
1185         CTGitPath path;\r
1186         list.AddPath(path);\r
1187 \r
1188         this->m_FileListCtrl.GetStatus(&list,true);\r
1189         this->m_FileListCtrl.Show(CTGitPath::LOGACTIONS_UNMERGED|CTGitPath::LOGACTIONS_MODIFIED|CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_DELETED,\r
1190                                                            CTGitPath::LOGACTIONS_UNMERGED);\r
1191         if( this->m_FileListCtrl.GetItemCount() == 0 )\r
1192         {\r
1193                 \r
1194         }\r
1195 }\r
1196 \r
1197 LRESULT CRebaseDlg::OnRebaseUpdateUI(WPARAM,LPARAM)\r
1198 {\r
1199         UpdateCurrentStatus();\r
1200         if(m_CurrentRebaseIndex <0)\r
1201                 return 0;\r
1202         if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )\r
1203                 return 0;\r
1204         GitRev *curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
1205         \r
1206         switch(m_RebaseStage)\r
1207         {\r
1208         case REBASE_CONFLICT:\r
1209         case REBASE_SQUASH_CONFLICT:\r
1210                 ListConflictFile();                     \r
1211                 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_CONFLICT);\r
1212                 this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body);\r
1213                 break;\r
1214         case REBASE_EDIT:\r
1215                 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);\r
1216                 this->m_LogMessageCtrl.SetText(curRev->m_Subject+_T("\n")+curRev->m_Body);\r
1217                 break;\r
1218         case REBASE_SQUASH_EDIT:\r
1219                 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_MESSAGE);\r
1220                 this->m_LogMessageCtrl.SetText(this->m_SquashMessage);\r
1221                 break;\r
1222         default:\r
1223                 this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
1224         }       \r
1225         return 0;\r
1226 }\r
1227 void CRebaseDlg::OnCancel()\r
1228 {\r
1229         OnBnClickedAbort();\r
1230 }\r
1231 void CRebaseDlg::OnBnClickedAbort()\r
1232 {\r
1233         CString cmd,out;\r
1234         if(m_OrigUpstreamHash.IsEmpty())\r
1235         {\r
1236                 __super::OnCancel();\r
1237         }\r
1238         \r
1239         if(m_RebaseStage == CHOOSE_BRANCH || m_RebaseStage== CHOOSE_COMMIT_PICK_MODE)\r
1240         {\r
1241                 return;\r
1242         }\r
1243 \r
1244         if(CMessageBox::Show(NULL,_T("Are you sure you want to abort the rebase process?"),_T("TortoiseGit"),MB_YESNO) != IDYES)\r
1245                 return;\r
1246 \r
1247         cmd.Format(_T("git.exe checkout -f %s"),this->m_UpstreamCtrl.GetString());\r
1248         if(g_Git.Run(cmd,&out,CP_UTF8))\r
1249         {\r
1250                 AddLogString(out);\r
1251                 return ;\r
1252         }\r
1253 \r
1254         cmd.Format(_T("git.exe reset --hard  %s"),this->m_OrigUpstreamHash.Left(40));\r
1255         if(g_Git.Run(cmd,&out,CP_UTF8))\r
1256         {\r
1257                 AddLogString(out);\r
1258                 return ;\r
1259         }\r
1260         \r
1261         if(this->m_IsCherryPick) //there are not "branch" at cherry pick mode\r
1262                 return;\r
1263 \r
1264         cmd.Format(_T("git checkout -f %s"),this->m_BranchCtrl.GetString());\r
1265         if(g_Git.Run(cmd,&out,CP_UTF8))\r
1266         {\r
1267                 AddLogString(out);\r
1268                 return ;\r
1269         }\r
1270         \r
1271         cmd.Format(_T("git.exe reset --hard  %s"),this->m_OrigBranchHash.Left(40));\r
1272         if(g_Git.Run(cmd,&out,CP_UTF8))\r
1273         {\r
1274                 AddLogString(out);\r
1275                 return ;\r
1276         }\r
1277         __super::OnCancel();\r
1278 }\r
1279 \r
1280 void CRebaseDlg::OnBnClickedButtonBrowse()\r
1281 {\r
1282         if(CBrowseRefsDlg::PickRefForCombo(&m_UpstreamCtrl, gPickRef_NoTag))\r
1283                 OnCbnSelchangeUpstream();\r
1284 }\r
1285 \r
1286 void CRebaseDlg::OnBnClickedRebaseCheckForce()\r
1287 {\r
1288         // TODO: Add your control notification handler code here\r
1289         this->UpdateData();\r
1290         this->FetchLogList();\r
1291 }\r