void CCachedDirectory::AddEntry(const CTGitPath& path, const git_wc_status2_t* pGitStatus, DWORD validuntil /* = 0*/) { AutoLocker lock(m_critSec); if(path.IsDirectory()) { CCachedDirectory * childDir = CGitStatusCache::Instance().GetDirectoryCacheEntry(path); if (childDir) { if ((childDir->GetCurrentFullStatus() != git_wc_status_missing)||(pGitStatus==NULL)||(pGitStatus->text_status != git_wc_status_unversioned)) { if(pGitStatus) { if(childDir->GetCurrentFullStatus() != GitStatus::GetMoreImportant(pGitStatus->prop_status, pGitStatus->text_status)) { CGitStatusCache::Instance().UpdateShell(path); //CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": shell update for %s\n"), path.GetWinPath()); childDir->m_ownStatus.SetKind(git_node_dir); childDir->m_ownStatus.SetStatus(pGitStatus); } } } childDir->m_ownStatus.SetKind(git_node_dir); } } else { CCachedDirectory * childDir = CGitStatusCache::Instance().GetDirectoryCacheEntry(path.GetContainingDirectory()); bool bNotified = false; if(!childDir) return ; AutoLocker lock2(childDir->m_critSec); CString cachekey = GetCacheKey(path); CacheEntryMap::iterator entry_it = childDir->m_entryCache.lower_bound(cachekey); if (entry_it != childDir->m_entryCache.end() && entry_it->first == cachekey) { if (pGitStatus) { if (entry_it->second.GetEffectiveStatus() > git_wc_status_none && entry_it->second.GetEffectiveStatus() != GitStatus::GetMoreImportant(pGitStatus->prop_status, pGitStatus->text_status) ) { bNotified =true; } } } else { entry_it = childDir->m_entryCache.insert(entry_it, std::make_pair(cachekey, CStatusCacheEntry())); bNotified = true; } entry_it->second = CStatusCacheEntry(pGitStatus, path.GetLastWriteTime(), path.IsReadOnly(), validuntil); // TEMP(?): git status doesn't not have "entry" that contains node type, so manually set as file entry_it->second.SetKind(git_node_file); childDir->m_entryCache_tmp[cachekey] = entry_it->second; if(bNotified) { CGitStatusCache::Instance().UpdateShell(path); //CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": shell update for %s\n"), path.GetWinPath()); } //CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": Path Entry Add %s %s %s %d\n"), path.GetWinPath(), cachekey, m_directoryPath.GetWinPath(), pGitStatus->text_status); } }
CStatusCacheEntry CCachedDirectory::GetStatusFromCache(const CTGitPath& path, bool bRecursive) { if(path.IsDirectory()) { // We don't have directory status in our cache // Ask the directory if it knows its own status CCachedDirectory * dirEntry = CGitStatusCache::Instance().GetDirectoryCacheEntry(path); if( dirEntry) { if (dirEntry->IsOwnStatusValid()) return dirEntry->GetOwnStatus(bRecursive); else { /* cache have outof date, need crawl again*/ /*AutoLocker lock(dirEntry->m_critSec); ChildDirStatus::const_iterator it; for(it = dirEntry->m_childDirectories.begin(); it != dirEntry->m_childDirectories.end(); ++it) { CGitStatusCache::Instance().AddFolderForCrawling(it->first); }*/ CGitStatusCache::Instance().AddFolderForCrawling(path); /*Return old status during crawling*/ return dirEntry->GetOwnStatus(bRecursive); } } else { CGitStatusCache::Instance().AddFolderForCrawling(path); } return CStatusCacheEntry(); } else { //All file ignored if under ignore directory if (m_ownStatus.GetEffectiveStatus() == git_wc_status_ignored) return CStatusCacheEntry(git_wc_status_ignored); if (m_ownStatus.GetEffectiveStatus() == git_wc_status_unversioned) return CStatusCacheEntry(git_wc_status_unversioned); // Look up a file in our own cache AutoLocker lock(m_critSec); CString strCacheKey = GetCacheKey(path); CacheEntryMap::iterator itMap = m_entryCache.find(strCacheKey); if(itMap != m_entryCache.end()) { // We've hit the cache - check for timeout if(!itMap->second.HasExpired((long)GetTickCount())) { if(itMap->second.DoesFileTimeMatch(path.GetLastWriteTime())) { if ((itMap->second.GetEffectiveStatus()!=git_wc_status_missing)||(!PathFileExists(path.GetWinPath()))) { // Note: the filetime matches after a modified has been committed too. // So in that case, we would return a wrong status (e.g. 'modified' instead // of 'normal') here. return itMap->second; } } } } CGitStatusCache::Instance().AddFolderForCrawling(path.GetContainingDirectory()); return CStatusCacheEntry(); } }