static LPTSTR l_processEnv = NULL;\r
\r
\r
-BOOL CGit::IsVista()\r
-{\r
-\r
- if( CRegStdWORD(_T("Software\\TortoiseGit\\CacheType") ) == 0)\r
- {\r
- return TRUE;\r
- }\r
-\r
- OSVERSIONINFO osvi;\r
- BOOL bIsWindowsXPorLater;\r
-\r
- ZeroMemory(&osvi, sizeof(OSVERSIONINFO));\r
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
-\r
- GetVersionEx(&osvi);\r
- \r
- if(osvi.dwMajorVersion >= 6)\r
- return TRUE;\r
- else\r
- return FALSE;\r
-}\r
\r
CGit::CGit(void)\r
{\r
{\r
//USES_CONVERSION;\r
//str->Append(A2W_CP((LPCSTR)p,code));\r
+ if(str == NULL)\r
+ return ;\r
+\r
WCHAR * buf;\r
\r
int len ;\r
return CString("");\r
}\r
\r
+int CGit::GetCurrentBranchFromFile(const CString &sProjectRoot, CString &sBranchOut)\r
+{\r
+ // read current branch name like git-gui does, by parsing the .git/HEAD file directly\r
+\r
+ if ( sProjectRoot.IsEmpty() )\r
+ return -1;\r
+\r
+ CString sHeadFile = sProjectRoot + _T("\\") + g_GitAdminDir.GetAdminDirName() + _T("\\HEAD");\r
+\r
+ FILE *pFile;\r
+ _tfopen_s(&pFile, sHeadFile.GetString(), _T("r"));\r
+\r
+ if (!pFile)\r
+ {\r
+ return -1;\r
+ }\r
+\r
+ char s[256] = {0};\r
+ fgets(s, sizeof(s), pFile);\r
+\r
+ fclose(pFile);\r
+\r
+ const char *pfx = "ref: refs/heads/";\r
+ const int len = 16;//strlen(pfx)\r
+\r
+ if ( !strncmp(s, pfx, len) )\r
+ {\r
+ //# We're on a branch. It might not exist. But\r
+ //# HEAD looks good enough to be a branch.\r
+ sBranchOut = s + len;\r
+ sBranchOut.TrimRight(_T(" \r\n\t"));\r
+\r
+ if ( sBranchOut.IsEmpty() )\r
+ return -1;\r
+ }\r
+ else\r
+ {\r
+ //# Assume this is a detached head.\r
+ sBranchOut = "HEAD";\r
+\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
int CGit::BuildOutputFormat(CString &format,bool IsFull)\r
{\r
CString log;\r
return 0;\r
}\r
\r
-int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash, CTGitPath *path ,int count,int mask)\r
+int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash, CTGitPath *path ,int count,int mask,CString *from,CString *to)\r
{\r
CGitCall_ByteVector gitCall(CString(),&logOut);\r
- return GetLog(&gitCall,hash,path,count,mask);\r
+ return GetLog(&gitCall,hash,path,count,mask,from,to);\r
}\r
\r
//int CGit::GetLog(CGitCall* pgitCall, CString &hash, CTGitPath *path ,int count,int mask)\r
-int CGit::GetLog(CGitCall* pgitCall, CString &hash, CTGitPath *path, int count, int mask)\r
+int CGit::GetLog(CGitCall* pgitCall, CString &hash, CTGitPath *path, int count, int mask,CString *from,CString *to)\r
{\r
\r
CString cmd;\r
if(mask& CGit::LOG_INFO_FOLLOW)\r
param += _T(" --follow ");\r
\r
+ if(from != NULL && to != NULL)\r
+ {\r
+ CString range;\r
+ range.Format(_T(" %s..%s "),*from,*to);\r
+ param += range;\r
+ }\r
param+=hash;\r
\r
cmd.Format(_T("git.exe log %s -z --topo-order %s --parents --pretty=format:\""),\r
CString out;\r
cmd.Format(_T("git.exe rev-parse %s" ),friendname);\r
Run(cmd,&out,CP_UTF8);\r
- int pos=out.ReverseFind(_T('\n'));\r
+// int pos=out.ReverseFind(_T('\n'));\r
+ int pos=out.FindOneOf(_T("\r\n"));\r
if(pos>0)\r
return out.Left(pos);\r
return out;\r
class CGitCall_EnumFiles : public CGitCall\r
{\r
public:\r
- CGitCall_EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
+ CGitCall_EnumFiles(const TCHAR *pszProjectPath, const TCHAR *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
: m_pszProjectPath(pszProjectPath),\r
m_pszSubPath(pszSubPath),\r
m_nFlags(nFlags),\r
\r
typedef std::map<CStringA,char> TStrCharMap;\r
\r
- const char * m_pszProjectPath;\r
- const char * m_pszSubPath;\r
+ const TCHAR * m_pszProjectPath;\r
+ const TCHAR * m_pszSubPath;\r
unsigned int m_nFlags;\r
WGENUMFILECB * m_pEnumCb;\r
void * m_pUserData;\r
fileStatus.nFlags = 0;\r
if (*line == 'D')\r
fileStatus.nFlags |= WGFF_Directory;\r
+ else if (*line != 'F')\r
+ // parse error\r
+ return false;\r
line += 2;\r
\r
// status\r
case 'I': fileStatus.nStatus = WGFS_Ignored; break;\r
case 'U': fileStatus.nStatus = WGFS_Unversioned; break;\r
case 'E': fileStatus.nStatus = WGFS_Empty; break;\r
+ case '?': fileStatus.nStatus = WGFS_Unknown; break;\r
+ default:\r
+ // parse error\r
+ return false;\r
}\r
line += 2;\r
\r
{\r
for (int i=0; i<20; i++)\r
{\r
- sha1[i] = (HexChar(line[0]) << 8) | HexChar(line[1]);\r
+ sha1[i] = (BYTE)((HexChar(line[0]) << 8) | HexChar(line[1]));\r
line += 2;\r
}\r
\r
}\r
\r
// filename\r
- fileStatus.sFileName = line;\r
+ int len = strlen(line);\r
+ if (len && len < 2048)\r
+ {\r
+ WCHAR *buf = (WCHAR*)alloca((len*4+2)*sizeof(WCHAR));\r
+ *buf = 0;\r
+ MultiByteToWideChar(CP_ACP, 0, line, len+1, buf, len*4+1);\r
+ fileStatus.sFileName = buf;\r
\r
- if ( (*m_pEnumCb)(&fileStatus,m_pUserData) )\r
- return false;\r
+ if (*buf && (*m_pEnumCb)(&fileStatus,m_pUserData))\r
+ return false;\r
+ }\r
\r
return true;\r
}\r
};\r
\r
-BOOL CGit::EnumFiles(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
+BOOL CGit::EnumFiles(const TCHAR *pszProjectPath, const TCHAR *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
{\r
if(!pszProjectPath || *pszProjectPath=='\0')\r
return FALSE;\r
SetCurrentDirectoryA(W_szToDir);\r
GetCurrentDirectoryA(sizeof(W_szToDir)-1,W_szToDir);\r
*/\r
- SetCurrentDir(CUnicodeUtils::GetUnicode(pszProjectPath));\r
+ SetCurrentDir(pszProjectPath);\r
\r
CString sMode;\r
if (nFlags)\r
}\r
\r
if (pszSubPath)\r
- cmd.Format(_T("igit.exe %s status %s %s"), CUnicodeUtils::GetUnicode(pszProjectPath), sMode, CUnicodeUtils::GetUnicode(pszSubPath));\r
+ cmd.Format(_T("igit.exe \"%s\" status %s \"%s\""), pszProjectPath, sMode, pszSubPath);\r
else\r
- cmd.Format(_T("igit.exe %s status %s"), CUnicodeUtils::GetUnicode(pszProjectPath), sMode);\r
+ cmd.Format(_T("igit.exe \"%s\" status %s"), pszProjectPath, sMode);\r
\r
W_GitCall.SetCmd(cmd);\r
// NOTE: should igit get added as a part of msysgit then use below line instead of the above one\r
\r
return TRUE;\r
}\r
+\r
+BOOL CGit::CheckCleanWorkTree()\r
+{\r
+ CString out;\r
+ CString cmd;\r
+ cmd=_T("git.exe rev-parse --verify HEAD");\r
+\r
+ if(g_Git.Run(cmd,&out,CP_UTF8))\r
+ return FALSE;\r
+\r
+ cmd=_T("git.exe update-index --ignore-submodules --refresh");\r
+ if(g_Git.Run(cmd,&out,CP_UTF8))\r
+ return FALSE;\r
+\r
+ cmd=_T("git.exe diff-files --quiet --ignore-submodules");\r
+ if(g_Git.Run(cmd,&out,CP_UTF8))\r
+ return FALSE;\r
+\r
+ cmd=_T("git diff-index --cached --quiet HEAD --ignore-submodules");\r
+ if(g_Git.Run(cmd,&out,CP_UTF8))\r
+ return FALSE;\r
+\r
+ return TRUE;\r
+}\r
+int CGit::Revert(CTGitPathList &list,bool keep)\r
+{\r
+ int ret;\r
+ for(int i=0;i<list.GetCount();i++)\r
+ { \r
+ ret = Revert((CTGitPath&)list[i],keep);\r
+ if(ret)\r
+ return ret;\r
+ }\r
+ return 0;\r
+}\r
+int CGit::Revert(CTGitPath &path,bool keep)\r
+{\r
+ CString cmd, out;\r
+ if(path.m_Action & CTGitPath::LOGACTIONS_ADDED)\r
+ { //To init git repository, there are not HEAD, so we can use git reset command\r
+ cmd.Format(_T("git.exe rm --cache -- \"%s\""),path.GetGitPathString());\r
+ if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+ return -1;\r
+ }\r
+ else if(path.m_Action & CTGitPath::LOGACTIONS_REPLACED )\r
+ {\r
+ cmd.Format(_T("git.exe mv \"%s\" \"%s\""),path.GetGitPathString(),path.GetGitOldPathString());\r
+ if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+ return -1;\r
+ \r
+ cmd.Format(_T("git.exe checkout HEAD -f -- \"%s\""),path.GetGitOldPathString());\r
+ if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+ return -1;\r
+ }\r
+ else\r
+ {\r
+ cmd.Format(_T("git.exe checkout HEAD -f -- \"%s\""),path.GetGitPathString());\r
+ if(g_Git.Run(cmd,&out,CP_OEMCP))\r
+ return -1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+int CGit::ListConflictFile(CTGitPathList &list,CTGitPath *path)\r
+{\r
+ BYTE_VECTOR vector;\r
+\r
+ CString cmd;\r
+ if(path)\r
+ cmd.Format(_T("git.exe ls-files -u -t -z -- \"%s\""),path->GetGitPathString());\r
+ else\r
+ cmd=_T("git.exe ls-files -u -t -z");\r
+\r
+ if(g_Git.Run(cmd,&vector))\r
+ {\r
+ return -1;\r
+ }\r
+\r
+ list.ParserFromLsFile(vector);\r
+\r
+ return 0;\r
+}
\ No newline at end of file