OSDN Git Service

RebaseDlg: Disable Reset\Swtich Command at context menu.
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / GitLogListBase.cpp
index 63bf3eb..3bc63a3 100644 (file)
@@ -86,10 +86,13 @@ CGitLogListBase::CGitLogListBase():CHintListCtrl()
 \r
        m_From=CTime(1970,1,2,0,0,0);\r
        m_To=CTime::GetCurrentTime();\r
-    m_bAllBranch = FALSE;\r
+    m_ShowMask = 0;\r
        m_LoadingThread = NULL;\r
 \r
        m_bExitThread=FALSE;\r
+       m_IsOldFirst = FALSE;\r
+       m_IsRebaseReplaceGraph = FALSE;\r
+\r
 \r
        for(int i=0;i<Lanes::COLORS_NUM;i++)\r
        {\r
@@ -105,6 +108,15 @@ CGitLogListBase::CGitLogListBase():CHintListCtrl()
        {\r
                m_DateFormat = DATE_LONGDATE;\r
        }\r
+       // get relative time display setting from registry\r
+       DWORD regRelativeTimes = CRegDWORD(_T("Software\\TortoiseGit\\RelativeTimes"), FALSE);\r
+       m_bRelativeTimes = (regRelativeTimes != 0);\r
+       m_ContextMenuMask = 0xFFFFFFFFFFFFFFFF;\r
+\r
+       m_ContextMenuMask &= ~GetContextMenuBit(ID_REBASE_PICK);\r
+       m_ContextMenuMask &= ~GetContextMenuBit(ID_REBASE_SQUASH);\r
+       m_ContextMenuMask &= ~GetContextMenuBit(ID_REBASE_EDIT);\r
+       m_ContextMenuMask &= ~GetContextMenuBit(ID_REBASE_SKIP);\r
 }\r
 \r
 CGitLogListBase::~CGitLogListBase()\r
@@ -170,6 +182,14 @@ void CGitLogListBase::InsertGitColumn()
                DeleteColumn(c--);\r
        temp.LoadString(IDS_LOG_GRAPH);\r
 \r
+       if(m_IsRebaseReplaceGraph)\r
+       {\r
+               temp=_T("Rebase");\r
+       }\r
+       else\r
+       {\r
+               temp.LoadString(IDS_LOG_GRAPH);\r
+       }\r
        InsertColumn(this->LOGLIST_GRAPH, temp);\r
        \r
 #if 0  \r
@@ -236,6 +256,18 @@ void CGitLogListBase::ResizeAllListCtrlCols()
                        regentry.Format( _T("Software\\TortoiseGit\\log\\ColWidth%d"), col);\r
                        CRegDWORD regwidth(regentry, 0);\r
                        int cx = regwidth;\r
+                       if ( cx == 0 )\r
+                       {\r
+                               // no saved value, setup sensible defaults\r
+                               if (col == this->LOGLIST_MESSAGE)\r
+                               {\r
+                                       cx = LOGLIST_MESSAGE_MIN;\r
+                               }\r
+                               else\r
+                               {\r
+                                       cx = ICONITEMBORDER+16*4;\r
+                               }\r
+                       }\r
                        if (cx < nMinimumWidth)\r
                        {\r
                                cx = nMinimumWidth;\r
@@ -273,6 +305,8 @@ void CGitLogListBase::FillBackGround(HDC hdc, int Index,CRect &rect)
        rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;\r
        GetItem(&rItem);\r
 \r
+       GitRev* pLogEntry = (GitRev*)m_arShownList.GetAt(Index);\r
+\r
        if (m_Theme.IsAppThemed() && m_bVista)\r
        {\r
                m_Theme.Open(m_hWnd, L"Explorer");\r
@@ -326,6 +360,11 @@ void CGitLogListBase::FillBackGround(HDC hdc, int Index,CRect &rect)
                        //if (pLogEntry->bCopiedSelf)\r
                        //      brush = ::CreateSolidBrush(::GetSysColor(COLOR_MENU));\r
                        //else\r
+                       if(pLogEntry->m_Action&CTGitPath::LOGACTIONS_REBASE_SQUASH)\r
+                               brush = ::CreateSolidBrush(RGB(156,156,156));\r
+                       else if(pLogEntry->m_Action&CTGitPath::LOGACTIONS_REBASE_EDIT)\r
+                               brush = ::CreateSolidBrush(RGB(200,200,128));\r
+                       else \r
                                brush = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOW));\r
                }\r
                if (brush == NULL)\r
