Add error code when run git command
[TortoiseGit.git] / src / TortoiseProc / ProgressDlg.cpp
blob979108f124e710cbe511a0c6ec9a408f32323d16
1 // ProgressDlg.cpp : implementation file
2 //
4 #include "stdafx.h"
5 #include "TortoiseProc.h"
6 #include "ProgressDlg.h"
7 #include "Git.h"
8 #include "atlconv.h"
9 // CProgressDlg dialog
11 IMPLEMENT_DYNAMIC(CProgressDlg, CResizableStandAloneDialog)
13 CProgressDlg::CProgressDlg(CWnd* pParent /*=NULL*/)
14 : CResizableStandAloneDialog(CProgressDlg::IDD, pParent), m_bShowCommand(true), m_bAutoCloseOnSuccess(false), m_bAbort(false), m_bDone(false)
16 m_pThread = NULL;
17 m_bAltAbortPress=false;
18 m_bBufferAll=false;
21 CProgressDlg::~CProgressDlg()
23 if(m_pThread != NULL)
25 delete m_pThread;
29 void CProgressDlg::DoDataExchange(CDataExchange* pDX)
31 CDialog::DoDataExchange(pDX);
32 DDX_Control(pDX, IDC_CURRENT, this->m_CurrentWork);
33 DDX_Control(pDX, IDC_TITLE_ANIMATE, this->m_Animate);
34 DDX_Control(pDX, IDC_RUN_PROGRESS, this->m_Progress);
35 DDX_Control(pDX, IDC_LOG, this->m_Log);
39 BEGIN_MESSAGE_MAP(CProgressDlg, CResizableStandAloneDialog)
40 ON_MESSAGE(MSG_PROGRESSDLG_UPDATE_UI, OnProgressUpdateUI)
41 ON_BN_CLICKED(IDOK, &CProgressDlg::OnBnClickedOk)
42 ON_BN_CLICKED(IDC_PROGRESS_BUTTON1,&CProgressDlg::OnBnClickedButton1)
43 END_MESSAGE_MAP()
45 BOOL CProgressDlg::OnInitDialog()
47 CResizableStandAloneDialog::OnInitDialog();
49 AddAnchor(IDC_TITLE_ANIMATE, TOP_LEFT, TOP_RIGHT);
50 AddAnchor(IDC_RUN_PROGRESS, TOP_LEFT,TOP_RIGHT);
51 AddAnchor(IDC_LOG, TOP_LEFT,BOTTOM_RIGHT);
53 AddAnchor(IDOK,BOTTOM_RIGHT);
54 AddAnchor(IDCANCEL,BOTTOM_RIGHT);
55 AddAnchor(IDC_PROGRESS_BUTTON1,BOTTOM_RIGHT);
57 this->GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_HIDE);
58 m_Animate.Open(IDR_DOWNLOAD);
60 CString InitialText;
61 if ( !m_PreText.IsEmpty() )
63 InitialText = m_PreText + _T("\r\n");
65 #if 0
66 if (m_bShowCommand && (!m_GitCmd.IsEmpty() ))
68 InitialText += m_GitCmd+_T("\r\n\r\n");
70 #endif
71 m_Log.SetWindowTextW(InitialText);
72 m_CurrentWork.SetWindowTextW(_T(""));
74 m_pThread = AfxBeginThread(ProgressThreadEntry, this, THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
75 if (m_pThread==NULL)
77 // ReportError(CString(MAKEINTRESOURCE(IDS_ERR_THREADSTARTFAILED)));
79 else
81 m_pThread->m_bAutoDelete = FALSE;
82 m_pThread->ResumeThread();
85 if(!m_Title.IsEmpty())
86 this->SetWindowText(m_Title);
87 return TRUE;
90 UINT CProgressDlg::ProgressThreadEntry(LPVOID pVoid)
92 return ((CProgressDlg*)pVoid)->ProgressThread();
95 //static function, Share with SyncDialog
96 UINT CProgressDlg::RunCmdList(CWnd *pWnd,std::vector<CString> &cmdlist,bool bShowCommand,CString *pfilename,bool *bAbort,std::vector<TCHAR>*pdata)
98 UINT ret=0;
100 PROCESS_INFORMATION pi;
101 HANDLE hRead;
103 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_START,0);
105 if(pdata)
106 pdata->clear();
108 for(int i=0;i<cmdlist.size();i++)
110 if(cmdlist[i].IsEmpty())
111 continue;
113 if (bShowCommand)
115 CString str;
116 str+= cmdlist[i]+_T("\n\n");
117 for(int j=0;j<str.GetLength();j++)
119 if(pdata)
120 pdata->push_back(str[j]);
121 else
122 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,str[j]);
124 if(pdata)
125 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0);
128 g_Git.RunAsync(cmdlist[i],&pi, &hRead,pfilename);
130 DWORD readnumber;
131 char buffer[2];
132 CString output;
133 while(ReadFile(hRead,buffer,1,&readnumber,NULL))
135 buffer[readnumber]=0;
137 if(pdata)
139 pdata->push_back((TCHAR)buffer[0]);
141 if(buffer[0] == '\r' || buffer[0] == '\n')
142 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0);
143 }else
144 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,buffer[0]);
147 CloseHandle(pi.hThread);
149 WaitForSingleObject(pi.hProcess, INFINITE);
151 DWORD status=0;
152 if(!GetExitCodeProcess(pi.hProcess,&status) || *bAbort)
154 CloseHandle(pi.hProcess);
156 CloseHandle(hRead);
158 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_FAILED,0);
159 return GIT_ERROR_GET_EXIT_CODE;
161 ret |= status;
164 CloseHandle(pi.hProcess);
166 CloseHandle(hRead);
168 pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_END,0);
170 return ret;
174 UINT CProgressDlg::ProgressThread()
177 m_GitCmdList.push_back(m_GitCmd);
179 CString *pfilename;
181 if(m_LogFile.IsEmpty())
182 pfilename=NULL;
183 else
184 pfilename=&m_LogFile;
186 m_GitStatus = RunCmdList(this,m_GitCmdList,m_bShowCommand,pfilename,&m_bAbort,&this->m_Databuf);;
187 return 0;
190 LRESULT CProgressDlg::OnProgressUpdateUI(WPARAM wParam,LPARAM lParam)
192 if(wParam == MSG_PROGRESSDLG_START)
194 m_BufStart = 0 ;
195 m_Animate.Play(0,-1,-1);
196 this->DialogEnableWindow(IDOK,FALSE);
198 if(wParam == MSG_PROGRESSDLG_END || wParam == MSG_PROGRESSDLG_FAILED)
200 if(m_bBufferAll)
202 m_Databuf.push_back(0);
203 InsertCRLF();
204 m_Log.SetWindowText(&m_Databuf[0]);
206 m_BufStart=0;
207 this->m_Databuf.clear();
209 m_bDone = true;
210 m_Animate.Stop();
211 m_Progress.SetPos(100);
212 this->DialogEnableWindow(IDOK,TRUE);
214 CString err;
215 err.Format(_T("\r\nFailed 0x%x(git return wrong reture code at sometime )\r\n"),m_GitStatus);
216 if(this->m_GitStatus)
217 InsertColorText(this->m_Log,err,RGB(255,0,0));
218 else
219 InsertColorText(this->m_Log,_T("\r\nSuccess\r\n"),RGB(0,0,255));
221 if(wParam == MSG_PROGRESSDLG_END && m_GitStatus == 0)
223 if(m_bAutoCloseOnSuccess)
224 EndDialog(IDOK);
226 if(!m_changeAbortButtonOnSuccessTo.IsEmpty())
228 GetDlgItem(IDC_PROGRESS_BUTTON1)->SetWindowText(m_changeAbortButtonOnSuccessTo);
229 GetDlgItem(IDC_PROGRESS_BUTTON1)->ShowWindow(SW_SHOW);
230 GetDlgItem(IDCANCEL)->ShowWindow(SW_HIDE);
231 //Set default button is "close" rather than "push"
232 this->SendMessage(WM_NEXTDLGCTL, (WPARAM)GetDlgItem(IDOK)->m_hWnd, TRUE);
234 else
235 DialogEnableWindow(IDCANCEL, FALSE);
237 else
238 DialogEnableWindow(IDCANCEL, FALSE);
241 if(!m_bBufferAll)
243 if(lParam == 0)
245 for(int i=this->m_BufStart;i<this->m_Databuf.size();i++)
247 ParserCmdOutput(this->m_Databuf[m_BufStart]);
248 m_BufStart++;
250 }else
251 ParserCmdOutput((TCHAR)lParam);
253 return 0;
256 //static function, Share with SyncDialog
257 int CProgressDlg::FindPercentage(CString &log)
259 int s1=log.Find(_T('%'));
260 if(s1<0)
261 return -1;
263 int s2=s1-1;
264 for(int i=s1-1;i>=0;i--)
266 if(log[i]>=_T('0') && log[i]<=_T('9'))
267 s2=i;
268 else
269 break;
271 return _ttol(log.Mid(s2,s1-s2));
274 #if 0
275 void CProgressDlg::ParserCmdOutput(TCHAR ch)
277 TRACE(_T("%c"),ch);
278 if( ch == _T('\r') || ch == _T('\n'))
280 TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));
281 TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));
283 int lines=m_Log.GetLineCount();
285 if(ch == _T('\r'))
287 int start=m_Log.LineIndex(lines-1);
288 int length=m_Log.LineLength(lines-1);
289 m_Log.SetSel( start,start+length);
290 m_Log.ReplaceSel(m_LogText);
292 }else
294 m_Log.SetSel(m_Log.GetWindowTextLength(),
295 m_Log.GetWindowTextLength());
296 m_Log.ReplaceSel(CString(_T("\r\n"))+m_LogText);
299 if( lines > 500 ) //limited log length
301 int end=m_Log.LineIndex(1);
302 m_Log.SetSel(0,end);
303 m_Log.ReplaceSel(_T(""));
305 m_Log.LineScroll(m_Log.GetLineCount());
307 int s1=m_LogText.Find(_T(':'));
308 int s2=m_LogText.Find(_T('%'));
309 if(s1>0 && s2>0)
311 this->m_CurrentWork.SetWindowTextW(m_LogText.Left(s1));
312 int pos=FindPercentage(m_LogText);
313 TRACE(_T("Pos %d\r\n"),pos);
314 if(pos>0)
315 this->m_Progress.SetPos(pos);
318 m_LogText=_T("");
320 }else
322 m_LogText+=ch;
326 #endif
328 void CProgressDlg::ParserCmdOutput(TCHAR ch)
330 ParserCmdOutput(this->m_Log,this->m_Progress,this->m_LogText,ch,&this->m_CurrentWork);
332 void CProgressDlg::ParserCmdOutput(CRichEditCtrl &log,CProgressCtrl &progressctrl,CString &oneline, TCHAR ch, CWnd *CurrentWork)
334 //TRACE(_T("%c"),ch);
335 TRACE(_T("%c"),ch);
336 if( ch == _T('\r') || ch == _T('\n'))
338 TRACE(_T("End Char %s \r\n"),ch==_T('\r')?_T("lf"):_T(""));
339 TRACE(_T("End Char %s \r\n"),ch==_T('\n')?_T("cr"):_T(""));
341 int lines=log.GetLineCount();
343 if(ch == _T('\r'))
345 int start=log.LineIndex(lines-1);
346 int length=log.LineLength(lines-1);
347 log.SetSel( start,start+length);
348 log.ReplaceSel(oneline);
350 }else
352 log.SetSel(log.GetWindowTextLength(),
353 log.GetWindowTextLength());
354 log.ReplaceSel(CString(_T("\r\n"))+oneline);
357 if( lines > 500 ) //limited log length
359 int end=log.LineIndex(1);
360 log.SetSel(0,end);
361 log.ReplaceSel(_T(""));
363 log.LineScroll(log.GetLineCount());
365 int s1=oneline.Find(_T(':'));
366 int s2=oneline.Find(_T('%'));
367 if(s1>0 && s2>0)
369 if(CurrentWork)
370 CurrentWork->SetWindowTextW(oneline.Left(s1));
372 int pos=FindPercentage(oneline);
373 TRACE(_T("Pos %d\r\n"),pos);
374 if(pos>0)
375 progressctrl.SetPos(pos);
378 oneline=_T("");
380 }else
382 oneline+=ch;
386 void CProgressDlg::RemoveLastLine(CString &str)
388 int start;
389 start=str.ReverseFind(_T('\n'));
390 if(start>0)
391 str=str.Left(start);
392 return;
394 // CProgressDlg message handlers
396 void CProgressDlg::OnBnClickedOk()
398 // TODO: Add your control notification handler code here
399 m_Log.GetWindowText(this->m_LogText);
400 OnOK();
403 void CProgressDlg::OnBnClickedButton1()
405 this->EndDialog(IDC_PROGRESS_BUTTON1);
408 void CProgressDlg::OnCancel()
410 m_bAbort = true;
411 if(m_bDone)
413 CResizableStandAloneDialog::OnCancel();
414 return;
417 if( g_Git.m_CurrentGitPi.hProcess )
419 if(::GenerateConsoleCtrlEvent(CTRL_C_EVENT,0))
421 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);
422 }else
424 int error=::GetLastError();
427 HANDLE hProcessHandle = ::OpenProcess( PROCESS_TERMINATE, FALSE,g_Git.m_CurrentGitPi.dwProcessId);
428 if( hProcessHandle )
429 if(!::TerminateProcess(hProcessHandle,-1) )
431 int error =::GetLastError();
435 ::WaitForSingleObject(g_Git.m_CurrentGitPi.hProcess ,10000);
436 CResizableStandAloneDialog::OnCancel();
440 void CProgressDlg::InsertCRLF()
442 for(int i=0;i<m_Databuf.size();i++)
444 if(m_Databuf[i]==_T('\n'))
446 if(i==0 || m_Databuf[i-1]!= _T('\r'))
448 m_Databuf.insert(m_Databuf.begin()+i,_T('\r'));
449 i++;
455 void CProgressDlg::InsertColorText(CRichEditCtrl &edit,CString text,COLORREF rgb)
457 CHARFORMAT old,cf;
458 edit.GetDefaultCharFormat(cf);
459 old=cf;
460 cf.dwMask|=CFM_COLOR;
461 cf.crTextColor=rgb;
462 cf.dwEffects|=CFE_BOLD;
463 cf.dwEffects &= ~CFE_AUTOCOLOR ;
464 edit.SetSel(edit.GetTextLength()-1,edit.GetTextLength());
465 edit.ReplaceSel(text);
466 edit.SetSel(edit.LineIndex(edit.GetLineCount()-2),edit.GetTextLength());
467 edit.SetSelectionCharFormat(cf);
468 edit.SetSel(edit.GetTextLength(),edit.GetTextLength());
469 edit.SetDefaultCharFormat(old);
470 edit.LineScroll(edit.GetLineCount());