OSDN Git Service

Experiment with retrieving full log in one git.exe call
authorJohan t Hart <johanthart@gmail.com>
Mon, 2 Feb 2009 23:01:04 +0000 (00:01 +0100)
committerFrank Li <lznuaa@gmail.com>
Sun, 8 Feb 2009 07:04:50 +0000 (15:04 +0800)
src/Git/Git.cpp
src/Git/Git.h
src/TortoiseProc/GitLogListBase.cpp
src/TortoiseProc/GitLogListBase.h
src/TortoiseProc/LogDlgHelper.h

index df2ce46..6dd0ad8 100644 (file)
@@ -416,6 +416,13 @@ int CGit::BuildOutputFormat(CString &format,bool IsFull)
 \r
 int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash,  CTGitPath *path ,int count,int mask)\r
 {\r
+       CGitCall_ByteVector gitCall(CString(),&logOut);\r
+       return GetLog(&gitCall,hash,path,count,mask);\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
+{\r
 \r
        CString cmd;\r
        CString log;\r
@@ -471,7 +478,10 @@ int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash,  CTGitPath *path ,int count
        cmd += log;\r
        cmd += CString(_T("\"  "))+hash+file;\r
 \r
-       return Run(cmd,&logOut);\r
+       pgitCall->SetCmd(cmd);\r
+\r
+       return Run(pgitCall);\r
+//     return Run(cmd,&logOut);\r
 }\r
 \r
 #if 0\r
index b527790..4daf9f6 100644 (file)
@@ -7,10 +7,13 @@
 class CGitCall\r
 {\r
 public:\r
+       CGitCall(){}\r
        CGitCall(CString cmd):m_Cmd(cmd){}\r
 \r
        CString                 GetCmd()const{return m_Cmd;}\r
+       void                    SetCmd(CString cmd){m_Cmd=cmd;}\r
 \r
+       //This function is called when command output data is available.\r
        //When this function returns 'true' the git command should be aborted.\r
        //This behavior is not implemented yet.\r
        virtual bool    OnOutputData(const BYTE* data, size_t size)=0;\r
@@ -20,6 +23,8 @@ private:
 \r
 };\r
 \r
+class CTGitPath;\r
+\r
 class CGit\r
 {\r
 private:\r
@@ -77,6 +82,8 @@ public:
        int GetMapHashToFriendName(MAP_HASH_NAME &map);\r
        \r
        //hash is empty means all. -1 means all\r
+\r
+       int GetLog(CGitCall* pgitCall, CString &hash, CTGitPath *path = NULL,int count=-1,int InfoMask=LOG_INFO_STAT|LOG_INFO_FILESTATE|LOG_INFO_BOUNDARY|LOG_INFO_DETECT_COPYRENAME);\r
        int GetLog(BYTE_VECTOR& logOut,CString &hash, CTGitPath *path = NULL,int count=-1,int InfoMask=LOG_INFO_STAT|LOG_INFO_FILESTATE|LOG_INFO_BOUNDARY|LOG_INFO_DETECT_COPYRENAME);\r
 \r
        git_revnum_t GetHash(CString &friendname);\r
index 02dc958..4eaa143 100644 (file)
@@ -1446,6 +1446,94 @@ void CGitLogListBase::GetTimeRange(CTime &oldest, CTime &latest)
        }\r
 }\r
 \r