@@ -673,6 +712,22 @@ void CGitLogListBase::OnNMCustomdrawLoglist(NMHDR *pNMHDR, LRESULT *pResult)
                                        if (data->bCopies)\r
                                                crText = m_Colors.GetColor(CColors::Modified);\r
 #endif\r
+                                       if (data->m_Action& (CTGitPath::LOGACTIONS_REBASE_DONE| CTGitPath::LOGACTIONS_REBASE_SKIP) ) \r
+                                               crText = RGB(128,128,128);\r
+\r
+                                       if(data->m_Action&CTGitPath::LOGACTIONS_REBASE_SQUASH)\r
+                                               pLVCD->clrTextBk = RGB(156,156,156);\r
+                                       else if(data->m_Action&CTGitPath::LOGACTIONS_REBASE_EDIT)\r
+                                               pLVCD->clrTextBk  = RGB(200,200,128);\r
+                                       else \r
+                                               pLVCD->clrTextBk  = ::GetSysColor(COLOR_WINDOW);\r
+\r
+                                       if(data->m_Action&CTGitPath::LOGACTIONS_REBASE_CURRENT)\r
+                                       {\r
+                                               SelectObject(pLVCD->nmcd.hdc, m_boldFont);\r
+                                               *pResult = CDRF_NOTIFYSUBITEMDRAW | CDRF_NEWFONT;\r
+                                       }\r
+\r
 //                                     if ((data->childStackDepth)||(m_mergedRevs.find(data->Rev) != m_mergedRevs.end()))\r
 //                                             crText = GetSysColor(COLOR_GRAYTEXT);\r
 //                                     if (data->Rev == m_wcRev)\r
