Example #1
0
void CGitStatusCache::RemoveCacheForPath(const CTGitPath& path)
{
    // Stop the crawler starting on a new folder
    CCrawlInhibitor crawlInhibit(&m_folderCrawler);
    CCachedDirectory::ItDir itMap;
    CCachedDirectory * dirtoremove = NULL;

    itMap = m_directoryCache.find(path);
    if ((itMap != m_directoryCache.end())&&(itMap->second))
        dirtoremove = itMap->second;
    if (dirtoremove == NULL)
        return;
    ATLASSERT(path.IsEquivalentToWithoutCase(dirtoremove->m_directoryPath));
    RemoveCacheForDirectory(dirtoremove);
}
Example #2
0
CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bool bRecursive,  bool bFetch /* = true */)
{
	CString sProjectRoot;
	bool bIsVersionedPath;

	bool bRequestForSelf = false;
	if(path.IsEquivalentToWithoutCase(m_directoryPath))
	{
		bRequestForSelf = true;
		AutoLocker lock(m_critSec);
		// HasAdminDir might modify m_directoryPath, so we need to do it synchronized
		bIsVersionedPath = m_directoryPath.HasAdminDir(&sProjectRoot);
	}
	else
		bIsVersionedPath = path.HasAdminDir(&sProjectRoot);

	// In all most circumstances, we ask for the status of a member of this directory.
	ATLASSERT(m_directoryPath.IsEquivalentToWithoutCase(path.GetContainingDirectory()) || bRequestForSelf);

	//If is not version control path
	if( !bIsVersionedPath)
	{
		CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": %s is not underversion control\n"), path.GetWinPath());
		return CStatusCacheEntry();
	}

	// We've not got this item in the cache - let's add it
	// We never bother asking SVN for the status of just one file, always for its containing directory

	if (GitAdminDir::IsAdminDirPath(path.GetWinPathString()))
	{
		// We're being asked for the status of an .git directory
		// It's not worth asking for this
		return CStatusCacheEntry();
	}


	if(bFetch)
	{
		return GetStatusFromGit(path, sProjectRoot);
	}
	else
	{
		return GetStatusFromCache(path, bRecursive);
	}
}
Example #3
0
CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bool bRecursive,  bool bFetch /* = true */)
{
	CString strCacheKey;
	bool bRequestForSelf = false;
	if(path.IsEquivalentToWithoutCase(m_directoryPath))
	{
		bRequestForSelf = true;
	}
//OutputDebugStringA("GetStatusForMember: ");OutputDebugStringW(path.GetWinPathString());OutputDebugStringA("\r\n");
	// In all most circumstances, we ask for the status of a member of this directory.
	ATLASSERT(m_directoryPath.IsEquivalentToWithoutCase(path.GetContainingDirectory()) || bRequestForSelf);

	CString sProjectRoot;
	const BOOL bIsVersionedPath = path.HasAdminDir(&sProjectRoot);

	//If is not version control path
	if( !bIsVersionedPath)
	{
		ATLTRACE(_T("%s is not underversion control\n"), path.GetWinPath());
		return CStatusCacheEntry();
	}

	// We've not got this item in the cache - let's add it
	// We never bother asking SVN for the status of just one file, always for its containing directory

	if (g_GitAdminDir.IsAdminDirPath(path.GetWinPathString()))
	{
		// We're being asked for the status of an .git directory
		// It's not worth asking for this
		return CStatusCacheEntry();
	}


	if(bFetch)
	{
		return GetStatusFromGit(path, sProjectRoot);
	}
	else
	{
		return GetStatusFromCache(path, bRecursive);
	}
}
Example #4
0
/* Fetch is false, means fetch status from cache */
CStatusCacheEntry CGitStatusCache::GetStatusForPath(const CTGitPath& path, DWORD flags,  bool bFetch /* = true */)
{
    bool bRecursive = !!(flags & TGITCACHE_FLAGS_RECUSIVE_STATUS);

    // Check a very short-lived 'mini-cache' of the last thing we were asked for.
    long now = (long)GetTickCount();
    if(now-m_mostRecentExpiresAt < 0)
    {
        if(path.IsEquivalentToWithoutCase(m_mostRecentPath))
        {
            return m_mostRecentStatus;
        }
    }
    m_mostRecentPath = path;
    m_mostRecentExpiresAt = now+1000;

    if (IsPathGood(path))
    {
        // Stop the crawler starting on a new folder while we're doing this much more important task...
        // Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath().
        CCrawlInhibitor crawlInhibit(&m_folderCrawler);

        CTGitPath dirpath = path.GetContainingDirectory();
        if ((dirpath.IsEmpty()) || (!m_shellCache.IsPathAllowed(dirpath.GetWinPath())))
            dirpath = path.GetDirectory();
        CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath);
        if (cachedDir != NULL)
        {
            //ATLTRACE(_T("GetStatusForMember %d\n"), bFetch);
            m_mostRecentStatus = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
            return m_mostRecentStatus;
        }
    }
    ATLTRACE(_T("ignored no good path %s\n"), path.GetWinPath());
    m_mostRecentStatus = CStatusCacheEntry();
    if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.HasGITAdminDir(path.GetWinPath(), true))
    {
        ATLTRACE(_T("force status %s\n"), path.GetWinPath());
        m_mostRecentStatus.ForceStatus(git_wc_status_normal);
    }
    return m_mostRecentStatus;
}
Example #5
0
/* Fetch is false, means fetch status from cache */
CStatusCacheEntry CGitStatusCache::GetStatusForPath(const CTGitPath& path, DWORD flags,  bool bFetch /* = true */)
{
    bool bRecursive = !!(flags & TGITCACHE_FLAGS_RECUSIVE_STATUS);

    // Check a very short-lived 'mini-cache' of the last thing we were asked for.
    long now = (long)GetTickCount();
    if(now-m_mostRecentExpiresAt < 0)
    {
        if(path.IsEquivalentToWithoutCase(m_mostRecentPath))
        {
            return m_mostRecentStatus;
        }
    }
    {
        AutoLocker lock(m_critSec);
        m_mostRecentPath = path;
        m_mostRecentExpiresAt = now + 1000;
    }

    if (IsPathGood(path))
    {
        // Stop the crawler starting on a new folder while we're doing this much more important task...
        // Please note, that this may be a second "lock" used concurrently to the one in RemoveCacheForPath().
        CCrawlInhibitor crawlInhibit(&m_folderCrawler);

        CTGitPath dirpath = path.GetContainingDirectory();
        if ((dirpath.IsEmpty()) || (!m_shellCache.IsPathAllowed(dirpath.GetWinPath())))
            dirpath = path.GetDirectory();
        CCachedDirectory * cachedDir = GetDirectoryCacheEntry(dirpath);
        if (cachedDir != NULL)
        {
            //ATLTRACE(_T("GetStatusForMember %d\n"), bFetch);
            CStatusCacheEntry entry = cachedDir->GetStatusForMember(path, bRecursive, bFetch);
            {
                AutoLocker lock(m_critSec);
                m_mostRecentStatus = entry;
                return m_mostRecentStatus;
            }
        }
    }
    else
    {
        // path is blocked for some reason: return the cached status if we have one
        // we do here only a cache search, absolutely no disk access is allowed!
        CCachedDirectory::ItDir itMap = m_directoryCache.find(path.GetDirectory());
        if ((itMap != m_directoryCache.end())&&(itMap->second))
        {
            if (path.IsDirectory())
            {
                CStatusCacheEntry entry = itMap->second->GetOwnStatus(false);
                AutoLocker lock(m_critSec);
                m_mostRecentStatus = entry;
                return m_mostRecentStatus;
            }
            else
            {
                // We've found this directory in the cache
                CCachedDirectory * cachedDir = itMap->second;
                CStatusCacheEntry entry = cachedDir->GetCacheStatusForMember(path);
                {
                    AutoLocker lock(m_critSec);
                    m_mostRecentStatus = entry;
                    return m_mostRecentStatus;
                }
            }
        }
    }
    AutoLocker lock(m_critSec);
    ATLTRACE(_T("ignored no good path %s\n"), path.GetWinPath());
    m_mostRecentStatus = CStatusCacheEntry();
    if (m_shellCache.ShowExcludedAsNormal() && path.IsDirectory() && m_shellCache.HasGITAdminDir(path.GetWinPath(), true))
    {
        ATLTRACE(_T("force status %s\n"), path.GetWinPath());
        m_mostRecentStatus.ForceStatus(git_wc_status_normal);
    }
    return m_mostRecentStatus;
}
Example #6
0
void CGitStatusCache::UpdateShell(const CTGitPath& path)
{
	if (path.IsEquivalentToWithoutCase(m_mostRecentPath))
		m_mostRecentExpiresAt = 0;
	m_shellUpdater.AddPathForUpdate(path);
}
Example #7
0
git_error_t * CCachedDirectory::GetStatusCallback(void *baton, const char *path, git_wc_status2_t *status)
{
	CCachedDirectory* pThis = (CCachedDirectory*)baton;

	if (path == NULL)
		return 0;

	CTGitPath svnPath;

	if(status->entry)
	{
		if ((status->text_status != git_wc_status_none)&&(status->text_status != git_wc_status_missing))
			svnPath.SetFromSVN(path, (status->entry->kind == svn_node_dir));
		else
			svnPath.SetFromSVN(path);

		if(svnPath.IsDirectory())
		{
			if(!svnPath.IsEquivalentToWithoutCase(pThis->m_directoryPath))
			{
				if (pThis->m_bRecursive)
				{
					// Add any versioned directory, which is not our 'self' entry, to the list for having its status updated
					CGitStatusCache::Instance().AddFolderForCrawling(svnPath);
				}

				// Make sure we know about this child directory
				// This initial status value is likely to be overwritten from below at some point
				git_wc_status_kind s = GitStatus::GetMoreImportant(status->text_status, status->prop_status);
				CCachedDirectory * cdir = CGitStatusCache::Instance().GetDirectoryCacheEntryNoCreate(svnPath);
				if (cdir)
				{
					// This child directory is already in our cache!
					// So ask this dir about its recursive status
					git_wc_status_kind st = GitStatus::GetMoreImportant(s, cdir->GetCurrentFullStatus());
					AutoLocker lock(pThis->m_critSec);
					pThis->m_childDirectories[svnPath] = st;
				}
				else
				{
					// the child directory is not in the cache. Create a new entry for it in the cache which is
					// initially 'unversioned'. But we added that directory to the crawling list above, which
					// means the cache will be updated soon.
					CGitStatusCache::Instance().GetDirectoryCacheEntry(svnPath);
					AutoLocker lock(pThis->m_critSec);
					pThis->m_childDirectories[svnPath] = s;
				}
			}
		}
		else
		{
			// Keep track of the most important status of all the files in this directory
			// Don't include subdirectories in this figure, because they need to provide their
			// own 'most important' value
			pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, status->text_status);
			pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, status->prop_status);
			if (((status->text_status == git_wc_status_unversioned)||(status->text_status == git_wc_status_none))
				&&(CGitStatusCache::Instance().IsUnversionedAsModified()))
			{
				// treat unversioned files as modified
				if (pThis->m_mostImportantFileStatus != git_wc_status_added)
					pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, git_wc_status_modified);
			}
		}
	}
	else
	{
		svnPath.SetFromSVN(path);
		// Subversion returns no 'entry' field for versioned folders if they're
		// part of another working copy (nested layouts).
		// So we have to make sure that such an 'unversioned' folder really
		// is unversioned.
		if (((status->text_status == git_wc_status_unversioned)||(status->text_status == git_wc_status_missing))&&(!svnPath.IsEquivalentToWithoutCase(pThis->m_directoryPath))&&(svnPath.IsDirectory()))
		{
			if (svnPath.HasAdminDir())
			{
				CGitStatusCache::Instance().AddFolderForCrawling(svnPath);
				// Mark the directory as 'versioned' (status 'normal' for now).
				// This initial value will be overwritten from below some time later
				{
					AutoLocker lock(pThis->m_critSec);
					pThis->m_childDirectories[svnPath] = git_wc_status_normal;
				}
				// Make sure the entry is also in the cache
				CGitStatusCache::Instance().GetDirectoryCacheEntry(svnPath);
				// also mark the status in the status object as normal
				status->text_status = git_wc_status_normal;
			}
		}
		else if (status->text_status == git_wc_status_external)
		{
			CGitStatusCache::Instance().AddFolderForCrawling(svnPath);
			// Mark the directory as 'versioned' (status 'normal' for now).
			// This initial value will be overwritten from below some time later
			{
				AutoLocker lock(pThis->m_critSec);
				pThis->m_childDirectories[svnPath] = git_wc_status_normal;
			}
			// we have added a directory to the child-directory list of this
			// directory. We now must make sure that this directory also has
			// an entry in the cache.
			CGitStatusCache::Instance().GetDirectoryCacheEntry(svnPath);
			// also mark the status in the status object as normal
			status->text_status = git_wc_status_normal;
		}
		else
		{
			if (svnPath.IsDirectory())
			{
				AutoLocker lock(pThis->m_critSec);
				pThis->m_childDirectories[svnPath] = GitStatus::GetMoreImportant(status->text_status, status->prop_status);
			}
			else if ((CGitStatusCache::Instance().IsUnversionedAsModified())&&(status->text_status != git_wc_status_missing))
			{
				// make this unversioned item change the most important status of this
				// folder to modified if it doesn't already have another status
				if (pThis->m_mostImportantFileStatus != git_wc_status_added)
					pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, git_wc_status_modified);
			}
		}
	}

	pThis->AddEntry(svnPath, status);

	return 0;
}