No "Add" "Ignore" ....
Signed-off-by: Frank Li <lznuaa@gmail.com>
\r
LPBYTE wgGetRevisionID_safe(const char *pszProjectPath, const char *pszName)\r
{\r
- if(g_IsWingitDllload)\r
- return wgGetRevisionID(pszProjectPath,pszName);\r
- else\r
- return NULL;\r
+ //if(g_IsWingitDllload)\r
+ // return wgGetRevisionID(pszProjectPath,pszName);\r
+ //else\r
+ return NULL;\r
}\r
\r
BOOL wgEnumFiles_safe(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
{\r
- if(g_IsWingitDllload)\r
- return wgEnumFiles(pszProjectPath,pszSubPath,nFlags,pEnumCb,pUserData);\r
- else\r
- return g_Git.EnumFiles(pszProjectPath,pszSubPath,nFlags,pEnumCb,pUserData);\r
+ //if(g_IsWingitDllload)\r
+ // return wgEnumFiles(pszProjectPath,pszSubPath,nFlags,pEnumCb,pUserData);\r
+ //else\r
+ // return g_Git.EnumFiles(pszProjectPath,pszSubPath,nFlags,pEnumCb,pUserData);\r
+ return FALSE;\r
}\r
\r
BOOL CGit::IsVista()\r
}\r
CGit::CGit(void)\r
{\r
+#if 0\r
GetCurrentDirectory(MAX_DIRBUFFER,m_CurrentDir.GetBuffer(MAX_DIRBUFFER));\r
m_CurrentDir.ReleaseBuffer();\r
// make sure git/bin is in PATH before wingit.dll gets (delay) loaded by wgInit()\r
// TODO\r
}\r
InitWinGitDll();\r
+#endif\r
}\r
\r
CGit::~CGit(void)\r
<?xml version="1.0" encoding="gb2312"?>\r
<VisualStudioProject\r
ProjectType="Visual C++"\r
- Version="9,00"\r
+ Version="9.00"\r
Name="Git"\r
ProjectGUID="{7CA5B1EB-8CC9-40A6-96D8-83649C1A870B}"\r
RootNamespace="Git"\r
>\r
</File>\r
<File\r
+ RelativePath=".\GitIndex.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\GitRev.cpp"\r
>\r
</File>\r
>\r
</File>\r
<File\r
+ RelativePath=".\gitindex.h"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\GitRev.h"\r
>\r
</File>\r
#include "..\TGitCache\CacheInterface.h"\r
#include "Git.h"\r
//#include "GitGlobal.h"\r
+#include "gitindex.h"\r
\r
extern ShellCache g_ShellCache;\r
\r
+extern CGitIndexFileMap g_IndexFileMap;\r
\r
// get / auto-alloc a string "copy"\r
\r
{\r
// extract the sub-path (relative to project root)\r
//MessageBox(NULL, filepath.GetDirectory().GetWinPathString(), sProjectRoot, MB_OK);\r
- LPCSTR lpszSubPath = NULL;\r
- CStringA sSubPath;\r
- CString s = filepath.GetDirectory().GetWinPathString();\r
+// LPCSTR lpszSubPath = NULL;\r
+ CString sSubPath;\r
+ CString s = filepath.GetWinPathString();\r
if (s.GetLength() > sProjectRoot.GetLength())\r
{\r
- sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
- lpszSubPath = sSubPath;\r
+ sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/);\r
+// lpszSubPath = sSubPath;\r
}\r
\r
//if (lpszSubPath) MessageBoxA(NULL, lpszSubPath, "BuildCache", MB_OK);\r
//MessageBoxA(NULL, CStringA(sProjectRoot), sSubPath, MB_OK);\r
- err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, WGEFF_NoRecurse|WGEFF_FullPath|WGEFF_DirStatusAll, &fillstatusmap, this);\r
+ //err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, WGEFF_NoRecurse|WGEFF_FullPath|WGEFF_DirStatusAll, &fillstatusmap, this);\r
+ //CTGitPath path;\r
+ //path.SetFromWin(sSubPath);\r
+ git_wc_status_kind status;\r
\r
+ err = g_IndexFileMap.GetFileStatus((CString&)sProjectRoot,sSubPath,&status,true,true,fillstatusmap,this);\r
+ \r
+ //err = g_IndexFileMap.GetFileStatus(sProjectRoot,&path,\r
/*err = svn_client_status4 (&youngest,\r
filepath.GetDirectory().GetSVNApiPath(pool),\r
&rev,\r
return NULL;\r
}\r
\r
-BOOL GitFolderStatus::fillstatusmap(const struct wgFile_s *pFile, void *pUserData)\r
+void GitFolderStatus::fillstatusmap(CString &path,git_wc_status_kind status,void *pUserData)\r
{\r
GitFolderStatus *Stat = (GitFolderStatus*)pUserData;\r
\r
// s.rev = -1;\r
s.owner = Stat->owners.GetString(NULL);\r
\r
- s.status = git_wc_status_none;\r
+ s.status = status;\r
\r
//s.status = GitStatus::GetMoreImportant(s.status, status->text_status);\r
//s.status = GitStatus::GetMoreImportant(s.status, status->prop_status);\r
- s.status = GitStatusFromWingit(pFile->nStatus);\r
+ //s.status = GitStatusFromWingit(pFile->nStatus);\r
\r
// TODO ?: s.blaha = pFile->nStage\r
\r
//s.tree_conflict = (status->tree_conflict != NULL);\r
\r
s.askedcounter = GITFOLDERSTATUS_CACHETIMES;\r
- stdstring str;\r
- if (pFile->sFileName)\r
- {\r
- str = CUnicodeUtils::StdGetUnicode(pFile->sFileName);\r
- std::replace(str.begin(), str.end(), '/', '\\');\r
+ //stdstring str;\r
+ //if (pFile->sFileName)\r
+ //{\r
+ // str = CUnicodeUtils::StdGetUnicode(pFile->sFileName);\r
+ // std::replace(str.begin(), str.end(), '/', '\\');\r
//MessageBox(NULL, str.c_str(), _T(""), MB_OK);\r
+ //}\r
+ //else\r
+ // str = _T(" ");\r
+ if( path.Right(1) == _T("\\"))\r
+ {\r
+ path=path.Left(path.GetLength()-1);\r
}\r
- else\r
- str = _T(" ");\r
+ stdstring str;\r
+ str=path;\r
cache[str] = s;\r
\r
- return FALSE;\r
+ return;\r
}\r
\r
#if 0\r
DWORD GetTimeoutValue();\r
//static git_error_t* fillstatusmap (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);\r
//static git_error_t* findfolderstatus (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);\r
- static BOOL fillstatusmap(const struct wgFile_s *pFile, void *pUserData);\r
+ static void fillstatusmap(CString &path,git_wc_status_kind status,void *pdata);\r
+\r
static CTGitPath folderpath;\r
void ClearCache();\r
\r
--- /dev/null
+#include "StdAfx.h"\r
+#include "Git.h"\r
+#include "atlconv.h"\r
+#include "GitRev.h"\r
+#include "registry.h"\r
+#include "GitConfig.h"\r
+#include <map>\r
+#include "UnicodeUtils.h"\r
+#include "TGitPath.h"\r
+#include "gitindex.h"\r
+#include <sys/types.h> \r
+#include <sys/stat.h>\r
+\r
+#define FILL_DATA() \\r
+ m_FileName.Empty();\\r
+ g_Git.StringAppend(&m_FileName,(BYTE*)entry->name,CP_OEMCP,Big2lit(entry->flags)&CE_NAMEMASK);\\r
+ m_FileName.Replace(_T('/'),_T('\\'));\\r
+ this->m_Flags=Big2lit(entry->flags);\\r
+ this->m_ModifyTime=Big2lit(entry->mtime.sec);\r
+ \r
+int CGitIndex::FillData(ondisk_cache_entry * entry)\r
+{\r
+ FILL_DATA();\r
+ return 0;\r
+}\r
+\r
+int CGitIndex::FillData(ondisk_cache_entry_extended * entry)\r
+{\r
+ FILL_DATA();\r
+ this->m_Flags |= ((int)Big2lit(entry->flags2))<<16;\r
+ return 0;\r
+}\r
+\r
+CGitIndexList::CGitIndexList()\r
+{\r
+ this->m_LastModifyTime=0;\r
+}\r
+\r
+int CGitIndexList::ReadIndex(CString IndexFile)\r
+{\r
+ HANDLE hfile=0;\r
+ int ret=0;\r
+ BYTE *buffer=NULL,*p;\r
+ CGitIndex GitIndex;\r
+\r
+ try\r
+ {\r
+ do\r
+ {\r
+ this->clear();\r
+ this->m_Map.clear();\r
+\r
+ hfile = CreateFile(IndexFile,\r
+ GENERIC_READ,\r
+ FILE_SHARE_READ,\r
+ NULL,\r
+ OPEN_EXISTING,\r
+ FILE_ATTRIBUTE_NORMAL,\r
+ NULL);\r
+\r
+\r
+ if(hfile == INVALID_HANDLE_VALUE)\r
+ {\r
+ ret = -1 ;\r
+ break;\r
+ }\r
+\r
+ cache_header *header;\r
+ DWORD size=0,filesize=0;\r
+ \r
+ filesize=GetFileSize(hfile,NULL);\r
+\r
+ if(filesize == INVALID_FILE_SIZE )\r
+ {\r
+ ret =-1;\r
+ break;\r
+ }\r
+\r
+ buffer = new BYTE[filesize];\r
+ p=buffer;\r
+ if(buffer == NULL)\r
+ {\r
+ ret = -1;\r
+ break;\r
+ }\r
+ if(! ReadFile( hfile, buffer,filesize,&size,NULL) )\r
+ {\r
+ ret = GetLastError();\r
+ break;\r
+ }\r
+\r
+ if (size != filesize)\r
+ {\r
+ ret = -1;\r
+ break;\r
+ }\r
+ header = (cache_header *) buffer;\r
+ if( Big2lit(header->hdr_signature) != CACHE_SIGNATURE )\r
+ {\r
+ ret = -1;\r
+ break;\r
+ }\r
+ p+= sizeof(cache_header);\r
+\r
+ int entries = Big2lit(header->hdr_entries);\r
+ for(int i=0;i<entries;i++)\r
+ {\r
+ ondisk_cache_entry *entry;\r
+ ondisk_cache_entry_extended *entryex;\r
+ entry=(ondisk_cache_entry*)p;\r
+ entryex=(ondisk_cache_entry_extended*)p;\r
+ int flags=Big2lit(entry->flags);\r
+ if( flags & CE_EXTENDED)\r
+ {\r
+ GitIndex.FillData(entryex);\r
+ p+=ondisk_ce_size(entryex);\r
+\r
+ }else\r
+ {\r
+ GitIndex.FillData(entry);\r
+ p+=ondisk_ce_size(entry);\r
+ }\r
+ \r
+ if(p>buffer+filesize)\r
+ {\r
+ ret = -1;\r
+ break;\r
+ }\r
+ this->push_back(GitIndex);\r
+ this->m_Map[GitIndex.m_FileName]=this->size()-1;\r
+\r
+ }\r
+ }while(0);\r
+ }catch(...)\r
+ {\r
+ ret= -1;\r
+ }\r
+\r
+ if(hfile != INVALID_HANDLE_VALUE)\r
+ CloseHandle(hfile);\r
+ if(buffer)\r
+ delete buffer;\r
+ return ret;\r
+}\r
+\r
+int CGitIndexList::GetFileStatus(CString &gitdir,CString &path,git_wc_status_kind *status,struct __stat64 &buf,FIll_STATUS_CALLBACK callback,void *pData)\r
+{\r
+\r
+ if(status)\r
+ {\r
+ if(m_Map.find(path) == m_Map.end() )\r
+ {\r
+ *status = git_wc_status_unversioned;\r
+ }else\r
+ {\r
+ int index = m_Map[path];\r
+ if(index <0)\r
+ return -1;\r
+ if(index >= size() )\r
+ return -1;\r
+ \r
+ if( buf.st_mtime == at(index).m_ModifyTime )\r
+ {\r
+ *status = git_wc_status_normal;\r
+ }else\r
+ {\r
+ *status = git_wc_status_modified;\r
+ }\r
+\r
+ if(at(index).m_Flags & CE_STAGEMASK )\r
+ *status = git_wc_status_conflicted;\r
+ else if(at(index).m_Flags & CE_INTENT_TO_ADD)\r
+ *status = git_wc_status_added;\r
+\r
+ }\r
+ if(callback)\r
+ callback(gitdir+_T("\\")+path,*status,pData);\r
+ }\r
+ return 0;\r
+}\r
+\r
+int CGitIndexList::GetStatus(CString &gitdir,CString &path, git_wc_status_kind *status,\r
+ BOOL IsFull, BOOL IsRecursive,\r
+ FIll_STATUS_CALLBACK callback,void *pData)\r
+{\r
+ int result;\r
+ struct __stat64 buf;\r
+ git_wc_status_kind dirstatus = git_wc_status_none;\r
+ if(status)\r
+ {\r
+ if(path.IsEmpty())\r
+ result = _tstat64( gitdir, &buf );\r
+ else\r
+ result = _tstat64( gitdir+_T("\\")+path, &buf );\r
+\r
+ if(result)\r
+ return -1;\r
+\r
+ if(buf.st_mode & _S_IFDIR)\r
+ {\r
+ if(!path.IsEmpty())\r
+ {\r
+ if( path.Right(1) != _T("\\"))\r
+ path+=_T("\\");\r
+ }\r
+ int len =path.GetLength();\r
+\r
+ for(int i=0;i<size();i++)\r
+ {\r
+ if( at(i).m_FileName.GetLength() > len )\r
+ {\r
+ if(at(i).m_FileName.Left(len) == path)\r
+ {\r
+ if( !IsFull )\r
+ {\r
+ *status = git_wc_status_normal; \r
+ if(callback)\r
+ callback(gitdir+_T("\\")+path,*status,pData);\r
+ return 0;\r
+\r
+ }else\r
+ { \r
+ result = _tstat64( gitdir+_T("\\")+at(i).m_FileName, &buf );\r
+ if(result)\r
+ continue;\r
+ \r
+ *status = git_wc_status_none;\r
+ GetFileStatus(gitdir,at(i).m_FileName,status,buf,callback,pData);\r
+ if( *status != git_wc_status_none )\r
+ {\r
+ if( dirstatus == git_wc_status_none)\r
+ {\r
+ dirstatus = git_wc_status_normal;\r
+ }\r
+ if( *status != git_wc_status_normal )\r
+ {\r
+ dirstatus = git_wc_status_modified;\r
+ }\r
+ }\r
+ \r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if( dirstatus != git_wc_status_none )\r
+ {\r
+ *status = dirstatus;\r
+ }\r
+ else\r
+ {\r
+ *status = git_wc_status_unversioned;\r
+ }\r
+ if(callback)\r
+ callback(gitdir+_T("\\")+path,*status,pData);\r
+ \r
+ return 0;\r
+\r
+ }else\r
+ {\r
+ GetFileStatus(gitdir,path,status,buf,callback,pData);\r
+ }\r
+ } \r
+ return 0;\r
+}\r
+\r
+int CGitIndexFileMap::GetFileStatus(CString &gitdir, CString &path, git_wc_status_kind *status,BOOL IsFull, BOOL IsRecursive,\r
+ FIll_STATUS_CALLBACK callback,void *pData)\r
+{\r
+ struct __stat64 buf;\r
+ int result;\r
+ try\r
+ {\r
+ CString IndexFile;\r
+ IndexFile=gitdir+_T("\\.git\\index");\r
+ /* Get data associated with "crt_stat.c": */\r
+ result = _tstat64( IndexFile, &buf );\r
+\r
+// WIN32_FILE_ATTRIBUTE_DATA FileInfo;\r
+// GetFileAttributesEx(_T("D:\\tortoisegit\\src\\gpl.txt"),GetFileExInfoStandard,&FileInfo);\r
+// result = _tstat64( _T("D:\\tortoisegit\\src\\gpl.txt"), &buf );\r
+\r
+ if(result)\r
+ return result;\r
+\r
+ if((*this)[IndexFile].m_LastModifyTime != buf.st_mtime )\r
+ {\r
+ if((*this)[IndexFile].ReadIndex(IndexFile))\r
+ return -1;\r
+ }\r
+ (*this)[IndexFile].m_LastModifyTime = buf.st_mtime;\r
+\r
+ (*this)[IndexFile].GetStatus(gitdir,path,status,IsFull,IsRecursive,callback,pData);\r
+ \r
+ }catch(...)\r
+ {\r
+ return -1;\r
+ }\r
+ return 0;\r
+}
\ No newline at end of file
//# include "PathUtils.h"\r
#endif\r
#include "git.h"\r
+#include "gitindex.h"\r
+\r
+CGitIndexFileMap g_IndexFileMap;\r
\r
GitStatus::GitStatus(bool * pbCanceled)\r
: status(NULL)\r
\r
const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source\r
\r
- LPCSTR lpszSubPath = NULL;\r
- CStringA sSubPath;\r
+ //LPCSTR lpszSubPath = NULL;\r
+ CString sSubPath;\r
CString s = path.GetWinPathString();\r
if (s.GetLength() > sProjectRoot.GetLength())\r
{\r
sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
- lpszSubPath = sSubPath;\r
+ // lpszSubPath = sSubPath;\r
}\r
\r
#if 1\r
// when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here\r
- UINT nFlags = WGEFF_SingleFile;\r
- if (!bIsRecursive)\r
- nFlags |= WGEFF_NoRecurse;\r
- if (!lpszSubPath)\r
+ //UINT nFlags = WGEFF_SingleFile;\r
+ //if (!bIsRecursive)\r
+ // nFlags |= WGEFF_NoRecurse;\r
+ //if (!lpszSubPath)\r
// report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?)\r
- nFlags |= WGEFF_EmptyAsNormal;\r
+ // nFlags |= WGEFF_EmptyAsNormal;\r
#else\r
// enumerate all files, recursively if requested\r
UINT nFlags = 0;\r
nFlags |= WGEFF_NoRecurse;\r
#endif\r
\r
- err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, nFlags, &getallstatus, &statuskind);\r
+ //err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, nFlags, &getallstatus, &statuskind);\r
+ \r
+ err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&statuskind);\r
\r
/*err = git_client_status4 (&youngest,\r
path.GetSVNApiPath(pool),\r
// hashbaton.exthash = exthash;\r
hashbaton.pThis = this;\r
\r
- LPCSTR lpszSubPath = NULL;\r
- CStringA sSubPath;\r
+ //LPCSTR lpszSubPath = NULL;\r
+ CString sSubPath;\r
CString s = path.GetWinPathString();\r
if (s.GetLength() > sProjectRoot.GetLength())\r
{\r
- sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
- lpszSubPath = sSubPath;\r
+ sSubPath = CString(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
+ // lpszSubPath = sSubPath;\r
}\r
\r
+ \r
// when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here\r
- UINT nFlags = WGEFF_SingleFile | WGEFF_NoRecurse;\r
- if (!lpszSubPath)\r
- // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?)\r
- nFlags |= WGEFF_EmptyAsNormal;\r
+ //UINT nFlags = WGEFF_SingleFile | WGEFF_NoRecurse;\r
+ //if (!lpszSubPath)\r
+ // // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?)\r
+ // nFlags |= WGEFF_EmptyAsNormal;\r
\r
m_status.prop_status = m_status.text_status = git_wc_status_none;\r
\r
// NOTE: currently wgEnumFiles_safe_safe_safe will not enumerate file if it isn't versioned (so status will be git_wc_status_none)\r
- m_err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, nFlags, &getstatus, &m_status);\r
+ //m_err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, nFlags, &getstatus, &m_status);\r
\r
+ m_err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&m_status.text_status);\r
+ \r
/*m_err = git_client_status4 (&youngest,\r
path.GetGitApiPath(m_pool),\r
&rev,\r
\r
\r
// Error present if function is not under version control\r
- if ((m_err != NULL) /*|| (apr_hash_count(statushash) == 0)*/)\r
+ if (m_err) /*|| (apr_hash_count(statushash) == 0)*/\r
{\r
status = NULL;\r
// return -2; \r
\r
if (update)\r
{\r
- const BYTE *sha1 = wgGetRevisionID_safe(CStringA(sProjectRoot), NULL);\r
- if (sha1)\r
- youngest = ConvertHashToRevnum(sha1);\r
+ //const BYTE *sha1 = wgGetRevisionID_safe(CStringA(sProjectRoot), NULL);\r
+ //if (sha1)\r
+ // youngest = ConvertHashToRevnum(sha1);\r
}\r
\r
return youngest;\r
// git_client_ctx_t * ctx;\r
git_wc_status_kind m_allstatus; ///< used by GetAllStatus and GetAllStatusRecursive\r
// git_error_t * m_err; ///< Subversion error baton\r
- BOOL m_err;\r
+ git_error_t m_err;\r
\r
git_wc_status2_t m_status; // used for GetStatus\r
\r
--- /dev/null
+/* Copy from Git cache.h*/\r
+#define FLEX_ARRAY 4\r
+\r
+#pragma pack(push)\r
+#pragma pack(1)\r
+//#pragma pack(show) \r
+#define CACHE_SIGNATURE 0x44495243 /* "DIRC" */\r
+struct cache_header {\r
+ unsigned int hdr_signature;\r
+ unsigned int hdr_version;\r
+ unsigned int hdr_entries;\r
+};\r
+\r
+/*\r
+ * The "cache_time" is just the low 32 bits of the\r
+ * time. It doesn't matter if it overflows - we only\r
+ * check it for equality in the 32 bits we save.\r
+ */\r
+struct cache_time {\r
+ UINT32 sec;\r
+ UINT32 nsec;\r
+};\r
+\r
+/*\r
+ * dev/ino/uid/gid/size are also just tracked to the low 32 bits\r
+ * Again - this is just a (very strong in practice) heuristic that\r
+ * the inode hasn't changed.\r
+ *\r
+ * We save the fields in big-endian order to allow using the\r
+ * index file over NFS transparently.\r
+ */\r
+struct ondisk_cache_entry {\r
+ struct cache_time ctime;\r
+ struct cache_time mtime;\r
+ UINT32 dev;\r
+ UINT32 ino;\r
+ UINT32 mode;\r
+ UINT32 uid;\r
+ UINT32 gid;\r
+ UINT32 size;\r
+ BYTE sha1[20];\r
+ UINT16 flags;\r
+ char name[FLEX_ARRAY]; /* more */\r
+};\r
+\r
+/*\r
+ * This struct is used when CE_EXTENDED bit is 1\r
+ * The struct must match ondisk_cache_entry exactly from\r
+ * ctime till flags\r
+ */\r
+struct ondisk_cache_entry_extended {\r
+ struct cache_time ctime;\r
+ struct cache_time mtime;\r
+ UINT32 dev;\r
+ UINT32 ino;\r
+ UINT32 mode;\r
+ UINT32 uid;\r
+ UINT32 gid;\r
+ UINT32 size;\r
+ BYTE sha1[20];\r
+ UINT16 flags;\r
+ UINT16 flags2;\r
+ char name[FLEX_ARRAY]; /* more */\r
+};\r
+\r
+#pragma pack(pop)\r
+\r
+#define CE_NAMEMASK (0x0fff)\r
+#define CE_STAGEMASK (0x3000)\r
+#define CE_EXTENDED (0x4000)\r
+#define CE_VALID (0x8000)\r
+#define CE_STAGESHIFT 12\r
+/*\r
+ * Range 0xFFFF0000 in ce_flags is divided into\r
+ * two parts: in-memory flags and on-disk ones.\r
+ * Flags in CE_EXTENDED_FLAGS will get saved on-disk\r
+ * if you want to save a new flag, add it in\r
+ * CE_EXTENDED_FLAGS\r
+ *\r
+ * In-memory only flags\r
+ */\r
+#define CE_UPDATE (0x10000)\r
+#define CE_REMOVE (0x20000)\r
+#define CE_UPTODATE (0x40000)\r
+#define CE_ADDED (0x80000)\r
+\r
+#define CE_HASHED (0x100000)\r
+#define CE_UNHASHED (0x200000)\r
+\r
+/*\r
+ * Extended on-disk flags\r
+ */\r
+#define CE_INTENT_TO_ADD 0x20000000\r
+/* CE_EXTENDED2 is for future extension */\r
+#define CE_EXTENDED2 0x80000000\r
+\r
+#define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD)\r
+\r
+/*\r
+ * Safeguard to avoid saving wrong flags:\r
+ * - CE_EXTENDED2 won't get saved until its semantic is known\r
+ * - Bits in 0x0000FFFF have been saved in ce_flags already\r
+ * - Bits in 0x003F0000 are currently in-memory flags\r
+ */\r
+#if CE_EXTENDED_FLAGS & 0x803FFFFF\r
+#error "CE_EXTENDED_FLAGS out of range"\r
+#endif\r
+\r
+/*\r
+ * Copy the sha1 and stat state of a cache entry from one to\r
+ * another. But we never change the name, or the hash state!\r
+ */\r
+#define CE_STATE_MASK (CE_HASHED | CE_UNHASHED)\r
+\r
+template<class T> \r
+T Big2lit(T data)\r
+{\r
+ T ret;\r
+ BYTE *p1=(BYTE*)&data;\r
+ BYTE *p2=(BYTE*)&ret;\r
+ for(int i=0;i<sizeof(T);i++)\r
+ {\r
+ p2[sizeof(T)-i-1] = p1[i];\r
+ }\r
+ return ret;\r
+}\r
+\r
+template<class T>\r
+static inline size_t ce_namelen(T *ce)\r
+{\r
+ size_t len = Big2lit(ce->flags) & CE_NAMEMASK;\r
+ if (len < CE_NAMEMASK)\r
+ return len;\r
+ return strlen(ce->name + CE_NAMEMASK) + CE_NAMEMASK;\r
+}\r
+\r
+#define flexible_size(STRUCT,len) ((offsetof(STRUCT,name) + (len) + 8) & ~7)\r
+\r
+//#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)\r
+//#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)\r
+\r
+//#define ondisk_ce_size(ce) (((ce)->flags & CE_EXTENDED) ? \\r
+// ondisk_cache_entry_extended_size(ce_namelen(ce)) : \\r
+// ondisk_cache_entry_size(ce_namelen(ce)))\r
+\r
+template<class T>\r
+static inline size_t ondisk_ce_size(T *ce)\r
+{\r
+ return flexible_size(T,ce_namelen(ce));\r
+}\r
+\r
+class CGitIndex\r
+{\r
+public:\r
+ CString m_FileName;\r
+ __time64_t m_ModifyTime;\r
+ int m_Flags;\r
+ //int m_Status;\r
+ \r
+ int FillData(ondisk_cache_entry* entry);\r
+ int FillData(ondisk_cache_entry_extended* entry);\r
+};\r
+\r
+\r
+typedef void (*FIll_STATUS_CALLBACK)(CString &path,git_wc_status_kind status,void *pdata);\r
+\r
+class CGitIndexList:public std::vector<CGitIndex>\r
+{\r
+protected:\r
+ \r
+public:\r
+ std::map<CString,int> m_Map;\r
+ __time64_t m_LastModifyTime;\r
+ CGitIndexList();\r
+ int ReadIndex(CString file);\r
+ int GetStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL); \r
+protected:\r
+ int GetFileStatus(CString &gitdir,CString &path, git_wc_status_kind * status,struct __stat64 &buf,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL);\r
+\r
+};\r
+\r
+class CGitIndexFileMap:public std::map<CString,CGitIndexList> \r
+{\r
+public:\r
+ int GetFileStatus(CString &gitdir,CString &path,git_wc_status_kind * status,BOOL IsFull=false, BOOL IsRecursive=false,FIll_STATUS_CALLBACK callback=NULL,void *pData=NULL);\r
+};\r
+\r
};\r
typedef std::vector<CString> STRING_VECTOR;\r
typedef std::map<CString, STRING_VECTOR> MAP_HASH_NAME;\r
-typedef CGitByteArray BYTE_VECTOR;
\ No newline at end of file
+typedef CGitByteArray BYTE_VECTOR;\r
+\r
<?xml version="1.0" encoding="Windows-1252"?>\r
<VisualStudioProject\r
ProjectType="Visual C++"\r
- Version="9,00"\r
+ Version="9.00"\r
Name="TGitCache"\r
ProjectGUID="{A00D2EDC-B4F5-4B41-94BA-13961DE5D296}"\r
RootNamespace="TSVNCache"\r
>\r
</File>\r
<File\r
+ RelativePath="..\Git\GitIndex.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath="..\Git\GitRev.cpp"\r
>\r
</File>\r
#include "CommonResource.h"\r
#include "..\version.h"\r
#include "..\Settings\Settings.h"\r
+#include "gitindex.h"\r
\r
#define STRUCT_IOVEC_DEFINED\r
//#include "sasl.h"\r
retSuccess = false;\r
//CGit git;\r
//git.GetUserName();\r
+\r
+ \r
}\r
\r
CTortoiseProcApp::~CTortoiseProcApp()\r
\r
BOOL CTortoiseProcApp::CheckMsysGitDir()\r
{\r
+ CGitIndexFileMap map;\r
+ //int status;\r
+ //CTGitPath path;\r
+ //path.SetFromGit(_T("src/gpl.txt"));\r
+ //map.GetFileStatus(_T("D:\\TortoiseGit"),&path, &status);\r
return CGit::CheckMsysGitDir(); \r
}\r
CCrashReport crasher("tortoisegit-bug@googlegroups.com", "Crash Report for TortoiseGit " APP_X64_STRING " : " STRPRODUCTVER, TRUE);// crash\r
// ITEMIS_FOLDER, ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
\r
{ ShellMenuBlame, MENUBLAME, IDI_BLAME, IDS_MENUBLAME, IDS_MENUDESCBLAME,\r
- ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_FOLDER|ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
+ ITEMIS_NORMAL|ITEMIS_ONLYONE, ITEMIS_FOLDER|ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
\r
{ ShellMenuIgnoreSub, MENUIGNORE, IDI_IGNORE, IDS_MENUIGNORE, IDS_MENUDESCIGNORE,\r
ITEMIS_INVERSIONEDFOLDER, ITEMIS_IGNORED|ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
{\r
ATLTRACE2(_T("Exception in GitStatus::GetStatus()\n"));\r
}\r
- //if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
- if (askedpath.HasAdminDir())\r
+\r
+ if ( askedpath.IsDirectory() )\r
+ {\r
+ if (askedpath.HasAdminDir())\r
+ itemStates |= ITEMIS_INSVN;\r
+ }\r
+ if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
+ //if (askedpath.HasAdminDir())\r
itemStates |= ITEMIS_INSVN;\r
if (status == git_wc_status_ignored)\r
itemStates |= ITEMIS_IGNORED;\r
ATLTRACE2(_T("Exception in GitStatus::GetStatus()\n"));\r
}\r
}\r
- //if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
- if (strpath.HasAdminDir())\r
+\r
+ if ( strpath.IsDirectory() )\r
+ {\r
+ if (strpath.HasAdminDir())\r
+ itemStates |= ITEMIS_INSVN;\r
+ }\r
+ if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
+ //if (strpath.HasAdminDir())\r
itemStates |= ITEMIS_INSVN;\r
if (status == git_wc_status_ignored)\r
{\r
//as it seems that if one handler returns S_OK then that handler is used, no matter\r
//if other handlers would return S_OK too (they're never called on my machine!)\r
//So we return S_OK for ONLY ONE handler!\r
+\r
+ if(g_ShellCache.HasSVNAdminDir(pPath, true) && status == git_wc_status_none)\r
+ status = git_wc_status_unversioned;\r
+\r
switch (status)\r
{\r
// note: we can show other overlays if due to lack of enough free overlay\r
IgnoreImportLibrary="true"\r
UseLibraryDependencyInputs="false"\r
AdditionalOptions="/MACHINE:I386"\r
- AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib wingit.lib"\r
+ AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib"\r
OutputFile="$(OutDir)/TortoiseGit.dll"\r
LinkIncremental="0"\r
SuppressStartupBanner="true"\r
Name="VCLinkerTool"\r
IgnoreImportLibrary="true"\r
AdditionalOptions="/MACHINE:I386"\r
- AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib wingit.lib"\r
+ AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib"\r
OutputFile="$(OutDir)/TortoiseGit.dll"\r
LinkIncremental="1"\r
SuppressStartupBanner="true"\r
>\r
</File>\r
<File\r
+ RelativePath="..\Git\GitIndex.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath="..\Git\GitRev.cpp"\r
>\r
</File>\r