@@ -703,7 +758,7 @@ void CGitLogListBase::OnNMCustomdrawLoglist(NMHDR *pNMHDR, LRESULT *pResult)
 \r
                        if (pLVCD->iSubItem == LOGLIST_GRAPH)\r
                        {\r
-                               if (m_arShownList.GetCount() > (INT_PTR)pLVCD->nmcd.dwItemSpec)\r
+                               if (m_arShownList.GetCount() > (INT_PTR)pLVCD->nmcd.dwItemSpec && (!this->m_IsRebaseReplaceGraph) )\r
                                {\r
                                        CRect rect;\r
                                        GetSubItemRect(pLVCD->nmcd.dwItemSpec, pLVCD->iSubItem, LVIR_BOUNDS, rect);\r
@@ -775,7 +830,7 @@ void CGitLogListBase::OnNMCustomdrawLoglist(NMHDR *pNMHDR, LRESULT *pResult)
                                        ::DrawIconEx(pLVCD->nmcd.hdc, rect.left + ICONITEMBORDER, rect.top, m_hModifiedIcon, iconwidth, iconheight, 0, NULL, DI_NORMAL);\r
                                nIcons++;\r
 \r
-                               if (pLogEntry->m_Action & CTGitPath::LOGACTIONS_ADDED)\r
+                               if (pLogEntry->m_Action & (CTGitPath::LOGACTIONS_ADDED|CTGitPath::LOGACTIONS_COPY) )\r
                                        ::DrawIconEx(pLVCD->nmcd.hdc, rect.left+nIcons*iconwidth + ICONITEMBORDER, rect.top, m_hAddedIcon, iconwidth, iconheight, 0, NULL, DI_NORMAL);\r
                                nIcons++;\r
 \r
@@ -825,7 +880,14 @@ void CGitLogListBase::OnLvnGetdispinfoLoglist(NMHDR *pNMHDR, LRESULT *pResult)
                pLogEntry = reinterpret_cast<GitRev*>(m_arShownList.GetAt(pItem->iItem));\r
 \r
        CString temp;\r
-       temp.Format(_T("%d"),m_arShownList.GetCount()-pItem->iItem);\r
+       if(m_IsOldFirst)\r
+       {\r
+               temp.Format(_T("%d"),pItem->iItem+1);\r
+\r
+       }else\r
+       {\r
+               temp.Format(_T("%d"),m_arShownList.GetCount()-pItem->iItem);\r
+       }\r
            \r
        // Which column?\r
        switch (pItem->iSubItem)\r
@@ -833,6 +895,13 @@ void CGitLogListBase::OnLvnGetdispinfoLoglist(NMHDR *pNMHDR, LRESULT *pResult)
        case this->LOGLIST_GRAPH:       //Graphic\r
                if (pLogEntry)\r
                {\r
+                       if(this->m_IsRebaseReplaceGraph)\r
+                       {\r
+                               CTGitPath path;\r
+                               path.m_Action=pLogEntry->m_Action&CTGitPath::LOGACTIONS_REBASE_MODE_MASK;\r
+\r
+                               lstrcpyn(pItem->pszText,path.GetActionName(), pItem->cchTextMax);\r
+                       }\r
                }\r
                break;\r
        case this->LOGLIST_ACTION: //action -- no text in the column\r
@@ -850,7 +919,7 @@ void CGitLogListBase::OnLvnGetdispinfoLoglist(NMHDR *pNMHDR, LRESULT *pResult)
        case this->LOGLIST_DATE: //Date\r
                if (pLogEntry)\r
                        lstrcpyn(pItem->pszText,\r
-                               CAppUtils::FormatDateAndTime( pLogEntry->m_AuthorDate, m_DateFormat ), \r
+                               CAppUtils::FormatDateAndTime( pLogEntry->m_AuthorDate, m_DateFormat, true, m_bRelativeTimes ), \r
                                pItem->cchTextMax);\r
                break;\r
                \r
@@ -951,6 +1020,23 @@ void CGitLogListBase::OnContextMenu(CWnd* pWnd, CPoint point)
        CIconMenu popup;\r
        if (popup.CreatePopupMenu())\r
        {\r
+\r
+               if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_PICK))\r
+                       popup.AppendMenuIcon(ID_REBASE_PICK,   _T("Pick"),   IDI_OPEN);\r
+\r
+               if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_SQUASH))\r
+                       popup.AppendMenuIcon(ID_REBASE_SQUASH, _T("Squash"), IDI_OPEN);\r
+\r
+               if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_EDIT))\r
+                       popup.AppendMenuIcon(ID_REBASE_EDIT,   _T("Edit"),   IDI_OPEN);\r
+\r
+               if(m_ContextMenuMask&GetContextMenuBit(ID_REBASE_SKIP))\r
+                       popup.AppendMenuIcon(ID_REBASE_SKIP,   _T("SKIP"),   IDI_OPEN);\r
+               \r
+               if(m_ContextMenuMask&(GetContextMenuBit(ID_REBASE_SKIP)|GetContextMenuBit(ID_REBASE_EDIT)|\r
+                             GetContextMenuBit(ID_REBASE_SQUASH)|GetContextMenuBit(ID_REBASE_PICK)))\r
+                       popup.AppendMenu(MF_SEPARATOR, NULL);\r
+\r
                if (GetSelectedCount() == 1)\r
                {\r
 #if 0\r
@@ -975,7 +1061,8 @@ void CGitLogListBase::OnContextMenu(CWnd* pWnd, CPoint point)
                        {\r
                                if (m_hasWC)\r
                                {\r
-                                       popup.AppendMenuIcon(ID_COMPARE, IDS_LOG_POPUP_COMPARE, IDI_DIFF);\r
+                                       if(m_ContextMenuMask&GetContextMenuBit(ID_COMPARE))\r
+                                               popup.AppendMenuIcon(ID_COMPARE, IDS_LOG_POPUP_COMPARE, IDI_DIFF);\r
                                        // TODO:\r
                                        // TortoiseMerge could be improved to take a /blame switch\r
                                        // and then not 'cat' the files from a unified diff but\r
@@ -984,8 +1071,11 @@ void CGitLogListBase::OnContextMenu(CWnd* pWnd, CPoint point)
                                        // this feature is commented out.\r
                                        //popup.AppendMenu(ID_BLAMECOMPARE, IDS_LOG_POPUP_BLAMECOMPARE, IDI_BLAME);\r
                                }\r
-                               popup.AppendMenuIcon(ID_GNUDIFF1, IDS_LOG_POPUP_GNUDIFF_CH, IDI_DIFF);\r
-                               popup.AppendMenuIcon(ID_COMPAREWITHPREVIOUS, IDS_LOG_POPUP_COMPAREWITHPREVIOUS, IDI_DIFF);\r
+                               if(m_ContextMenuMask&GetContextMenuBit(ID_GNUDIFF1))\r
+                                       popup.AppendMenuIcon(ID_GNUDIFF1, IDS_LOG_POPUP_GNUDIFF_CH, IDI_DIFF);\r
+\r
+                               if(m_ContextMenuMask&GetContextMenuBit(ID_COMPAREWITHPREVIOUS))\r
+                                       popup.AppendMenuIcon(ID_COMPAREWITHPREVIOUS, IDS_LOG_POPUP_COMPAREWITHPREVIOUS, IDI_DIFF);\r
                                //popup.AppendMenuIcon(ID_BLAMEWITHPREVIOUS, IDS_LOG_POPUP_BLAMEWITHPREVIOUS, IDI_BLAME);\r
                                popup.AppendMenu(MF_SEPARATOR, NULL);\r
                        }\r
@@ -1013,12 +1103,24 @@ void CGitLogListBase::OnContextMenu(CWnd* pWnd, CPoint point)
                        \r
                        CString str;\r
                        str.Format(_T("Reset %s to this"),g_Git.GetCurrentBranch());\r
-                       popup.AppendMenuIcon(ID_RESET,str,IDI_REVERT);\r
-                       popup.AppendMenuIcon(ID_SWITCHTOREV, _T("Switch/Checkout to this") , IDI_SWITCH);\r
-                       popup.AppendMenuIcon(ID_CREATE_BRANCH, _T("Create Branch at this version") , IDI_COPY);\r
-                       popup.AppendMenuIcon(ID_CREATE_TAG, _T("Create Tag at this version"), IDI_COPY);\r
-                       popup.AppendMenuIcon(ID_CHERRY_PICK, _T("Cherry Pick this version"), IDI_EXPORT);\r
-                       popup.AppendMenuIcon(ID_EXPORT, _T("Export this version"), IDI_EXPORT);\r
+\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_RESET))\r
+                               popup.AppendMenuIcon(ID_RESET,str,IDI_REVERT);\r
+\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_SWITCHTOREV))\r
+                               popup.AppendMenuIcon(ID_SWITCHTOREV, _T("Switch/Checkout to this") , IDI_SWITCH);\r
+\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_CREATE_BRANCH))\r
+                               popup.AppendMenuIcon(ID_CREATE_BRANCH, _T("Create Branch at this version") , IDI_COPY);\r
+\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_CREATE_TAG))\r
+                               popup.AppendMenuIcon(ID_CREATE_TAG, _T("Create Tag at this version"), IDI_COPY);\r
+\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_CHERRY_PICK))\r
+                               popup.AppendMenuIcon(ID_CHERRY_PICK, _T("Cherry Pick this version"), IDI_EXPORT);\r
+\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_EXPORT))\r
+                               popup.AppendMenuIcon(ID_EXPORT, _T("Export this version"), IDI_EXPORT); \r
                        \r
 \r
                        popup.AppendMenu(MF_SEPARATOR, NULL);\r
