//static function, Share with SyncDialog UINT CProgressDlg::RunCmdList(CWnd* pWnd, STRING_VECTOR& cmdlist, STRING_VECTOR& dirlist, bool bShowCommand, CString* pfilename, volatile bool* bAbort, CGitGuardedByteArray* pdata, CGit* git) { UINT ret=0; std::vector<std::unique_ptr<CBlockCacheForPath>> cacheBlockList; std::vector<std::unique_ptr<CGit>> gitList; if (dirlist.empty()) cacheBlockList.push_back(std::make_unique<CBlockCacheForPath>(git->m_CurrentDir)); else { for (const auto& dir : dirlist) { auto pGit = std::make_unique<CGit>(); pGit->m_CurrentDir = dir; gitList.push_back(std::move(pGit)); cacheBlockList.push_back(std::make_unique<CBlockCacheForPath>(dir)); } } EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_START, 0); if(pdata) pdata->clear(); for (size_t i = 0; i < cmdlist.size(); ++i) { if(cmdlist[i].IsEmpty()) continue; if (bShowCommand) { CStringA str; if (gitList.empty() || gitList.size() == 1 && gitList[0]->m_CurrentDir == git->m_CurrentDir) str = CUnicodeUtils::GetMulti(cmdlist[i].Trim() + _T("\r\n\r\n"), CP_UTF8); else str = CUnicodeUtils::GetMulti((i > 0 ? _T("\r\n") : _T("")) + gitList[i]->m_CurrentDir + _T("\r\n") + cmdlist[i].Trim() + _T("\r\n\r\n"), CP_UTF8); for (int j = 0; j < str.GetLength(); ++j) { if(pdata) { pdata->m_critSec.Lock(); pdata->push_back(str[j]); pdata->m_critSec.Unlock(); } else pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,str[j]); } if(pdata) pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0); } PROCESS_INFORMATION pi; CAutoGeneralHandle hRead; int runAsyncRet = -1; if (gitList.empty()) runAsyncRet = git->RunAsync(cmdlist[i].Trim(), &pi, hRead.GetPointer(), nullptr, pfilename); else runAsyncRet = gitList[i]->RunAsync(cmdlist[i].Trim(), &pi, hRead.GetPointer(), nullptr, pfilename); if (runAsyncRet) { EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_FAILED, -1 * runAsyncRet); return runAsyncRet; } CAutoGeneralHandle piProcess(pi.hProcess); CAutoGeneralHandle piThread(pi.hThread); DWORD readnumber; char lastByte = '\0'; char byte; CString output; while (ReadFile(hRead, &byte, 1, &readnumber, nullptr)) { if(pdata) { if(byte == 0) byte = '\n'; pdata->m_critSec.Lock(); if (byte == '\n' && lastByte != '\r') pdata->push_back('\r'); pdata->push_back( byte); lastByte = byte; pdata->m_critSec.Unlock(); if(byte == '\r' || byte == '\n') pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0); } else pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,byte); } if (pdata) { pdata->m_critSec.Lock(); bool post = !pdata->empty(); pdata->m_critSec.Unlock(); if (post) EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_RUN, 0); } CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": waiting for process to finish (%s), aborted: %d\n"), (LPCTSTR)cmdlist[i], *bAbort); WaitForSingleObject(pi.hProcess, INFINITE); DWORD status=0; if(!GetExitCodeProcess(pi.hProcess,&status) || *bAbort) { CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": process %s finished, status code could not be fetched, (error %d; %s), aborted: %d\n"), (LPCTSTR)cmdlist[i], GetLastError(), (LPCTSTR)CFormatMessageWrapper(), *bAbort); EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_FAILED, status); return TGIT_GIT_ERROR_GET_EXIT_CODE; } CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": process %s finished with code %d\n"), (LPCTSTR)cmdlist[i], status); ret |= status; } EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_END, ret); return ret; }
//static function, Share with SyncDialog UINT CProgressDlg::RunCmdList(CWnd *pWnd,std::vector<CString> &cmdlist,bool bShowCommand,CString *pfilename,bool *bAbort,CGitByteArray *pdata, CGit *git) { UINT ret=0; PROCESS_INFORMATION pi; HANDLE hRead = 0; memset(&pi,0,sizeof(PROCESS_INFORMATION)); CBlockCacheForPath cacheBlock(git->m_CurrentDir); EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_START, 0); if(pdata) pdata->clear(); for (size_t i = 0; i < cmdlist.size(); ++i) { if(cmdlist[i].IsEmpty()) continue; if (bShowCommand) { CStringA str = CUnicodeUtils::GetMulti(cmdlist[i].Trim() + _T("\r\n\r\n"), CP_UTF8); for (int j = 0; j < str.GetLength(); ++j) { if(pdata) { pdata->m_critSec.Lock(); pdata->push_back(str[j]); pdata->m_critSec.Unlock(); } else pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,str[j]); } if(pdata) pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0); } git->RunAsync(cmdlist[i].Trim(),&pi, &hRead, NULL, pfilename); DWORD readnumber; char lastByte = '\0'; char byte; CString output; while(ReadFile(hRead,&byte,1,&readnumber,NULL)) { if(pdata) { if(byte == 0) byte = '\n'; pdata->m_critSec.Lock(); if (byte == '\n' && lastByte != '\r') pdata->push_back('\r'); pdata->push_back( byte); lastByte = byte; pdata->m_critSec.Unlock(); if(byte == '\r' || byte == '\n') pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,0); } else pWnd->PostMessage(MSG_PROGRESSDLG_UPDATE_UI,MSG_PROGRESSDLG_RUN,byte); } if (pdata) { pdata->m_critSec.Lock(); bool post = !pdata->empty(); pdata->m_critSec.Unlock(); if (post) EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_RUN, 0); } CloseHandle(pi.hThread); CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": waiting for process to finish (%s), aborted: %d\n"), cmdlist[i], *bAbort); WaitForSingleObject(pi.hProcess, INFINITE); DWORD status=0; if(!GetExitCodeProcess(pi.hProcess,&status) || *bAbort) { CloseHandle(pi.hProcess); CloseHandle(hRead); CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": process %s finished, status code could not be fetched, (error %d; %s), aborted: %d\n"), cmdlist[i], GetLastError(), (CString)CFormatMessageWrapper(), *bAbort); EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_FAILED, status); return TGIT_GIT_ERROR_GET_EXIT_CODE; } CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": process %s finished with code %d\n"), cmdlist[i], status); ret |= status; } CloseHandle(pi.hProcess); CloseHandle(hRead); EnsurePostMessage(pWnd, MSG_PROGRESSDLG_UPDATE_UI, MSG_PROGRESSDLG_END, ret); return ret; }