OSDN Git Service

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