OSDN Git Service

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