@@ -1028,12 +1130,14 @@ void CGitLogListBase::OnContextMenu(CWnd* pWnd, CPoint point)
                        bool bAddSeparator = false;\r
                        if (IsSelectionContinuous() || (GetSelectedCount() == 2))\r
                        {\r
-                               popup.AppendMenuIcon(ID_COMPARETWO, IDS_LOG_POPUP_COMPARETWO, IDI_DIFF);\r
+                               if(m_ContextMenuMask&GetContextMenuBit(ID_COMPARETWO))\r
+                                       popup.AppendMenuIcon(ID_COMPARETWO, IDS_LOG_POPUP_COMPARETWO, IDI_DIFF);\r
                        }\r
                        if (GetSelectedCount() == 2)\r
                        {\r
                                //popup.AppendMenuIcon(ID_BLAMETWO, IDS_LOG_POPUP_BLAMEREVS, IDI_BLAME);\r
-                               popup.AppendMenuIcon(ID_GNUDIFF2, IDS_LOG_POPUP_GNUDIFF, IDI_DIFF);\r
+                               if(m_ContextMenuMask&GetContextMenuBit(ID_GNUDIFF2))\r
+                                       popup.AppendMenuIcon(ID_GNUDIFF2, IDS_LOG_POPUP_GNUDIFF, IDI_DIFF);\r
                                bAddSeparator = true;\r
                        }\r
                        if (m_hasWC)\r
