OSDN Git Service

Git Log Cache Basic working
authorFrank Li <lznuaa@gmail.com>
Tue, 27 Jan 2009 16:13:54 +0000 (00:13 +0800)
committerFrank Li <lznuaa@gmail.com>
Tue, 27 Jan 2009 16:13:54 +0000 (00:13 +0800)
Signed-off-by: Frank Li <lznuaa@gmail.com>
src/Git/Git.cpp
src/Git/GitRev.cpp
src/Git/GitRev.h
src/TortoiseProc/GitLogCache.cpp
src/TortoiseProc/GitLogListBase.cpp
src/TortoiseProc/GitLogListBase.h
src/TortoiseProc/TortoiseProc.vcproj
src/TortoiseProc/gitlogcache.h

index 7fafa44..d776a13 100644 (file)
@@ -89,7 +89,7 @@ void CGit::StringAppend(CString *str,BYTE *p,int code,int length)
        //buf = new WCHAR[len*4 + 1];\r
        buf = str->GetBuffer(len*4+1+str->GetLength())+str->GetLength();\r
        SecureZeroMemory(buf, (len*4 + 1)*sizeof(WCHAR));\r
-       MultiByteToWideChar(code, 0, (LPCSTR)p, -1, buf, len*4);\r
+       MultiByteToWideChar(code, 0, (LPCSTR)p, len, buf, len*4);\r
        str->ReleaseBuffer();\r
        //str->Append(buf);\r
        //delete buf;\r
index 2aaab15..9ae6b61 100644 (file)
@@ -36,7 +36,7 @@ void GitRev::Clear()
        m_Mark=0;\r
 \r
 }\r
-int GitRev::CopyFrom(GitRev &rev)\r
+int GitRev::CopyFrom(GitRev &rev,bool OmitParentAndMark)\r
 {\r
        m_AuthorName    =rev.m_AuthorName       ;\r
        m_AuthorEmail   =rev.m_AuthorEmail      ;\r
@@ -47,10 +47,14 @@ int GitRev::CopyFrom(GitRev &rev)
        m_Subject               =rev.m_Subject          ;\r
        m_Body                  =rev.m_Body                     ;\r
        m_CommitHash    =rev.m_CommitHash       ;\r
-       m_ParentHash    =rev.m_ParentHash       ;\r
        m_Files                 =rev.m_Files                    ;       \r
        m_Action                =rev.m_Action           ;\r
-       m_Mark                  =rev.m_Mark;\r
+\r
+       if(!OmitParentAndMark)\r
+       {\r
+               m_ParentHash    =rev.m_ParentHash       ;\r
+               m_Mark                  =rev.m_Mark;\r
+       }\r
        return 0;\r
 }\r
 int GitRev::ParserFromLog(BYTE_VECTOR &log,int start)\r
index 45f3755..0f630a7 100644 (file)
@@ -37,7 +37,7 @@ public:
                REV_UNSPECIFIED = -4,   ///< unspecified revision\r
        };\r
        \r
-       int CopyFrom(GitRev &rev);\r
+       int CopyFrom(GitRev &rev,bool OmitParentAndMark=false);\r
 \r
        static CString GetHead(){return CString(_T("HEAD"));};\r
        static CString GetWorkingCopy(){return CString(GIT_REV_ZERO);};\r
index 36eff94..0e022ae 100644 (file)
@@ -8,12 +8,38 @@ CLogCache::CLogCache()
 \r
 CLogCache::~CLogCache()\r
 {\r
-       this->m_IndexFile.Close();\r
-       this->m_DataFile.Close();\r
+       //this->m_IndexFile.Close();\r
+       //this->m_DataFile.Close();\r
+}\r
+int CLogCache::AddCacheEntry(GitRev &Rev)\r
+{\r
+       this->m_NewCacheEntry.push_back(Rev);\r
+       return 0;\r
 }\r
 \r
