OSDN Git Service

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