OSDN Git Service

RebaseDlg: Fix Commit List show Current Rebase commit problem
[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 // CRebaseDlg dialog\r
11 \r
12 IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)\r
13 \r
14 CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/)\r
15         : CResizableStandAloneDialog(CRebaseDlg::IDD, pParent)\r
16     , m_bPickAll(FALSE)\r
17     , m_bSquashAll(FALSE)\r
18     , m_bEditAll(FALSE)\r
19 {\r
20         m_RebaseStage=CHOOSE_BRANCH;\r
21         m_CurrentRebaseIndex=-1;\r
22         m_bThreadRunning =FALSE;\r
23 }\r
24 \r
25 CRebaseDlg::~CRebaseDlg()\r
26 {\r
27 }\r
28 \r
29 void CRebaseDlg::DoDataExchange(CDataExchange* pDX)\r
30 {\r
31     CDialog::DoDataExchange(pDX);\r
32     DDX_Control(pDX, IDC_REBASE_PROGRESS, m_ProgressBar);\r
33     DDX_Control(pDX, IDC_STATUS_STATIC, m_CtrlStatusText);\r
34     DDX_Check(pDX, IDC_PICK_ALL, m_bPickAll);\r
35     DDX_Check(pDX, IDC_SQUASH_ALL, m_bSquashAll);\r
36     DDX_Check(pDX, IDC_EDIT_ALL, m_bEditAll);\r
37         DDX_Control(pDX, IDC_REBASE_SPLIT, m_wndSplitter);\r
38         DDX_Control(pDX,IDC_COMMIT_LIST,m_CommitList);\r
39         DDX_Control(pDX,IDC_REBASE_COMBOXEX_BRANCH, this->m_BranchCtrl);\r
40         DDX_Control(pDX,IDC_REBASE_COMBOXEX_UPSTREAM,   this->m_UpstreamCtrl);\r
41 \r
42 }\r
43 \r
44 \r
45 BEGIN_MESSAGE_MAP(CRebaseDlg, CResizableStandAloneDialog)\r
46     ON_BN_CLICKED(IDC_PICK_ALL, &CRebaseDlg::OnBnClickedPickAll)\r
47     ON_BN_CLICKED(IDC_SQUASH_ALL, &CRebaseDlg::OnBnClickedSquashAll)\r
48     ON_BN_CLICKED(IDC_EDIT_ALL, &CRebaseDlg::OnBnClickedEditAll)\r
49     ON_BN_CLICKED(IDC_REBASE_SPLIT, &CRebaseDlg::OnBnClickedRebaseSplit)\r
50         ON_BN_CLICKED(IDC_REBASE_CONTINUE,OnBnClickedContinue)\r
51         ON_WM_SIZE()\r
52         ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH,   &CRebaseDlg::OnCbnSelchangeBranch)\r
53         ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream)\r
54 END_MESSAGE_MAP()\r
55 \r
56 void CRebaseDlg::AddRebaseAnchor()\r
57 {\r
58         AddAnchor(IDC_REBASE_TAB,TOP_LEFT,BOTTOM_RIGHT);\r
59         AddAnchor(IDC_COMMIT_LIST,TOP_LEFT, TOP_RIGHT);\r
60         AddAnchor(IDC_REBASE_SPLIT,TOP_LEFT, TOP_RIGHT);\r
61         AddAnchor(IDC_STATUS_STATIC, BOTTOM_LEFT,BOTTOM_RIGHT);\r
62         AddAnchor(IDC_REBASE_CONTINUE,BOTTOM_RIGHT);\r
63         AddAnchor(IDC_REBASE_ABORT, BOTTOM_RIGHT);\r
64         AddAnchor(IDC_REBASE_PROGRESS,BOTTOM_LEFT, BOTTOM_RIGHT);\r
65         AddAnchor(IDC_PICK_ALL,TOP_LEFT);\r
66         AddAnchor(IDC_SQUASH_ALL,TOP_LEFT);\r
67         AddAnchor(IDC_EDIT_ALL,TOP_LEFT);       \r
68         AddAnchor(IDC_REBASE_COMBOXEX_UPSTREAM,TOP_LEFT);\r
69         AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT);\r
70         AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT);\r
71         AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT);\r
72         \r
73 }\r
74 \r
75 BOOL CRebaseDlg::OnInitDialog()\r
76 {\r
77         CResizableStandAloneDialog::OnInitDialog();\r
78 \r
79         CRect rectDummy;\r
80         //IDC_REBASE_DUMY_TAB\r
81         \r
82         GetClientRect(m_DlgOrigRect);\r
83         m_CommitList.GetClientRect(m_CommitListOrigRect);\r
84 \r
85         CWnd *pwnd=this->GetDlgItem(IDC_REBASE_DUMY_TAB);\r
86         pwnd->GetWindowRect(&rectDummy);\r
87 \r
88         rectDummy.top-=20;\r
89         rectDummy.bottom-=20;\r
90 \r
91         rectDummy.left-=5;\r
92         rectDummy.right-=5;\r
93         \r
94         if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_REBASE_TAB))\r
95         {\r
96                 TRACE0("Failed to create output tab window\n");\r
97                 return FALSE;      // fail to create\r
98         }\r
99         m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);\r
100         // Create output panes:\r
101         //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;\r
102         DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;\r
103 \r
104         if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) )\r
105         {\r
106                 TRACE0("Failed to create output windows\n");\r
107                 return FALSE;      // fail to create\r
108         }\r
109 \r
110         if( ! this->m_LogMessageCtrl.Create(_T("Scintilla"),_T("source"),0,rectDummy,&m_ctrlTabCtrl,0,0) )\r
111         {\r
112                 TRACE0("Failed to create log message control");\r
113                 return FALSE;\r
114         }\r
115         m_LogMessageCtrl.Init(0);\r
116 \r
117         dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;\r
118 \r
119         if (!m_wndOutputRebase.Create(_T("Scintilla"),_T("source"),0,rectDummy, &m_ctrlTabCtrl, 0,0) )\r
120         {\r
121                 TRACE0("Failed to create output windows\n");\r
122                 return -1;      // fail to create\r
123         }\r
124         m_wndOutputRebase.Init(0);\r
125         m_wndOutputRebase.Call(SCI_SETREADONLY, TRUE);\r
126         \r
127         m_tooltips.Create(this);\r
128 \r
129         m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS , _T("RebaseDlg"));\r
130 \r
131         m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Conflict File"));\r
132         m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Commit Message"),1);\r
133         m_ctrlTabCtrl.AddTab(&m_wndOutputRebase,_T("Log"),2);\r
134         AddRebaseAnchor();\r
135 \r
136 \r
137         EnableSaveRestore(_T("RebaseDlg"));\r
138 \r
139         DWORD yPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));\r
140         RECT rcDlg, rcLogMsg, rcFileList;\r
141         GetClientRect(&rcDlg);\r
142         m_CommitList.GetWindowRect(&rcLogMsg);\r
143         ScreenToClient(&rcLogMsg);\r
144         this->m_ctrlTabCtrl.GetWindowRect(&rcFileList);\r
145         ScreenToClient(&rcFileList);\r
146         if (yPos)\r
147         {\r
148                 RECT rectSplitter;\r
149                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
150                 ScreenToClient(&rectSplitter);\r
151                 int delta = yPos - rectSplitter.top;\r
152                 if ((rcLogMsg.bottom + delta > rcLogMsg.top)&&(rcLogMsg.bottom + delta < rcFileList.bottom - 30))\r
153                 {\r
154                         m_wndSplitter.SetWindowPos(NULL, 0, yPos, 0, 0, SWP_NOSIZE);\r
155                         DoSize(delta);\r
156                 }\r
157         }\r
158 \r
159         if( this->m_RebaseStage == CHOOSE_BRANCH)\r
160         {\r
161                 this->LoadBranchInfo();\r
162 \r
163         }else\r
164         {\r
165                 this->m_BranchCtrl.EnableWindow(FALSE);\r
166                 this->m_UpstreamCtrl.EnableWindow(FALSE);\r
167         }\r
168 \r
169         m_CommitList.m_IsIDReplaceAction = TRUE;\r
170 //      m_CommitList.m_IsOldFirst = TRUE;\r
171         m_CommitList.m_IsRebaseReplaceGraph = TRUE;\r
172 \r
173         m_CommitList.DeleteAllItems();\r
174         m_CommitList.InsertGitColumn();\r
175 \r
176         FetchLogList();\r
177         SetContinueButtonText();\r
178         return TRUE;\r
179 }\r
180 // CRebaseDlg message handlers\r
181 \r
182 void CRebaseDlg::OnBnClickedPickAll()\r
183 {\r
184     // TODO: Add your control notification handler code here\r
185         this->UpdateData();\r
186         if(this->m_bPickAll)\r
187                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK);\r
188 \r
189         this->m_bEditAll=FALSE;\r
190         this->m_bSquashAll=FALSE;\r
191         this->UpdateData(FALSE);\r
192         \r
193 }\r
194 \r
195 void CRebaseDlg::OnBnClickedSquashAll()\r
196 {\r
197     // TODO: Add your control notification handler code here\r
198         this->UpdateData();\r
199         if(this->m_bSquashAll)\r
200                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH);\r
201 \r
202         this->m_bEditAll=FALSE;\r
203         this->m_bPickAll=FALSE;\r
204         this->UpdateData(FALSE);\r
205 \r
206 }\r
207 \r
208 void CRebaseDlg::OnBnClickedEditAll()\r
209 {\r
210     // TODO: Add your control notification handler code here\r
211         this->UpdateData();\r
212         if( this->m_bEditAll )\r
213                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT);\r
214 \r
215         this->m_bPickAll=FALSE;\r
216         this->m_bSquashAll=FALSE;\r
217         this->UpdateData(FALSE);\r
218 \r
219 }\r
220 \r
221 void CRebaseDlg::SetAllRebaseAction(int action)\r
222 {\r
223         for(int i=0;i<this->m_CommitList.m_logEntries.size();i++)\r
224         {\r
225                 m_CommitList.m_logEntries[i].m_Action=action;\r
226         }\r
227         m_CommitList.Invalidate();\r
228 }\r
229 \r
230 void CRebaseDlg::OnBnClickedRebaseSplit()\r
231 {\r
232         this->UpdateData();\r
233     // TODO: Add your control notification handler code here\r
234 }\r
235 \r
236 LRESULT CRebaseDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)\r
237 {\r
238         switch (message) {\r
239         case WM_NOTIFY:\r
240                 if (wParam == IDC_REBASE_SPLIT)\r
241                 { \r
242                         SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;\r
243                         DoSize(pHdr->delta);\r
244                 }\r
245                 break;\r
246         }\r
247 \r
248         return __super::DefWindowProc(message, wParam, lParam);\r
249 }\r
250 \r
251 void CRebaseDlg::DoSize(int delta)\r
252 {\r
253         \r
254         this->RemoveAllAnchors();\r
255 \r
256         CSplitterControl::ChangeHeight(GetDlgItem(IDC_COMMIT_LIST), delta, CW_TOPALIGN);\r
257         //CSplitterControl::ChangeHeight(GetDlgItem(), delta, CW_TOPALIGN);\r
258         CSplitterControl::ChangeHeight(GetDlgItem(IDC_REBASE_TAB), -delta, CW_BOTTOMALIGN);\r
259         //CSplitterControl::ChangeHeight(GetDlgItem(), -delta, CW_BOTTOMALIGN);\r
260         CSplitterControl::ChangePos(GetDlgItem(IDC_SQUASH_ALL),0,delta);\r
261         CSplitterControl::ChangePos(GetDlgItem(IDC_PICK_ALL),0,delta);\r
262         CSplitterControl::ChangePos(GetDlgItem(IDC_EDIT_ALL),0,delta);\r
263         \r
264         this->AddRebaseAnchor();\r
265         // adjust the minimum size of the dialog to prevent the resizing from\r
266         // moving the list control too far down.\r
267         CRect rcLogMsg;\r
268         m_CommitList.GetClientRect(rcLogMsg);\r
269         SetMinTrackSize(CSize(m_DlgOrigRect.Width(), m_DlgOrigRect.Height()-m_CommitListOrigRect.Height()+rcLogMsg.Height()));\r
270 \r
271         SetSplitterRange();\r
272 //      m_CommitList.Invalidate();\r
273 \r
274 //      GetDlgItem(IDC_LOGMESSAGE)->Invalidate();\r
275 \r
276         this->m_ctrlTabCtrl.Invalidate();\r
277         this->m_CommitList.Invalidate();\r
278         this->m_FileListCtrl.Invalidate();\r
279         this->m_LogMessageCtrl.Invalidate();\r
280 \r
281 }\r
282 \r
283 void CRebaseDlg::SetSplitterRange()\r
284 {\r
285         if ((m_CommitList)&&(m_ctrlTabCtrl))\r
286         {\r
287                 CRect rcTop;\r
288                 m_CommitList.GetWindowRect(rcTop);\r
289                 ScreenToClient(rcTop);\r
290                 CRect rcMiddle;\r
291                 m_ctrlTabCtrl.GetWindowRect(rcMiddle);\r
292                 ScreenToClient(rcMiddle);\r
293                 if (rcMiddle.Height() && rcMiddle.Width())\r
294                         m_wndSplitter.SetRange(rcTop.top+60, rcMiddle.bottom-80);\r
295         }\r
296 }\r
297 \r
298 void CRebaseDlg::OnSize(UINT nType,int cx, int cy)\r
299 {\r
300          // first, let the resizing take place\r
301     __super::OnSize(nType, cx, cy);\r
302 \r
303     //set range\r
304     SetSplitterRange();\r
305 }\r
306 \r
307 void CRebaseDlg::SaveSplitterPos()\r
308 {\r
309         if (!IsIconic())\r
310         {\r
311                 CRegDWORD regPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));\r
312                 RECT rectSplitter;\r
313                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
314                 ScreenToClient(&rectSplitter);\r
315                 regPos = rectSplitter.top;\r
316         }\r
317 }\r
318 \r
319 void CRebaseDlg::LoadBranchInfo()\r
320 {\r
321         m_BranchCtrl.SetMaxHistoryItems(0x7FFFFFFF);\r
322         m_UpstreamCtrl.SetMaxHistoryItems(0x7FFFFFFF);\r
323 \r
324         STRING_VECTOR list;\r
325         list.clear();\r
326         int current;\r
327         g_Git.GetBranchList(list,&current,CGit::BRANCH_ALL);\r
328         m_BranchCtrl.AddString(list);\r
329         m_UpstreamCtrl.AddString(list);\r
330 \r
331         m_BranchCtrl.SetCurSel(current);\r
332 \r
333         AddBranchToolTips(&m_BranchCtrl);\r
334         AddBranchToolTips(&m_UpstreamCtrl);\r
335 \r
336 }\r
337 \r
338 void CRebaseDlg::OnCbnSelchangeBranch()\r
339 {\r
340         FetchLogList();\r
341 }\r
342 \r
343 void CRebaseDlg::OnCbnSelchangeUpstream()\r
344 {\r
345         FetchLogList();\r
346 }\r
347 \r
348 void CRebaseDlg::FetchLogList()\r
349 {\r
350         m_CommitList.Clear();\r
351         this->m_CommitList.FillGitLog(NULL,0,&m_UpstreamCtrl.GetString(),&m_BranchCtrl.GetString());\r
352         if( m_CommitList.GetItemCount() == 0 )\r
353                 m_CommitList.ShowText(_T("Nothing Rebase"));\r
354 \r
355         CString hash=g_Git.GetHash(m_UpstreamCtrl.GetString());\r
356         \r
357 #if 0\r
358         if(m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash.size() >=0 )\r
359         {\r
360                 if(hash ==  m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash[0])\r
361                 {\r
362                         m_CommitList.Clear();\r
363                         m_CommitList.ShowText(_T("Nothing Rebase"));\r
364                 }\r
365         }\r
366 #endif\r
367 \r
368         m_tooltips.Pop();\r
369         AddBranchToolTips(&this->m_BranchCtrl);\r
370         AddBranchToolTips(&this->m_UpstreamCtrl);\r
371         \r
372         for(int i=0;i<m_CommitList.m_logEntries.size();i++)\r
373         {\r
374                 m_CommitList.m_logEntries[i].m_Action = CTGitPath::LOGACTIONS_REBASE_PICK;\r
375         }\r
376         \r
377         m_CommitList.Invalidate();\r
378 \r
379         if(m_CommitList.m_IsOldFirst)\r
380                 this->m_CurrentRebaseIndex = -1;\r
381         else\r
382                 this->m_CurrentRebaseIndex = m_CommitList.m_logEntries.size();\r
383         \r
384 }\r
385 \r
386 void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)\r
387 {\r
388         if(pBranch)\r
389         {\r
390                 CString text=pBranch->GetString();\r
391                 CString tooltip;\r
392                 BYTE_VECTOR data;\r
393                 g_Git.GetLog(data,text,NULL,1,0);\r
394                 GitRev rev;\r
395                 rev.ParserFromLog(data);\r
396                 tooltip.Format(_T("CommitHash:%s\nCommit by: %s  %s\n <b>%s</b> \n %s"),\r
397                         rev.m_CommitHash,\r
398                         rev.m_AuthorName,\r
399                         CAppUtils::FormatDateAndTime(rev.m_AuthorDate,DATE_LONGDATE),\r
400                         rev.m_Subject,\r
401                         rev.m_Body);\r
402 \r
403                 pBranch->DisableTooltip();\r
404                 this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip);\r
405         }\r
406 }\r
407 \r
408 BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg)\r
409 {\r
410         m_tooltips.RelayEvent(pMsg);\r
411         return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
412 }\r
413 int CRebaseDlg::CheckRebaseCondition()\r
414 {\r
415         this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
416 \r
417         if( !g_Git.CheckCleanWorkTree()  )\r
418         {\r
419                 CMessageBox::Show(NULL,_T("Rebase Need Clean Working Tree"),_T("TortoiseGit"),MB_OK);\r
420                 return -1;\r
421         }\r
422         //Todo Check $REBASE_ROOT\r
423         //Todo Check $DOTEST\r
424 \r
425         CString cmd;\r
426         cmd=_T("git.exe var GIT_COMMITTER_IDENT");\r
427         if(g_Git.Run(cmd,NULL,CP_UTF8))\r
428                 return -1;\r
429 \r
430         //Todo call pre_rebase_hook\r
431 }\r
432 int CRebaseDlg::StartRebase()\r
433 {\r
434         CString cmd,out;\r
435         //Todo call comment_for_reflog\r
436         cmd.Format(_T("git.exe checkout %s"),this->m_BranchCtrl.GetString());\r
437         this->AddLogString(cmd);\r
438 \r
439         if(g_Git.Run(cmd,&out,CP_UTF8))\r
440                 return -1;\r
441 \r
442         this->AddLogString(out);\r
443 \r
444         cmd=_T("git.exe rev-parse --verify HEAD");\r
445         if(g_Git.Run(cmd,&out,CP_UTF8))\r
446         {\r
447                 AddLogString(_T("No Head"));\r
448                 return -1;\r
449         }\r
450         //Todo \r
451         //git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||
452         //              echo "detached HEAD" > "$DOTEST"/head-name\r
453 \r
454         cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));\r
455         if(g_Git.Run(cmd,&out,CP_UTF8))\r
456         {\r
457                 AddLogString(_T("update ORIG_HEAD Fail"));\r
458                 return -1;\r
459         }\r
460         \r
461         cmd.Format(_T("git.exe update-ref ORIG_HEAD HEAD"));\r
462 \r
463         cmd.Format(_T("git.exe checkout %s"),this->m_UpstreamCtrl.GetString());\r
464         this->AddLogString(cmd);\r
465 \r
466         out.Empty();\r
467         if(g_Git.Run(cmd,&out,CP_UTF8))\r
468         {\r
469                 return -1;\r
470         }\r
471 \r
472         this->AddLogString(_T("Start Rebase\r\n"));\r
473         return 0;\r
474 }\r
475 void CRebaseDlg::OnBnClickedContinue()\r
476 {\r
477         if( m_RebaseStage == CHOOSE_BRANCH|| m_RebaseStage == CHOOSE_COMMIT_PICK_MODE )\r
478         {\r
479                 if(CheckRebaseCondition())\r
480                         return ;\r
481                 m_RebaseStage = REBASE_START;\r
482         }\r
483 \r
484         InterlockedExchange(&m_bThreadRunning, TRUE);\r
485         SetControlEnable();\r
486         \r
487         if (AfxBeginThread(RebaseThreadEntry, this)==NULL)\r
488         {\r
489                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
490                 CMessageBox::Show(NULL, _T("Create Rebase Thread Fail"), _T("TortoiseGit"), MB_OK | MB_ICONERROR);\r
491                 SetControlEnable();\r
492         }\r
493 }\r
494 int CRebaseDlg::GoNext()\r
495 {\r
496         if(m_CommitList.m_IsOldFirst)\r
497                 m_CurrentRebaseIndex++;\r
498         else\r
499                 m_CurrentRebaseIndex--; \r
500         return 0;\r
501 \r
502 }\r
503 int CRebaseDlg::StateAction()\r
504 {\r
505         switch(this->m_RebaseStage)\r
506         {\r
507         case CHOOSE_BRANCH:\r
508         case CHOOSE_COMMIT_PICK_MODE:\r
509                 if(StartRebase())\r
510                         return -1;\r
511                 m_RebaseStage = REBASE_START;\r
512                 GoNext();\r
513                 break;\r
514         }\r
515 \r
516         return 0;       \r
517 }\r
518 void CRebaseDlg::SetContinueButtonText()\r
519 {\r
520         CString Text;\r
521         switch(this->m_RebaseStage)\r
522         {\r
523         case CHOOSE_BRANCH:\r
524         case CHOOSE_COMMIT_PICK_MODE:\r
525                 Text = _T("Start");\r
526                 break;\r
527 \r
528         case REBASE_START:\r
529         case REBASE_CONTINUE:\r
530                 Text = _T("Continue");\r
531                 break;\r
532         case REBASE_ABORT:\r
533         case REBASE_FINISH:\r
534                 Text = _T("Finish");\r
535                 break;\r
536         }\r
537         this->GetDlgItem(IDC_REBASE_CONTINUE)->SetWindowText(Text);\r
538 }\r
539 \r
540 void CRebaseDlg::SetControlEnable()\r
541 {\r
542         switch(this->m_RebaseStage)\r
543         {\r
544         case CHOOSE_BRANCH:\r
545         case CHOOSE_COMMIT_PICK_MODE:\r
546                 \r
547                 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(TRUE);\r
548                 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(TRUE);\r
549                 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(TRUE);\r
550                 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(TRUE);\r
551                 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(TRUE);\r
552                 this->m_CommitList.m_IsEnableRebaseMenu=TRUE;\r
553                 break;\r
554 \r
555         case REBASE_START:\r
556         case REBASE_CONTINUE:\r
557         case REBASE_ABORT:\r
558         case REBASE_FINISH:\r
559                 this->GetDlgItem(IDC_PICK_ALL)->EnableWindow(FALSE);\r
560                 this->GetDlgItem(IDC_EDIT_ALL)->EnableWindow(FALSE);\r
561                 this->GetDlgItem(IDC_SQUASH_ALL)->EnableWindow(FALSE);\r
562                 this->GetDlgItem(IDC_REBASE_COMBOXEX_BRANCH)->EnableWindow(FALSE);\r
563                 this->GetDlgItem(IDC_REBASE_COMBOXEX_UPSTREAM)->EnableWindow(FALSE);\r
564                 this->m_CommitList.m_IsEnableRebaseMenu=FALSE;\r
565                 break;\r
566         }\r
567 \r
568         if(m_bThreadRunning)\r
569         {\r
570                 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(FALSE);\r
571                 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(FALSE);\r
572 \r
573         }else\r
574         {\r
575                 this->GetDlgItem(IDC_REBASE_CONTINUE)->EnableWindow(TRUE);\r
576                 this->GetDlgItem(IDC_REBASE_ABORT)->EnableWindow(TRUE);\r
577         }\r
578 }\r
579 \r
580 void CRebaseDlg::UpdateProgress()\r
581 {\r
582         int index;\r
583         CRect rect;\r
584 \r
585         if(m_CommitList.m_IsOldFirst)\r
586                 index = m_CurrentRebaseIndex+1;\r
587         else\r
588                 index = m_CommitList.GetItemCount()-m_CurrentRebaseIndex;\r
589 \r
590         m_ProgressBar.SetRange(1,m_CommitList.GetItemCount());\r
591         m_ProgressBar.SetPos(index);\r
592 \r
593         if(m_CurrentRebaseIndex>0 && m_CurrentRebaseIndex< m_CommitList.GetItemCount())\r
594         {\r
595                 CString text;\r
596                 text.Format(_T("Rebasing...(%d/%d)"),index,m_CommitList.GetItemCount());\r
597                 m_CtrlStatusText.SetWindowText(text);\r
598 \r
599         }\r
600 \r
601         GitRev *prevRev=NULL, *curRev=NULL;\r
602         int prevIndex;\r
603 \r
604         if( m_CurrentRebaseIndex >= 0 && m_CurrentRebaseIndex< m_CommitList.m_arShownList.GetSize())\r
605         {\r
606                 curRev=(GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
607         }\r
608         \r
609         if(m_CommitList.m_IsOldFirst)\r
610                 prevIndex=m_CurrentRebaseIndex-1;\r
611         else\r
612                 prevIndex=m_CurrentRebaseIndex+1;\r
613 \r
614         if(prevIndex >= 0 && prevIndex<m_CommitList.m_arShownList.GetSize())\r
615         {\r
616                 prevRev=(GitRev*)m_CommitList.m_arShownList[prevIndex];\r
617         }\r
618 \r
619         if(prevRev)\r
620         {\r
621                 prevRev->m_Action &= ~ CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
622                 m_CommitList.GetItemRect(prevIndex,&rect,LVIR_BOUNDS);\r
623                 m_CommitList.InvalidateRect(rect);\r
624         }\r
625 \r
626         if(curRev)\r
627         {\r
628                 curRev->m_Action |= CTGitPath::LOGACTIONS_REBASE_CURRENT;\r
629                 m_CommitList.GetItemRect(m_CurrentRebaseIndex,&rect,LVIR_BOUNDS);\r
630                 m_CommitList.InvalidateRect(rect);\r
631         }\r
632         m_CommitList.EnsureVisible(m_CurrentRebaseIndex,FALSE);\r
633 \r
634 }\r
635 \r
636 void CRebaseDlg::UpdateCurrentStatus()\r
637 {\r
638         if( m_CurrentRebaseIndex < 0)\r
639         {\r
640                 if(m_CommitList.m_IsOldFirst)\r
641                         m_RebaseStage = CRebaseDlg::REBASE_START;\r
642                 else\r
643                         m_RebaseStage = CRebaseDlg::REBASE_FINISH;\r
644         }\r
645 \r
646         if( m_CurrentRebaseIndex == m_CommitList.m_arShownList.GetSize())\r
647         {\r
648                 if(m_CommitList.m_IsOldFirst)\r
649                         m_RebaseStage = CRebaseDlg::REBASE_FINISH;\r
650                 else\r
651                         m_RebaseStage = CRebaseDlg::REBASE_START;\r
652         }\r
653 \r
654         SetContinueButtonText();\r
655         SetControlEnable();\r
656         UpdateProgress();\r
657 }\r
658 \r
659 void CRebaseDlg::AddLogString(CString str)\r
660 {\r
661         this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, FALSE);\r
662         CStringA sTextA = m_wndOutputRebase.StringForControl(str);//CUnicodeUtils::GetUTF8(str);\r
663         this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)sTextA);\r
664         this->m_wndOutputRebase.SendMessage(SCI_REPLACESEL, 0, (LPARAM)(LPCSTR)"\n");\r
665         this->m_wndOutputRebase.SendMessage(SCI_SETREADONLY, TRUE);\r
666 }\r
667 \r
668 int CRebaseDlg::DoRebase()\r
669 {       \r
670         if(m_CurrentRebaseIndex <0)\r
671                 return 0;\r
672         if(m_CurrentRebaseIndex >= m_CommitList.GetItemCount() )\r
673                 return 0;\r
674 \r
675         this->m_ctrlTabCtrl.SetActiveTab(REBASE_TAB_LOG);\r
676 \r
677         GitRev *pRev = (GitRev*)m_CommitList.m_arShownList[m_CurrentRebaseIndex];\r
678         int mode=pRev->m_Action & CTGitPath::LOGACTIONS_REBASE_MODE_MASK;\r
679         switch(mode)\r
680         {\r
681         case CTGitPath::LOGACTIONS_REBASE_PICK:\r
682                 AddLogString(CString(_T("Pick "))+pRev->m_CommitHash);\r
683                 pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
684                 break;\r
685         case CTGitPath::LOGACTIONS_REBASE_SQUASH:\r
686                 break;\r
687         case CTGitPath::LOGACTIONS_REBASE_EDIT:\r
688                 break;\r
689         case CTGitPath::LOGACTIONS_REBASE_SKIP:\r
690                 pRev->m_Action|= CTGitPath::LOGACTIONS_REBASE_DONE;\r
691                 return 0;\r
692                 break;\r
693         default:\r
694                 AddLogString(CString(_T("Unknow Action for "))+pRev->m_CommitHash);\r
695                 break;\r
696         }\r
697         return 0;\r
698 }\r
699 \r
700 BOOL CRebaseDlg::IsEnd()\r
701 {\r
702         if(m_CommitList.m_IsOldFirst)\r
703                 return m_CurrentRebaseIndex>= this->m_CommitList.GetItemCount();\r
704         else\r
705                 return m_CurrentRebaseIndex<0;\r
706 }\r
707 \r
708 int CRebaseDlg::RebaseThread()\r
709 {\r
710         int ret=0;\r
711         while(1)\r
712         {\r
713                 if( m_RebaseStage == REBASE_START )\r
714                 {\r
715                         if( this->StartRebase() )\r
716                         {\r
717                                 InterlockedExchange(&m_bThreadRunning, FALSE);\r
718                                 ret = -1;\r
719                                 break;\r
720                         }\r
721                         m_RebaseStage = REBASE_CONTINUE;\r
722                 }\r
723 \r
724                 if( m_RebaseStage == REBASE_CONTINUE )\r
725                 {\r
726                         this->GoNext(); \r
727                         if(IsEnd())\r
728                         {\r
729                                 ret = 0;\r
730                                 m_RebaseStage = REBASE_FINISH;\r
731                                 break;\r
732                         }\r
733 \r
734                         ret = DoRebase();\r
735 \r
736                         if( ret )\r
737                         {       \r
738                                 break;\r
739                         }\r
740                 }\r
741                 this->UpdateCurrentStatus();\r
742         }\r
743 \r
744         InterlockedExchange(&m_bThreadRunning, FALSE);\r
745         this->UpdateCurrentStatus();\r
746         this->SetControlEnable();\r
747         this->SetContinueButtonText();\r
748         return ret;\r
749 }