OSDN Git Service

*Read Index File Directory. Overlay basic working. include "conflict, modified and...
authorFrank Li <lznuaa@gmail.com>
Tue, 10 Feb 2009 14:33:53 +0000 (22:33 +0800)
committerFrank Li <lznuaa@gmail.com>
Tue, 10 Feb 2009 14:33:53 +0000 (22:33 +0800)
No "Add" "Ignore" ....

Signed-off-by: Frank Li <lznuaa@gmail.com>
16 files changed:
src/Git/Git.cpp
src/Git/Git.vcproj
src/Git/GitFolderStatus.cpp
src/Git/GitFolderStatus.h
src/Git/GitIndex.cpp [new file with mode: 0644]
src/Git/GitStatus.cpp
src/Git/GitStatus.h
src/Git/gitindex.h [new file with mode: 0644]
src/Git/gittype.h
src/TGitCache/TSVNCache.vcproj
src/TortoiseProc/TortoiseProc.cpp
src/TortoiseShell/ContextMenu.cpp
src/TortoiseShell/IconOverlay.cpp
src/TortoiseShell/TortoiseShell.vcproj
src/TortoiseShell/register.reg
src/TortoiseShell/register_recover.reg [new file with mode: 0644]

index 145f47b..1bb0531 100644 (file)
@@ -116,18 +116,19 @@ BOOL g_IsWingitDllload = TRUE;
 \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
@@ -177,6 +178,7 @@ static void InitWinGitDll()
 }\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
@@ -185,6 +187,7 @@ CGit::CGit(void)
                // TODO\r
        }\r
        InitWinGitDll();\r
+#endif\r
 }\r
 \r
 CGit::~CGit(void)\r
index b990dc2..eed787b 100644 (file)
@@ -1,7 +1,7 @@
 <?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
index 356948e..17f1b3f 100644 (file)
 #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
@@ -231,19 +233,25 @@ const FileStatusCacheEntry * GitFolderStatus::BuildCache(const CTGitPath& filepa
        {\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
@@ -397,7 +405,7 @@ const FileStatusCacheEntry * GitFolderStatus::GetCachedItem(const CTGitPath& fil
        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
@@ -411,11 +419,11 @@ BOOL GitFolderStatus::fillstatusmap(const struct wgFile_s *pFile, void *pUserDat
 //     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
@@ -423,18 +431,24 @@ BOOL GitFolderStatus::fillstatusmap(const struct wgFile_s *pFile, void *pUserDat
        //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
index 222a5f3..dba9f4f 100644 (file)
@@ -117,7 +117,8 @@ private:
        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
diff --git a/src/Git/GitIndex.cpp b/src/Git/GitIndex.cpp
new file mode 100644 (file)
index 0000000..b9819eb
--- /dev/null
@@ -0,0 +1,300 @@
+#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
index 6d549a6..9aeca87 100644 (file)
@@ -33,6 +33,9 @@
 //#    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
@@ -214,23 +217,23 @@ git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t de
 \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
@@ -238,7 +241,9 @@ git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t de
                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
@@ -343,26 +348,29 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false
 //     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
@@ -379,7 +387,7 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false
 \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
@@ -399,9 +407,9 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false
 \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
index a2f757e..9e16536 100644 (file)
@@ -261,7 +261,7 @@ private:
 //     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
diff --git a/src/Git/gitindex.h b/src/Git/gitindex.h
new file mode 100644 (file)
index 0000000..9db2ad1
--- /dev/null
@@ -0,0 +1,187 @@
+/* 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
index 395aeb5..a66f4b6 100644 (file)
@@ -88,4 +88,5 @@ public:
 };\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
index da24fc1..8859989 100644 (file)
@@ -1,7 +1,7 @@
 <?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
index deaeb03..569b011 100644 (file)
@@ -43,6 +43,7 @@
 #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
@@ -78,6 +79,8 @@ CTortoiseProcApp::CTortoiseProcApp()
        retSuccess = false;\r
        //CGit git;\r
        //git.GetUserName();\r
+\r
+       \r
 }\r
 \r
 CTortoiseProcApp::~CTortoiseProcApp()\r
@@ -107,6 +110,11 @@ CString sOrigCWD;
 \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
index 6e26662..c341248 100644 (file)
@@ -156,7 +156,7 @@ CShellExt::MenuInfo CShellExt::menuInfo[] =
 //     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
@@ -335,8 +335,14 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                        {\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
@@ -437,8 +443,14 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                                        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
index 91acf49..2b76670 100644 (file)
@@ -242,6 +242,10 @@ STDMETHODIMP CShellExt::IsMemberOf(LPCWSTR pwszPath, DWORD /*dwAttrib*/)
        //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
index 9aee418..7dfb43f 100644 (file)
@@ -84,7 +84,7 @@
                                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
index e44d662..f0e9f4a 100644 (file)
Binary files a/src/TortoiseShell/register.reg and b/src/TortoiseShell/register.reg differ
diff --git a/src/TortoiseShell/register_recover.reg b/src/TortoiseShell/register_recover.reg
new file mode 100644 (file)
index 0000000..ac9382f
Binary files /dev/null and b/src/TortoiseShell/register_recover.reg differ