5 #include "registry.h"
\r
6 #include "GitConfig.h"
\r
8 #include "UnicodeUtils.h"
\r
11 static LPTSTR nextpath(LPCTSTR src, LPTSTR dst, UINT maxlen)
\r
15 while (*src == _T(';'))
\r
23 while (*src && *src != _T(';'))
\r
25 if (*src != _T('"'))
\r
37 while (*src && *src != _T('"'))
\r
52 while (*src == _T(';'))
\r
59 return (orgsrc != src) ? (LPTSTR)src : NULL;
\r
62 static inline BOOL FileExists(LPCTSTR lpszFileName)
\r
65 return _tstat(lpszFileName, &st) == 0;
\r
68 static BOOL FindGitPath()
\r
71 _tgetenv_s(&size, NULL, 0, _T("PATH"));
\r
78 TCHAR *env = (TCHAR*)alloca(size * sizeof(TCHAR));
\r
79 _tgetenv_s(&size, env, size, _T("PATH"));
\r
81 TCHAR buf[_MAX_PATH];
\r
83 // search in all paths defined in PATH
\r
84 while ((env = nextpath(env, buf, _MAX_PATH-1)) && *buf)
\r
86 TCHAR *pfin = buf + _tcslen(buf)-1;
\r
88 // ensure trailing slash
\r
89 if (*pfin != _T('/') && *pfin != _T('\\'))
\r
90 _tcscpy(++pfin, _T("\\"));
\r
92 const int len = _tcslen(buf);
\r
94 if ((len + 7) < _MAX_PATH)
\r
95 _tcscpy(pfin+1, _T("git.exe"));
\r
99 if ( FileExists(buf) )
\r
103 CGit::ms_LastMsysGitDir = buf;
\r
112 #define MAX_DIRBUFFER 1000
\r
113 #define CALL_OUTPUT_READ_CHUNK_SIZE 1024
\r
115 CString CGit::ms_LastMsysGitDir;
\r
118 // contains system environment that should be used by child processes (RunAsync)
\r
119 // initialized by CheckMsysGitDir
\r
120 static LPTSTR l_processEnv = NULL;
\r
123 BOOL CGit::IsVista()
\r
126 if( CRegStdWORD(_T("Software\\TortoiseGit\\CacheType") ) == 0)
\r
131 OSVERSIONINFO osvi;
\r
132 BOOL bIsWindowsXPorLater;
\r
134 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
\r
135 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
\r
137 GetVersionEx(&osvi);
\r
139 if(osvi.dwMajorVersion >= 6)
\r
147 GetCurrentDirectory(MAX_DIRBUFFER,m_CurrentDir.GetBuffer(MAX_DIRBUFFER));
\r
148 m_CurrentDir.ReleaseBuffer();
\r
157 static char g_Buffer[4096];
\r
159 int CGit::RunAsync(CString cmd,PROCESS_INFORMATION *piOut,HANDLE *hReadOut,CString *StdioFile)
\r
161 SECURITY_ATTRIBUTES sa;
\r
162 HANDLE hRead, hWrite;
\r
163 HANDLE hStdioFile = NULL;
\r
165 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
\r
166 sa.lpSecurityDescriptor=NULL;
\r
167 sa.bInheritHandle=TRUE;
\r
168 if(!CreatePipe(&hRead,&hWrite,&sa,0))
\r
170 return GIT_ERROR_OPEN_PIP;
\r
175 hStdioFile=CreateFile(*StdioFile,GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,
\r
176 &sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
\r
180 PROCESS_INFORMATION pi;
\r
181 si.cb=sizeof(STARTUPINFO);
\r
182 GetStartupInfo(&si);
\r
184 si.hStdError=hWrite;
\r
186 si.hStdOutput=hStdioFile;
\r
188 si.hStdOutput=hWrite;
\r
190 si.wShowWindow=SW_HIDE;
\r
191 si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
\r
193 LPTSTR pEnv = l_processEnv;
\r
194 DWORD dwFlags = pEnv ? CREATE_UNICODE_ENVIRONMENT : 0;
\r
196 if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,dwFlags,pEnv,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))
\r
199 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
\r
200 NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
\r
203 return GIT_ERROR_CREATE_PROCESS;
\r
206 CloseHandle(hWrite);
\r
215 //Must use sperate function to convert ANSI str to union code string
\r
216 //Becuase A2W use stack as internal convert buffer.
\r
217 void CGit::StringAppend(CString *str,BYTE *p,int code,int length)
\r
220 //str->Append(A2W_CP((LPCSTR)p,code));
\r
228 len= strlen((const char*)p);
\r
233 //buf = new WCHAR[len*4 + 1];
\r
234 buf = str->GetBuffer(len*4+1+str->GetLength())+str->GetLength();
\r
235 SecureZeroMemory(buf, (len*4 + 1)*sizeof(WCHAR));
\r
236 MultiByteToWideChar(code, 0, (LPCSTR)p, len, buf, len*4);
\r
237 str->ReleaseBuffer();
\r
238 //str->Append(buf);
\r
241 BOOL CGit::IsInitRepos()
\r
245 if(g_Git.Run(_T("git.exe rev-parse --revs-only HEAD"),&cmdout,CP_UTF8))
\r
247 // CMessageBox::Show(NULL,cmdout,_T("TortoiseGit"),MB_OK);
\r
250 if(cmdout.IsEmpty())
\r
255 int CGit::Run(CGitCall* pcall)
\r
257 PROCESS_INFORMATION pi;
\r
259 if(RunAsync(pcall->GetCmd(),&pi,&hRead))
\r
260 return GIT_ERROR_CREATE_PROCESS;
\r
263 BYTE data[CALL_OUTPUT_READ_CHUNK_SIZE];
\r
264 bool bAborted=false;
\r
265 while(ReadFile(hRead,data,CALL_OUTPUT_READ_CHUNK_SIZE,&readnumber,NULL))
\r
267 //Todo: when OnOutputData() returns 'true', abort git-command. Send CTRL-C signal?
\r
268 if(!bAborted)//For now, flush output when command aborted.
\r
269 if(pcall->OnOutputData(data,readnumber))
\r
276 CloseHandle(pi.hThread);
\r
278 WaitForSingleObject(pi.hProcess, INFINITE);
\r
281 if(!GetExitCodeProcess(pi.hProcess,&exitcode))
\r
283 return GIT_ERROR_GET_EXIT_CODE;
\r
286 CloseHandle(pi.hProcess);
\r
288 CloseHandle(hRead);
\r
291 class CGitCall_ByteVector : public CGitCall
\r
294 CGitCall_ByteVector(CString cmd,BYTE_VECTOR* pvector):CGitCall(cmd),m_pvector(pvector){}
\r
295 virtual bool OnOutputData(const BYTE* data, size_t size)
\r
297 size_t oldsize=m_pvector->size();
\r
298 m_pvector->resize(m_pvector->size()+size);
\r
299 memcpy(&*(m_pvector->begin()+oldsize),data,size);
\r
302 BYTE_VECTOR* m_pvector;
\r
305 int CGit::Run(CString cmd,BYTE_VECTOR *vector)
\r
307 CGitCall_ByteVector call(cmd,vector);
\r
310 int CGit::Run(CString cmd, CString* output,int code)
\r
312 BYTE_VECTOR vector;
\r
314 ret=Run(cmd,&vector);
\r
316 vector.push_back(0);
\r
318 StringAppend(output,&(vector[0]),code);
\r
322 CString CGit::GetUserName(void)
\r
325 Run(_T("git.exe config user.name"),&UserName,CP_UTF8);
\r
328 CString CGit::GetUserEmail(void)
\r
331 Run(_T("git.exe config user.email"),&UserName,CP_UTF8);
\r
335 CString CGit::GetCurrentBranch(void)
\r
338 //Run(_T("git.exe branch"),&branch);
\r
340 int ret=g_Git.Run(_T("git.exe branch"),&output,CP_UTF8);
\r
348 one=output.Tokenize(_T("\n"),pos);
\r
349 //list.push_back(one.Right(one.GetLength()-2));
\r
350 if(one[0] == _T('*'))
\r
351 return one.Right(one.GetLength()-2);
\r
354 return CString("");
\r
357 int CGit::BuildOutputFormat(CString &format,bool IsFull)
\r
360 log.Format(_T("#<%c>%%x00"),LOG_REV_ITEM_BEGIN);
\r
364 log.Format(_T("#<%c>%%an%%x00"),LOG_REV_AUTHOR_NAME);
\r
366 log.Format(_T("#<%c>%%ae%%x00"),LOG_REV_AUTHOR_EMAIL);
\r
368 log.Format(_T("#<%c>%%ai%%x00"),LOG_REV_AUTHOR_DATE);
\r
370 log.Format(_T("#<%c>%%cn%%x00"),LOG_REV_COMMIT_NAME);
\r
372 log.Format(_T("#<%c>%%ce%%x00"),LOG_REV_COMMIT_EMAIL);
\r
374 log.Format(_T("#<%c>%%ci%%x00"),LOG_REV_COMMIT_DATE);
\r
376 log.Format(_T("#<%c>%%s%%x00"),LOG_REV_COMMIT_SUBJECT);
\r
378 log.Format(_T("#<%c>%%b%%x00"),LOG_REV_COMMIT_BODY);
\r
381 log.Format(_T("#<%c>%%m%%H%%x00"),LOG_REV_COMMIT_HASH);
\r
383 log.Format(_T("#<%c>%%P%%x00"),LOG_REV_COMMIT_PARENT);
\r
388 log.Format(_T("#<%c>%%x00"),LOG_REV_COMMIT_FILE);
\r
394 int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash, CTGitPath *path ,int count,int mask,CString *from,CString *to)
\r
396 CGitCall_ByteVector gitCall(CString(),&logOut);
\r
397 return GetLog(&gitCall,hash,path,count,mask,from,to);
\r
400 //int CGit::GetLog(CGitCall* pgitCall, CString &hash, CTGitPath *path ,int count,int mask)
\r
401 int CGit::GetLog(CGitCall* pgitCall, CString &hash, CTGitPath *path, int count, int mask,CString *from,CString *to)
\r
412 file.Format(_T(" -- \"%s\""),path->GetGitPathString());
\r
415 num.Format(_T("-n%d"),count);
\r
419 if(mask& LOG_INFO_STAT )
\r
420 param += _T(" --numstat ");
\r
421 if(mask& LOG_INFO_FILESTATE)
\r
422 param += _T(" --raw ");
\r
424 if(mask& LOG_INFO_FULLHISTORY)
\r
425 param += _T(" --full-history ");
\r
427 if(mask& LOG_INFO_BOUNDARY)
\r
428 param += _T(" --left-right --boundary ");
\r
430 if(mask& CGit::LOG_INFO_ALL_BRANCH)
\r
431 param += _T(" --all ");
\r
433 if(mask& CGit::LOG_INFO_DETECT_COPYRENAME)
\r
434 param += _T(" -C ");
\r
436 if(mask& CGit::LOG_INFO_DETECT_RENAME )
\r
437 param += _T(" -M ");
\r
439 if(mask& CGit::LOG_INFO_FIRST_PARENT )
\r
440 param += _T(" --first-parent ");
\r
442 if(mask& CGit::LOG_INFO_NO_MERGE )
\r
443 param += _T(" --no-merges ");
\r
445 if(mask& CGit::LOG_INFO_FOLLOW)
\r
446 param += _T(" --follow ");
\r
448 if(from != NULL && to != NULL)
\r
451 range.Format(_T(" %s..%s "),*from,*to);
\r
456 cmd.Format(_T("git.exe log %s -z --topo-order %s --parents --pretty=format:\""),
\r
459 BuildOutputFormat(log,!(mask&CGit::LOG_INFO_ONLY_HASH));
\r
462 cmd += CString(_T("\" "))+hash+file;
\r
464 pgitCall->SetCmd(cmd);
\r
466 return Run(pgitCall);
\r
467 // return Run(cmd,&logOut);
\r
471 int CGit::GetShortLog(CString &logOut,CTGitPath * path, int count)
\r
480 cmd.Format(_T("git.exe log --left-right --boundary --topo-order -n%d --pretty=format:\""),n);
\r
481 BuildOutputFormat(log,false);
\r
482 cmd += log+_T("\"");
\r
484 cmd+= _T(" -- \"")+path->GetGitPathString()+_T("\"");
\r
485 //cmd += CString(_T("\" HEAD~40..HEAD"));
\r
486 return Run(cmd,&logOut);
\r
490 #define BUFSIZE 512
\r
491 void GetTempPath(CString &path)
\r
493 TCHAR lpPathBuffer[BUFSIZE];
\r
495 DWORD dwBufSize=BUFSIZE;
\r
496 dwRetVal = GetTempPath(dwBufSize, // length of the buffer
\r
497 lpPathBuffer); // buffer for path
\r
498 if (dwRetVal > dwBufSize || (dwRetVal == 0))
\r
502 path.Format(_T("%s"),lpPathBuffer);
\r
504 CString GetTempFile()
\r
506 TCHAR lpPathBuffer[BUFSIZE];
\r
508 DWORD dwBufSize=BUFSIZE;
\r
509 TCHAR szTempName[BUFSIZE];
\r
512 dwRetVal = GetTempPath(dwBufSize, // length of the buffer
\r
513 lpPathBuffer); // buffer for path
\r
514 if (dwRetVal > dwBufSize || (dwRetVal == 0))
\r
518 // Create a temporary file.
\r
519 uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files
\r
520 TEXT("Patch"), // temp file name prefix
\r
521 0, // create unique name
\r
522 szTempName); // buffer for name
\r
530 return CString(szTempName);
\r
534 int CGit::RunLogFile(CString cmd,CString &filename)
\r
537 PROCESS_INFORMATION pi;
\r
538 si.cb=sizeof(STARTUPINFO);
\r
539 GetStartupInfo(&si);
\r
541 SECURITY_ATTRIBUTES psa={sizeof(psa),NULL,TRUE};;
\r
542 psa.bInheritHandle=TRUE;
\r
544 HANDLE houtfile=CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,
\r
545 &psa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
\r
548 si.wShowWindow=SW_HIDE;
\r
549 si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
\r
550 si.hStdOutput = houtfile;
\r
552 if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))
\r
555 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
\r
556 NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
\r
559 return GIT_ERROR_CREATE_PROCESS;
\r
562 WaitForSingleObject(pi.hProcess,INFINITE);
\r
564 CloseHandle(pi.hThread);
\r
565 CloseHandle(pi.hProcess);
\r
566 CloseHandle(houtfile);
\r
567 return GIT_SUCCESS;
\r
571 git_revnum_t CGit::GetHash(CString &friendname)
\r
575 cmd.Format(_T("git.exe rev-parse %s" ),friendname);
\r
576 Run(cmd,&out,CP_UTF8);
\r
577 int pos=out.ReverseFind(_T('\n'));
\r
579 return out.Left(pos);
\r
583 int CGit::GetTagList(STRING_VECTOR &list)
\r
586 CString cmd,output;
\r
587 cmd=_T("git.exe tag -l");
\r
589 ret=g_Git.Run(cmd,&output,CP_UTF8);
\r
597 one=output.Tokenize(_T("\n"),pos);
\r
598 list.push_back(one);
\r
604 int CGit::GetBranchList(STRING_VECTOR &list,int *current,BRANCH_TYPE type)
\r
607 CString cmd,output;
\r
608 cmd=_T("git.exe branch");
\r
610 if(type==(BRANCH_LOCAL|BRANCH_REMOTE))
\r
612 else if(type==BRANCH_REMOTE)
\r
616 ret=g_Git.Run(cmd,&output,CP_UTF8);
\r
623 one=output.Tokenize(_T("\n"),pos);
\r
624 list.push_back(one.Right(one.GetLength()-2));
\r
625 if(one[0] == _T('*'))
\r
634 int CGit::GetRemoteList(STRING_VECTOR &list)
\r
637 CString cmd,output;
\r
638 cmd=_T("git.exe config --get-regexp remote.*.url");
\r
639 ret=g_Git.Run(cmd,&output,CP_UTF8);
\r
646 one=output.Tokenize(_T("\n"),pos);
\r
647 int start=one.Find(_T("."),0);
\r
651 url=one.Right(one.GetLength()-start-1);
\r
653 one=one.Left(one.Find(_T("."),0));
\r
654 list.push_back(one);
\r
661 int CGit::GetMapHashToFriendName(MAP_HASH_NAME &map)
\r
664 CString cmd,output;
\r
665 cmd=_T("git show-ref -d");
\r
666 ret=g_Git.Run(cmd,&output,CP_UTF8);
\r
673 one=output.Tokenize(_T("\n"),pos);
\r
674 int start=one.Find(_T(" "),0);
\r
678 name=one.Right(one.GetLength()-start-1);
\r
681 hash=one.Left(start);
\r
683 map[hash].push_back(name);
\r
690 BOOL CGit::CheckMsysGitDir()
\r
692 static BOOL bInitialized = FALSE;
\r
699 TCHAR *oldpath,*home;
\r
702 // set HOME if not set already
\r
703 _tgetenv_s(&size, NULL, 0, _T("HOME"));
\r
706 _tdupenv_s(&home,&size,_T("USERPROFILE"));
\r
707 _tputenv_s(_T("HOME"),home);
\r
712 CRegString sshclient=CRegString(_T("Software\\TortoiseGit\\SSH"));
\r
713 CString ssh=sshclient;
\r
717 _tputenv_s(_T("GIT_SSH"),ssh);
\r
720 _tputenv_s(_T("GIT_SSH"),_T(""));
\r
723 // search PATH if git/bin directory is alredy present
\r
724 if ( FindGitPath() )
\r
726 bInitialized = TRUE;
\r
730 // add git/bin path to PATH
\r
732 CRegString msysdir=CRegString(REG_MSYSGIT_PATH,_T(""),FALSE,HKEY_LOCAL_MACHINE);
\r
733 CString str=msysdir;
\r
736 CRegString msysinstalldir=CRegString(REG_MSYSGIT_INSTALL,_T(""),FALSE,HKEY_LOCAL_MACHINE);
\r
737 str=msysinstalldir;
\r
738 if ( !str.IsEmpty() )
\r
740 str += (str[str.GetLength()-1] != '\\') ? "\\bin" : "bin";
\r
749 //CGit::m_MsysGitPath=str;
\r
753 _tdupenv_s(&oldpath,&size,_T("PATH"));
\r
756 path.Format(_T("%s;%s"),oldpath,str);
\r
758 _tputenv_s(_T("PATH"),path);
\r
760 CString sOldPath = oldpath;
\r
764 if( !FindGitPath() )
\r
770 #ifdef _TORTOISESHELL
\r
771 l_processEnv = GetEnvironmentStrings();
\r
772 // updated environment is now duplicated for use in CreateProcess, restore original PATH for current process
\r
773 _tputenv_s(_T("PATH"),sOldPath);
\r
776 bInitialized = TRUE;
\r
782 class CGitCall_EnumFiles : public CGitCall
\r
785 CGitCall_EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)
\r
786 : m_pszProjectPath(pszProjectPath),
\r
787 m_pszSubPath(pszSubPath),
\r
789 m_pEnumCb(pEnumCb),
\r
790 m_pUserData(pUserData)
\r
794 typedef std::map<CStringA,char> TStrCharMap;
\r
796 const char * m_pszProjectPath;
\r
797 const char * m_pszSubPath;
\r
798 unsigned int m_nFlags;
\r
799 WGENUMFILECB * m_pEnumCb;
\r
800 void * m_pUserData;
\r
802 BYTE_VECTOR m_DataCollector;
\r
804 virtual bool OnOutputData(const BYTE* data, size_t size)
\r
806 m_DataCollector.append(data,size);
\r
809 // lines from igit.exe are 0 terminated
\r
810 int found=m_DataCollector.findData((const BYTE*)"",1);
\r
813 OnSingleLine( (LPCSTR)&*m_DataCollector.begin() );
\r
814 m_DataCollector.erase(m_DataCollector.begin(), m_DataCollector.begin()+found+1);
\r
816 return false;//Should never reach this
\r
818 virtual void OnEnd()
\r
822 UINT HexChar(char ch)
\r
824 if (ch >= '0' && ch <= '9')
\r
825 return (UINT)(ch - '0');
\r
826 else if (ch >= 'A' && ch <= 'F')
\r
827 return (UINT)(ch - 'A') + 10;
\r
828 else if (ch >= 'a' && ch <= 'f')
\r
829 return (UINT)(ch - 'a') + 10;
\r
834 bool OnSingleLine(LPCSTR line)
\r
836 //Parse single line
\r
838 wgFile_s fileStatus;
\r
842 fileStatus.nFlags = 0;
\r
844 fileStatus.nFlags |= WGFF_Directory;
\r
849 fileStatus.nStatus = WGFS_Unknown;
\r
852 case 'N': fileStatus.nStatus = WGFS_Normal; break;
\r
853 case 'M': fileStatus.nStatus = WGFS_Modified; break;
\r
854 case 'S': fileStatus.nStatus = WGFS_Staged; break;
\r
855 case 'A': fileStatus.nStatus = WGFS_Added; break;
\r
856 case 'C': fileStatus.nStatus = WGFS_Conflicted; break;
\r
857 case 'D': fileStatus.nStatus = WGFS_Deleted; break;
\r
858 case 'I': fileStatus.nStatus = WGFS_Ignored; break;
\r
859 case 'U': fileStatus.nStatus = WGFS_Unversioned; break;
\r
860 case 'E': fileStatus.nStatus = WGFS_Empty; break;
\r
867 fileStatus.sha1 = NULL;
\r
868 if ( !(fileStatus.nFlags & WGFF_Directory) )
\r
870 for (int i=0; i<20; i++)
\r
872 sha1[i] = (HexChar(line[0]) << 8) | HexChar(line[1]);
\r
880 fileStatus.sFileName = line;
\r
882 if ( (*m_pEnumCb)(&fileStatus,m_pUserData) )
\r
889 BOOL CGit::EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)
\r
891 if(!pszProjectPath || *pszProjectPath=='\0')
\r
894 CGitCall_EnumFiles W_GitCall(pszProjectPath,pszSubPath,nFlags,pEnumCb,pUserData);
\r
897 /* char W_szToDir[MAX_PATH];
\r
898 strncpy(W_szToDir,pszProjectPath,sizeof(W_szToDir)-1);
\r
899 if(W_szToDir[strlen(W_szToDir)-1]!='\\')
\r
900 strncat(W_szToDir,"\\",sizeof(W_szToDir)-1);
\r
902 SetCurrentDirectoryA(W_szToDir);
\r
903 GetCurrentDirectoryA(sizeof(W_szToDir)-1,W_szToDir);
\r
905 SetCurrentDir(CUnicodeUtils::GetUnicode(pszProjectPath));
\r
910 if (nFlags & WGEFF_NoRecurse) sMode += _T("r");
\r
911 if (nFlags & WGEFF_FullPath) sMode += _T("f");
\r
912 if (nFlags & WGEFF_DirStatusDelta) sMode += _T("d");
\r
913 if (nFlags & WGEFF_DirStatusAll) sMode += _T("D");
\r
914 if (nFlags & WGEFF_EmptyAsNormal) sMode += _T("e");
\r
915 if (nFlags & WGEFF_SingleFile) sMode += _T("s");
\r
923 cmd.Format(_T("igit.exe \"%s\" status %s \"%s\""), CUnicodeUtils::GetUnicode(pszProjectPath), sMode, CUnicodeUtils::GetUnicode(pszSubPath));
\r
925 cmd.Format(_T("igit.exe \"%s\" status %s"), CUnicodeUtils::GetUnicode(pszProjectPath), sMode);
\r
927 W_GitCall.SetCmd(cmd);
\r
928 // NOTE: should igit get added as a part of msysgit then use below line instead of the above one
\r
929 //W_GitCall.SetCmd(CGit::ms_LastMsysGitDir + cmd);
\r
931 if ( Run(&W_GitCall) )
\r
937 BOOL CGit::CheckCleanWorkTree()
\r
941 cmd=_T("git.exe rev-parse --verify HEAD");
\r
943 if(g_Git.Run(cmd,&out,CP_UTF8))
\r
946 cmd=_T("git.exe update-index --ignore-submodules --refresh");
\r
947 if(g_Git.Run(cmd,&out,CP_UTF8))
\r
950 cmd=_T("git.exe diff-files --quiet --ignore-submodules");
\r
951 if(g_Git.Run(cmd,&out,CP_UTF8))
\r
954 cmd=_T("git diff-index --cached --quiet HEAD --ignore-submodules");
\r
955 if(g_Git.Run(cmd,&out,CP_UTF8))
\r
961 int CGit::ListConflictFile(CTGitPathList &list,CTGitPath *path)
\r
963 BYTE_VECTOR vector;
\r
967 cmd.Format(_T("git.exe ls-files -u -t -z -- \"%s\""),path->GetGitPathString());
\r
969 cmd=_T("git.exe ls-files -u -t -z");
\r
971 if(g_Git.Run(cmd,&vector))
\r
976 list.ParserFromLsFile(vector);
\r