X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;ds=sidebyside;f=src%2FGit%2FGit.cpp;h=2b7be0dbec814ae07a25e1e4f2f6b6ea48d02e67;hb=aafe33f262f0d6fa81293f574eed2c619afd910d;hp=a78504a05e74cc8c0c956884c7ca1e2c4282bfcd;hpb=b9211523db09c9e080812cd4541c3170ac09d7d6;p=tortoisegit%2FTortoiseGitJp.git diff --git a/src/Git/Git.cpp b/src/Git/Git.cpp index a78504a..2b7be0d 100644 --- a/src/Git/Git.cpp +++ b/src/Git/Git.cpp @@ -3,12 +3,125 @@ #include "atlconv.h" #include "GitRev.h" #include "registry.h" +#include "GitConfig.h" + + +static LPTSTR nextpath(LPCTSTR src, LPTSTR dst, UINT maxlen) +{ + LPCTSTR orgsrc; + + while (*src == _T(';')) + src++; + + orgsrc = src; + + if (!--maxlen) + goto nullterm; + + while (*src && *src != _T(';')) + { + if (*src != _T('"')) + { + *dst++ = *src++; + if (!--maxlen) + { + orgsrc = src; + goto nullterm; + } + } + else + { + src++; + while (*src && *src != _T('"')) + { + *dst++ = *src++; + if (!--maxlen) + { + orgsrc = src; + goto nullterm; + } + } + + if (*src) + src++; + } + } + + while (*src == _T(';')) + src++; + +nullterm: + + *dst = 0; + + return (orgsrc != src) ? (LPTSTR)src : NULL; +} + +static inline BOOL FileExists(LPCTSTR lpszFileName) +{ + struct _stat st; + return _tstat(lpszFileName, &st) == 0; +} + +static BOOL FindGitPath() +{ + size_t size; + _tgetenv_s(&size, NULL, 0, _T("PATH")); + + if (!size) + { + return FALSE; + } + + TCHAR *env = (TCHAR*)alloca(size * sizeof(TCHAR)); + _tgetenv_s(&size, env, size, _T("PATH")); + + TCHAR buf[_MAX_PATH]; + + // search in all paths defined in PATH + while ((env = nextpath(env, buf, _MAX_PATH-1)) && *buf) + { + TCHAR *pfin = buf + _tcslen(buf)-1; + + // ensure trailing slash + if (*pfin != _T('/') && *pfin != _T('\\')) + _tcscpy(++pfin, _T("\\")); + + const int len = _tcslen(buf); + + if ((len + 7) < _MAX_PATH) + _tcscpy(pfin+1, _T("git.exe")); + else + break; + + if ( FileExists(buf) ) + { + // dir found + return TRUE; + } + } + + return FALSE; +} + #define MAX_DIRBUFFER 1000 +CString CGit::ms_LastMsysGitDir; CGit g_Git; CGit::CGit(void) { GetCurrentDirectory(MAX_DIRBUFFER,m_CurrentDir.GetBuffer(MAX_DIRBUFFER)); + + // make sure git/bin is in PATH before wingit.dll gets (delay) loaded by wgInit() + if ( !CheckMsysGitDir() ) + { + // TODO + } + + if ( !wgInit() ) + { + // TODO + } } CGit::~CGit(void) @@ -21,7 +134,7 @@ int CGit::RunAsync(CString cmd,PROCESS_INFORMATION *piOut,HANDLE *hReadOut,CStri { SECURITY_ATTRIBUTES sa; HANDLE hRead, hWrite; - HANDLE hStdioFile; + HANDLE hStdioFile = NULL; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor=NULL; @@ -72,17 +185,32 @@ int CGit::RunAsync(CString cmd,PROCESS_INFORMATION *piOut,HANDLE *hReadOut,CStri } //Must use sperate function to convert ANSI str to union code string //Becuase A2W use stack as internal convert buffer. -void CGit::StringAppend(CString *str,char *p) +void CGit::StringAppend(CString *str,BYTE *p,int code,int length) { - USES_CONVERSION; - str->Append(A2W_CP(p,CP_UTF8)); + //USES_CONVERSION; + //str->Append(A2W_CP((LPCSTR)p,code)); + WCHAR * buf; + int len ; + if(length<0) + len= strlen((const char*)p); + else + len=length; + //if (len==0) + // return ; + //buf = new WCHAR[len*4 + 1]; + buf = str->GetBuffer(len*4+1+str->GetLength())+str->GetLength(); + SecureZeroMemory(buf, (len*4 + 1)*sizeof(WCHAR)); + MultiByteToWideChar(code, 0, (LPCSTR)p, len, buf, len*4); + str->ReleaseBuffer(); + //str->Append(buf); + //delete buf; } BOOL CGit::IsInitRepos() { CString cmdout; cmdout.Empty(); - if(g_Git.Run(_T("git.exe rev-parse --revs-only HEAD"),&cmdout)) + if(g_Git.Run(_T("git.exe rev-parse --revs-only HEAD"),&cmdout,CP_UTF8)) { // CMessageBox::Show(NULL,cmdout,_T("TortoiseGit"),MB_OK); return TRUE; @@ -92,7 +220,7 @@ BOOL CGit::IsInitRepos() return FALSE; } -int CGit::Run(CString cmd, CString* output) +int CGit::Run(CString cmd,BYTE_VECTOR *vector) { PROCESS_INFORMATION pi; HANDLE hRead; @@ -100,10 +228,12 @@ int CGit::Run(CString cmd, CString* output) return GIT_ERROR_CREATE_PROCESS; DWORD readnumber; - while(ReadFile(hRead,g_Buffer,1023,&readnumber,NULL)) + BYTE data; + while(ReadFile(hRead,&data,1,&readnumber,NULL)) { - g_Buffer[readnumber]=0; - StringAppend(output,g_Buffer); + //g_Buffer[readnumber]=0; + vector->push_back(data); +// StringAppend(output,g_Buffer,codes); } @@ -121,18 +251,30 @@ int CGit::Run(CString cmd, CString* output) CloseHandle(hRead); return exitcode; + +} +int CGit::Run(CString cmd, CString* output,int code) +{ + BYTE_VECTOR vector; + int ret; + ret=Run(cmd,&vector); + + vector.push_back(0); + + StringAppend(output,&(vector[0]),code); + return ret; } CString CGit::GetUserName(void) { CString UserName; - Run(_T("git.exe config user.name"),&UserName); + Run(_T("git.exe config user.name"),&UserName,CP_UTF8); return UserName; } CString CGit::GetUserEmail(void) { CString UserName; - Run(_T("git.exe config user.email"),&UserName); + Run(_T("git.exe config user.email"),&UserName,CP_UTF8); return UserName; } @@ -141,7 +283,7 @@ CString CGit::GetCurrentBranch(void) CString output; //Run(_T("git.exe branch"),&branch); - int ret=g_Git.Run(_T("git.exe branch"),&output); + int ret=g_Git.Run(_T("git.exe branch"),&output,CP_UTF8); if(!ret) { int pos=0; @@ -161,41 +303,41 @@ CString CGit::GetCurrentBranch(void) int CGit::BuildOutputFormat(CString &format,bool IsFull) { CString log; - log.Format(_T("#<%c>%%n"),LOG_REV_ITEM_BEGIN); + log.Format(_T("#<%c>%%x00"),LOG_REV_ITEM_BEGIN); format += log; if(IsFull) { - log.Format(_T("#<%c>%%an%%n"),LOG_REV_AUTHOR_NAME); + log.Format(_T("#<%c>%%an%%x00"),LOG_REV_AUTHOR_NAME); format += log; - log.Format(_T("#<%c>%%ae%%n"),LOG_REV_AUTHOR_EMAIL); + log.Format(_T("#<%c>%%ae%%x00"),LOG_REV_AUTHOR_EMAIL); format += log; - log.Format(_T("#<%c>%%ai%%n"),LOG_REV_AUTHOR_DATE); + log.Format(_T("#<%c>%%ai%%x00"),LOG_REV_AUTHOR_DATE); format += log; - log.Format(_T("#<%c>%%cn%%n"),LOG_REV_COMMIT_NAME); + log.Format(_T("#<%c>%%cn%%x00"),LOG_REV_COMMIT_NAME); format += log; - log.Format(_T("#<%c>%%ce%%n"),LOG_REV_COMMIT_EMAIL); + log.Format(_T("#<%c>%%ce%%x00"),LOG_REV_COMMIT_EMAIL); format += log; - log.Format(_T("#<%c>%%ci%%n"),LOG_REV_COMMIT_DATE); + log.Format(_T("#<%c>%%ci%%x00"),LOG_REV_COMMIT_DATE); format += log; - log.Format(_T("#<%c>%%s%%n"),LOG_REV_COMMIT_SUBJECT); + log.Format(_T("#<%c>%%s%%x00"),LOG_REV_COMMIT_SUBJECT); format += log; - log.Format(_T("#<%c>%%b%%n"),LOG_REV_COMMIT_BODY); + log.Format(_T("#<%c>%%b%%x00"),LOG_REV_COMMIT_BODY); format += log; } - log.Format(_T("#<%c>%%m%%H%%n"),LOG_REV_COMMIT_HASH); + log.Format(_T("#<%c>%%m%%H%%x00"),LOG_REV_COMMIT_HASH); format += log; - log.Format(_T("#<%c>%%P%%n"),LOG_REV_COMMIT_PARENT); + log.Format(_T("#<%c>%%P%%x00"),LOG_REV_COMMIT_PARENT); format += log; if(IsFull) { - log.Format(_T("#<%c>%%n"),LOG_REV_COMMIT_FILE); + log.Format(_T("#<%c>%%x00"),LOG_REV_COMMIT_FILE); format += log; } return 0; } -int CGit::GetLog(CString& logOut, CString &hash, CTGitPath *path ,int count,int mask) +int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash, CTGitPath *path ,int count,int mask) { CString cmd; @@ -221,17 +363,41 @@ int CGit::GetLog(CString& logOut, CString &hash, CTGitPath *path ,int count,int if(mask& LOG_INFO_FULLHISTORY) param += _T(" --full-history "); - cmd.Format(_T("git.exe log %s -C --left-right --boundary --topo-order --parents %s --pretty=format:\""), + if(mask& LOG_INFO_BOUNDARY) + param += _T(" --left-right --boundary "); + + if(mask& CGit::LOG_INFO_ALL_BRANCH) + param += _T(" --all "); + + if(mask& CGit::LOG_INFO_DETECT_COPYRENAME) + param += _T(" -C "); + + if(mask& CGit::LOG_INFO_DETECT_RENAME ) + param += _T(" -M "); + + if(mask& CGit::LOG_INFO_FIRST_PARENT ) + param += _T(" --first-parent "); + + if(mask& CGit::LOG_INFO_NO_MERGE ) + param += _T(" --no-merges "); + + if(mask& CGit::LOG_INFO_FOLLOW) + param += _T(" --follow "); + + param+=hash; + + cmd.Format(_T("git.exe log %s -z --topo-order %s --parents --pretty=format:\""), num,param); - BuildOutputFormat(log); + BuildOutputFormat(log,!(mask&CGit::LOG_INFO_ONLY_HASH)); + cmd += log; cmd += CString(_T("\" "))+hash+file; return Run(cmd,&logOut); } - +#if 0 int CGit::GetShortLog(CString &logOut,CTGitPath * path, int count) { CString cmd; @@ -249,6 +415,7 @@ int CGit::GetShortLog(CString &logOut,CTGitPath * path, int count) //cmd += CString(_T("\" HEAD~40..HEAD")); return Run(cmd,&logOut); } +#endif #define BUFSIZE 512 void GetTempPath(CString &path) @@ -296,8 +463,6 @@ CString GetTempFile() int CGit::RunLogFile(CString cmd,CString &filename) { - HANDLE hRead, hWrite; - STARTUPINFO si; PROCESS_INFORMATION pi; si.cb=sizeof(STARTUPINFO); @@ -330,15 +495,17 @@ int CGit::RunLogFile(CString cmd,CString &filename) CloseHandle(pi.hProcess); CloseHandle(houtfile); return GIT_SUCCESS; - return 0; +// return 0; } git_revnum_t CGit::GetHash(CString &friendname) { + // NOTE: could replace this with wgGetRevisionID call + CString cmd; CString out; cmd.Format(_T("git.exe rev-parse %s" ),friendname); - Run(cmd,&out); + Run(cmd,&out,CP_UTF8); int pos=out.ReverseFind(_T('\n')); if(pos>0) return out.Left(pos); @@ -351,7 +518,7 @@ int CGit::GetTagList(STRING_VECTOR &list) CString cmd,output; cmd=_T("git.exe tag -l"); int i=0; - ret=g_Git.Run(cmd,&output); + ret=g_Git.Run(cmd,&output,CP_UTF8); if(!ret) { int pos=0; @@ -378,19 +545,19 @@ int CGit::GetBranchList(STRING_VECTOR &list,int *current,BRANCH_TYPE type) cmd+=_T(" -r"); int i=0; - ret=g_Git.Run(cmd,&output); + ret=g_Git.Run(cmd,&output,CP_UTF8); if(!ret) { int pos=0; CString one; while( pos>=0 ) { - i++; one=output.Tokenize(_T("\n"),pos); list.push_back(one.Right(one.GetLength()-2)); if(one[0] == _T('*')) if(current) *current=i; + i++; } } return ret; @@ -401,7 +568,7 @@ int CGit::GetRemoteList(STRING_VECTOR &list) int ret; CString cmd,output; cmd=_T("git.exe config --get-regexp remote.*.url"); - ret=g_Git.Run(cmd,&output); + ret=g_Git.Run(cmd,&output,CP_UTF8); if(!ret) { int pos=0; @@ -428,7 +595,7 @@ int CGit::GetMapHashToFriendName(MAP_HASH_NAME &map) int ret; CString cmd,output; cmd=_T("git show-ref -d"); - ret=g_Git.Run(cmd,&output); + ret=g_Git.Run(cmd,&output,CP_UTF8); if(!ret) { int pos=0; @@ -454,48 +621,84 @@ int CGit::GetMapHashToFriendName(MAP_HASH_NAME &map) BOOL CGit::CheckMsysGitDir() { - CRegString msysdir=CRegString(_T("Software\\TortoiseGit\\MSysGit"),_T(""),FALSE,HKEY_LOCAL_MACHINE); - CString str=msysdir; - if(str.IsEmpty()) - { - CRegString msysinstalldir=CRegString(_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1\\InstallLocation"),_T(""),FALSE,HKEY_LOCAL_MACHINE); - str=msysinstalldir; - str+="\\bin"; - msysdir=str; - msysdir.write(); + static BOOL bInitialized = FALSE; + if (bInitialized) + { + return TRUE; } - //CGit::m_MsysGitPath=str; TCHAR *oldpath,*home; size_t size; - _tdupenv_s(&home,&size,_T("HOME")); - - if(home == NULL) - { + // set HOME if not set already + _tgetenv_s(&size, NULL, 0, _T("HOME")); + if (!size) + { _tdupenv_s(&home,&size,_T("USERPROFILE")); _tputenv_s(_T("HOME"),home); free(home); } + + //setup ssh client + CRegString sshclient=CRegString(_T("Software\\TortoiseGit\\SSH")); + CString ssh=sshclient; + + if(!ssh.IsEmpty()) + { + _tputenv_s(_T("GIT_SSH"),ssh); + }else + { + _tputenv_s(_T("GIT_SSH"),_T("")); + } + + // search PATH if git/bin directory is alredy present + if ( FindGitPath() ) + { + bInitialized = TRUE; + return TRUE; + } + + // add git/bin path to PATH + + CRegString msysdir=CRegString(REG_MSYSGIT_PATH,_T(""),FALSE,HKEY_LOCAL_MACHINE); + CString str=msysdir; + if(str.IsEmpty()) + { + CRegString msysinstalldir=CRegString(REG_MSYSGIT_INSTALL,_T(""),FALSE,HKEY_LOCAL_MACHINE); + str=msysinstalldir; + if ( !str.IsEmpty() ) + { + str += (str[str.GetLength()-1] != '\\') ? "\\bin" : "bin"; + msysdir=str; + msysdir.write(); + } + else + { + return false; + } + } + //CGit::m_MsysGitPath=str; + //set path + _tdupenv_s(&oldpath,&size,_T("PATH")); CString path; - path.Format(_T("%s;"),str); - path+=oldpath; + path.Format(_T("%s;%s"),oldpath,str); _tputenv_s(_T("PATH"),path); free(oldpath); - CString cmd,out; - cmd=_T("git.exe --version"); - if(g_Git.Run(cmd,&out)) + + if( !FindGitPath() ) { return false; } else + { + bInitialized = TRUE; return true; - -} \ No newline at end of file + } +}