bool CSVNStatusCache::RemoveCacheForDirectory(CCachedDirectory * cdir)
{
    if (cdir == NULL)
        return false;
    CAutoWriteLock writeLock(m_guard);
    if (!cdir->m_childDirectories.empty())
    {
        auto it = cdir->m_childDirectories.begin();
        for (; it != cdir->m_childDirectories.end(); )
        {
            CTSVNPath path;
            CString winPath = CUnicodeUtils::GetUnicode (it->first);
            path.SetFromWin (winPath, true);

            CCachedDirectory * childdir = CSVNStatusCache::Instance().GetDirectoryCacheEntryNoCreate(path);
            if ((childdir)&&(!cdir->m_directoryPath.IsEquivalentTo(childdir->m_directoryPath))&&(cdir->m_directoryPath.GetFileOrDirectoryName()!=L".."))
                RemoveCacheForDirectory(childdir);
            cdir->m_childDirectories.erase(it->first);
            it = cdir->m_childDirectories.begin();
        }
    }
    cdir->m_childDirectories.clear();
    m_directoryCache.erase(cdir->m_directoryPath);

    // we could have entries versioned and/or stored in our cache which are
    // children of the specified directory, but not in the m_childDirectories
    // member: this can happen for nested layouts or if we fetched the status
    // while e.g., an update/checkout was in progress
    CCachedDirectory::ItDir itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
    do
    {
        if (itMap != m_directoryCache.end())
        {
            if (cdir->m_directoryPath.IsAncestorOf(itMap->first))
            {
                // just in case (see issue #255)
                if (itMap->second == cdir)
                {
                    m_directoryCache.erase(itMap);
                }
                else
                    RemoveCacheForDirectory(itMap->second);
            }
        }
        itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
    } while (itMap != m_directoryCache.end() && cdir->m_directoryPath.IsAncestorOf(itMap->first));

    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": removed from cache %s\n", cdir->m_directoryPath.GetWinPath());
    delete cdir;
    return true;
}
bool CGitStatusCache::RemoveCacheForDirectory(CCachedDirectory * cdir)
{
    if (cdir == NULL)
        return false;

    typedef std::map<CTGitPath, git_wc_status_kind>  ChildDirStatus;
    if (!cdir->m_childDirectories.empty())
    {
        ChildDirStatus::iterator it = cdir->m_childDirectories.begin();
        for (; it != cdir->m_childDirectories.end(); )
        {
            CCachedDirectory * childdir = CGitStatusCache::Instance().GetDirectoryCacheEntryNoCreate(it->first);
            if ((childdir) && (!cdir->m_directoryPath.IsEquivalentTo(childdir->m_directoryPath)) && (cdir->m_directoryPath.GetFileOrDirectoryName() != L".."))
                RemoveCacheForDirectory(childdir);
            cdir->m_childDirectories.erase(it->first);
            it = cdir->m_childDirectories.begin();
        }
    }
    cdir->m_childDirectories.clear();
    m_directoryCache.erase(cdir->m_directoryPath);

    // we could have entries versioned and/or stored in our cache which are
    // children of the specified directory, but not in the m_childDirectories
    // member
    CCachedDirectory::ItDir itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
    do
    {
        if (itMap != m_directoryCache.end())
        {
            if (cdir->m_directoryPath.IsAncestorOf(itMap->first))
            {
                // just in case (see TortoiseSVN issue #255)
                if (itMap->second == cdir)
                {
                    m_directoryCache.erase(itMap);
                }
                else
                    RemoveCacheForDirectory(itMap->second);
            }
        }
        itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
    } while (itMap != m_directoryCache.end() && cdir->m_directoryPath.IsAncestorOf(itMap->first));

    ATLTRACE(_T("removed path %s from cache\n"), cdir->m_directoryPath.GetWinPathString());
    delete cdir;
    cdir = NULL;
    return true;
}
bool CGitStatusCache::RemoveCacheForDirectory(CCachedDirectory * cdir)
{
    if (cdir == NULL)
        return false;
    AssertWriting();
    typedef std::map<CTGitPath, git_wc_status_kind>  ChildDirStatus;
    if (cdir->m_childDirectories.size())
    {
        ChildDirStatus::iterator it = cdir->m_childDirectories.begin();
        for (; it != cdir->m_childDirectories.end(); )
        {
            CCachedDirectory * childdir = CGitStatusCache::Instance().GetDirectoryCacheEntryNoCreate(it->first);
            if ((childdir)&&(!cdir->m_directoryPath.IsEquivalentTo(childdir->m_directoryPath)))
                RemoveCacheForDirectory(childdir);
            cdir->m_childDirectories.erase(it->first);
            it = cdir->m_childDirectories.begin();
        }
    }
    cdir->m_childDirectories.clear();
    m_directoryCache.erase(cdir->m_directoryPath);
    ATLTRACE(_T("removed path %s from cache\n"), cdir->m_directoryPath.GetWinPathString());
    delete cdir;
    cdir = NULL;
    return true;
}
bool CSVNStatusCache::RemoveCacheForDirectory(CCachedDirectory * cdir)
{
	if (cdir == NULL)
		return false;
	AssertWriting();
	typedef std::map<CTSVNPath, svn_wc_status_kind>  ChildDirStatus;
	if (cdir->m_childDirectories.size())
	{
		ChildDirStatus::iterator it = cdir->m_childDirectories.begin();
		for (; it != cdir->m_childDirectories.end(); )
		{
			CCachedDirectory * childdir = CSVNStatusCache::Instance().GetDirectoryCacheEntryNoCreate(it->first);
			if ((childdir)&&(!cdir->m_directoryPath.IsEquivalentTo(childdir->m_directoryPath)))
				RemoveCacheForDirectory(childdir);
			cdir->m_childDirectories.erase(it->first);
			it = cdir->m_childDirectories.begin();
		}
	}
	cdir->m_childDirectories.clear();
	m_directoryCache.erase(cdir->m_directoryPath);

	// we could have entries versioned and/or stored in our cache which are
	// children of the specified directory, but not in the m_childDirectories
	// member: this can happen for nested layouts or if we fetched the status
	// while e.g., an update/checkout was in progress
	CCachedDirectory::ItDir itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
	do 
	{
		if (itMap != m_directoryCache.end())
		{
			if (cdir->m_directoryPath.IsAncestorOf(itMap->first))
			{
				RemoveCacheForDirectory(itMap->second);
			}
		}
		itMap = m_directoryCache.lower_bound(cdir->m_directoryPath);
	} while (itMap != m_directoryCache.end() && cdir->m_directoryPath.IsAncestorOf(itMap->first));

	CTraceToOutputDebugString::Instance()(_T("SVNStatusCache.cpp: removed from cache %s\n"), cdir->m_directoryPath.GetWinPath());
	delete cdir;
	cdir = NULL;
	return true;
}
void CSVNStatusCache::RemoveCacheForPath(const CTSVNPath& path)
{
    // Stop the crawler starting on a new folder
    CCrawlInhibitor crawlInhibit(&m_folderCrawler);
    CCachedDirectory::ItDir itMap = m_directoryCache.find(path);

    CCachedDirectory * dirtoremove = NULL;
    if ((itMap != m_directoryCache.end())&&(itMap->second))
        dirtoremove = itMap->second;
    if (dirtoremove == NULL)
        return;
    ATLASSERT(path.IsEquivalentToWithoutCase(dirtoremove->m_directoryPath));
    RemoveCacheForDirectory(dirtoremove);
}