@@ -1062,13 +1166,17 @@ void CGitLogListBase::OnContextMenu(CWnd* pWnd, CPoint point)
                \r
                if (GetSelectedCount() == 1)\r
                {\r
-                       popup.AppendMenuIcon(ID_COPYHASH, _T("Copy Commit Hash"));\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_COPYHASH))\r
+                               popup.AppendMenuIcon(ID_COPYHASH, _T("Copy Commit Hash"));\r
                }\r
                if (GetSelectedCount() != 0)\r
                {\r
-                       popup.AppendMenuIcon(ID_COPYCLIPBOARD, IDS_LOG_POPUP_COPYTOCLIPBOARD);\r
+                       if(m_ContextMenuMask&GetContextMenuBit(ID_COPYCLIPBOARD))\r
+                               popup.AppendMenuIcon(ID_COPYCLIPBOARD, IDS_LOG_POPUP_COPYTOCLIPBOARD);\r
                }\r
-               popup.AppendMenuIcon(ID_FINDENTRY, IDS_LOG_POPUP_FIND);\r
+\r
+               if(m_ContextMenuMask&GetContextMenuBit(ID_FINDENTRY))\r
+                       popup.AppendMenuIcon(ID_FINDENTRY, IDS_LOG_POPUP_FIND);\r
 \r
                int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);\r
 //             DialogEnableWindow(IDOK, FALSE);\r
@@ -1144,7 +1252,8 @@ void CGitLogListBase::CopySelectionToClipBoard(bool HashOnly)
                                sLogCopyText.Format(_T("%s: %s\r\n%s: %s\r\n%s: %s\r\n%s:\r\n%s\r\n----\r\n%s\r\n\r\n"),\r
                                        (LPCTSTR)sRev, pLogEntry->m_CommitHash,\r
                                        (LPCTSTR)sAuthor, (LPCTSTR)pLogEntry->m_AuthorName,\r
-                                       (LPCTSTR)sDate, (LPCTSTR)CAppUtils::FormatDateAndTime( pLogEntry->m_AuthorDate, m_DateFormat ),\r
+                                       (LPCTSTR)sDate, \r
+                                       (LPCTSTR)CAppUtils::FormatDateAndTime( pLogEntry->m_AuthorDate, m_DateFormat, true, m_bRelativeTimes ),\r
                                        (LPCTSTR)sMessage, pLogEntry->m_Subject+_T("\r\n")+pLogEntry->m_Body,\r
                                        (LPCTSTR)sPaths);\r
                                sClipdata +=  sLogCopyText;\r
@@ -1285,12 +1394,12 @@ void CGitLogListBase::OnLvnOdfinditemLoglist(NMHDR *pNMHDR, LRESULT *pResult)
        *pResult = -1;\r
 }\r
 \r