-int CLogCache::FetchCache(CString GitDir)\r
+int CLogCache::GetCacheData(GitRev &Rev)\r
 {\r
+       if(this->m_HashMapIndex.find(Rev.m_CommitHash)==m_HashMapIndex.end())\r
+       {\r
+               for(int i=0;i<this->m_NewCacheEntry.size();i++)\r
+               {\r
+                       if(m_NewCacheEntry[i].m_CommitHash==Rev.m_CommitHash)\r
+                       {\r
+                               Rev.CopyFrom(m_NewCacheEntry[i],true);\r
+                               return 0;\r
+                       }\r
+               }\r
+               return -1;\r
+       }\r
+       else\r
+       {\r
+               return LoadOneItem(Rev,m_HashMapIndex[Rev.m_CommitHash]);\r
+       }\r
+       return 0;\r
+}\r
+int CLogCache::FetchCacheIndex(CString GitDir)\r
+{\r
+\r
        if(this->m_IndexFile.m_hFile == CFile::hFileNull)\r
        {\r
                BOOL b=m_IndexFile.Open(GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
@@ -22,6 +48,12 @@ int CLogCache::FetchCache(CString GitDir)
                if(!b)\r
                        return -1;\r
        }\r
+       //Cache has been fetched.\r
+       //if(m_GitDir == GitDir)\r
+       //      return 0;\r
+\r
+       m_GitDir=GitDir;\r
+       m_IndexFile.SeekToBegin();\r
 \r
        SLogCacheIndexHeader header;\r
        UINT count=m_IndexFile.Read(&header,sizeof(SLogCacheIndexHeader));\r
@@ -37,7 +69,10 @@ int CLogCache::FetchCache(CString GitDir)
 \r
        SLogCacheItem Item;\r
 \r
-       for(int i=0;i<header.m_ItemCount;i++)\r
+       //for(int i=0;i<header.m_ItemCount;i++)\r
+       this->m_HashMapIndex.clear();\r
+\r
+       while(1)\r
        {\r
                count=m_IndexFile.Read(&Item,sizeof(SLogCacheItem));    \r
                if( count != sizeof(SLogCacheItem) )\r
@@ -51,7 +86,7 @@ int CLogCache::FetchCache(CString GitDir)
        return 0;\r
 }\r
 \r
-int CLogCache::SaveOneItem(CString &GitDir,GitRev &Rev,UINT offset)\r
+int CLogCache::SaveOneItem(GitRev &Rev,ULONGLONG offset)\r
 {\r
        \r
        SLogCacheRevItemHeader header;\r
@@ -59,7 +94,7 @@ int CLogCache::SaveOneItem(CString &GitDir,GitRev &Rev,UINT offset)
 \r
        if(this->m_DataFile.m_hFile == CFile::hFileNull)\r
        {\r
-               BOOL b=m_DataFile.Open(GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
+               BOOL b=m_DataFile.Open(m_GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
                        CFile::modeRead|CFile::shareDenyNone|\r
                        CFile::modeNoTruncate|CFile::modeCreate);\r
                if(!b)\r
@@ -93,29 +128,29 @@ int CLogCache::SaveOneItem(CString &GitDir,GitRev &Rev,UINT offset)
 \r
                ar<<header.m_Magic;\r
                ar<<header.m_Version;\r
-\r
+               ar<<Rev.m_Files[i].GetGitPathString();\r
                ar<<Rev.m_Files[i].m_Action;\r
                ar<<Rev.m_Files[i].m_Stage;\r
                ar<<Rev.m_Files[i].m_StatAdd;\r
                ar<<Rev.m_Files[i].m_StatDel;\r
-               ar<<Rev.m_Files[i].GetGitPathString();\r
+               \r
        }\r
        return 0;\r
 }\r
 \r
-int CLogCache::LoadOneItem(CString &GitDir,GitRev &Rev,UINT offset)\r
+int CLogCache::LoadOneItem(GitRev &Rev,ULONGLONG offset)\r
 {\r
        SLogCacheRevItemHeader header;\r
-       m_DataFile.Seek(offset,CFile::begin);\r
 \r
        if(this->m_DataFile.m_hFile == CFile::hFileNull)\r
        {\r
-               BOOL b=m_DataFile.Open(GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
+               BOOL b=m_DataFile.Open(m_GitDir+_T("\\.git\\")+DATA_FILE_NAME,\r
                        CFile::modeRead|CFile::shareDenyNone|\r
                        CFile::modeNoTruncate|CFile::modeCreate);\r
                if(!b)\r
                        return -1;\r
        }\r
+       m_DataFile.Seek(offset,CFile::begin);\r
 \r
        UINT count=m_DataFile.Read(&header,sizeof(SLogCacheRevItemHeader));\r
        if( count != sizeof(SLogCacheRevItemHeader))\r
@@ -151,14 +186,114 @@ int CLogCache::LoadOneItem(CString &GitDir,GitRev &Rev,UINT offset)
 \r
                if( this->CheckHeader(header) )\r
                        return -1;\r
+               ar>>file;\r
+               path.SetFromGit(file);\r
 \r
                ar>>path.m_Action;\r
                ar>>path.m_Stage;\r
                ar>>path.m_StatAdd;\r
                ar>>path.m_StatDel;\r
-               ar>>file;\r
-               path.SetFromGit(file);\r
+               \r
+               \r
                Rev.m_Files.AddPath(path);\r
        }\r
        return 0;\r
+}\r
+int CLogCache::RebuildCacheFile()\r
+{\r
+       m_IndexFile.SetLength(0);\r
+       m_DataFile.SetLength(0);\r
+       {\r
+               SLogCacheIndexHeader header;\r
+               header.m_Magic=LOG_INDEX_MAGIC;\r
+               header.m_Version=LOG_INDEX_VERSION;\r
+               m_IndexFile.SeekToBegin();\r
+               m_IndexFile.Write(&header,sizeof(SLogCacheIndexHeader));\r
+       }\r
+       \r
+       {\r
+               SLogCacheRevFileHeader header;\r
+               header.m_Magic=LOG_DATA_MAGIC;\r
+               header.m_Version=LOG_INDEX_VERSION;\r
+\r
+               m_DataFile.SeekToBegin();\r
+               m_DataFile.Write(&header,sizeof(SLogCacheRevFileHeader));\r
+       }\r
+       return 0;\r
+}\r
+int CLogCache::SaveCache()\r
+{\r
+       bool bIsRebuild=false;\r
+       if(this->m_DataFile.m_hFile != CFile::hFileNull)\r
+               m_DataFile.Close();\r
+       if(this->m_IndexFile.m_hFile!=CFile::hFileNull)\r
+               m_IndexFile.Close();\r
+\r
+       if(this->m_IndexFile.m_hFile == CFile::hFileNull)\r
+       {\r
+               BOOL b=m_IndexFile.Open(m_GitDir+_T("\\.git\\")+INDEX_FILE_NAME,\r
+                       CFile::modeReadWrite|CFile::shareDenyWrite|\r
+                       CFile::modeNoTruncate|CFile::modeCreate);\r
+               if(!b)\r
+                       return -1;\r
+       }\r
+\r
+       if(this->m_DataFile.m_hFile == CFile::hFileNull)\r
+       {\r
+               BOOL b=m_DataFile.Open(m_GitDir+_T("\\.git\\")+DATA_FILE_NAME,\r
+                       CFile::modeReadWrite|CFile::shareDenyWrite|\r
+                       CFile::modeNoTruncate|CFile::modeCreate);\r
+\r
+               \r
+               if(!b)\r
+               {\r
+                       m_IndexFile.Close();\r
+                       return -1;\r
+               }\r
+       }\r
+\r
+       {\r
+               SLogCacheIndexHeader header;\r
+               memset(&header,0,sizeof(SLogCacheIndexHeader));\r
+               UINT count=m_IndexFile.Read(&header,sizeof(SLogCacheIndexHeader));\r
+               if(count != sizeof(SLogCacheIndexHeader) || !this->CheckHeader(header))\r
+               {// new file\r
+                       RebuildCacheFile();\r
+                       bIsRebuild=true;\r
+               }\r
+       }\r
+\r
+       {\r
+\r
+               SLogCacheRevFileHeader header;\r
+       \r
+               UINT count=m_DataFile.Read(&header,sizeof(SLogCacheRevFileHeader));\r
+               if( count != sizeof(SLogCacheRevFileHeader) || !CheckHeader(header))\r
+               {\r
+                       RebuildCacheFile();\r
+                       bIsRebuild=true;\r
+               }\r
+       \r
+       }\r
+\r
+       m_DataFile.SeekToEnd();\r
+       m_IndexFile.SeekToEnd();\r
+       for(int i=0;i<this->m_NewCacheEntry.size();i++)\r
+       {\r
+               if(this->m_HashMapIndex.find(m_NewCacheEntry[i].m_CommitHash) == m_HashMapIndex.end() || bIsRebuild)\r
+               {\r
+                       ULONGLONG offset = m_DataFile.GetPosition();\r
+                       this->SaveOneItem(m_NewCacheEntry[i],offset);\r
+\r
+                       SLogCacheItem item;\r
+                       for(int j=0; j<40;j++)\r
+                               item.m_Hash[j]=(BYTE)m_NewCacheEntry[i].m_CommitHash[j];\r
+                       item.m_Offset=offset;\r
+\r
+                       m_IndexFile.Write(&item,sizeof(SLogCacheItem));\r
+               }\r
+       }\r
+       m_IndexFile.Close();\r
+       m_DataFile.Close();\r
+       return 0;\r
 }
\ No newline at end of file
index 09a4e3e..f02f247 100644 (file)
@@ -126,6 +126,7 @@ BEGIN_MESSAGE_MAP(CGitLogListBase, CHintListCtrl)
        ON_NOTIFY_REFLECT(NM_DBLCLK, OnNMDblclkLoglist)\r
        ON_NOTIFY_REFLECT(LVN_ODFINDITEM,OnLvnOdfinditemLoglist)\r
        ON_WM_CREATE()\r
+       ON_WM_DESTROY()\r
 END_MESSAGE_MAP()\r
 \r
 int CGitLogListBase:: OnCreate(LPCREATESTRUCT lpCreateStruct)\r
@@ -756,12 +757,12 @@ void CGitLogListBase::OnNMCustomdrawLoglist(NMHDR *pNMHDR, LRESULT *pResult)
                                if (m_arShownList.GetCount() > (INT_PTR)pLVCD->nmcd.dwItemSpec)\r
                                {\r
                                        GitRev* data = (GitRev*)m_arShownList.GetAt(pLVCD->nmcd.dwItemSpec);\r
-                                       if(!data->m_IsFull)\r
-                                       {\r
-                                               if(data->SafeFetchFullInfo(&g_Git))\r
-                                                       this->Invalidate();\r
-                                               TRACE(_T("Update ... %d\r\n"),pLVCD->nmcd.dwItemSpec);\r
-                                       }\r
+                                       //if(!data->m_IsFull)\r
+                                       //{\r
+                                               //if(data->SafeFetchFullInfo(&g_Git))\r
+                                               //      this->Invalidate();\r
+                                               //TRACE(_T("Update ... %d\r\n"),pLVCD->nmcd.dwItemSpec);\r
+                                       //}\r
 \r
                                        if(m_HashMap[data->m_CommitHash].size()!=0)\r
                                        {\r
@@ -1346,6 +1347,9 @@ int CGitLogListBase::FillGitShortLog()
        ClearText();\r
 \r
        this->m_logEntries.ClearAll();\r
+\r
+       m_LogCache.FetchCacheIndex(g_Git.m_CurrentDir);\r
+\r
     CTGitPath *path;\r
     if(this->m_Path.IsEmpty())\r
         path=NULL;\r
@@ -1508,13 +1512,29 @@ UINT CGitLogListBase::LogThread()
        int index=0;\r
        unsigned int updated=0;\r
        int percent=0;\r
+       CRect rect;\r
        while(1)\r
        {\r
                for(unsigned int i=0;i<m_logEntries.size();i++)\r
                {\r
-                       if(!m_logEntries.FetchFullInfo(i))\r
+                       if(m_LogCache.GetCacheData(m_logEntries[i]))\r
+                       {\r
+                               if(!m_logEntries.FetchFullInfo(i))\r
+                               {\r
+                                       updated++;\r
+                                       this->GetItemRect(i,&rect,LVIR_BOUNDS);\r
+                                       this->InvalidateRect(rect);\r
+                               }\r
+                               m_LogCache.AddCacheEntry(m_logEntries[i]);\r
+\r
+                       }else\r
                        {\r
                                updated++;\r
+                               InterlockedExchange(&m_logEntries[i].m_IsUpdateing,FALSE);\r
+                               InterlockedExchange(&m_logEntries[i].m_IsFull,TRUE);\r
+\r
+                               this->GetItemRect(i,&rect,LVIR_BOUNDS);\r
+                               this->InvalidateRect(rect);\r
                        }\r
                        \r
                        percent=updated*98/m_logEntries.size() + GITLOG_START+1;\r
@@ -1834,4 +1854,15 @@ void CGitLogListBase::Clear()
        m_logEntries.m_FirstFreeLane=0;\r
        m_logEntries.m_Lns.clear();\r
 \r
+}\r
+\r
+void CGitLogListBase::OnDestroy()\r
+{\r
+       while(m_LogCache.SaveCache())\r
+       {\r
+               if(CMessageBox::Show(NULL,_T("Can Save Log Cache to Disk,click yes for retry, click no for give up"),_T("TortoiseGit"),\r
+                                                       MB_YESNO) == IDNO)\r
+                                                       break;\r
+       }\r
+       CHintListCtrl::OnDestroy();\r
 }
\ No newline at end of file
index fc27629..16b99f0 100644 (file)
@@ -17,7 +17,7 @@
 #include "HintListCtrl.h"\r
 //#include "GitLogList.h"\r
 #include "lanes.h"\r
-\r
+#include "GitLogCache.h"\r
 #include <regex>\r
 // CGitLogList\r
 #if (NTDDI_VERSION < NTDDI_LONGHORN)\r
@@ -71,6 +71,7 @@ public:
        bool                            m_hasWC;\r
        GitRev                          m_wcRev;\r
        volatile LONG           m_bThreadRunning;\r
+       CLogCache                       m_LogCache;\r
 \r
        enum\r
        {\r
@@ -171,6 +172,7 @@ public:
        CWinThread*                     m_LoadingThread;\r
 protected:\r
        DECLARE_MESSAGE_MAP()\r
+       afx_msg void OnDestroy();\r
        afx_msg void OnNMCustomdrawLoglist(NMHDR *pNMHDR, LRESULT *pResult);\r
        afx_msg void OnLvnGetdispinfoLoglist(NMHDR *pNMHDR, LRESULT *pResult);\r
        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);\r
index 7fe42bb..aaa2659 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\explorer.ico"\r
+                               RelativePath="..\Resources\explorer.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\explorer.ico"\r
+                               RelativePath=".\explorer.ico"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\newfolder.ico"\r
+                               RelativePath="..\Resources\newfolder.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\newfolder.ico"\r
+                               RelativePath=".\newfolder.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\open.ico"\r
+                               RelativePath="..\Resources\open.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\open.ico"\r
+                               RelativePath=".\open.ico"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\save.ico"\r
+                               RelativePath="..\Resources\save.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\save.ico"\r
+                               RelativePath=".\save.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\saveas.ico"\r
+                               RelativePath="..\Resources\saveas.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\saveas.ico"\r
+                               RelativePath=".\saveas.ico"\r
                                >\r
                        </File>\r
                        <File\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath=".\up.ico"\r
+                               RelativePath="..\Resources\up.ico"\r
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\Resources\up.ico"\r
+                               RelativePath=".\up.ico"\r
                                >\r
                        </File>\r
                        <File\r
index a0d9ecc..901a880 100644 (file)
@@ -20,7 +20,7 @@ struct SLogCacheIndexHeader
 struct SLogCacheItem\r
 {\r
        BYTE  m_Hash[40];\r
-       DWORD m_Offset;\r
+       ULONGLONG m_Offset;\r
 };\r
 \r
 struct SLogCacheRevFileHeader\r
@@ -47,43 +47,53 @@ protected:
        CFile m_DataFile;\r
        CFile m_LockFile;\r
 \r
+       BOOL CheckHeader(SLogCacheIndexHeader &header)\r
+       {\r
+               if(header.m_Magic != LOG_INDEX_MAGIC)\r
+                       return FALSE;\r
+\r
+               if(header.m_Version != LOG_INDEX_VERSION)\r
+                       return FALSE;\r
+\r
+               return TRUE;\r
+       }\r
+\r
        BOOL CheckHeader(SLogCacheRevFileHeader &header)\r
        {\r
-               if(header.m_Magic == LOG_DATA_MAGIC)\r
-                       return TRUE;\r
-               else\r
+               if(header.m_Magic != LOG_DATA_MAGIC)\r
                        return FALSE;\r
 \r
-               if(header.m_Version == LOG_INDEX_VERSION)\r
-                       return TRUE;\r
-               else\r
+               if(header.m_Version != LOG_INDEX_VERSION)\r
                        return FALSE;\r
+\r
+               return TRUE;\r
        }\r
 \r
        BOOL CheckHeader(SLogCacheRevItemHeader &header)\r
        {\r
-               if(header.m_Magic == LOG_DATA_ITEM_MAGIC)\r
-                       return TRUE;\r
-               else\r
+               if(header.m_Magic != LOG_DATA_ITEM_MAGIC)\r
                        return FALSE;\r
 \r
-               if(header.m_Version == LOG_INDEX_VERSION)\r
-                       return TRUE;\r
-               else\r
+               if(header.m_Version != LOG_INDEX_VERSION)\r
                        return FALSE;\r
-\r
+               \r
+               return TRUE;\r
        }\r
 \r
-       int SaveOneItem(CString &GitDir,GitRev &Rev,UINT offset);\r
-       int LoadOneItem(CString &GitDir,GitRev &Rev,UINT offset);\r
+       int SaveOneItem(GitRev &Rev,ULONGLONG offset);\r
+       int LoadOneItem(GitRev &Rev,ULONGLONG offset);\r
+       CString m_GitDir;\r
+       int RebuildCacheFile();\r
 \r
 public:\r
        CLogCache();\r
        ~CLogCache();\r
-       int FetchCache(CString GitDir);\r
+       int FetchCacheIndex(CString GitDir);\r
        std::vector<GitRev> m_NewCacheEntry;\r
-       std::map<CString, DWORD> m_HashMapIndex;\r
+       std::map<CString, ULONGLONG> m_HashMapIndex;\r
        int GetCacheData(GitRev &Rev);\r
        int AddCacheEntry(GitRev &Rev);\r
+       int SaveCache();\r
+\r
 \r
 };
\ No newline at end of file