OSDN Git Service

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