-int CGitLogListBase::FillGitLog(CTGitPath *path,int info)\r
+int CGitLogListBase::FillGitLog(CTGitPath *path,int info,CString *from,CString *to)\r
 {\r
        ClearText();\r
 \r
        this->m_logEntries.ClearAll();\r
-       this->m_logEntries.ParserFromLog(path,-1,info);\r
+       this->m_logEntries.ParserFromLog(path,-1,info,from,to);\r
 \r
        //this->m_logEntries.ParserFromLog();\r
        SetItemCountEx(this->m_logEntries.size());\r
@@ -1299,8 +1408,16 @@ int CGitLogListBase::FillGitLog(CTGitPath *path,int info)
 \r
        for(unsigned int i=0;i<m_logEntries.size();i++)\r
        {\r
-               m_logEntries[i].m_IsFull=TRUE;\r
-               this->m_arShownList.Add(&m_logEntries[i]);\r
+               if(m_IsOldFirst)\r
+               {\r
+                       m_logEntries[m_logEntries.size()-i-1].m_IsFull=TRUE;\r
+                       this->m_arShownList.Add(&m_logEntries[m_logEntries.size()-i-1]);\r
+               \r
+               }else\r
+               {\r
+                       m_logEntries[i].m_IsFull=TRUE;\r
+                       this->m_arShownList.Add(&m_logEntries[i]);\r
+               }\r
        }\r
 \r
     if(path)\r
@@ -1326,8 +1443,8 @@ int CGitLogListBase::FillGitShortLog()
        CString hash;\r
        int mask;\r
        mask = CGit::LOG_INFO_ONLY_HASH | CGit::LOG_INFO_BOUNDARY;\r
-       if(this->m_bAllBranch)\r
-               mask |= CGit::LOG_INFO_ALL_BRANCH;\r
+//     if(this->m_bAllBranch)\r
+       mask |= m_ShowMask;\r
 \r
        this->m_logEntries.ParserShortLog(path,hash,-1,mask);\r
        \r
@@ -1341,8 +1458,16 @@ int CGitLogListBase::FillGitShortLog()
        this->m_arShownList.RemoveAll();\r
 \r
        for(unsigned int i=0;i<m_logEntries.size();i++)\r
-               this->m_arShownList.Add(&m_logEntries[i]);\r
+       {\r
+               if(this->m_IsOldFirst)\r
+               {\r
+                       this->m_arShownList.Add(&m_logEntries[m_logEntries.size()-1-i]);\r
 \r
+               }else\r
+               {\r
+                       this->m_arShownList.Add(&m_logEntries[i]);\r
+               }\r
+       }\r
        return 0;\r
 }\r
 \r
@@ -1430,6 +1555,155 @@ 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
+               if(size==0)\r
+                       return m_ploglist->m_bExitThread;\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
+       virtual void OnEnd()\r
+       {\r
+               //Rest should be a complete log line.\r
+               if(!m_ByteCollector.empty())\r
+                       OnLogInfo(m_ByteCollector);\r
+       }\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_IsFull,TRUE);\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
+       int mask=\r
+               CGit::LOG_INFO_STAT|\r
+               CGit::LOG_INFO_FILESTATE|\r
+               CGit::LOG_INFO_DETECT_COPYRENAME|\r
+               m_ShowMask;\r
+       g_Git.GetLog(&fetcher,CString(),NULL,-1,mask);\r
+}\r
+\r
+void CGitLogListBase::FetchFullLogInfoOrig()\r
+{\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_LogCache.GetCacheData(m_logEntries[i]))\r
+                       {\r
+                               if(!m_logEntries.FetchFullInfo(i))\r
+                               {\r
+                                       updated++;\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
+                       \r
+                       ::PostMessage(m_hWnd,MSG_LOADED,(WPARAM)i,0);\r
+\r
+                       if(m_bExitThread)\r
+                       {\r
+                               InterlockedExchange(&m_bThreadRunning, FALSE);\r
+                               InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
+                               return;\r
+                       }\r
+\r
+                       percent=updated*98/m_logEntries.size() + GITLOG_START+1;\r
+                       if(percent == GITLOG_END)\r
+                               percent = GITLOG_END -1;\r
+                       \r
+                       ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent,0);\r
+\r
+                       \r
+               }\r
+               if(updated==m_logEntries.size())\r
+                       break;\r
+       }\r
+}\r
+\r
 UINT CGitLogListBase::LogThread()\r
 {\r
 \r
@@ -1450,7 +1724,11 @@ UINT CGitLogListBase::LogThread()
        FillGitShortLog();\r
        \r
        if(this->m_bExitThread)\r
+       {\r
+               InterlockedExchange(&m_bThreadRunning, FALSE);\r
+               InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
                return 0;\r
+       }\r
 #if 0\r
        RedrawItems(0, m_arShownList.GetCount());\r
 //     SetRedraw(false);\r
@@ -1477,46 +1755,9 @@ UINT CGitLogListBase::LogThread()
 #endif\r
        InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
 \r
-       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_LogCache.GetCacheData(m_logEntries[i]))\r
-                       {\r
-                               if(!m_logEntries.FetchFullInfo(i))\r
-                               {\r
-                                       updated++;\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
-                       \r
-                       ::PostMessage(m_hWnd,MSG_LOADED,(WPARAM)i,0);\r
-\r
-                       if(m_bExitThread)\r
-                               return 0;\r
-\r
-                       percent=updated*98/m_logEntries.size() + GITLOG_START+1;\r
-                       if(percent == GITLOG_END)\r
-                               percent = GITLOG_END -1;\r
-                       \r
-                       ::PostMessage(this->GetParent()->m_hWnd,MSG_LOAD_PERCENTAGE,(WPARAM) percent,0);\r
-\r
-                       \r
-               }\r
-               if(updated==m_logEntries.size())\r
-                       break;\r
-       }\r
 \r
