OSDN Git Service

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