+//Helper class for FetchFullLogInfo()\r
+class CGitCall_FetchFullLogInfo : public CGitCall\r
+{\r
+public:\r
+       CGitCall_FetchFullLogInfo(CGitLogListBase* ploglist):m_ploglist(ploglist),m_CollectedCount(0){}\r
+       virtual bool OnOutputData(const BYTE* data, size_t size)\r
+       {\r
+               //Add received data to byte collector\r
+               m_ByteCollector.append(data,size);\r
+\r
+               //Find loginfo endmarker\r
+               static const BYTE dataToFind[]={0,0};\r
+               int found=m_ByteCollector.findData(dataToFind,2);\r
+               if(found<0)\r
+                       return m_ploglist->m_bExitThread;//Not found\r
+               found+=2;//Position after loginfo end-marker\r
+\r
+               //Prepare data for OnLogInfo and call it\r
+               BYTE_VECTOR logInfo;\r
+               logInfo.append(&*m_ByteCollector.begin(),found);\r
+               OnLogInfo(logInfo);\r
+\r
+               //Remove loginfo from bytecollector\r
+               m_ByteCollector.erase(m_ByteCollector.begin(),m_ByteCollector.begin()+found);\r
+\r
+               return m_ploglist->m_bExitThread;\r
+       }\r
+\r
+       void OnLogInfo(BYTE_VECTOR& logInfo)\r
+       {\r
+               GitRev fullRev;\r
+               fullRev.ParserFromLog(logInfo);\r
+               MAP_HASH_REV::iterator itRev=m_ploglist->m_logEntries.m_HashMap.find(fullRev.m_CommitHash);\r
+               if(itRev==m_ploglist->m_logEntries.m_HashMap.end())\r
+               {\r
+                       //Should not occur, only when Git-tree updated in the mean time. (Race condition)\r
+                       return;//Ignore\r
+               }\r
+               //Set updating\r
+               int rev=itRev->second;\r
+               GitRev* revInVector=&m_ploglist->m_logEntries[rev];\r
+\r
+\r
+//             fullRev.m_IsUpdateing=TRUE;\r
+//             fullRev.m_IsFull=TRUE;\r
+\r
+\r
+               if(InterlockedExchange(&revInVector->m_IsUpdateing,TRUE))\r
+                       return;//Cannot update this row now. Ignore.\r
+               TCHAR oldmark=revInVector->m_Mark;\r
+               GIT_REV_LIST oldlist=revInVector->m_ParentHash;\r
+//             CString oldhash=m_CommitHash;\r
+\r
+               //Parse new rev info\r
+               revInVector->ParserFromLog(logInfo);\r
+\r
+               if(oldmark!=0)\r
+                       revInVector->m_Mark=oldmark;  //parser full log will cause old mark overwrited. \r
+                                                              //So we need keep old bound mark.\r
+               revInVector->m_ParentHash=oldlist;\r
+\r
+               //Reset updating\r
+               InterlockedExchange(&revInVector->m_IsUpdateing,FALSE);\r
+\r
+               //Notify listcontrol and update progress bar\r
+               ++m_CollectedCount;\r
+\r
+               ::PostMessage(m_ploglist->m_hWnd,MSG_LOADED,(WPARAM)rev,0);\r
+\r
+               DWORD percent=m_CollectedCount*98/m_ploglist->m_logEntries.size() + GITLOG_START+1;\r
+               if(percent == GITLOG_END)\r
+                       percent = GITLOG_END -1;\r
+               \r
+               ::PostMessage(m_ploglist->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent,0);\r
+       }\r
+\r
+       CGitLogListBase*        m_ploglist;\r
+       BYTE_VECTOR                     m_ByteCollector;\r
+       int                                     m_CollectedCount;\r
+\r
+};\r
+\r
+void CGitLogListBase::FetchFullLogInfo()\r
+{\r
+       CGitCall_FetchFullLogInfo fetcher(this);\r
+       g_Git.GetLog(&fetcher,CString(),NULL,-1,CGit::LOG_INFO_STAT|CGit::LOG_INFO_FILESTATE|CGit::LOG_INFO_DETECT_COPYRENAME);\r
+}\r
+\r
 UINT CGitLogListBase::LogThread()\r
 {\r
 \r
@@ -1500,7 +1588,7 @@ UINT CGitLogListBase::LogThread()
        unsigned int updated=0;\r
        int percent=0;\r
        CRect rect;\r
-       while(1)\r
+/*     while(1)\r
        {\r
                for(unsigned int i=0;i<m_logEntries.size();i++)\r
                {\r
@@ -1538,8 +1626,11 @@ UINT CGitLogListBase::LogThread()
                }\r
                if(updated==m_logEntries.size())\r
                        break;\r
-       }\r
 \r
+               //m_logEntries.FetchFullInfo(i);\r
+       }\r
+*/\r
+       FetchFullLogInfo();\r
        //RefreshCursor();\r
        // make sure the filter is applied (if any) now, after we refreshed/fetched\r
        // the log messages\r
@@ -1903,3 +1994,4 @@ void CGitLogListBase::SaveColumnWidths()
                }\r
        }\r
 }\r
+\r
index 325c8fc..2446c0e 100644 (file)
@@ -191,6 +191,7 @@ protected:
        virtual BOOL PreTranslateMessage(MSG* pMsg);\r
        static UINT LogThreadEntry(LPVOID pVoid);\r
        UINT LogThread();\r
+       void FetchFullLogInfo();\r
        void FillBackGround(HDC hdc, int Index,CRect &rect);\r
        void DrawTagBranch(HDC,CRect &rect,INT_PTR index);\r
        void DrawGraph(HDC,CRect &rect,INT_PTR index);\r
index 2d4c5e2..6658bd4 100644 (file)
@@ -61,6 +61,7 @@ public:
        int  ParserFromLog(CTGitPath *path =NULL,int count = -1,int infomask=CGit::LOG_INFO_STAT|CGit::LOG_INFO_FILESTATE);\r
        int  ParserShortLog(CTGitPath *path ,CString &hash,int count=-1 ,int mask=CGit::LOG_INFO_ONLY_HASH );\r
        int FetchFullInfo(int i);\r
+//     void AddFullInfo(\r
 \r
        Lanes m_Lns;\r
        int      m_FirstFreeLane;\r