+       //FetchFullLogInfo();\r
+       FetchFullLogInfoOrig();\r
        //RefreshCursor();\r
        // make sure the filter is applied (if any) now, after we refreshed/fetched\r
        // the log messages\r
@@ -1529,11 +1770,22 @@ UINT CGitLogListBase::LogThread()
 }\r
 \r
 void CGitLogListBase::Refresh()\r
-{\r
-       if(!m_bThreadRunning)\r
+{      \r
+       m_bExitThread=TRUE;\r
+       DWORD ret =::WaitForSingleObject(m_LoadingThread->m_hThread,20000);\r
+       if(ret == WAIT_TIMEOUT)\r
+               TerminateThread();\r
+\r
+       this->Clear();\r
+\r
+       //Update branch and Tag info\r
+       ReloadHashMap();\r
+       //Assume Thread have exited\r
+       //if(!m_bThreadRunning)\r
        {\r
                this->SetItemCountEx(0);\r
                m_logEntries.clear();\r
+               m_bExitThread=FALSE;\r
                InterlockedExchange(&m_bThreadRunning, TRUE);\r
                InterlockedExchange(&m_bNoDispUpdates, TRUE);\r
                if (AfxBeginThread(LogThreadEntry, this)==NULL)\r
@@ -1645,7 +1897,7 @@ void CGitLogListBase::RecalculateShownList(CPtrArray * pShownlist)
                        }\r
                        if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_REVS))\r
                        {\r
-                               sRev.Format(_T("%ld"), m_logEntries[i].m_CommitHash);\r
+                               sRev.Format(_T("%s"), m_logEntries[i].m_CommitHash);\r
                                if (regex_search(wstring((LPCTSTR)sRev), pat, flags)&&IsEntryInDateRange(i))\r
                                {\r
                                        pShownlist->Add(&m_logEntries[i]);\r
@@ -1737,7 +1989,7 @@ void CGitLogListBase::RecalculateShownList(CPtrArray * pShownlist)
                        }\r
                        if ((m_nSelectedFilter == LOGFILTER_ALL)||(m_nSelectedFilter == LOGFILTER_REVS))\r
                        {\r
-                               sRev.Format(_T("%ld"), m_logEntries[i].m_CommitHash);\r
+                               sRev.Format(_T("%s"), m_logEntries[i].m_CommitHash);\r
                                if ((sRev.Find(find) >= 0)&&(IsEntryInDateRange(i)))\r
                                {\r
                                        pShownlist->Add(&m_logEntries[i]);\r
@@ -1794,7 +2046,13 @@ void CGitLogListBase::RemoveFilter()
 \r
        for (DWORD i=0; i<m_logEntries.size(); ++i)\r
        {\r
-               m_arShownList.Add(&m_logEntries[i]);\r
+               if(this->m_IsOldFirst)\r
+               {\r
+                       m_arShownList.Add(&m_logEntries[m_logEntries.size()-i-1]);\r
+               }else\r
+               {\r
+                       m_arShownList.Add(&m_logEntries[i]);\r
+               }\r
        }\r
 //     InterlockedExchange(&m_bNoDispUpdates, FALSE);\r
        DeleteAllItems();\r
@@ -1834,7 +2092,7 @@ void CGitLogListBase::OnDestroy()
        }\r
        while(m_LogCache.SaveCache())\r
        {\r
-               if(CMessageBox::Show(NULL,_T("Cannot Save Log Cache to Disk,click yes for retry, click no for give up"),_T("TortoiseGit"),\r
+               if(CMessageBox::Show(NULL,_T("Cannot Save Log Cache to Disk. To retry click yes. To give up click no."),_T("TortoiseGit"),\r
                                                        MB_YESNO) == IDNO)\r
                                                        break;\r
        }\r
@@ -1869,3 +2127,4 @@ void CGitLogListBase::SaveColumnWidths()
                }\r
        }\r
 }\r
+\r