OSDN Git Service

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