Ejemplo n.º 1
0
void CCachedDirectory::RefreshStatus(bool bRecursive)
{
	// Make sure that our own status is up-to-date
	GetStatusForMember(m_directoryPath,bRecursive);

	AutoLocker lock(m_critSec);
	// We also need to check if all our file members have the right date on them
	CacheEntryMap::iterator itMembers;
	std::set<CTGitPath> refreshedpaths;
	DWORD now = GetTickCount();
	if (m_entryCache.empty())
		return;
	for (itMembers = m_entryCache.begin(); itMembers != m_entryCache.end(); ++itMembers)
	{
		if (itMembers->first)
		{
			CTGitPath filePath(m_directoryPath);
			filePath.AppendPathString(itMembers->first);
			std::set<CTGitPath>::iterator refr_it;
			if ((!filePath.IsEquivalentToWithoutCase(m_directoryPath))&&
				(((refr_it = refreshedpaths.lower_bound(filePath)) == refreshedpaths.end()) || !filePath.IsEquivalentToWithoutCase(*refr_it)))
			{
				if ((itMembers->second.HasExpired(now))||(!itMembers->second.DoesFileTimeMatch(filePath.GetLastWriteTime())))
				{
					lock.Unlock();
					// We need to request this item as well
					GetStatusForMember(filePath,bRecursive);
					// GetStatusForMember now has recreated the m_entryCache map.
					// So start the loop again, but add this path to the refreshed paths set
					// to make sure we don't refresh this path again. This is to make sure
					// that we don't end up in an endless loop.
					lock.Lock();
					refreshedpaths.insert(refr_it, filePath);
					itMembers = m_entryCache.begin();
					if (m_entryCache.empty())
						return;
					continue;
				}
				else if ((bRecursive)&&(itMembers->second.IsDirectory()))
				{
					// crawl all sub folders too! Otherwise a change deep inside the
					// tree which has changed won't get propagated up the tree.
					CGitStatusCache::Instance().AddFolderForCrawling(filePath);
				}
			}
		}
	}
}
Ejemplo n.º 2
0
void CCachedDirectory::RefreshStatus(bool bRecursive)
{
    // Make sure that our own status is up-to-date
    GetStatusForMember(m_directoryPath,bRecursive);

    CTSVNPathList updatePathList;
    CTSVNPathList crawlPathList;
    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": RefreshStatus for %s\n"), m_directoryPath.GetWinPath());

    DWORD now = GetTickCount();
    {
        // get the file write times with FindFirstFile/FindNextFile since those
        // APIs only access the folder, not each file individually.
        // This reduces the disk access a *lot*.
        std::map<CStringA, ULONGLONG> filetimes;
        WIN32_FIND_DATA FindFileData;
        CAutoFindFile hFind = FindFirstFile(m_directoryPath.GetWinPathString() + L"\\*.*", &FindFileData);
        if (hFind)
        {
            while (FindNextFile(hFind, &FindFileData))
            {
                if ( (wcscmp(FindFileData.cFileName, L"..")==0) ||
                     (wcscmp(FindFileData.cFileName, L".")==0) )
                     continue;
                ULARGE_INTEGER ft;
                ft.LowPart = FindFileData.ftLastWriteTime.dwLowDateTime;
                ft.HighPart = FindFileData.ftLastWriteTime.dwHighDateTime;

                CStringA nameUTF8 = CUnicodeUtils::GetUTF8(FindFileData.cFileName);
                filetimes[nameUTF8] = ft.QuadPart;
            }
            hFind.CloseHandle(); // explicit close handle to shorten its life time
        }

        AutoLocker lock(m_critSec);
        // We also need to check if all our file members have the right date on them
        for (CacheEntryMap::iterator itMembers = m_entryCache.begin(); itMembers != m_entryCache.end(); ++itMembers)
        {
            if ((itMembers->first)&&(!itMembers->first.IsEmpty()))
            {
                CTSVNPath filePath (GetFullPathString (itMembers->first));
                if (!filePath.IsEquivalentToWithoutCase(m_directoryPath))
                {
                    // we only have file members in our entry cache
                    ATLASSERT(!itMembers->second.IsDirectory());

                    auto ftIt = filetimes.find(itMembers->first.Mid(1));
                    if (ftIt != filetimes.end())
                    {
                        ULONGLONG ft = ftIt->second;
                        if ((itMembers->second.HasExpired(now))||(!itMembers->second.DoesFileTimeMatch(ft)))
                        {
                            // We need to request this item as well
                            updatePathList.AddPath(filePath);
                        }
                    }
                }
            }
        }

        if (bRecursive)
        {
            // crawl all sub folders too! Otherwise a change deep inside the
            // tree which has changed won't get propagated up the tree.
            for(ChildDirStatus::const_iterator it = m_childDirectories.begin(); it != m_childDirectories.end(); ++it)
            {
                CTSVNPath path;
                CString winPath = CUnicodeUtils::GetUnicode (it->first);
                path.SetFromWin (winPath, true);

                crawlPathList.AddPath(path);
            }
        }
    }

    for (int i = 0; i < updatePathList.GetCount(); ++i)
        GetStatusForMember(updatePathList[i], bRecursive);

    for (int i = 0; i < crawlPathList.GetCount(); ++i)
        CSVNStatusCache::Instance().AddFolderForCrawling(crawlPathList[i]);
}